考虑一种常用于处理图像的标准卷积神经网络 (CNN)。输入是像素网格。每个像素都有一个数据值向量,例如红色、绿色和蓝色通道。数据通过一系列卷积层。每层结合来自像素及其相邻像素的数据,为该像素生成新的数据向量。前面的卷积层检测小规模的局部模式,而后面的卷积层检测更大、更抽象的模式。通常,卷积层与池化层交替出现,池化层在局部区域执行一些操作,例如最大值或最小值。
图卷积是一种基于图结构的卷积操作。与传统的卷积操作不同,图卷积的输入是一个图形,包含节点和边,而不是一个二维或三维的张量。图卷积的目的是通过学习节点之间的关系来进行特征提取和分类等任务。
图卷积的原理可以概括为以下几个步骤:
聚合:对于每个节点,将其邻近节点的特征进行聚合,可以使用均值、最大值、加权和等方式来计算邻近节点的特征。
更新:根据聚合后的邻居节点特征以及当前节点自身的特征,更新当前节点的特征表示。
激活:对更新后的节点特征进行激活函数操作,例如ReLU函数等。
图1 图卷积神经网络原理
DeepChem有一个名为GraphConvModel的类,它在其内部包装了一个标准的图卷积网络结构,以方便用户使用。
import deepchem as dc
tasks, datasets, transformers = dc.molnet.load_tox21(featurizer='GraphConv')
train_dataset, valid_dataset, test_dataset = datasets
n_tasks = len(tasks)
model = dc.models.GraphConvModel(n_tasks, mode='classification')
model.fit(train_dataset, nb_epoch=50)
metric = dc.metrics.Metric(dc.metrics.roc_auc_score)
print('Training set score:', model.evaluate(train_dataset, [metric], transformers))
print('Test set score:', model.evaluate(test_dataset, [metric], transformers))
DeepChem为图卷积中涉及的所有计算提供了Keras层。我们将使用以下DeepChem层:
GraphConv层:该层实现了图卷积。图卷积以非线性方式将每个节点的特征向量与相邻节点的特征向量组合在一起,从而“混合”了图的局部邻域信息。
GraphPool层:该层对邻域中原子的特征向量进行最大池化。可以将此层视为类似于2D卷积的最大池化层,但是在图上操作。
GraphGather层:许多图卷积网络会操作每个节点的特征向量,例如对于分子,每个节点可能表示一个原子,网络会操作汇总该原子局部化学信息的原子特征向量。然而,在应用结束时,我们可能希望使用分子级别的特征表示。该层通过组合所有节点级别的特征向量创建一个图级别的特征向量。
batch_size = 100
class MyGraphConvModel(tf.keras.Model):
def __init__(self):
super(MyGraphConvModel, self).__init__()
self.gc1 = GraphConv(128, activation_fn=tf.nn.tanh)
self.batch_norm1 = layers.BatchNormalization()
self.gp1 = GraphPool()
self.gc2 = GraphConv(128, activation_fn=tf.nn.tanh)
self.batch_norm2 = layers.BatchNormalization()
self.gp2 = GraphPool()
self.dense1 = layers.Dense(256, activation=tf.nn.tanh)
self.batch_norm3 = layers.BatchNormalization()
self.readout = GraphGather(batch_size=batch_size, activation_fn=tf.nn.tanh)
self.dense2 = layers.Dense(n_tasks*2)
self.logits = layers.Reshape((n_tasks, 2))
self.softmax = layers.Softmax()
def call(self, inputs):
gc1_output = self.gc1(inputs)
batch_norm1_output = self.batch_norm1(gc1_output)
gp1_output = self.gp1([batch_norm1_output] + inputs[1:])
gc2_output = self.gc2([gp1_output] + inputs[1:])
batch_norm2_output = self.batch_norm1(gc2_output)
gp2_output = self.gp2([batch_norm2_output] + inputs[1:])
dense1_output = self.dense1(gp2_output)
batch_norm3_output = self.batch_norm3(dense1_output)
readout_output = self.readout([batch_norm3_output] + inputs[1:])
logits_output = self.logits(self.dense2(readout_output))
return self.softmax(logits_output)
model = dc.models.KerasModel(MyGraphConvModel(), loss=dc.models.losses.CategoricalCrossEntropy())
我们现在可以更清晰地看到:有两个卷积层,每个卷积层由一个GraphConv组成,后跟归一化,然后是一个GraphPool进行最大池化。最后我们使用一个图聚合层,另一个归一化,一个GraphGather来组合所有不同节点的数据,最后一个全连接层产生全局输出。
关注我获得
联系客服