目录
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,