本次要总结的论文是 Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering,论文链接GCN[1],参考的代码实现GCN-code[2]。
不得不说,读懂这篇论文难度较大,因为里面有许多数学推导,要了解较多的数学知识。本人数学一般,因此在读本论文的同时参考了网上部分较优秀的讲解,这里会结合我对论文的理解,对本论文下总结,文末会详细列出我参考的讲解链接。
「建议在非深色主题下阅读本文,pc端阅读点击文末左下角“原文链接”,体验更佳」
回顾卷积定义与CNN
传统傅里叶变换与卷积
拉普拉斯算子与拉普拉斯矩阵
GCN模型
切比雪夫多项式及其捕捉局部特征
Graph Coarsening(图粗化)
文本分类实验(Text Categorization on 20NEWS)
数据预处理步骤
模型部分
实验结果
个人总结
参考文献
我们知道卷积神经网络(cnn)在图像、视频、语音识别等领域取得了巨大的成功。cnn的一个核心内容就是卷积操作。
卷积核:上图中的feature map 参数共享机制:假设每个神经元连接数据窗口的权重是固定的
❝对于input layer中,不同的数据区域,卷积核参数是共享的,但是不同的输入通道卷积核参数可以不同
❞
这种参数共享机制有如下两个优点
在维基百科里,可以得到卷积操作的定义: 为 的卷积
❝更深入的理解可参考知乎这个回答:如何通俗易懂地解释卷积?[3]
❞
那么对于「不规则或非欧几里德域上」的结构数据,例如社交网络用户数据、生物调控网络上的基因数据、电信网络上的日志数据或单词嵌入的文本文档数据等,可以用图形(graph)来构造,cnn上的卷积操作想直接推广到graph上并不是简单可行的,「因为卷积核池化操作只能作用在规则的网格中。」
由上面一张社交网络图可以看出,每个顶点的邻居顶点数量可能都不一致,无法直接使用卷积核池化操作进行特征提取。
为此还需要了解傅里叶变换以及拉普拉斯算子。
傅里叶变换的核心是「从时域到频域的变换,而这种变换是通过一组特殊的正交基来实现的。即把任意一个函数表示成了若干个正交函数(由sin,cos 构成)的线性组合。」
❝为傅里叶变换基函数,且为拉普拉斯算子的特征函数
❞
定义
是
和
的卷积,则有代入
最后对等式的两边同时作用
,得到
也即是:「即对于函数
与
两者的卷积是其函数傅立叶变换乘积的逆变换」
即可以通过傅里叶变换得到函数卷积结果。
那么问题来了,如何类比到graph上的傅里叶变换呢?
这里只说几点重要的结论
❝拉普拉斯矩阵实际上是对图的一种矩阵表示形式,这句话太重要了 更深入的证明请查看拉普拉斯矩阵与拉普拉斯算子的关系[4]
❞
上面讲到传统的傅里叶变换:
其中 为拉普拉斯算子的特征函数:
类比到图上,拉普拉斯算子可以由拉普拉斯矩阵 代替。而由于 为半正定对称矩阵,有如下三个性质:
其中 为特征向量, 为特征值构成的对角矩阵。
那么 在图上的傅里叶变换可以表示如下:
其中 表示第 个特征, 表示graph上顶点个数。
❝可以看出等式左边是以特征值为自变量,等式右边以顶点为自变量,同样可以类别理解为从一个域转换到另外一个域
❞
表示图 上的顶点数量, 可理解为输入 可理解为作用在顶点 上的函数, 故 为长度为 的向量
其中 个特征向量组成的矩阵如下:
其中 为 特征值为 对应的特征向量, 类似
则 「在图上的傅里叶变换」的矩阵形式如下:
即:
同理可以推导 在图上的逆傅里叶变换:
上面已经得出:类比得到图上卷积:
其中 :
其中 为 的参数。
则可得:
=
由此可得:
其中 为激活函数, 就是「卷积核」,注意 为特征值组成的对角矩阵,所以 也是对角的,可以将卷积核记为如下形式
❝这里面的 就是我们要定义的卷积核具体形式
❞
这里面的参数 即为模型需要学习的卷积核参数。
论文中将 ,也即
❝为 个shape相同的矩阵相加,结果还是矩阵形式 注意上式中不同的特征值共享相同的参数 ,做到了参数共享
❞
继续推导可得:
❝注意得到的还是 个矩阵相加形式
❞
可得:
好了,直观上看这样做有以下几个优点:
可以利用切比雪夫多项式来逼近卷积核函数:
其中 表示切比雪夫多项式, 表示模型需要学习的参数, 表示re-scaled的特征值对角矩阵,进行这个shift变换的原因是Chebyshev多项式的输入要在 之间,因此
由 可得:
其中
在实际运算过程中,可以利用Chebyshev多项式的性质,进行「递推」:
那么这种切比雪夫展开式如何体现其"localize" 呢?可以看看下面这个简单例子
可以由上面这个简单的graph得到图的拉普拉斯矩阵
❝显然K=0时,卷积核只能关注到每个节点本身
❞
❝K=1时,卷积核能关注到每个节点本身与其一阶相邻的节点
❞
❝K=2时,卷积核能关注到每个节点本身与其一阶相邻和二阶相邻的节点
❞
显然由上面推导可知:「切比雪夫多项式的项数,就是图卷积的感受野 」参数共享机制:「同阶共享相同参数,不同阶的参数不一样」。
图的粗化可以理解为cnn中的pooling操作,这里面将相似的顶点合并成一个超级顶点。
论文中采用一种贪心(Graclus)算法来计算给定图的粗化结果,在每个coarsening level(可能存在多次粗化),使用一个unmarked的顶点 ,将这些顶点 与unmarked的邻居 相互匹配,找到
这两个匹配上的顶点然后mark一下,使用他们的权重的和 来作为粗化后的权重。一直重复这个过程,知道所有的点都被marked。
❝这里面相当于pool_size=2
❞
❝图粗化的目的就是找到合适的填充fake node方式,方便后面在1D数据上pooling
❞
上面大概的把gcn的数学原理总结了一遍,来看看代码中 gcn是如何应用在文本分类这个task上的。
❝代码中顶点数量M_0 = |V| = 1000 nodes (0 fake node added),边数量|E| = 11390 edges 其实就是以词袋内每个token作为图上的顶点,以token之间相似度来随机构造边
❞
表示一个batch的样本,论文代码中
这里以以下参数为例
name = 'cgconv_fc_softmax'
params = common.copy()
params['dir_name'] += name
params['regularization'] = 0
params['dropout'] = 1
params['learning_rate'] = 0.1
params['decay_rate'] = 0.999
params['momentum'] = 0
params['F'] = [5]
params['K'] = [15]
params['p'] = [1]
params['M'] = [100, C]
model_perf.test(models.cgcnn(L, **params), name, params,
train_data, train_labels, val_data, val_labels, test_data, test_labels)
def _inference(self, x, dropout):
# Graph convolutional layers.
x = tf.expand_dims(x, 2) # N x M x F=1
for i in range(len(self.p)):
with tf.variable_scope('conv{}'.format(i+1)):
with tf.name_scope('filter'):
## filter表示切比雪夫的卷积过程
# self.L[i]表示当前level邻接矩阵的拉普拉斯矩阵
# self.F[i] 当前level卷积操作的输出维度
# self.K[i] 当前level卷积切比雪夫展开项数
x = self.filter(x, self.L[i], self.F[i], self.K[i])
with tf.name_scope('bias_relu'):
x = self.brelu(x)
with tf.name_scope('pooling'):
x = self.pool(x, self.p[i])
# Fully connected hidden layers.
N, M, F = x.get_shape()
x = tf.reshape(x, [int(N), int(M*F)]) # N x M
for i,M in enumerate(self.M[:-1]):
with tf.variable_scope('fc{}'.format(i+1)):
x = self.fc(x, M)
x = tf.nn.dropout(x, dropout)
# Logits linear layer, i.e. softmax without normalization.
with tf.variable_scope('logits'):
x = self.fc(x, self.M[-1], relu=False)
return x
切比雪夫过程
def chebyshev5(self, x, L, Fout, K):
N, M, Fin = x.get_shape()
N, M, Fin = int(N), int(M), int(Fin)
# Rescale Laplacian and store as a TF sparse tensor. Copy to not modify the shared L.
L = scipy.sparse.csr_matrix(L)
L = graph.rescale_L(L, lmax=2)
L = L.tocoo()
indices = np.column_stack((L.row, L.col))
L = tf.SparseTensor(indices, L.data, L.shape)
L = tf.sparse_reorder(L)
# Transform to Chebyshev basis
x0 = tf.transpose(x, perm=[1, 2, 0]) # M x Fin x N
x0 = tf.reshape(x0, [M, Fin*N]) # M x Fin*N
x = tf.expand_dims(x0, 0) # 1 x M x Fin*N
def concat(x, x_):
x_ = tf.expand_dims(x_, 0) # 1 x M x Fin*N
return tf.concat([x, x_], axis=0) # K x M x Fin*N
if K > 1:
x1 = tf.sparse_tensor_dense_matmul(L, x0)
x = concat(x, x1)
for k in range(2, K):
x2 = 2 * tf.sparse_tensor_dense_matmul(L, x1) - x0 # M x Fin*N
x = concat(x, x2)
x0, x1 = x1, x2
x = tf.reshape(x, [K, M, Fin, N]) # K x M x Fin x N
x = tf.transpose(x, perm=[3,1,2,0]) # N x M x Fin x K
x = tf.reshape(x, [N*M, Fin*K]) # N*M x Fin*K
# Filter: Fin*Fout filters of order K, i.e. one filterbank per feature pair.
W = self._weight_variable([Fin*K, Fout], regularization=False)
x = tf.matmul(x, W) # N*M x Fout
return tf.reshape(x, [N, M, Fout]) # N x M x Fout
pool过程:
def mpool1(self, x, p):
"""Max pooling of size p. Should be a power of 2."""
if p > 1:
x = tf.expand_dims(x, 3) # N x M x F x 1
x = tf.nn.max_pool(x, ksize=[1,p,1,1], strides=[1,p,1,1], padding='SAME')
#tf.maximum
return tf.squeeze(x, [3]) # N x M/p x F
else:
return x
可以看出加了fake node后,可以直接在输入矩阵上做pool
GCN: http://papers.nips.cc/paper/6081-convolutional-neural-networks-on-graphs-with-fast-localized-spectral-filtering.pdf
[2]GCN-code: https://github.com/mdeff/cnn_graph
[3]如何通俗易懂地解释卷积?: https://www.zhihu.com/question/22298352
[4]拉普拉斯矩阵与拉普拉斯算子的关系: https://zhuanlan.zhihu.com/p/85287578
由于微信平台算法改版,公号内容将不再以时间排序展示,如果大家想第一时间看到我们的推送,强烈建议星标我们和给我们多点点【在看】。星标具体步骤为:
(1)点击页面最上方"AINLP",进入公众号主页。
(2)点击右上角的小点点,在弹出页面点击“设为星标”,就可以啦。
感谢支持,比心。
推荐阅读
征稿启示| 200元稿费+5000DBC(价值20个小时GPU算力)
完结撒花!李宏毅老师深度学习与人类语言处理课程视频及课件(附下载)
模型压缩实践系列之——bert-of-theseus,一个非常亲民的bert压缩方法
文本自动摘要任务的“不完全”心得总结番外篇——submodular函数优化
斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用
关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。
阅读至此了,分享、点赞、在看三选一吧🙏