百度飛漿PGL圖神經網絡學習心得-1
- 目錄
-
- Paddlepaddle
- PGL本地運作出現的問題
- 第一課:圖學習初印象習題
-
- 1. 環境搭建
- 2. 下載下傳PGL代碼庫
- 3. 運作示例
-
- 3.1 GCN
- 3.2 DeepWalk
- 4 PGL相關資訊
- 5. 代碼架構梳理
-
- 5.1 參數設定
- 5.2 資料預處理
- 5.3 模型建構
- 5.4 模型訓練和測試
目錄
這是我第一次在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 虛拟環境環境路徑:
第一課:圖學習初印象習題
搭建環境,運作GCN和DeepWalk。
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:
- 在GCN模型中,對于圖中的某個節點N,相鄰節點會将學到的資訊發送給它。節點N根據節點的度數給收到的資訊加上權重,組合起來作為它新的表示向量。
/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:
- DeepWalk的主要原理是通過随機遊走生成節點路徑,然後将其作為詞向量模型SkipGram的輸入來學習節點表示。
- DeepWalk 模型會在第二節課詳細介紹。
Step1 學習節點表示
檢視deepwalk.py中的parser(239行起),修改不同參數的值,觀察其對訓練結果的影響,比如遊走路徑長度walk_len,SkipGram視窗大小win_size等
Tips
- 如果出現記憶體不足的問題,可以調小batch_size參數
- 以下設定的參數為了讓同學們可以快速跑出結果,設定的 epoch、walk_len、hidden_size 均比較小,可以自行嘗試調大這些值。
/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
/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 執行個體化GraphWrapper和Program
- 定義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不需要梯度計算和反向傳播過程。
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了
Step1 初始化
執行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)
圖模型訓練的基本架構大概就是這樣啦,下次再見咯~