图神经网络(GNN)结合了图结构和机器学习的优势. GraphScope提供了处理学习任务的功能。本次教程,我们将会展示GraphScope如何使用GraphSAGE算法训练一个模型。
本次教程的学习任务是在文献引用网络上的点分类任务。在点分类任务中,算法会确定Cora数据集上每个顶点的标签。在Cora
数据集中,由学术出版物作为顶点,出版物之间的引用作为边,如果出版物A引用了出版物B,则图中会存在一条从A到B的边。Cora数据集中的节点被分为了七个主题类,我们的模型将会训练来预测出版物顶点的主题。
这一教程将会分为以下几个步骤:
# Install graphscope package if you are NOT in the Playground
!pip3 install graphscope
# Import the graphscope module.
import graphscope
graphscope.set_option(show_log=False) # enable logging
# Load cora dataset
from graphscope.dataset import load_cora
graph = load_cora()
然后,我们需要定义一个特征列表用于图的训练。训练特征集合必须从点的属性集合中选取。在这个例子中,我们选择了属性集合中所有以"feat_"为前缀的属性作为训练特征集,这一特征集也是Cora数据中点的特征集。
借助定义的特征列表,接下来,我们使用 graphlearn 方法来开启一个学习引擎。
在这个例子中,我们在 "graphlearn" 方法中,指定在数据中 "paper" 类型的顶点和 "cites" 类型边上进行模型训练。
利用 "gen_labels" 参数,我们将 "paper" 点数据集进行划分,其中75%作为训练集,10%作为验证集,15%作为测试集。
# define the features for learning
paper_features = []
for i in range(1433):
paper_features.append("feat_" + str(i))
# launch a learning engine.
lg = graphscope.graphlearn(
graph,
nodes=[("paper", paper_features)],
edges=[("paper", "cites", "paper")],
gen_labels=[
("train", "paper", 100, (0, 75)),
("val", "paper", 100, (75, 85)),
("test", "paper", 100, (85, 100)),
],
)
这里我们使用内置的GraphSAGE模型定义训练过程。
在本次示例中,我们使用tensorflow作为NN后端训练器。
try:
# https://www.tensorflow.org/guide/migrate
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
except ImportError:
import tensorflow as tf
import argparse
import graphscope.learning as gl
import graphscope.learning.graphlearn.python.nn.tf as tfg
from graphscope.learning.examples import EgoGraphSAGE
from graphscope.learning.examples import EgoSAGESupervisedDataLoader
from graphscope.learning.examples.tf.trainer import LocalTrainer
def parse_args():
argparser = argparse.ArgumentParser("Train EgoSAGE Supervised.")
argparser.add_argument('--class_num', type=int, default=7)
argparser.add_argument('--features_num', type=int, default=1433)
argparser.add_argument('--train_batch_size', type=int, default=140)
argparser.add_argument('--val_batch_size', type=int, default=300)
argparser.add_argument('--test_batch_size', type=int, default=1000)
argparser.add_argument('--hidden_dim', type=int, default=128)
argparser.add_argument('--in_drop_rate', type=float, default=0.5)
argparser.add_argument('--hops_num', type=int, default=2)
argparser.add_argument('--nbrs_num', type=list, default=[25, 10])
argparser.add_argument('--agg_type', type=str, default="gcn")
argparser.add_argument('--learning_algo', type=str, default="adam")
argparser.add_argument('--learning_rate', type=float, default=0.05)
argparser.add_argument('--weight_decay', type=float, default=0.0005)
argparser.add_argument('--epochs', type=int, default=40)
argparser.add_argument('--node_type', type=str, default='paper')
argparser.add_argument('--edge_type', type=str, default='cites')
return argparser.parse_args()
args = parse_args()
def supervised_loss(logits, labels):
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=labels, logits=logits)
return tf.reduce_mean(loss)
def accuracy(logits, labels):
indices = tf.math.argmax(logits, 1, output_type=tf.int32)
correct = tf.reduce_sum(tf.cast(tf.math.equal(indices, labels), tf.float32))
return correct / tf.cast(tf.shape(labels)[0], tf.float32)
# Define Model
dims = [args.features_num] + [args.hidden_dim] * (args.hops_num - 1) \
+ [args.class_num]
model = EgoGraphSAGE(dims,
agg_type=args.agg_type,
act_func=tf.nn.relu,
dropout=args.in_drop_rate)
# prepare train dataset
train_data = EgoSAGESupervisedDataLoader(lg, gl.Mask.TRAIN, 'random', args.train_batch_size,
node_type=args.node_type, edge_type=args.edge_type,
nbrs_num=args.nbrs_num, hops_num=args.hops_num)
train_embedding = model.forward(train_data.src_ego)
loss = supervised_loss(train_embedding, train_data.src_ego.src.labels)
optimizer = tf.train.AdamOptimizer(learning_rate=args.learning_rate)
# prepare test dataset
test_data = EgoSAGESupervisedDataLoader(lg, gl.Mask.TEST, 'random', args.test_batch_size,
node_type=args.node_type, edge_type=args.edge_type,
nbrs_num=args.nbrs_num, hops_num=args.hops_num)
test_embedding = model.forward(test_data.src_ego)
test_acc = accuracy(test_embedding, test_data.src_ego.src.labels)
在定义完训练过程和超参后,现在我们可以使用学习引擎和定义的超参开始训练过程。
# train and test
trainer = LocalTrainer()
trainer.train(train_data.iterator, loss, optimizer, epochs=args.epochs)
trainer.test(test_data.iterator, test_acc)