到现在为止,我们使用的是DeepChem提供的标准模型。这对于许多应用来说是好的。但是很快你就会希望用你自己定义的框架创建你自已的模型。DeepChem提供了TensorFlow (Keras) 和PyTorch集成,所以你可以使用这两个框架来创建模型。
实际上,DeepChem中使用 TensorFlow 或 PyTorch模型有两种不同的方法。这取决于你想用TensorFlow/PyTorch APIs还是DeepChem APIs来训练和评估模型。对于前者,DeepChem's Dataset类易于适配到其它的框架。make_tf_dataset() 返回一个 tensorflow.data.Dataset对象,它迭代所有的数据。make_pytorch_dataset()返回一个 torch.utils.data.IterableDataset对象,它迭代所有的数据。这可以让你使用DeepChem的datasets, loaders, featurizers, transformers, splitters, 等,并易于集成到你已有的TensorFlow或PyTorch代码。但是DeepChem也提供很多其它有用的特性。另一个方法,你可以使用这些特性,就是将你的模型打包到 DeepChem模型对象中。
我们来看一下如何操作。
KerasModel
KerasModel是DeepChem模型类的子类。它作为tensorflow.keras.Model打包器。我们来看一下使用它的例子。这个例子中,我们创建一个简单的串行模型由个全链接层组成。
In [1]:
import deepchem as dc
import tensorflow as tf
keras_model = tf.keras.Sequential([
tf.keras.layers.Dense(1000, activation='relu'),
tf.keras.layers.Dropout(rate=0.5),
tf.keras.layers.Dense(1)
])
model = dc.models.KerasModel(keras_model, dc.models.losses.L2Loss())
这个例子,我们使用Keras的Sequential类。我们的模型由带有 ReLU激活函数的全链接层组成。用 50% dropout进行规定化,最后一层产一标量输出。训练模型时我们要指定使用的损失函数,这个例子使用L2损失函数。我们现在可以训练和评估模型了,就像其它的DeepChem模型一样。例如,我们加载 Delaney溶解度数据集。我们的模型基于
extended-connectivity fingerprints (ECFPs)预测分子的溶解度的表现如何呢?
In [2]:
tasks, datasets, transformers = dc.molnet.load_delaney(featurizer='ECFP', splitter='random')
train_dataset, valid_dataset, test_dataset = datasets
model.fit(train_dataset, nb_epoch=50)
metric = dc.metrics.Metric(dc.metrics.pearson_r2_score)
print('training set score:', model.evaluate(train_dataset, [metric]))
print('test set score:', model.evaluate(test_dataset, [metric]))
training set score: {'pearson_r2_score': 0.9787445597470444}
test set score: {'pearson_r2_score': 0.736905850092889}
TorchModel
TorchModel与KerasModel一样,除了它打包torch.nn.Module外。我们用PyTorch来创建其它的模型就像前面一样并用同样的数据来训练模型。
In [3]:
import torch
pytorch_model = torch.nn.Sequential(
torch.nn.Linear(1024, 1000),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(1000, 1)
)
model = dc.models.TorchModel(pytorch_model, dc.models.losses.L2Loss())
model.fit(train_dataset, nb_epoch=50)
print('training set score:', model.evaluate(train_dataset, [metric]))
print('test set score:', model.evaluate(test_dataset, [metric]))
training set score: {'pearson_r2_score': 0.9798256761766225}
test set score: {'pearson_r2_score': 0.7256745385608444}
计算损失
我们看一下更先进的例子。上面的模型中,损失函数直拉由模型的输出计算得到。这通常是好的,但并不总是好的。考虑一下输出概率分布的模型,尽管可能从概率计算损失,但是从logits计算损失的数值稳定性更好。为了这么做,我们创建一个返回多个输出的模型,可以是概率和logitsKerasModel 和 TorchModel 可以让你指定“输出类型”列表。如果有特殊的输出类型“prediction“,意味着当你调用predict()函数时应返回正常的输出如果类型为 'loss',意味着它应传递给损失函数正常的输出。Sequential模型并不总是多输出,因此我们可以使用子类。
In [4]:
class ClassificationModel(tf.keras.Model):
def __init__(self):
super(ClassificationModel, self).__init__()
self.dense1 = tf.keras.layers.Dense(1000, activation='relu')
self.dense2 = tf.keras.layers.Dense(1)
def call(self, inputs, training=False):
y = self.dense1(inputs)
if training:
y = tf.nn.dropout(y, 0.5)
logits = self.dense2(y)
output = tf.nn.sigmoid(logits)
return output, logits
keras_model = ClassificationModel()
output_types = ['prediction', 'loss']
model = dc.models.KerasModel(keras_model, dc.models.losses.SigmoidCrossEntropy(), output_types=output_types)
我们可以用BACE数据集来训练我们的模型。这是一个二值分类任务,试图预测分子是否抑制BACE-1酶。
In [5]:
tasks, datasets, transformers = dc.molnet.load_bace_classification(feturizer='ECFP', split='scaffold')
train_dataset, valid_dataset, test_dataset = datasets
model.fit(train_dataset, nb_epoch=100)
metric = dc.metrics.Metric(dc.metrics.roc_auc_score)
print('training set score:', model.evaluate(train_dataset, [metric]))
print('test set score:', model.evaluate(test_dataset, [metric]))
training set score: {'roc_auc_score': 0.9996116504854369}
test set score: {'roc_auc_score': 0.7701992753623188}
其它特征
KerasMode和TorchModel有许多其它特征。以下是一些重要的特征。
在训练过程中自动保存断点。
向控制台输出过程日志,如 TensorBoard, 或Weights & Biases。
你用函数形式f(outputs, labels, weights)定制损失函数。
用ValidationCallback类早期停止。
从预训练模型加载参数。
评估模型输出的不确定性。
通过特征映射识别重要特征。
通过打包你的模型于KerasModel 或TorchModel,你可以立即访问这些特征。
全部的细节你可以见API文档。