《SEMI-SUPERVISED CLASSIFICATION WITH GRAPH CONVOLUTIONAL NETWORKS》代码详解(Tensorflow版)

paper链接

code链接

1.文件目录结构

在这里插入图片描述

2.运行方法、要求

2.1运行方法

cd gcn
python train.py --model gcn  --dataset citeseer

模型选择:

  • gcn: Graph convolutional network
  • gcn_cheby: Chebyshev polynomial version of graph convolutional network
  • dense: Basic multi-layer perceptron that supports sparse inputs

2.2.运行要求

  • ‘numpy>=1.15.4’, ‘tensorflow>=1.15.2,<2.0’,
  • ‘networkx>=2.2’,
  • ‘scipy>=1.1.0’
  • setuptools==40.6.3
    可通过bash运行setup.py 安装运行必要的包版本。
python setup.py install

3. 数据集

LIL(Row-Based Linked List Format)-基于行的链表格式

载入数据的维度(以Cora数据集为例)

metrics.py

inits.py
从gcn/data文件夹下读取数据,文件包括有:

ind.dataset_str.x => 训练实例的特征向量,如scipy.sparse.csr.csr_matrix类的实例

ind.dataset_str.tx => 测试实例的特征向量,如scipy.sparse.csr.csr_matrix类的实例

ind.dataset_str.allx => 有标签的+无无标签训练实例的特征向量,是ind.dataset_str.x的超集

ind.dataset_str.y => 训练实例的标签,独热编码,numpy.ndarray类的实例

ind.dataset_str.ty => 测试实例的标签,独热编码,numpy.ndarray类的实例

ind.dataset_str.ally => 有标签的+无无标签训练实例的标签,独热编码,numpy.ndarray类的实例

ind.dataset_str.graph => 图数据,collections.defaultdict类的实例,格式为 {index:[index_of_neighbor_nodes]}

ind.dataset_str.test.index => 测试实例的id

载入数据的维度(以Cora数据集为例)
adj(邻接矩阵):由于比较稀疏,邻接矩阵格式是LIL的,并且shape为(2708, 2708)

features(特征矩阵):每个节点的特征向量也是稀疏的,也用LIL格式存储,features.shape: (2708, 1433)

labels:ally, ty数据集叠加构成,labels.shape:(2708, 7)

train_mask, val_mask, test_mask:shaped都为(2708, )的向量,但是train_mask中的[0,140)范围的是True,其余是False;val_mask中范围为(140, 640]范围为True,其余的是False;test_mask中范围为[1708,2707]范围是True,其余的是False

y_train, y_val, y_test:shape都是(2708, 7) 。y_train的值为对应与labels中train_mask为True的行,其余全是0;y_val的值为对应与labels中val_mask为True的行,其余全是0;y_test的值为对应与labels中test_mask为True的行,其余全是0

特征矩阵进行归一化并返回一个格式为(coords, values, shape)的元组

将邻接矩阵加上自环以后,对称归一化,并存储为COO模式,最后返回格式为(coords, values, shape)的元组

总共2708个节点,但是训练数据仅用了140个,范围是(0, 140),验证集用了500个,范围是(140, 640],测试集用了1000个,范围是[1708,2707],其余范围从[641,1707]的数据集呢

4.代码分析

4.1requirements.txt

networkx==2.2
scipy==1.1.0
setuptools==40.6.3
numpy==1.15.4
tensorflow==1.15.2

4.2setup.py

from setuptools import setup
from setuptools import find_packages

setup(name='gcn',
      version='1.0',
      description='Graph Convolutional Networks in Tensorflow',
      author='Thomas Kipf',
      author_email='thomas.kipf@gmail.com',
      url='https://tkipf.github.io',
      download_url='https://github.com/tkipf/gcn',
      license='MIT',
      install_requires=['numpy>=1.15.4',
                        'tensorflow>=1.15.2,<2.0',
                        'networkx>=2.2',
                        'scipy>=1.1.0'
                        ],
      package_data={
   'gcn': ['README.md']},
      packages=find_packages())

4.3__init__.py

from __future__ import division
#即使在python2.X,使用print就得像python3.X那样加括号使用。
from __future__ import print_function
# 导入python未来支持的语言特征division(精确除法),
# 当我们没有在程序中导入该特征时,"/"操作符执行的是截断除法(Truncating Division);
# 当我们导入精确除法之后,"/"执行的是精确除法, "//"执行截断除除法

4.4train.py

from __future__ import division
'''即使在python2.X,使用print就得像python3.X那样加括号使用'''
from __future__ import print_function
'''导入python未来支持的语言特征division(精确除法),
6 # 当我们没有在程序中导入该特征时,"/"操作符执行的是截断除法(Truncating Division);
7 # 当我们导入精确除法之后,"/"执行的是精确除法, "//"执行截断除除法'''

import time   #导入time模块
import tensorflow as tf #导入TensorFlow

from gcn.utils import *  #导入GCN工具函数
from gcn.models import GCN, MLP #导入GCN模型

# Set random seed
seed = 123#random是一个算法,设置随机数种子,再不同设备上生成的随机数一样。
np.random.seed(seed)
tf.set_random_seed(seed)

# Settings
"""# 构造了一个解析器FLAGS  这样就可以从命令行中传入数据,从外部定义参数,如python train.py --model gcn
flags.DEFINE_float(参数1,参数2,参数3)  
flags.DEFINE_integer(参数1,参数2,参数3)  
flags.DEFINE_string(参数1,参数2,参数3) 
flags.DEFINE_boolean(参数1,参数2,参数3) 

参数1:定义的参数名称;
参数2:参数默认值;
参数3:对参数的描述
"""
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('dataset', 'cora', 'Dataset string.')  # 'cora', 'citeseer', 'pubmed'
flags.DEFINE_string('model', 'gcn', 'Model string.')  # 'gcn', 'gcn_cheby', 'dense'
flags.DEFINE_float('learning_rate', 0.01, 'Initial learning rate.')
flags.DEFINE_integer('epochs', 200, 'Number of epochs to train.')
#输出维度为16  
flags.DEFINE_integer('hidden1', 16, 'Number of units in hidden layer 1.')
#dropout率 避免过拟合(按照一定的概率随机丢弃一部分神经元)
flags.DEFINE_float('dropout', 0.5, 'Dropout rate (1 - keep probability).')

#权衰减 目的就是为了让权重减少到更小的值,在一定程度上减少模型过拟合的问题
# loss计算方式(权值衰减+正则化):self.loss += FLAGS.weight_decay * tf.nn.l2_loss(var)
flags.DEFINE_float('weight_decay', 5e-4, 'Weight for L2 loss on embedding matrix.')
flags.DEFINE_integer('early_stopping', 10, 'Tolerance for early stopping (# of epochs).')

 #K阶的切比雪夫近似矩阵的参数k
flags.DEFINE_integer('max_degree', 3, 'Maximum Chebyshev polynomial degree.')

# Load data
#print(np.shape(adj))#(2708, 2708)
#print(np.shape(features))#(2708, 1433)
#print(np.shape(y_train))#(2708, 7)
#print(np.shape(y_val))#(2708, 7)
#print(np.shape(y_test))#(2708, 7)
#print(np.shape(train_mask))#(2708,)
#print(np.shape(val_mask))#(2708,)
#prin t(np.shape(test_mask))#(2708,)
# 数据的读取,这个预处理是把训练集(其中一部分带有标签),测试集,标签的位置,对应的掩码训练标签等返回。
adj, features, y_train, y_val, y_test, train_mask, val_mask, test_mask = load_data(FLAGS.dataset)

# Some preprocessing
#预处理特征矩阵:将特征矩阵进行归一化并返回tuple (coords, values, shape)
features = preprocess_features(features)#X  2708 *1433
if FLAGS.model == 'gcn':
    support = [preprocess_adj(adj)]# Z = D -1/2( A +IN) D -1/2  2708*2708
    num_supports = 1
    model_func = GCN
elif FLAGS.model == 'gcn_cheby':
    support = chebyshev_polynomials(adj, FLAGS.max_degree)
    num_supports = 1 + FLAGS.max_degree
    model_func = GCN
elif FLAGS.model == 'dense':
    support = [preprocess_adj(adj)]  # Not used
    num_supports = 1
    model_func = MLP
else:
    raise ValueError('Invalid argument for model: ' + str(FLAGS.model))

# Define placeholders
placeholders = {
   
    # #由于邻接矩阵是稀疏的,并且用LIL格式表示,因此定义为一个tf.sparse_placeholder(tf.float32),可以节省内存
    'support': [tf.sparse_placeholder(tf.float32) for _ in range(num_supports)],
    # features也是稀疏矩阵,也用LIL格式表示,因此定义为tf.sparse_placeholder(tf.float32),维度(2708, 1433)
    'features': tf.sparse_placeholder(tf.float32, shape=tf.constant(features[2], dtype=tf.int64)),#(2708, 1433)
    'labels': tf.placeholder(tf.float32, shape=(None, y_train.shape[1])),#y_train.shape(2708, 7)   ->  7
    'labels_mask': tf.placeholder(tf.int32),
    'dropout': tf.placeholder_with_default(0., shape=()),#可以用作手段来提供值但不直接评估的张量。
    'num_features_nonzero': tf.placeholder(tf.int32)  # helper variable for sparse dropout
}

# Create model
model = model_func(placeholders, input_dim=features[2][1], logging=True)#features[2][1] = 1433

# Initialize session
sess = tf.Session()


# Define model evaluation function
def evaluate(features, support, labels, mask,
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值