zoukankan      html  css  js  c++  java
  • GraphSAGE 代码解析(三)

    原创文章~转载请注明出处哦。其他部分内容参见以下链接~

    GraphSAGE 代码解析(一) - unsupervised_train.py

    GraphSAGE 代码解析(二) - layers.py

    GraphSAGE 代码解析(四) - models.py

    1. class MeanAggregator(Layer):

    该类主要用于实现

    1. __init__() 

    __init_() 用于获取并初始化成员变量 dropout, bias(False), act(ReLu), concat(False), input_dim, output_dim, name(Variable scopr)

    用glorot()方法初始化节点v的权值矩阵 vars['self_weights'] 和邻居节点均值u的权值矩阵 vars['neigh_weights']

    用零向量初始化vars['bias']。(见inits.py: zeros(shape))

    若logging为True,则调用 layers.py 中 class Layer()的成员函数_log_vars(), 生成vars中各个变量的直方图。

    glorot()

    其中,glorot() 在inits.py中定义,用于权值初始化。(from .inits import glorot)

    均匀分布初始化方法,又称Xavier均匀初始化,参数从 [-limit, limit] 的均匀分布产生,其中limit为 sqrt(6 / (fan_in + fan_out))。fan_in为权值张量的输入单元数,fan_out是权重张量的输出单元数。该函数返回 [fan_in, fan_out]大小的Variable。

    1 def glorot(shape, name=None):
    2     """Glorot & Bengio (AISTATS 2010) init."""
    3     init_range = np.sqrt(6.0/(shape[0]+shape[1]))
    4     initial = tf.random_uniform(shape, minval=-init_range, maxval=init_range, dtype=tf.float32)
    5     return tf.Variable(initial, name=name)
    View Code

    2. _call(inputs)

    class MeanAggregator(Layer) 中的 _call(inputs) 函数是对父类class Layer(object)方法_call(inputs)的重写。

    用于实现最上方的迭代更新式子。

    在layer.py 中定义的 class Layer(object)中,执行特殊函数def __call__(inputs) 时有: outputs = self._call(inputs)调用_call(inputs) 方法,也即在这里调用子类MeanAggregator(Layer)中的_call(inputs)方法。

    tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)

    With probability keep_prob, outputs the input element scaled up by 1 / keep_prob, otherwise outputs 0. The scaling is so that the expected sum is unchanged.

    注意:输出的非0元素是原来的 “1/keep_prob” 倍,以保证总和不变。

    tf.add_n(inputs, name=None)

    Adds all input tensors element-wise.
    
    Args:
    inputs: A list of Tensor or IndexedSlices objects, each with same shape and type.
    name: A name for the operation (optional).
    Returns:
    A Tensor of same shape and type as the elements of inputs.
    
    Raises:
    ValueError: If inputs don't all have same shape and dtype or the shape cannot be inferred.
    View Code

    output = tf.concat([from_self, from_neighs], axis=1)

    这里注意在concat后其维数变为之前的2倍。

    3. class MeanAggregator(Layer) 代码

     1 class MeanAggregator(Layer):
     2     """
     3     Aggregates via mean followed by matmul and non-linearity.
     4     """
     5 
     6     def __init__(self, input_dim, output_dim, neigh_input_dim=None,
     7             dropout=0., bias=False, act=tf.nn.relu, 
     8             name=None, concat=False, **kwargs):
     9         super(MeanAggregator, self).__init__(**kwargs)
    10 
    11         self.dropout = dropout
    12         self.bias = bias
    13         self.act = act
    14         self.concat = concat
    15 
    16         if neigh_input_dim is None:
    17             neigh_input_dim = input_dim
    18 
    19         if name is not None:
    20             name = '/' + name
    21         else:
    22             name = ''
    23 
    24         with tf.variable_scope(self.name + name + '_vars'):
    25             self.vars['neigh_weights'] = glorot([neigh_input_dim, output_dim],
    26                                                         name='neigh_weights')
    27             self.vars['self_weights'] = glorot([input_dim, output_dim],
    28                                                         name='self_weights')
    29             if self.bias:
    30                 self.vars['bias'] = zeros([self.output_dim], name='bias')
    31 
    32         if self.logging:
    33             self._log_vars()
    34 
    35         self.input_dim = input_dim
    36         self.output_dim = output_dim
    37 
    38     def _call(self, inputs):
    39         self_vecs, neigh_vecs = inputs
    40 
    41         neigh_vecs = tf.nn.dropout(neigh_vecs, 1-self.dropout)
    42         self_vecs = tf.nn.dropout(self_vecs, 1-self.dropout)
    43         neigh_means = tf.reduce_mean(neigh_vecs, axis=1)
    44        
    45         # [nodes] x [out_dim]
    46         from_neighs = tf.matmul(neigh_means, self.vars['neigh_weights'])
    47 
    48         from_self = tf.matmul(self_vecs, self.vars["self_weights"])
    49          
    50         if not self.concat:
    51             output = tf.add_n([from_self, from_neighs])
    52         else:
    53             output = tf.concat([from_self, from_neighs], axis=1)
    54 
    55         # bias
    56         if self.bias:
    57             output += self.vars['bias']
    58        
    59         return self.act(output)
    View Code

    2. class GCNAggregator(Layer)

    这里__init__()与MeanAggregator基本相同,在_call()的实现中略有不同。

     1 def _call(self, inputs):
     2     self_vecs, neigh_vecs = inputs
     3 
     4     neigh_vecs = tf.nn.dropout(neigh_vecs, 1-self.dropout)
     5     self_vecs = tf.nn.dropout(self_vecs, 1-self.dropout)
     6     means = tf.reduce_mean(tf.concat([neigh_vecs, 
     7         tf.expand_dims(self_vecs, axis=1)], axis=1), axis=1)
     8    
     9     # [nodes] x [out_dim]
    10     output = tf.matmul(means, self.vars['weights'])
    11 
    12     # bias
    13     if self.bias:
    14         output += self.vars['bias']
    15    
    16     return self.act(output)
    View Code

    其中对means求解时,

    1. 先将self_vecs行列转换(tf.expand_dims(self_vecs, axis=1)),

    2. 之后self_vecs的行数与neigh_vecs行数相同时,将二者concat, 即相当于在原先的neigh_vecs矩阵后面新增一列self_vecs的转置

    3. 最后将得到的矩阵每行求均值,即得means.

    之后means与权值矩阵vars['weights']求内积,并加上vars['bias'], 最终将该值带入激活函数(ReLu)。

    下面举个例子简单说明(例子中省略了点乘W的操作):

     1 import tensorflow as tf
     2 
     3 neigh_vecs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
     4 self_vecs = [2, 3, 4]
     5 
     6 means = tf.reduce_mean(tf.concat([neigh_vecs,
     7                                   tf.expand_dims(self_vecs, axis=1)], axis=1), axis=1)
     8 
     9 print(tf.shape(self_vecs))
    10 
    11 print(tf.expand_dims(self_vecs, axis=0))
    12 # Tensor("ExpandDims_1:0", shape=(1, 3), dtype=int32)
    13 
    14 print(tf.expand_dims(self_vecs, axis=1))
    15 # Tensor("ExpandDims_2:0", shape=(3, 1), dtype=int32)
    16 
    17 sess = tf.Session()
    18 print(sess.run(tf.expand_dims(self_vecs, axis=1)))
    19 # [[2]
    20 #  [3]
    21 #  [4]]
    22 
    23 print(sess.run(tf.concat([neigh_vecs,
    24                           tf.expand_dims(self_vecs, axis=1)], axis=1)))
    25 # [[1 2 3 2]
    26 #  [4 5 6 3]
    27 #  [7 8 9 4]]
    28 
    29 print(means)
    30 # Tensor("Mean:0", shape=(3,), dtype=int32)
    31 
    32 print(sess.run(tf.reduce_mean(tf.concat([neigh_vecs,
    33                                          tf.expand_dims(self_vecs, axis=1)], axis=1), axis=1)))
    34 # [2 4 7]
    35 
    36 # [[1 2 3 2]   = 8 // 4  = 2
    37 #  [4 5 6 3]   = 18 // 4 = 4
    38 #  [7 8 9 4]]  = 28 // 4 = 7
    39 
    40 bias = [1]
    41 output = means + bias
    42 print(sess.run(output))
    43 # [3 5 8]
    44 # [2 + 1, 4 + 1, 7 + 1] = [3, 5, 8]
    View Code

  • 相关阅读:
    php总结4——数组的定义及函数、冒泡排序
    php总结3——基本函数、流程控制中的循环
    php总结2——php中的变量、数据类型及转换、运算符、流程控制中的分支结构
    php总结1 ——php简介、工作原理、运行环境、文件构成、语法结构、注释
    php中$t=date()函数参数意义及时间更改
    80端口未被占用,apache无法启动,命令行运行httpd.exe提示文档内容有错
    创建node.js一个简单的应用实例
    windows系统下nodejs、npm、express的下载和安装教程——2016.11.09
    前端工程师必备技能
    用于string对象中字符截取的几种函数总结——语法、参数意义及用途举例
  • 原文地址:https://www.cnblogs.com/shiyublog/p/9895333.html
Copyright © 2011-2022 走看看