《GATED GRAPH SEQUENCE NEURAL NETWORKS》结合代码的论文阅读笔记
通过这篇文章,学习GNN实现细节,确定用在手部图像上的可行性,初步确定实现方案。
文章及代码链接:https://github.com/Microsoft/gated-graph-neural-network-samples
2.1:prepare_specific_graph_model
2.2:final_node_representations
2.2.2:对于每个时间步长,更新cur_node_states
2.3.1:对每个task,计算gated_regression
2.3.2:把每个图中所有的点求个和得到一个图的输出结果——computed_values(float)
论文初步阅读
这是Microsoft Research2016年发表于ICLR的文章,作者是Yujia Li
图的特征学习包括两个步骤:输入图的表达和中间环节的特征聚合。在图的表达上,本文沿用2009年的 Scarselli的工作,我们在它上面融入了RNN的思想。 后续特征聚合十分重要我们引入了GGS-NNs。
1:GG-NNs计算过程
可以用6个公式表达
-
initialization
-
imformation pass
-
update gate
-
reset gate
-
activate
-
activate
-
output
2:GGS-NNs计算流程
用了两个 GG-NNs: Fo(k) 和 FX(k)。 Fo(k) for predicting o(k) from X(k), and FX(k) forpredicting X(k+1) from X(k). when training GGS-NN,there are two setting:specifying all intermediate annotations or only the first one.
结合代码深入理解
1:加载数据
训练数据12083张图,测试数据13082张图。图是稀疏图用邻接矩阵表达,节点数量不大于30,边有权重大概40到50条边,每个节点有5种取值(onehot编码),整个图有一个label(大概是-4到4之间的一个浮点数)。
2:创建计算图
所有操作记录在self.ops['final_node_representations']中
网络输入有4个,暂时不知道怎么用
创建计算图的核心代码:
with tf.variable_scope("graph_model"):
self.prepare_specific_graph_model()
# This does the actual graph work:
if self.params['use_graph']:
self.ops['final_node_representations'] = self.compute_final_node_representations()
else:
self.ops['final_node_representations'] = tf.zeros_like(self.placeholders['initial_node_representation'])
2.1:prepare_specific_graph_model
首先增加了5个网络输入,按照字面意义理解:点的初始化参数,邻接矩阵,邻接矩阵权重,点集合,图状态保持概率
增加网络权重,每个时间步骤一个,总共4个时间步所以是4个,每个与邻接矩阵大小相同
2.2:final_node_representations
计算每个点的结果,应该跟上面的6个公式相关。
2.2.1:获取图
根据placeholders中的initial_node_representation的值初始化cur_node_states,根据placeholders中的adjacency_list和adjacency_weights中的值初始化一个adjacency_matrix。
tf.shape(x),其中x可以是tensor,也可不是tensor,返回是一个tensor.
shape=tf.placeholder(tf.float32, shape=[None, 227,227,3] )
- 我们经常会这样来
feed
数据,如果在运行的时候想知道None
到底是多少,这时候,只能通过tf.shape(x)[0]
这种方式来获得
2.2.2:对于每个时间步长,更新cur_node_states
adjacency_matrix(node_num,node_num) * cur_node_states(node_num,100)* 位于该时间步的权重(100*100)
得到 new_node_states (node_num*100)
有需要的话可以加个bias。
2.3:计算loss:
2.3.1:对每个task,计算gated_regression
增加两个权重矩阵,组成MLP多层感知机,其实就是全连接和relu。
regression_gate_task0(输入200,输出1)和regression_transform_task0(输入100,输出1)
将cur_node_states与初始化node连起来组成gate_input(node_num*200)。计算流程如下:
- gate_input输入regression_gate_task0这个MLP
- 输入Sigmoid函数,变换到0~1
- 输入到regression_transform_task0这个MLP
- 得到的结果gated_outputs(node_num*1)
2.3.2:把每个图中所有的点求个和得到一个图的输出结果——computed_values(float)
2.3.3:Mask out unused values
diff = computed_values - self.placeholders['target_values'][internal_id,:]
task_target_mask = self.placeholders['target_mask'][internal_id,:]
task_target_num = tf.reduce_sum(task_target_mask) + SMALL_NUMBER
diff = diff * task_target_mask # Mask out unused values
self.ops['accuracy_task%i' % task_id] = tf.reduce_sum(tf.abs(diff)) / task_target_num
task_loss = tf.reduce_sum(0.5 * tf.square(diff)) / task_target_num
# Normalise loss to account for fewer task-specific examples in batch:
task_loss = task_loss * (1.0 / (self.params['task_sample_ratios'].get(task_id) or 1.0))
self.ops['losses'].append(task_loss)