美文网首页算法工程图与图算法
图神经网络:GAT在GraphSAGE下的实现(基于tensor

图神经网络:GAT在GraphSAGE下的实现(基于tensor

作者: xiaogp | 来源:发表于2022-07-05 21:00 被阅读0次

    标签:图神经网络GAT注意力机制tensorflow

    GraphSAGE+GNN换成GAT的本质分析

    在GraphSAGE+GNN的实现中,对邻居节点采用某种方式聚合计算(例如求向量均值),再和中心节点拼接的方式,GraphSAGE固定每层采样的个数,GNN固定层数,模型学习的就是每一层邻居聚合之后的W以及中心节点向量的W,以及最后一个分类的全连接。将GNN换为GAT之后,还是采用邻居聚合计算的方式(带上中心节点一起加权求和),此时要多学习一个权重,比如中心节点采样了10个邻居,要学习11个权重参数,如果有8个注意力机制,就要学习88个权重参数,这个权重参数不是直接定义学习的,而是通过一个共享的W和两个单独a运算得到,模型实际上学习迭代的是W和a1,a2,每套注意力机制下W和a1,a2共享,W,a1,a2在训练之后保存在tensorflow网络结构中,新的节点在预测的时候拿到计算权重再加权求和得到下一层的表征。这三个参数的训练结果是由中心节点和他的一组邻居节点的特征向量决定的,直接应用在新的预测中心节点和他的一组邻居节点上,且这个和邻居节点采样的排列顺序无关,跟着特征向量走


    数据准备预处理

    使用CORA数据集,数据预处理如下,主要是sample函数,会进行一个两层采样。将前1000个作为训练,1000~1708为验证,1708到最后为测试

    import os
    import pickle
    
    import numpy as np
    import scipy.sparse as sp
    
    BASIC_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    def data_split():
        names = ['x', 'y', 'tx', 'ty', 'allx', 'ally', 'graph']
        objects = []
        for i in range(len(names)):
            with open(os.path.join(BASIC_PATH, "./data/ind.cora.{}".format(names[i])), 'rb') as f:
                objects.append(pickle.load(f, encoding='latin1'))
    
        x, y, tx, ty, allx, ally, graph = tuple(objects)
        test_idx_reorder = [int(x.strip()) for x in open(os.path.join(BASIC_PATH, "./data/ind.cora.test.index"), "r").readlines()]
        test_idx_range = np.sort(test_idx_reorder)
        # 测试索引位置修正
        features = sp.vstack((allx, tx)).tolil()
        features[test_idx_reorder, :] = features[test_idx_range, :]
        labels = np.vstack((ally, ty))
        labels[test_idx_reorder, :] = labels[test_idx_range, :]
    
        # 训练[:1000],验证[1000:1708],测试[1708:]
        train_nodes = list(range(1000))
        train_y = labels[train_nodes]
        val_nodes = list(range(1000, 1708))
        val_y = labels[val_nodes]
        test_nodes = list(range(1708, 2708))
        test_y = labels[test_nodes]
    
        return train_nodes, train_y, val_nodes, val_y, test_nodes, test_y, graph, features
    
    
    def sample(nodes, neighbour_list, k=2, num_supports=None):
        if num_supports is None:
            num_supports = [10, 25]
        assert len(num_supports) == k, "num_supports长度必须和k阶相等"
        layer_neighbours = {}
        for i in range(k):
            neighbours = []
            num_support = num_supports[i]
            for node in nodes:
                one_neighbour = neighbour_list[node]
                if len(one_neighbour) >= num_support:
                    neighbours.append(np.random.choice(neighbour_list[node], num_support, replace=False).tolist())
                else:
                    neighbours.append(np.random.choice(neighbour_list[node], num_support, replace=True).tolist())
            layer_neighbours[k - i] = neighbours
            nodes = sum(neighbours, [])
        return layer_neighbours
    
    
    def get_nodes_features(nodes, features_embedding, std=True):
        embedding = features_embedding[nodes]
        if std:
            embedding = embedding / embedding.sum(axis=1)
        return embedding
    
    
    if __name__ == '__main__':
        train_nodes, train_y, val_nodes, val_y, test_nodes, test_y, graph, features = data_split()
        pickle.dump((train_nodes, train_y), open(os.path.join(BASIC_PATH, "./data/train.pkl"), "wb"))
        pickle.dump((val_nodes, val_y), open(os.path.join(BASIC_PATH, "./data/val.pkl"), "wb"))
        pickle.dump((test_nodes, test_y), open(os.path.join(BASIC_PATH, "./data/test.pkl"), "wb"))
        pickle.dump(graph, open(os.path.join(BASIC_PATH, "./data/graph.pkl"), "wb"))
        pickle.dump(features, open(os.path.join(BASIC_PATH, "./data/features.pkl"), "wb"))
    

    模型部分

    模型部分直接上代码,模型中写死了只有2层的GAT,tensor的链路参考GAT源码阅读和tensor链路

    import numpy as np
    import tensorflow as tf
    
    
    def glorot(shape, name=None):
        init_range = np.sqrt(6.0 / (shape[0] + shape[1]))
        initial = tf.random_uniform(shape, minval=-init_range, maxval=init_range, dtype=tf.float32)
        return tf.Variable(initial, name=name)
    
    
    def zeros(shape, name=None):
        initial = tf.zeros(shape, dtype=tf.float32)
        return tf.Variable(initial, name=name)
    
    
    class GraphSageGAT(object):
        def __init__(self, num_class, feature_size, num_supports_1=10, num_supports_2=10, learning_rate=0.01,
                     weight_decay=0.01, decay_learning_rate=0.99):
            # 中心节点
            self.input_self = tf.placeholder(tf.float32, [None, feature_size], name="input_self")
            # 1跳
            self.input_neigh_1 = tf.placeholder(tf.float32, [None, num_supports_1, feature_size], name="input_neigh_1")
            # 2跳
            self.input_neigh_2 = tf.placeholder(tf.float32, [None, num_supports_1, num_supports_2, feature_size], name="input_neigh_2")
            # label
            self.input_y = tf.placeholder(tf.int64, [None, num_class])
            self.feature_size = feature_size
            self.num_supports_1 = num_supports_1
            self.num_supports_2 = num_supports_2
            self.weight_decay = weight_decay
            self.learning_rate = learning_rate
            self.decay_learning_rate = decay_learning_rate
            self.w_dropout_keep_prob = tf.placeholder(tf.float32, name="w_dropout_keep_prob")
            self.e_dropout_keep_prob = tf.placeholder(tf.float32, name="e_dropout_keep_prob")
            self.global_step = tf.Variable(0, name="global_step", trainable=False)
    
        def build(self, n_heads_1=8, n_heads_2=8, w_size_1=8, w_size_2=7):
            """
            模型网络构建,指定第一层聚合注意力个数和第二层个数
            :param w_size_2:
            :param w_size_1:
            :param n_heads_1:
            :param n_heads_2:
            :return:
            """
            # 第一层
            one_att_out_one_hop = []
            one_att_out_two_hop = []
            for i in range(n_heads_1):
                # [512, 8]
                one_att_out_one_hop.append(self.attn_head(self.input_self, self.input_neigh_1, w_size=w_size_1,
                                                          w_drop=self.w_dropout_keep_prob, eij_drop=self.e_dropout_keep_prob,
                                                          input_size=self.feature_size))
                # [5120, 8]
                one_att_out_two_hop.append(self.attn_head(
                    tf.reshape(self.input_neigh_1, [-1, self.feature_size]),
                    tf.reshape(self.input_neigh_2, [-1, self.num_supports_2, self.feature_size]), w_size=w_size_1,
                    w_drop=self.w_dropout_keep_prob, eij_drop=self.e_dropout_keep_prob, input_size=self.feature_size))
            h_1_one_hop = tf.concat(one_att_out_one_hop, axis=-1)  # [512, 64]
            h_1_two_hop = tf.concat(one_att_out_two_hop, axis=-1)  # [5120, 64]
            # 第二层
            two_att_out = []
            for i in range(n_heads_2):
                # [512, 7]
                two_att_out.append(self.attn_head(h_1_one_hop, tf.reshape(h_1_two_hop, [-1, self.num_supports_1, w_size_1 * n_heads_1]),
                                                  w_size=w_size_2, w_drop=self.w_dropout_keep_prob, eij_drop=self.e_dropout_keep_prob,
                                                  input_size=w_size_1 * n_heads_1))
            # [512, 7]
            output = tf.add_n(two_att_out) / n_heads_2
            # softmax
            with tf.name_scope("softmax_out"):
                self.probs = tf.nn.softmax(output, dim=1, name="probs")
                self.accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.arg_max(self.probs, 1), tf.arg_max(self.input_y, 1)), dtype=tf.float32))
    
            # loss
            with tf.name_scope('loss'):
                self.loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=output, labels=self.input_y))
                # 增加l2 loss
                vars = tf.trainable_variables()
                loss_l2 = tf.add_n([tf.nn.l2_loss(v) for v in vars if v.name not in ['bias', 'gamma', 'b', 'g', 'beta']]) * self.weight_decay
                self.loss += loss_l2
    
            # optimizer
            with tf.name_scope("optimizer"):
                if self.decay_learning_rate:
                    learning_rate = tf.train.exponential_decay(self.learning_rate, self.global_step, 100, self.decay_learning_rate)
                optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
                self.train_step = optimizer.minimize(self.loss, global_step=self.global_step)
    
            with tf.name_scope("summaries"):
                tf.summary.scalar("loss", self.loss)
                tf.summary.scalar("accuracy", self.accuracy)
                self.summary_op = tf.summary.merge_all()
    
        def attn_head(self, center_tensor, neigh_tensor, w_size, w_drop, eij_drop, input_size):
            """
            注意力机制,输入中心节点特征向量和采样的一度邻居特征向量,输出注意力机制后的中心节点聚合特征向量
            :param input_size:
            :param center_tensor: 中心节点特征向量
            :param neigh_tensor: 邻居节点特征向量
            :param w_size: W向量转化之后的维度
            :param w_drop: Wh的dropout
            :param eij_drop: eij的dropout
            :return: 下一层的中心节点特征向量
            """
            # w共享
            w = glorot([input_size, w_size])  # [1433, 8]
            wh_center = tf.matmul(center_tensor, w)  # [512, 1433] => [512, 8]
            wh_neigh = tf.matmul(neigh_tensor, w)  # [512, 10, 1433] => [512, 10, 8]
            # concat
            wh_center_neigh = tf.concat([wh_neigh, tf.expand_dims(wh_center, 1)], axis=1)  # [512, 10, 8] => [512, 11, 8]
            # a单独两个
            a_center = glorot([w_size, 1])  # [8, 1]
            a_neigh = glorot([w_size, 1])  # [8, 1]
            wha_center = tf.contrib.layers.bias_add(tf.matmul(wh_center, a_center))  # [512, 8] => [512, 1]
            wha_neigh = tf.contrib.layers.bias_add(tf.matmul(wh_center_neigh, a_neigh))  # [512, 11, 8] => [512, 11, 1]
            # wha+wha
            wha = tf.squeeze(wha_neigh + tf.reshape(wha_center, [-1, 1, 1]), axis=2)  # [512, 11]
            # eij
            eij = tf.nn.softmax(tf.nn.leaky_relu(wha))  # [512, 11]
            # dropout
            eij = tf.nn.dropout(eij, eij_drop)  # [512, 11]
            wh_center_neigh = tf.nn.dropout(wh_center_neigh, w_drop)  # [512, 11, 8]
            # 加权求和
            new_center_tensor = tf.matmul(tf.expand_dims(eij, axis=1), wh_center_neigh)
            new_center_tensor = tf.contrib.layers.bias_add(new_center_tensor)  # [512, 1, 8]
            new_center_tensor = tf.squeeze(tf.nn.elu(new_center_tensor), axis=1)  # [512, 8]
    
            return new_center_tensor
    
    

    训练部分

    训练部分通过实例化GAT对象的build方法构图,指定了第一层8个注意力,第二层8个注意力,第一层的维度转化向量到8维,第二层输出7维直接映射到label

    import sys
    import os
    import pickle
    import shutil
    import random
    import time
    
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    DATA_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ROOT_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    
    import numpy as np
    import tensorflow as tf
    from tensorflow.python.saved_model import tag_constants
    
    from model import GraphSageGAT
    from utils.config import get_string
    from preprocessing import sample, get_nodes_features
    
    (train_nodes, train_y) = pickle.load(open(os.path.join(DATA_PATH, get_string("train_data_path")), "rb"))
    (val_nodes, val_y) = pickle.load(open(os.path.join(DATA_PATH, get_string("val_data_path")), "rb"))
    (test_nodes, test_y) = pickle.load(open(os.path.join(DATA_PATH, get_string("test_data_path")), "rb"))
    neighbour_list = pickle.load(open(os.path.join(DATA_PATH, get_string("neighbour_data_path")), "rb"))
    nodes_features = pickle.load(open(os.path.join(DATA_PATH, get_string("feature_data_path")), "rb"))
    features_size = nodes_features.shape[1]
    
    
    def get_batch(epoches, batch_size, nodes, labels, neighbours, features, layer1_supports=10, layer2_supports=5):
        for epoch in range(epoches):
            tmp = list(zip(nodes, labels))
            random.shuffle(tmp)
            nodes, labels = zip(*tmp)
            for batch in range(0, len(nodes), batch_size):
                if batch + batch_size < len(nodes):
                    batch_nodes = nodes[batch: (batch + batch_size)]
                    batch_labels = labels[batch: (batch + batch_size)]
                else:
                    batch_nodes = nodes[batch: len(nodes)]
                    batch_labels = labels[batch: len(nodes)]
                # 得到训练集的1跳2跳
                layer_neighbours = sample(batch_nodes, neighbours, num_supports=[layer2_supports, layer1_supports])
                # 所有节点的embedding
                input_x = get_nodes_features(list(batch_nodes), features)
                input_x_1 = get_nodes_features(sum(layer_neighbours[2], []), features)
                input_x_2 = get_nodes_features(sum(layer_neighbours[1], []), features)
                yield [epoch, input_x, input_x_1, input_x_2, batch_labels]
    
    
    def train_main():
        tf.reset_default_graph()
        model = GraphSageGAT(num_class=7, feature_size=features_size,
                             num_supports_1=int(get_string("layer2_supports")),
                             num_supports_2=int(get_string("layer1_supports")),
                             decay_learning_rate=float(get_string("decay_learning_rate")),
                             learning_rate=float(get_string("learning_rate")),
                             weight_decay=float(get_string("weight_decay")))
        model.build(n_heads_1=8, n_heads_2=8, w_size_1=8, w_size_2=7)
        saver = tf.train.Saver(tf.global_variables(), max_to_keep=1)
        with tf.Session() as sess:
            init_op = tf.group(tf.global_variables_initializer())
            sess.run(init_op)
            shutil.rmtree(os.path.join(ROOT_PATH, "./summary"), ignore_errors=True)
            writer = tf.summary.FileWriter(os.path.join(ROOT_PATH, "./summary"), sess.graph)
            batches = get_batch(int(get_string("epoches")), int(get_string("batch_size")), train_nodes, train_y,
                                neighbour_list, nodes_features, layer1_supports=int(get_string("layer1_supports")),
                                layer2_supports=int(get_string("layer2_supports")))
            # 验证数据
            layer_neighbours = sample(val_nodes, neighbour_list,
                                      num_supports=[int(get_string("layer2_supports")), int(get_string("layer1_supports"))])
            val_input_x = get_nodes_features(val_nodes, nodes_features)
            val_input_x_1 = get_nodes_features(sum(layer_neighbours[2], []), nodes_features)
            val_input_x_2 = get_nodes_features(sum(layer_neighbours[1], []), nodes_features)
            val_feed_dict = {model.input_self: val_input_x,
                             model.input_neigh_1: val_input_x_1.A.reshape(-1, int(get_string("layer1_supports")),
                                                                          features_size),
                             model.input_neigh_2: val_input_x_2.A.reshape(-1, int(get_string("layer1_supports")),
                                                                          int(get_string("layer2_supports")),
                                                                          features_size),
                             model.input_y: val_y,
                             model.w_dropout_keep_prob: 1,
                             model.e_dropout_keep_prob: 1}
    
            val_loss_list = []
            for batch in batches:
                epoch, input_x, input_x_1, input_x_2, input_y = batch
                feed_dict = {model.input_self: input_x,
                             model.input_neigh_1: input_x_1.A.reshape(-1, int(get_string("layer1_supports")),
                                                                      features_size),
                             model.input_neigh_2: input_x_2.A.reshape(-1, int(get_string("layer1_supports")),
                                                                      int(get_string("layer2_supports")), features_size),
                             model.input_y: input_y,
                             model.w_dropout_keep_prob: float(get_string("dropout_keep_prob")),
                             model.e_dropout_keep_prob: float(get_string("dropout_keep_prob"))}
                _, step, loss_val, acc_val, merged = sess.run(
                    [model.train_step, model.global_step, model.loss, model.accuracy, model.summary_op],
                    feed_dict=feed_dict)
                writer.add_summary(merged, step)
                if step % 5 == 0:
                    print("epoch:", epoch + 1, "step:", step, "loss:", loss_val, "accuracy:", acc_val)
    
                if step % 50 == 0:
                    loss_val, acc_val = sess.run([model.loss, model.accuracy], feed_dict=val_feed_dict)
                    print("{:-^30}".format("evaluation"))
                    print("[evaluation]", "loss:", loss_val, "accuracy:", acc_val)
                    # 计算当前loss相比之前的最有loss下降多少
                    diff = (loss_val - min(val_loss_list)) if len(val_loss_list) else 0
                    val_loss_list.append(loss_val)
                    print("本轮loss比之前最小loss{}:{}, 当前最小loss: {}"
                          .format("上升" if diff > 0 else "下降", abs(diff), min(val_loss_list)))
                    if diff < 0:
                        saver.save(sess, os.path.join(ROOT_PATH, get_string("checkpoint_path")))
                        print("[save checkpoint]")
                    print("-" * 40)
                    if early_stop(val_loss_list, windows=int(get_string("early_stop_windows"))):
                        print("{:-^30}".format("early stop!"))
                        break
    
    
    def early_stop(loss_list, windows=5):
        if len(loss_list) <= windows:
            return False
        latest_loss = loss_list[-windows:]
        previous_loss = loss_list[:-windows]
        min_previous_loss = min(previous_loss)
        min_latest_loss = min(latest_loss)
        if min_latest_loss > min_previous_loss:
            return True
        return False
    

    运行train_main如下

    epoch: 52 step: 415 loss: 0.54380906 accuracy: 0.921875
    epoch: 53 step: 420 loss: 0.50763553 accuracy: 0.9296875
    epoch: 54 step: 425 loss: 0.50306284 accuracy: 0.953125
    epoch: 54 step: 430 loss: 0.5158588 accuracy: 0.953125
    epoch: 55 step: 435 loss: 0.51461077 accuracy: 0.953125
    epoch: 55 step: 440 loss: 0.48844844 accuracy: 0.96153843
    epoch: 56 step: 445 loss: 0.4956718 accuracy: 0.953125
    epoch: 57 step: 450 loss: 0.48547933 accuracy: 0.9609375
    ----------evaluation----------
    [evaluation] loss: 0.66410494 accuracy: 0.8926554
    本轮loss比之前最小loss上升:0.007818341255187988, 当前最小loss: 0.6562865972518921
    ----------------------------------------
    ---------early stop!----------
    

    训练集softmax7分类的准确率0.96,验证有0.89


    测试部分

    测试引入测试样本,直接去读ckpt预测对比测试集的label

    def test_main():
        layer_neighbours = sample(test_nodes, neighbour_list,
                                  num_supports=[int(get_string("layer2_supports")), int(get_string("layer1_supports"))])
        test_input_x = get_nodes_features(test_nodes, nodes_features)
        test_input_x_1 = get_nodes_features(sum(layer_neighbours[2], []), nodes_features)
        test_input_x_2 = get_nodes_features(sum(layer_neighbours[1], []), nodes_features)
    
        tf.reset_default_graph()
        with tf.Session() as sess:
            last_ckpt = tf.train.latest_checkpoint(
                os.path.join(ROOT_PATH, "/".join(get_string("checkpoint_path").split("/")[:-1])))
            print("读取ckpt: {}".format(last_ckpt))
            saver = tf.train.import_meta_graph("{}.meta".format(last_ckpt))
            saver.restore(sess, last_ckpt)
            graph = tf.get_default_graph()
            # get tensor
            input_self = graph.get_tensor_by_name("input_self:0")
            input_neigh_1 = graph.get_tensor_by_name("input_neigh_1:0")
            input_neigh_2 = graph.get_tensor_by_name("input_neigh_2:0")
            w_dropout_keep_prob = graph.get_tensor_by_name("w_dropout_keep_prob:0")
            e_dropout_keep_prob = graph.get_tensor_by_name("e_dropout_keep_prob:0")
            pred = graph.get_tensor_by_name("softmax_out/probs:0")
            prediction = sess.run(pred, feed_dict={input_self: test_input_x,
                                                   input_neigh_1: test_input_x_1.A.reshape(-1, int(get_string("layer1_supports")), features_size),
                                                   input_neigh_2: test_input_x_2.A.reshape(-1, int(get_string("layer1_supports")), int(get_string("layer2_supports")), features_size),
                                                   w_dropout_keep_prob: 1.0,
                                                   e_dropout_keep_prob: 1.0})
            hit = np.equal(np.argmax(prediction, axis=1), np.argmax(test_y, axis=1))
            accuracy = hit.sum() / len(hit)
            print("[test]:", accuracy)
    

    运行结果

    读取ckpt: /home/myproject/GRAPHSAGE_GAT_CORA/./ckpt/ckpt
    [test]: 0.85
    

    tensorboard查看训练标量

    切刀项目工程根目录下执行

    tensorboard --logdir ../summary
    
    tensorboard

    模型保存为pb

    将模型保存为pb文件

    def save_pb():
        # 模型保存
        pb_num = str(int(time.time()))
        pb_path = os.path.join(ROOT_PATH, get_string("pb_path"), pb_num)
        shutil.rmtree(pb_path, ignore_errors=True)
        tf.reset_default_graph()
        with tf.Session() as sess:
            last_ckpt = tf.train.latest_checkpoint(
                os.path.join(ROOT_PATH, "/".join(get_string("checkpoint_path").split("/")[:-1])))
            print("读取ckpt: {}".format(last_ckpt))
            saver = tf.train.import_meta_graph("{}.meta".format(last_ckpt))
            saver.restore(sess, last_ckpt)
            graph = tf.get_default_graph()
            # get tensor
            input_self = graph.get_tensor_by_name("input_self:0")
            input_neigh_1 = graph.get_tensor_by_name("input_neigh_1:0")
            input_neigh_2 = graph.get_tensor_by_name("input_neigh_2:0")
            w_dropout_keep_prob = graph.get_tensor_by_name("w_dropout_keep_prob:0")
            e_dropout_keep_prob = graph.get_tensor_by_name("e_dropout_keep_prob:0")
            pred = graph.get_tensor_by_name("softmax_out/probs:0")
            builder = tf.saved_model.builder.SavedModelBuilder(pb_path)
            inputs = {'input_self': tf.saved_model.utils.build_tensor_info(input_self),
                      'input_neigh_1': tf.saved_model.utils.build_tensor_info(input_neigh_1),
                      'input_neigh_2': tf.saved_model.utils.build_tensor_info(input_neigh_2),
                      'w_dropout_keep_prob': tf.saved_model.utils.build_tensor_info(w_dropout_keep_prob),
                      'e_dropout_keep_prob': tf.saved_model.utils.build_tensor_info(e_dropout_keep_prob)
                      }
            outputs = {'output': tf.saved_model.utils.build_tensor_info(pred)}
            signature = tf.saved_model.signature_def_utils.build_signature_def(
                inputs=inputs,
                outputs=outputs,
                method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)
    
            builder.add_meta_graph_and_variables(sess, [tag_constants.SERVING], {'my_signature': signature})
            builder.save()
        print("pb文件保存完成:", pb_num)
    

    运行结果

    读取ckpt: /home/myproject/GRAPHSAGE_GAT_CORA/./ckpt/ckpt
    pb文件保存完成: 1657025573
    

    模型server API服务

    先启一个docker tensorflow-model-server服务

    #!/bin/bash
    docker run --rm  \
    -p 13713:8501 \
    -v /home/myproject/GRAPHSAGE_GAT_CORA/tfserving/:/models/graphsage_gat_cora/ \
    -e MODEL_NAME=graphsage_gat_cora \
    --name graphsage_gat_api \
    tensorflow/serving \
    --enable_batching=true
    

    requests请求测试,请求原数据中2555节点的分类

    import os
    import pickle
    import sys
    
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    
    import requests
    
    from preprocessing import sample, get_nodes_features
    from utils.config import get_string
    
    DATA_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    neighbour_list = pickle.load(open(os.path.join(DATA_PATH, get_string("neighbour_data_path")), "rb"))
    nodes_features = pickle.load(open(os.path.join(DATA_PATH, get_string("feature_data_path")), "rb"))
    
    if __name__ == '__main__':
        nodes = [2555]
        layer_neighbours = sample(nodes, neighbour_list,
                                  num_supports=[int(get_string("layer2_supports")), int(get_string("layer1_supports"))])
        test_input_x = get_nodes_features(nodes, nodes_features)
        test_input_x_1 = get_nodes_features(sum(layer_neighbours[2], []), nodes_features)
        test_input_x_2 = get_nodes_features(sum(layer_neighbours[1], []), nodes_features)
        res = requests.post("http://127.0.0.1:13713/v1/models/graphsage_gat_cora:predict", json={"instances": [{
            "input_self": test_input_x.A[0].tolist(),
            "input_neigh_1": test_input_x_1.A.reshape(-1, 10, 1433)[0].tolist(),
            "input_neigh_2": test_input_x_2.A.reshape(-1, 10, 10, 1433)[0].tolist(),
            "w_dropout_keep_prob": 1.0,
            "e_dropout_keep_prob": 1.0
        }], "signature_name": "my_signature"})
        print(res.json())
    

    预测结果如下,结果是第四分类

    {'predictions': [[0.00618362846, 0.00481465, 0.00280520879, 0.973845184, 0.00697943475, 0.00364588178, 0.00172607298]]}
    

    相关文章

      网友评论

        本文标题:图神经网络:GAT在GraphSAGE下的实现(基于tensor

        本文链接:https://www.haomeiwen.com/subject/sgzsbrtx.html