1運行GCN和DeepWalk

目錄

這是我第一次在CSDN上發文章,之前寫代碼參考了無數篇CSDN上面的文章和code,也曾經想過自己寫一寫平常遇到的技術和代碼難點,但總是因爲懶所以一直擱置(咕咕咕)。有這個想法不是說想給別人有多大啓發與借鑑,主要是爲了記錄自己的學習心得。
這次參與了百度飛漿PGL圖神經網絡訓練營,其中一個結營作業就是寫一篇結營感想,既然總要寫,那不如順便就開始在CSDN上寫啦!這篇文章是圖神經網絡學習感想及課後作業的第一篇,以後有時間應該會繼續更下去(要是有時間的話!!!)。

Paddlepaddle

深度學習的框架很多,tensorflow、pytorch等很受關注。國內的開源深度學習框架我目前在學習使用的就是百度飛漿paddlepaddle。(PS:英文不好,用飛漿的話,遇到問題可以在中文討論區裏面找答案,而且配備了非常完善的各種視頻教程,對剛接觸這個框架的人很友好)

安裝推薦使用annaconda,可以省很多事(加一下國內的清華源)
飛槳安裝文檔:https://paddlepaddle.org.cn/install/quick

圖片: 在這裏插入圖片描述
提示:使用 python 進入python解釋器,輸入import paddle.fluid ,再輸入 paddle.fluid.install_check.run_check()。
如果出現 Your Paddle Fluid is installed successfully!,說明您已成功安裝。
顯示如下就算成功了:
在這裏插入圖片描述



本地安裝PaddlePaddle的常見錯誤:https://aistudio.baidu.com/aistudio/projectdetail/697227

手把手教你 win10 安裝Paddlepaddle-GPU:https://aistudio.baidu.com/aistudio/projectdetail/696822

PGL本地運行出現的問題

第一天的作業還是比較簡單的,運行GCN和deepwalk模型就好。
但我使用pycharm進行本地運行時,一直存在dll not load找不到指定模塊的問題:
在這裏插入圖片描述
在這裏非常感謝訓練營裏面的老師,很耐心細緻的幫我解決了問題,可參考如下鏈接裏的方法,pycharm配置一下conda 虛擬環境環境路徑:
添加虛擬環境的library/bin路徑



第一課:圖學習初印象習題

搭建環境,運行GCNDeepWalk

1. 環境搭建

# !pip install paddlepaddle==1.8.5 # 安裝PaddlePaddle
!pip install pgl # 安裝PGL

2. 下載PGL代碼庫

# 由於 AIStudio 上訪問 github速度比較慢,因此我們提供已經下載好了的 PGL 代碼庫
# !git clone --depth=1 https://github.com/PaddlePaddle/PGL
!ls PGL # 查看PGL庫根目錄

3. 運行示例

3.1 GCN

GCN層的具體實現見 PGL/pgl/layers/conv.py

NOTE:

  1. 在GCN模型中,對於圖中的某個節點N,相鄰節點會將學到的信息發送給它。節點N根據節點的度數給收到的信息加上權重,組合起來作爲它新的表示向量。
!cd PGL/examples/gcn; python train.py --epochs 100 # 切換到gcn的目錄,運行train.py在cora數據集上訓練  
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/sklearn/externals/joblib/externals/cloudpickle/cloudpickle.py:47: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
[INFO] 2020-11-24 14:35:23,012 [    train.py:  153]:	Namespace(dataset='cora', epochs=100, use_cuda=False)
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/numpy/core/fromnumeric.py:3118: RuntimeWarning: Mean of empty slice.
  out=out, **kwargs)
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/numpy/core/_methods.py:85: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
[INFO] 2020-11-24 14:35:24,072 [    train.py:  135]:	Epoch 0 (nan sec) Train Loss: 1.946185 Train Acc: 0.142857 Val Loss: 1.937398 Val Acc: 0.350000 
[INFO] 2020-11-24 14:35:24,115 [    train.py:  135]:	Epoch 1 (nan sec) Train Loss: 1.935671 Train Acc: 0.342857 Val Loss: 1.927820 Val Acc: 0.523333 
[INFO] .......此處太多,故省略
[INFO] 2020-11-24 14:35:28,392 [    train.py:  135]:	Epoch 99 (0.02773 sec) Train Loss: 0.696660 Train Acc: 0.864286 Val Loss: 0.935254 Val Acc: 0.793333 
[INFO] 2020-11-24 14:35:28,408 [    train.py:  143]:	Accuracy: 0.759000

3.2 DeepWalk

模型代碼詳見 PGL/examples/deepwalk/deepwalk.py

NOTE:

  1. DeepWalk的主要原理是通過隨機遊走生成節點路徑,然後將其作爲詞向量模型SkipGram的輸入來學習節點表示。

  2. DeepWalk 模型會在第二節課詳細介紹。


Step1 學習節點表示

查看deepwalk.py中的parser(239行起),修改不同參數的值,觀察其對訓練結果的影響,比如遊走路徑長度walk_len,SkipGram窗口大小win_size等

Tips

  1. 如果出現內存不足的問題,可以調小batch_size參數
  2. 以下設置的參數爲了讓同學們可以快速跑出結果,設置的 epoch、walk_len、hidden_size 均比較小,可以自行嘗試調大這些值。
!cd PGL/examples/deepwalk/; python deepwalk.py --dataset ArXiv --save_path ./tmp/deepwalk_ArXiv --offline_learning --epoch 2 --batch_size 256 --processes 1 --walk_len 10 --hidden_size 10 
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/sklearn/externals/joblib/externals/cloudpickle/cloudpickle.py:47: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
[INFO] 2020-11-24 14:36:01,632 [ deepwalk.py:  258]:	Namespace(batch_size=256, dataset='ArXiv', epoch=2, hidden_size=10, neg_num=20, offline_learning=True, processes=1, save_path='./tmp/deepwalk_ArXiv', use_cuda=False, walk_len=10, win_size=10)
[INFO] 2020-11-24 14:36:02,430 [ deepwalk.py:  172]:	Start random walk on disk...
[INFO] 2020-11-24 14:36:03,184 [ deepwalk.py:  182]:	Random walk on disk Done.
[INFO] .......此處太多,故省略
[INFO] 2020-11-24 14:36:03,601 [ deepwalk.py:  228]:	Step 0 Deepwalk Loss: 0.724576  0.372420 s/step.
[INFO] 2020-11-24 14:39:34,124 [ deepwalk.py:  228]:	Step 1450 Deepwalk Loss: 0.538972  0.078368 s/step.

Step2 鏈接預測任務上的測試

這裏選用的數據集是ArXiv,它包含了天體物理學類的論文作者間的合作關係圖,得到的節點表示存儲在 ./tmp/deepwalk_Arxiv

!cd ./PGL/examples/deepwalk/; python link_predict.py --ckpt_path ./tmp/deepwalk_Arxiv/paddle_model --epoch 50
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/sklearn/externals/joblib/externals/cloudpickle/cloudpickle.py:47: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
[INFO] 2020-11-24 14:40:44,192 [link_predict.py:  233]:	Namespace(batch_size=None, ckpt_path='./tmp/deepwalk_Arxiv/paddle_model', dataset='ArXiv', epoch=50, hidden_size=128, use_cuda=False)
2020-11-24 14:40:44,980-WARNING: paddle.fluid.layers.py_reader() may be deprecated in the near future. Please use paddle.fluid.io.DataLoader.from_generator() instead.
2020-11-24 14:40:44,999-WARNING: paddle.fluid.layers.py_reader() may be deprecated in the near future. Please use paddle.fluid.io.DataLoader.from_generator() instead.
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/executor.py:1093: UserWarning: There are no operators in the program to be executed. If you pass Program manually, please use fluid.program_guard to ensure the current Program is being used.
  warnings.warn(error_info)
[INFO] 2020-11-24 14:40:45,836 [link_predict.py:  215]:		Step 1 Test Loss: 0.693220 Test AUC: 0.503291 
[INFO] 2020-11-24 14:40:46,125 [link_predict.py:  215]:		Step 2 Test Loss: 0.693154 Test AUC: 0.504987 
[INFO] .......此處太多,故省略
[INFO] 2020-11-24 14:40:59,882 [link_predict.py:  192]:	Step 50 Train Loss: 0.693121 Train AUC: 0.528213 
[INFO] 2020-11-24 14:41:00,010 [link_predict.py:  215]:		Step 50 Test Loss: 0.693128 Test AUC: 0.520660 

4 PGL相關信息

pip install pgl # 安裝PGL

git clone --depth=1 https://github.com/PaddlePaddle/PGL #下載PGL代碼庫(或者直接把左邊文件中的下載到本地)
	
# 運行示例-GCN
cd PGL/examples/gcn; python train.py --epochs 100 # 切換到gcn的目錄,運行train.py在cora數據集上訓練  

5. 代碼框架梳理

本小節以GCN的 PGL/examples/gcn/train.py 爲例,簡單介紹一下圖模型的訓練框架。

5.1 參數設置

可修改parser的參數來使用不同的數據集進行訓練

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='GCN')
    # 設置數據集,默認選擇cora數據集
    parser.add_argument(
        "--dataset", type=str, default="cora", help="dataset (cora, pubmed)")
    # 設置是否使用GPU
    parser.add_argument("--use_cuda", action='store_true', help="use_cuda")
    args = parser.parse_args()
    log.info(args)
    main(args)

5.2 數據預處理

讀取數據後,需要進行一些預處理,例如GCN中對圖中節點度數進行了標準化

dataset = load(args.dataset)

indegree = dataset.graph.indegree()
norm = np.zeros_like(indegree, dtype="float32")
norm[indegree > 0] = np.power(indegree[indegree > 0], -0.5)
dataset.graph.node_feat["norm"] = np.expand_dims(norm, -1)

5.3 模型構建

Step1 實例化GraphWrapperProgram

  • 定義train_program、startup_program和test_program等程序
  place = fluid.CUDAPlace(0) if args.use_cuda else fluid.CPUPlace()
  train_program = fluid.Program()
  startup_program = fluid.Program()
  test_program = fluid.Program()
  • 實例化GraphWrapper,它提供了圖的基本信息,以及GNN算法message passing機制中的send和receive兩個接口。
with fluid.program_guard(train_program, startup_program): 
    gw = pgl.graph_wrapper.GraphWrapper(
        name="graph",
        place=place,
        node_feat=dataset.graph.node_feat_info())

Step2 模型定義

在train_program中定義要使用的模型結構,這裏是雙層的GCN模型

    output = pgl.layers.gcn(gw,
                            gw.node_feat["words"],
                            hidden_size,
                            activation="relu",
                            norm=gw.node_feat['norm'],
                            name="gcn_layer_1")
    output = fluid.layers.dropout(
        output, 0.5, dropout_implementation='upscale_in_train')
    output = pgl.layers.gcn(gw,
                            output,
                            dataset.num_classes,
                            activation=None,
                            norm=gw.node_feat['norm'],
                            name="gcn_layer_2")

Step3 損失函數計算

  • node_index和node_label定義了有標籤樣本的數據下標和標籤數據
    node_index = fluid.layers.data(
        "node_index",
        shape=[None, 1],
        dtype="int64",
        append_batch_size=False)
    node_label = fluid.layers.data(
        "node_label",
        shape=[None, 1],
        dtype="int64",
        append_batch_size=False)
  • 使用gather函數找出output中有標籤樣本的預測結果後,計算得到交叉熵損失函數值以及準確度
    pred = fluid.layers.gather(output, node_index)
    loss, pred = fluid.layers.softmax_with_cross_entropy(
        logits=pred, label=node_label, return_softmax=True)
    acc = fluid.layers.accuracy(input=pred, label=node_label, k=1)
    loss = fluid.layers.mean(loss)

Step4 構造測試程序

複製構造test_program的靜態圖。到此爲止,train_program和test_program的靜態圖結構完全相同,區別在於test_program不需要梯度計算和反向傳播過程。

test_program = train_program.clone(for_test=True)

Step5 定義優化器

爲了實現train_program上的參數更新,需要定義優化器和優化目標,這裏是用Adam最小化loss

with fluid.program_guard(train_program, startup_program):
    adam = fluid.optimizer.Adam(
        learning_rate=1e-2,
        regularization=fluid.regularizer.L2DecayRegularizer(
            regularization_coeff=0.0005))
    adam.minimize(loss)

5.4 模型訓練和測試

模型構建完成後,就可以定義一個Executor來執行program了

exe = fluid.Executor(place)

Step1 初始化

執行startup_program進行初始化

exe.run(startup_program)

Step2 數據準備

將預處理階段讀取到的數據集填充到GraphWrapper中,同時準備好訓練、驗證和測試階段用到的樣本下標和標籤數據

feed_dict = gw.to_feed(dataset.graph)

train_index = dataset.train_index
train_label = np.expand_dims(dataset.y[train_index], -1)
train_index = np.expand_dims(train_index, -1)

val_index = dataset.val_index
val_label = np.expand_dims(dataset.y[val_index], -1)
val_index = np.expand_dims(val_index, -1)

test_index = dataset.test_index
test_label = np.expand_dims(dataset.y[test_index], -1)
test_index = np.expand_dims(test_index, -1)

Step3 訓練和測試

給Executor分別傳入不同的program來執行訓練和測試過程

  • feed以字典形式給定了輸入數據 {變量名:numpy數據}
  • fetch_list給定了模型中需要取出結果的變量名,可以根據需要自行修改
dur = []
for epoch in range(200):
    if epoch >= 3:
        t0 = time.time()
    feed_dict["node_index"] = np.array(train_index, dtype="int64")
    feed_dict["node_label"] = np.array(train_label, dtype="int64")
    train_loss, train_acc = exe.run(train_program,
                                        feed=feed_dict,
                                        fetch_list=[loss, acc],
                                        return_numpy=True)

	# 3個epoch後,統計每輪訓練執行的時間然後求均值。
    if epoch >= 3:
        time_per_epoch = 1.0 * (time.time() - t0)
        dur.append(time_per_epoch)
    feed_dict["node_index"] = np.array(val_index, dtype="int64")
    feed_dict["node_label"] = np.array(val_label, dtype="int64")
    val_loss, val_acc = exe.run(test_program,
                                    feed=feed_dict,
                                    fetch_list=[loss, acc],
                                    return_numpy=True)

    log.info("Epoch %d " % epoch + "(%.5lf sec) " % np.mean(dur) +
                 "Train Loss: %f " % train_loss + "Train Acc: %f " % train_acc
                 + "Val Loss: %f " % val_loss + "Val Acc: %f " % val_acc)

feed_dict["node_index"] = np.array(test_index, dtype="int64")
feed_dict["node_label"] = np.array(test_label, dtype="int64")
test_loss, test_acc = exe.run(test_program,
                                  feed=feed_dict,
                                  fetch_list=[loss, acc],
                                  return_numpy=True)
log.info("Accuracy: %f" % test_acc)

圖模型訓練的基本框架大概就是這樣啦,下次再見咯~




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章