使用Keras构建具有自定义结构和层次的图卷积神经网络(GCNN)( 二 )


# Model 1: standard sequential neural networktf_set_seed(1102)np_seed(1102)model1 = Sequential([Dense(32, input_shape=input_shape, activation='relu'),Dense(16, activation='relu'),Dense(output_classes, activation='softmax')], name="Model_1")model1.save_weights("model1_initial_weights.h5")model1.summary()plot_model(model1, 'model1.png', show_shapes=True)我们可以绘制模型来查看序列结构 。
使用Keras构建具有自定义结构和层次的图卷积神经网络(GCNN)文章插图
让我们看看这个模型是如何运行的 。
# Testing model 1tf_set_seed(1102)np_seed(1102)acc_model1 = []for _ in range(iterations):mask = choice([True, False], size=data.shape[0], replace=True, p=[labeled_portion, 1-labeled_portion])labeled_data = http://kandian.youth.cn/index/data[mask, :]unlabeled_data = data[~mask, :]labeled_data_labels = labels[mask]unlabeled_data_labels = labels[~mask]model1.load_weights("model1_initial_weights.h5")model1.compile(optimizer='adam',loss=SparseCategoricalCrossentropy(from_logits=False),metrics=['accuracy'])model1.fit(labeled_data, labeled_data_labels, epochs=epochs, batch_size=batch_size, verbose=0)acc_model1.append(sum(argmax(model1.predict(unlabeled_data, batch_size=batch_size), axis=1) == unlabeled_data_labels) / len(unlabeled_data_labels) * 100)print("\nAverage accuracy on unlabeled set:", mean(acc_model1), "%")你可以得出准确率为55%
模型2:并行层的神经网络让我们对前面的模型做一个小修改 。 这一次 , 我们希望拥有一个具有两个并行隐藏层的网络 。 我们使用Keras函数API 。 可以构建具有非线性拓扑的模型、具有共享层的模型以及具有多个输入或输出的模型 。 基本上 , 我们需要给每一层分配一个变量 , 然后引用这个变量来连接不同的层 , 从而创建一个有向无环图(DAG) 。 然后通过输入层和输出层来建立模型 。
# Model 2: neural network with parallel layerstf_set_seed(1102)np_seed(1102)m2_input_layer = Input(shape=input_shape)m2_dense_layer_1 = Dense(32, activation='relu')(m2_input_layer)m2_dense_layer_2 = Dense(16, activation='relu')(m2_input_layer)m2_merged_layer = Concatenate()([m2_dense_layer_1, m2_dense_layer_2])m2_final_layer = Dense(output_classes, activation='softmax')(m2_merged_layer)model2 = Model(inputs=m2_input_layer, outputs=m2_final_layer, name="Model_2")model2.save_weights("model2_initial_weights.h5")model2.summary()plot_model(model2, 'model2.png', show_shapes=True)并行的两个层m2_dense_layer_1和m2_dense_layer_2依赖于相同的输入层m2_input_layer , 然后串联起来在m2_merged_layer中形成一个唯一的层 。 这个神经网络如下所示:
使用Keras构建具有自定义结构和层次的图卷积神经网络(GCNN)文章插图
让我们测试一下这个模型
# Testing model 2tf_set_seed(1102)np_seed(1102)acc_model2 = []for _ in range(iterations):mask = choice([True, False], size=data.shape[0], replace=True, p=[labeled_portion, 1-labeled_portion])labeled_data = http://kandian.youth.cn/index/data[mask, :]unlabeled_data = data[~mask, :]labeled_data_labels = labels[mask]unlabeled_data_labels = labels[~mask]model2.load_weights("model2_initial_weights.h5")model2.compile(optimizer='adam',loss=SparseCategoricalCrossentropy(from_logits=False),metrics=['accuracy'])model2.fit(labeled_data, labeled_data_labels, epochs=epochs, batch_size=batch_size, shuffle=False, verbose=0)acc_model2.append(sum(argmax(model2.predict(unlabeled_data, batch_size=batch_size), axis=1) == unlabeled_data_labels) / len(unlabeled_data_labels) * 100)print("\nAverage accuracy on unlabeled set:", mean(acc_model2), "%")平均准确度接近60% (+5)!
模型3:具有图卷积层的神经网络到目前为止 , 我们已经了解了如何使用Keras Functional API创建自定义网络结构 。 那如果我们需要使用用户自定义的操作自定义的层呢?在我们的例子中 , 我们想要定义一个简单的图卷积层 , 如本教程开始部分所解释的那样 。 为此 , 我们需要从类层创建一个子类 , 定义的_init_方法 , 构建和调用 。
# Graph convolutional layerclass GraphConv(Layer):def __init__(self, num_outputs, A, activation="sigmoid", **kwargs):super(GraphConv, self).__init__(**kwargs)self.num_outputs = num_outputsself.activation_function = activationself.A = Variable(A, trainable=False)def build(self, input_shape):# Weightsself.W = self.add_weight("W", shape=[int(input_shape[-1]), self.num_outputs])# biasself.bias = self.add_weight("bias", shape=[self.num_outputs])def call(self, input):if self.activation_function == 'relu':return relu(k_dot(k_dot(self.A, input), self.W) + self.bias)else:return sigmoid(k_dot(k_dot(self.A, input), self.W) + self.bias)在初始化期间 , 你可以要求并保存任何有用的参数(例如激活函数 , 输出神经元数) 。 在我们的例子中 , 我们还需要邻接矩阵a 。 在构建方法中 , 层的可训练权重被初始化 。 在call方法中 , 声明了前向传递计算 。