您当前的位置:首页 > 电脑百科 > 网络技术 > 网络知识

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

时间:2020-07-26 11:52:16  来源:  作者:

 

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

 

如何构建具有自定义结构和层次的神经网络:Keras中的图卷积神经网络(GCNN)。

在生活中的某个时刻我们会发现,在Tensorflow Keras中预先定义的层已经不够了!我们想要更多的层!我们想要建立一个具有创造性结构的自定义神经网络!幸运的是,通过定义自定义层和模型,我们可以在Keras中轻松地执行此任务。在这个循序渐进的教程中,我们将构建一个包含并行层的神经网络,其中包括一个图卷积层。那么什么是图上的卷积呢?

图卷积神经网络

在传统的神经网络层中,我们在层输入矩阵X和可训练权值矩阵w之间进行矩阵乘法,然后应用激活函数f。因此,下一层的输入(当前层的输出)可以表示为f(XW)。在图卷积神经网络中,我们假设把相似的实例在图中连接起来(如引文网络、基于距离的网络等),并且我们还假设来自相邻节点的特征在监督任务中可能有用。假设A是图的邻接矩阵,那么我们要在卷积层中执行的操作就是f(AXW)。对于图中的每个节点,我们将从其他相连节点聚合特征,然后将这个聚合特征乘以权重矩阵,然后将其激活。图卷积的这个公式是最简单的。对于我们的教程来说,这很好,但是graphCNN更棒!

好的!现在,我们准备开始了!

步骤1.准备工作

首先,我们需要导入一些包。

#Import packages
from tensorflow import __version__ as tf_version, float32 as tf_float32, Variable
from tensorflow.keras import Sequential, Model
from tensorflow.keras.backend import variable, dot as k_dot, sigmoid, relu
from tensorflow.keras.layers import Dense, Input, Concatenate, Layer
from tensorflow.keras.losses import SparseCategoricalCrossentropy
from tensorflow.keras.utils import plot_model
from tensorflow.random import set_seed as tf_set_seed
from numpy import __version__ as np_version, unique, array, mean, argmax
from numpy.random import seed as np_seed, choice
from pandas import __version__ as pd_version, read_csv, DataFrame, concat
from sklearn import __version__ as sk_version
from sklearn.preprocessing import normalizeprint("tensorflow version:", tf_version)
print("numpy version:", np_version)
print("pandas version:", pd_version)
print("scikit-learn version:", sk_version)

你应该把接收到的导入包版本作为输出。在我的例子中,输出是:

tensorflow version: 2.2.0 
numpy version: 1.18.5 
pandas version: 1.0.4 
scikit-learn version: 0.22.2.post1

在本教程中,我们将使用CORA数据集:

Cora数据集由2708份科学出版物组成,这些出版物被分为七个类别。引文网络由5429个链接组成。数据集中的每个发布都由值为0/1的词向量描述,该词向量表示字典中对应词的出现或消失。这部词典由1433个独特的单词组成。

让我们加载数据,创建邻接矩阵,把特征矩阵准备好。

# Load cora datadtf_data = read_csv("https://raw.githubusercontent.com/ngshya/datasets/master/cora/cora_content.csv").sort_values(["paper_id"], ascending=True)
dtf_graph = read_csv("https://raw.githubusercontent.com/ngshya/datasets/master/cora/cora_cites.csv")

# Adjacency matrix
array_papers_id = unique(dtf_data["paper_id"])
dtf_graph["connection"] = 1
dtf_graph_tmp = DataFrame({"cited_paper_id": array_papers_id, "citing_paper_id": array_papers_id, "connection": 0})
dtf_graph = concat((dtf_graph, dtf_graph_tmp)).sort_values(["cited_paper_id", "citing_paper_id"], ascending=True)
dtf_graph = dtf_graph.pivot_table(index="cited_paper_id", columns="citing_paper_id", values="connection", fill_value=0).reset_index(drop=True)
A = array(dtf_graph)
A = normalize(A, norm='l1', axis=1)
A = variable(A, dtype=tf_float32)

# Feature matrix
data = array(dtf_data.iloc[:, 1:1434])

# Labels
labels = array(
    dtf_data["label"].map({
	    'Case_Based': 0,
	    'Genetic_Algorithms': 1,
	    'Neural_Networks': 2,
	    'Probabilistic_Methods': 3,
	    'Reinforcement_Learning': 4,
	    'Rule_Learning': 5,
	    'Theory': 6
    })
)

# Check dimensions
print("Features matrix dimension:", data.shape, "| Label array dimension:", labels.shape, "| Adjacency matrix dimension:", A.shape)

最后,我们定义一些对神经网络的训练有用的参数。

# Training parameters
input_shape = (data.shape[1], )
output_classes = len(unique(labels))
iterations = 50
epochs = 100
batch_size = data.shape[0]
labeled_portion = 0.10

正如你可以从上面的代码中推断出的那样,对于每个模型,我们将执行50次迭代,在每次迭代中,我们将随机选择一个标记为10%的集合(训练集),并对模型进行100个epoch的训练。

需要指出的是,本教程的范围不是训练CORA数据集上最精确的模型。相反,我们只是想提供一个使用keras自定义层实现自定义模型的示例!

模型1:序列层的神经网络

作为基准,我们使用具有序列层的标准神经网络(熟悉的keras序列模型)。

# 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 1

tf_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 = 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 2

tf_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 = 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 layer

class GraphConv(Layer):

def __init__(self, num_outputs, A, activation="sigmoid", **kwargs):
    super(GraphConv, self).__init__(**kwargs)
    self.num_outputs = num_outputs
    self.activation_function = activation
    self.A = Variable(A, trainable=False)

def build(self, input_shape):
    # Weights
    self.W = self.add_weight("W", shape=[int(input_shape[-1]), self.num_outputs])
    # bias
    self.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方法中,声明了前向传递计算。

在前面的模型中,我们定义了一个具有并行层的网络。

# Model 3: neural network with graph convolutional layer

tf_set_seed(1102)
np_seed(1102)

m3_input_layer = Input(shape=input_shape)
m3_dense_layer = Dense(32, activation='relu')(m3_input_layer)
m3_gc_layer = GraphConv(16, A=A, activation='relu')(m3_input_layer)
m3_merged_layer = Concatenate()([m3_dense_layer, m3_gc_layer])
m3_final_layer = Dense(output_classes, activation='softmax')(m3_merged_layer)

model3 = Model(inputs=m3_input_layer, outputs=m3_final_layer, name="Model_3")

model3.save_weights("model3_initial_weights.h5")

model3.summary()
plot_model(model3, 'model3.png', show_shapes=True)

它看起来像以前的模型,但有一层是卷积的:每个实例的固有特征与从邻域计算出的聚合特征连接在了一起。

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

 

在编写这一模型时,需要进一步注意。由于卷积层需要整个邻接矩阵,所以我们需要传递整个特征矩阵(带标签的和没带标签的实例),但是模型应该只训练带标签的实例。因此,我们定义了一个自定义的损失函数,其中稀疏分类cossentropy只计算在标记的实例。此外,我们将未标记实例的标签随机化,以确保在训练期间不会使用它们。

# Testing model 3

tf_set_seed(1102)
np_seed(1102)

acc_model3 = []

for i in range(iterations):
    mask = choice([True, False], size=data.shape[0], replace=True, p=[labeled_portion, 1-labeled_portion])
    unlabeled_data_labels = labels[~mask]
    # Randomize the labels of unlabeled instances
    masked_labels = labels.copy()
    masked_labels[~mask] = choice(range(7), size=sum(~mask), replace=True)  

model3.load_weights("model3_initial_weights.h5")
    model3.compile(
    optimizer='adam', 
    loss=lambda y_true, y_pred: SparseCategoricalCrossentropy(from_logits=False)(y_true[mask], y_pred[mask]),
    metrics=['accuracy']
)

model3.fit(data, masked_labels, epochs=epochs, batch_size=batch_size, shuffle=False, verbose=0)   

predictions = argmax(model3.predict(data, batch_size=batch_size), axis=1)
acc_model3.append(sum(predictions[~mask] == unlabeled_data_labels) / len(unlabeled_data_labels) * 100)

print("nAverage accuracy on unlabeled set:", mean(acc_model3), "%")

这个实验的平均准确率为63%(+3)。

有趣的是,在最后这个实验中,我们基本上是在用graphCNN执行半监督学习:来自未标记实例的信息和来自标记实例的信息一起被用来构建一个基于图的转导模型。

参考网站

#https://tkipf.github.io/graph-convolutional-networks/
#https://www.tensorflow.org/api_docs/Python/tf/keras

作者:Shuyi Yang

deephub翻译组:钱三一



Tags:Keras   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
您是否曾经不得不加载一个非常消耗内存的数据集,以至于您希望有一个方法处理它呢?随着我们能够利用越来越多的数据,大型数据集正日益成为我们生活的一部分。我们必须记住,在某...【详细内容】
2020-09-10  Tags: Keras  点击:(162)  评论:(0)  加入收藏
介绍生成对抗网络通常也称为GANs,用于生成图像而不需要很少或没有输入。GANs允许我们生成由神经网络生成的图像。在我们深入讨论这个理论之前,我想向您展示GANs构建您兴奋感的...【详细内容】
2020-08-24  Tags: Keras  点击:(93)  评论:(0)  加入收藏
如何构建具有自定义结构和层次的神经网络:Keras中的图卷积神经网络(GCNN)。在生活中的某个时刻我们会发现,在Tensorflow Keras中预先定义的层已经不够了!我们想要更多的层!...【详细内容】
2020-07-26  Tags: Keras  点击:(68)  评论:(0)  加入收藏
朋友多次劝我,用大数据人工智能研究下金融股票,由于本人水平有限,一直没有去想。最近两天,突然想到LSTM是不是很适合做股票预测。通过上网学习,还是真有案例。适合多输入变量的神...【详细内容】
2020-06-21  Tags: Keras  点击:(316)  评论:(0)  加入收藏
▌简易百科推荐
HTTP 报文是在应用程序之间发送的数据块,这些数据块将通过以文本形式的元信息开头,用于 HTTP 协议交互。请求端(客户端)的 HTTP 报文叫做请求报文,响应端(服务器端)的叫做响应...【详细内容】
2021-12-27  程序员蛋蛋    Tags:HTTP 报文   点击:(1)  评论:(0)  加入收藏
一 网络概念:1.带宽: 标识网卡的最大传输速率,单位为 b/s,比如 1Gbps,10Gbps,相当于马路多宽2.吞吐量: 单位时间内传输数据量大小单位为 b/s 或 B/s ,吞吐量/带宽,就是网络的使用率...【详细内容】
2021-12-27  码农世界    Tags:网络   点击:(2)  评论:(0)  加入收藏
1.TCP/IP 网络模型有几层?分别有什么用? TCP/IP网络模型总共有五层 1.应用层:我们能接触到的就是应用层了,手机,电脑这些这些设备都属于应用层。 2.传输层:就是为应用层提供网络...【详细内容】
2021-12-22  憨猪哥08    Tags:TCP/IP   点击:(29)  评论:(0)  加入收藏
TCP握手的时候维护的队列 半连接队列(SYN队列) 全连接队列(accepted队列)半连接队列是什么?服务器收到客户端SYN数据包后,Linux内核会把该连接存储到半连接队列中,并响应SYN+ACK报...【详细内容】
2021-12-21  DifferentJava    Tags:TCP   点击:(9)  评论:(0)  加入收藏
你好,这里是科技前哨。 随着“元宇宙”概念的爆火,下一代互联网即将到来,也成了互联网前沿热议的话题,12月9日美国众议院的听证会上,共和党议员Patrick McHenry甚至宣称,要调整现...【详细内容】
2021-12-17  王煜全    Tags:Web3   点击:(14)  评论:(0)  加入收藏
一、demopublic static void main(String[] args) throws Exception { RetryPolicy retryPolicy = new ExponentialBackoffRetry( 1000, 3);...【详细内容】
2021-12-15  程序员阿龙    Tags:Curator   点击:(20)  评论:(0)  加入收藏
一、计算机网络概述 1.1 计算机网络的分类按照网络的作用范围:广域网(WAN)、城域网(MAN)、局域网(LAN);按照网络使用者:公用网络、专用网络。1.2 计算机网络的层次结构 TCP/IP四层模...【详细内容】
2021-12-14  一口Linux    Tags:网络知识   点击:(30)  评论:(0)  加入收藏
无论是在外面还是在家里,许多人都习惯了用手机连接 WiFi 进行上网。不知道大家有没有遇到过这样一种情况, 明明已经显示成功连接 WiFi,却仍然提示“网络不可用”或“不可上网”...【详细内容】
2021-12-14  UGREEN绿联    Tags:WiFi   点击:(25)  评论:(0)  加入收藏
拉了千兆宽带,买了标称 1300Mbps 的无线路由器,为什么 WiFi 还是跑不满千兆?要回答这个问题,我们先得知道这个 1300Mbps 是怎么来的。开始回答之前先说明一下,这期只讲 802.11ac,...【详细内容】
2021-12-14  Ubiquiti优倍快    Tags:WiFi   点击:(85)  评论:(0)  加入收藏
问题背景IPv6环境下,在浏览器中通过http://[vip:port]访问web业务,提示无法访问此网站,[vip]的响应时间过长。分析过程之前碰到过多次在PC浏览器上无法访问vip的情况,排查方法也...【详细内容】
2021-12-13  云原生知识星球    Tags:网络问题   点击:(27)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条