邻接矩阵表示成PyG需要的edge_index并进行带边权的网络构建

邻接矩阵 to pyg需要的edge_index格式

scipy

1
2
3
import torch
A = torch.rand([10,10]) # 10*10的邻接矩阵A,带有权值,而非0/1
A
tensor([[0.8253, 0.2458, 0.9340, 0.4631, 0.5114, 0.3248, 0.8528, 0.6354, 0.2988,
         0.1087],
        [0.0190, 0.5693, 0.4843, 0.9588, 0.6011, 0.5755, 0.4621, 0.7694, 0.0637,
         0.9790],
        [0.6978, 0.9686, 0.9701, 0.2234, 0.5633, 0.9978, 0.9766, 0.3365, 0.3512,
         0.2396],
        [0.3582, 0.9965, 0.7739, 0.5641, 0.7275, 0.3078, 0.1826, 0.5449, 0.6566,
         0.1949],
        [0.8194, 0.7996, 0.9177, 0.3419, 0.5239, 0.7048, 0.4503, 0.0758, 0.2244,
         0.0659],
        [0.6131, 0.3546, 0.0789, 0.2735, 0.0781, 0.8000, 0.0587, 0.6644, 0.2678,
         0.6351],
        [0.7244, 0.0463, 0.9280, 0.6456, 0.6837, 0.0763, 0.0759, 0.0440, 0.1849,
         0.8942],
        [0.3589, 0.6925, 0.2334, 0.3476, 0.6695, 0.1048, 0.1470, 0.5548, 0.4736,
         0.6934],
        [0.0356, 0.8016, 0.6176, 0.2867, 0.1340, 0.7196, 0.0562, 0.5548, 0.7376,
         0.2841],
        [0.9301, 0.1725, 0.4012, 0.3893, 0.8366, 0.1587, 0.3342, 0.7945, 0.8123,
         0.8724]])
1
2
3
4
import scipy.sparse as sp
adj = sp.coo_matrix(A) #转换成coo_matrix矩阵
values = adj.data
values,adj.row,adj.col
(array([0.825252  , 0.24581629, 0.9340454 , 0.4631123 , 0.51142365,
        0.32479858, 0.85282457, 0.63537604, 0.29877287, 0.10873711,
        0.01895636, 0.5693259 , 0.48427123, 0.9587981 , 0.6010562 ,
        0.57548887, 0.46208388, 0.7693816 , 0.06371653, 0.97895676,
        0.6978117 , 0.9685761 , 0.97011906, 0.22341514, 0.56326205,
        0.9978037 , 0.97661865, 0.33654213, 0.35123014, 0.23959029,
        0.358207  , 0.99651885, 0.7739324 , 0.5641022 , 0.72754997,
        0.3077591 , 0.18257308, 0.5449101 , 0.65663534, 0.1949212 ,
        0.8193548 , 0.79964596, 0.9176568 , 0.34189552, 0.5239384 ,
        0.70477635, 0.4503097 , 0.07584941, 0.22442049, 0.06589556,
        0.6130815 , 0.35458   , 0.07890564, 0.27350843, 0.07805085,
        0.79995   , 0.05868119, 0.66441715, 0.267847  , 0.6351336 ,
        0.72437716, 0.04632962, 0.92803836, 0.645646  , 0.6836786 ,
        0.07632524, 0.07594979, 0.04397732, 0.18492383, 0.89419115,
        0.3588807 , 0.6925135 , 0.23337674, 0.34763372, 0.66951907,
        0.10478634, 0.14702266, 0.55476344, 0.47362745, 0.69343317,
        0.03562325, 0.80160064, 0.6175768 , 0.2867241 , 0.13401723,
        0.719559  , 0.05618161, 0.55481714, 0.7375902 , 0.28414857,
        0.9300911 , 0.17248052, 0.4012187 , 0.38931435, 0.83664143,
        0.15867668, 0.3341686 , 0.7945494 , 0.81226593, 0.8724434 ],
       dtype=float32),
 array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
        4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
        6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
        8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], dtype=int32),
 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
        2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
        4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
        6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
        8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32))
1
2
3
4
import numpy as np
indices = np.vstack((adj.row,adj.col)) # 我们需要的coo形式的edge_index
edge_index = torch.LongTensor(indices)#PyG需要的edge_index
edge_index,edge_index.shape
(tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
          2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
          4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
          9, 9, 9, 9],
         [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
          4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
          8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
          2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
          6, 7, 8, 9]]),
 torch.Size([2, 100]))
1
2
3
edge_attr = adj.data #边权值
edge_attr = torch.FloatTensor(edge_attr)#to float tensor
edge_attr,edge_attr.shape
(tensor([0.8253, 0.2458, 0.9340, 0.4631, 0.5114, 0.3248, 0.8528, 0.6354, 0.2988,
         0.1087, 0.0190, 0.5693, 0.4843, 0.9588, 0.6011, 0.5755, 0.4621, 0.7694,
         0.0637, 0.9790, 0.6978, 0.9686, 0.9701, 0.2234, 0.5633, 0.9978, 0.9766,
         0.3365, 0.3512, 0.2396, 0.3582, 0.9965, 0.7739, 0.5641, 0.7275, 0.3078,
         0.1826, 0.5449, 0.6566, 0.1949, 0.8194, 0.7996, 0.9177, 0.3419, 0.5239,
         0.7048, 0.4503, 0.0758, 0.2244, 0.0659, 0.6131, 0.3546, 0.0789, 0.2735,
         0.0781, 0.8000, 0.0587, 0.6644, 0.2678, 0.6351, 0.7244, 0.0463, 0.9280,
         0.6456, 0.6837, 0.0763, 0.0759, 0.0440, 0.1849, 0.8942, 0.3589, 0.6925,
         0.2334, 0.3476, 0.6695, 0.1048, 0.1470, 0.5548, 0.4736, 0.6934, 0.0356,
         0.8016, 0.6176, 0.2867, 0.1340, 0.7196, 0.0562, 0.5548, 0.7376, 0.2841,
         0.9301, 0.1725, 0.4012, 0.3893, 0.8366, 0.1587, 0.3342, 0.7945, 0.8123,
         0.8724]),
 torch.Size([100]))

torch**

使用前面的方法,当传入cuda的输入然后进行转换时,前面的方法只能在cpu上执行,因为cuda不支持numpy(),需要进行cpu和cuda的转换。(一直以为是因为数据传输等方面可能的影响导致我的速度变慢,但是似乎影响更大的是因为后续模型加载非成batch))

torch的方法不需要

1
2
3
import torch
A = torch.rand([10,10]) # 10*10的邻接矩阵A,带有权值,而非0/1
A
tensor([[0.8176, 0.2545, 0.6473, 0.2937, 0.9869, 0.0929, 0.6526, 0.6831, 0.0242,
         0.3227],
        [0.8430, 0.0125, 0.0166, 0.2306, 0.6767, 0.7800, 0.3947, 0.5706, 0.1307,
         0.3265],
        [0.8983, 0.5701, 0.0590, 0.0370, 0.1142, 0.9176, 0.0413, 0.7737, 0.8839,
         0.9673],
        [0.2120, 0.0877, 0.8496, 0.2748, 0.2316, 0.1640, 0.2160, 0.1306, 0.4602,
         0.9815],
        [0.8076, 0.4725, 0.8042, 0.3854, 0.4384, 0.9577, 0.5992, 0.5335, 0.9595,
         0.1808],
        [0.3166, 0.5219, 0.1348, 0.2726, 0.6527, 0.7875, 0.2952, 0.6067, 0.5722,
         0.0738],
        [0.2799, 0.3344, 0.2588, 0.3888, 0.6586, 0.3389, 0.3849, 0.0184, 0.8913,
         0.5702],
        [0.5489, 0.5952, 0.3463, 0.6634, 0.1480, 0.4949, 0.3449, 0.6737, 0.5059,
         0.1255],
        [0.3011, 0.6796, 0.9407, 0.1118, 0.2194, 0.9374, 0.2392, 0.1681, 0.4226,
         0.9818],
        [0.7948, 0.4114, 0.2621, 0.5588, 0.2609, 0.7126, 0.6315, 0.7893, 0.2553,
         0.4072]])
1
2
adj = A.to_sparse()
adj, adj.indices(),adj.values()
(tensor(indices=tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                         1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
                         3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
                         5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
                         7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
                         9, 9, 9, 9, 9],
                        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8,
                         9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
                         8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
                         7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
                         6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4,
                         5, 6, 7, 8, 9]]),
        values=tensor([0.8176, 0.2545, 0.6473, 0.2937, 0.9869, 0.0929, 0.6526,
                       0.6831, 0.0242, 0.3227, 0.8430, 0.0125, 0.0166, 0.2306,
                       0.6767, 0.7800, 0.3947, 0.5706, 0.1307, 0.3265, 0.8983,
                       0.5701, 0.0590, 0.0370, 0.1142, 0.9176, 0.0413, 0.7737,
                       0.8839, 0.9673, 0.2120, 0.0877, 0.8496, 0.2748, 0.2316,
                       0.1640, 0.2160, 0.1306, 0.4602, 0.9815, 0.8076, 0.4725,
                       0.8042, 0.3854, 0.4384, 0.9577, 0.5992, 0.5335, 0.9595,
                       0.1808, 0.3166, 0.5219, 0.1348, 0.2726, 0.6527, 0.7875,
                       0.2952, 0.6067, 0.5722, 0.0738, 0.2799, 0.3344, 0.2588,
                       0.3888, 0.6586, 0.3389, 0.3849, 0.0184, 0.8913, 0.5702,
                       0.5489, 0.5952, 0.3463, 0.6634, 0.1480, 0.4949, 0.3449,
                       0.6737, 0.5059, 0.1255, 0.3011, 0.6796, 0.9407, 0.1118,
                       0.2194, 0.9374, 0.2392, 0.1681, 0.4226, 0.9818, 0.7948,
                       0.4114, 0.2621, 0.5588, 0.2609, 0.7126, 0.6315, 0.7893,
                       0.2553, 0.4072]),
        size=(10, 10), nnz=100, layout=torch.sparse_coo),
 tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
          2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
          4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
          9, 9, 9, 9],
         [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
          4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
          8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
          2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
          6, 7, 8, 9]]),
 tensor([0.8176, 0.2545, 0.6473, 0.2937, 0.9869, 0.0929, 0.6526, 0.6831, 0.0242,
         0.3227, 0.8430, 0.0125, 0.0166, 0.2306, 0.6767, 0.7800, 0.3947, 0.5706,
         0.1307, 0.3265, 0.8983, 0.5701, 0.0590, 0.0370, 0.1142, 0.9176, 0.0413,
         0.7737, 0.8839, 0.9673, 0.2120, 0.0877, 0.8496, 0.2748, 0.2316, 0.1640,
         0.2160, 0.1306, 0.4602, 0.9815, 0.8076, 0.4725, 0.8042, 0.3854, 0.4384,
         0.9577, 0.5992, 0.5335, 0.9595, 0.1808, 0.3166, 0.5219, 0.1348, 0.2726,
         0.6527, 0.7875, 0.2952, 0.6067, 0.5722, 0.0738, 0.2799, 0.3344, 0.2588,
         0.3888, 0.6586, 0.3389, 0.3849, 0.0184, 0.8913, 0.5702, 0.5489, 0.5952,
         0.3463, 0.6634, 0.1480, 0.4949, 0.3449, 0.6737, 0.5059, 0.1255, 0.3011,
         0.6796, 0.9407, 0.1118, 0.2194, 0.9374, 0.2392, 0.1681, 0.4226, 0.9818,
         0.7948, 0.4114, 0.2621, 0.5588, 0.2609, 0.7126, 0.6315, 0.7893, 0.2553,
         0.4072]))
1
2
3
indices = adj.indices() # 我们需要的coo形式的edge_index
edge_index = indices#PyG需要的edge_index
edge_index,edge_index.shape
(tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
          2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
          4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
          9, 9, 9, 9],
         [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
          4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
          8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
          2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
          6, 7, 8, 9]]),
 torch.Size([2, 100]))
1
2
edge_attr = adj.values()
edge_attr,edge_attr.shape
(tensor([0.8176, 0.2545, 0.6473, 0.2937, 0.9869, 0.0929, 0.6526, 0.6831, 0.0242,
         0.3227, 0.8430, 0.0125, 0.0166, 0.2306, 0.6767, 0.7800, 0.3947, 0.5706,
         0.1307, 0.3265, 0.8983, 0.5701, 0.0590, 0.0370, 0.1142, 0.9176, 0.0413,
         0.7737, 0.8839, 0.9673, 0.2120, 0.0877, 0.8496, 0.2748, 0.2316, 0.1640,
         0.2160, 0.1306, 0.4602, 0.9815, 0.8076, 0.4725, 0.8042, 0.3854, 0.4384,
         0.9577, 0.5992, 0.5335, 0.9595, 0.1808, 0.3166, 0.5219, 0.1348, 0.2726,
         0.6527, 0.7875, 0.2952, 0.6067, 0.5722, 0.0738, 0.2799, 0.3344, 0.2588,
         0.3888, 0.6586, 0.3389, 0.3849, 0.0184, 0.8913, 0.5702, 0.5489, 0.5952,
         0.3463, 0.6634, 0.1480, 0.4949, 0.3449, 0.6737, 0.5059, 0.1255, 0.3011,
         0.6796, 0.9407, 0.1118, 0.2194, 0.9374, 0.2392, 0.1681, 0.4226, 0.9818,
         0.7948, 0.4114, 0.2621, 0.5588, 0.2609, 0.7126, 0.6315, 0.7893, 0.2553,
         0.4072]),
 torch.Size([100]))

edge_index to 邻接矩阵

1
2
3
4
import scipy.sparse as sp
from torch import sparse_coo_tensor
adj = sparse_coo_tensor(edge_index,edge_attr,[10,10])
adj.to_dense()
tensor([[4.5977e-01, 6.6455e-01, 4.3946e-01, 3.8642e-01, 1.2331e-01, 2.9945e-01,
         2.5433e-01, 9.7476e-01, 4.5961e-04, 5.9594e-02],
        [2.2455e-01, 9.7698e-01, 8.7531e-01, 2.8142e-01, 7.0980e-01, 6.2595e-01,
         2.3625e-01, 5.7737e-01, 4.4227e-01, 6.5420e-01],
        [5.4512e-01, 2.4614e-01, 6.9270e-01, 6.8005e-01, 1.3384e-01, 5.9974e-01,
         9.2275e-01, 3.6578e-01, 3.5667e-01, 5.8081e-01],
        [9.6142e-02, 8.5471e-01, 5.9899e-02, 3.0163e-01, 2.9641e-01, 2.8706e-01,
         4.8757e-01, 8.8466e-01, 3.4357e-01, 9.9034e-01],
        [4.5909e-01, 7.2475e-01, 2.4294e-01, 7.3560e-01, 3.2247e-01, 7.6749e-01,
         3.6008e-01, 3.0816e-01, 7.4665e-01, 6.7713e-01],
        [6.6836e-01, 8.9111e-01, 8.0428e-01, 7.9984e-01, 6.5296e-01, 8.1743e-01,
         8.8702e-01, 3.6678e-01, 4.2774e-01, 2.3170e-02],
        [8.1350e-01, 1.6834e-01, 7.7933e-02, 3.8021e-01, 9.7750e-01, 5.6143e-01,
         7.9341e-01, 3.7514e-01, 9.3114e-01, 5.6821e-01],
        [8.4002e-01, 9.2273e-01, 5.6649e-01, 7.5386e-01, 9.1587e-01, 3.9596e-02,
         8.9435e-01, 5.6476e-01, 2.3289e-01, 1.9653e-01],
        [2.1682e-01, 2.8950e-01, 7.5310e-01, 6.7648e-01, 5.1057e-02, 1.6519e-01,
         5.8807e-01, 9.4542e-02, 6.3111e-01, 2.9049e-01],
        [5.7742e-02, 3.1503e-01, 5.6936e-01, 2.2748e-01, 4.8668e-01, 6.4949e-01,
         6.1752e-01, 3.9269e-01, 2.7897e-01, 5.5806e-01]])
1
2
adj = sp.coo_matrix((edge_attr,(edge_index[0],edge_index[1])),shape=[10,10])
adj.toarray()
array([[4.5977378e-01, 6.6455245e-01, 4.3945801e-01, 3.8642406e-01,
        1.2331247e-01, 2.9944807e-01, 2.5433010e-01, 9.7475851e-01,
        4.5961142e-04, 5.9593856e-02],
       [2.2454953e-01, 9.7697508e-01, 8.7531334e-01, 2.8141612e-01,
        7.0980257e-01, 6.2595367e-01, 2.3624879e-01, 5.7737088e-01,
        4.4226754e-01, 6.5420014e-01],
       [5.4512197e-01, 2.4613553e-01, 6.9269532e-01, 6.8004644e-01,
        1.3383734e-01, 5.9973723e-01, 9.2274553e-01, 3.6578351e-01,
        3.5666680e-01, 5.8080733e-01],
       [9.6142113e-02, 8.5471165e-01, 5.9899449e-02, 3.0162632e-01,
        2.9641372e-01, 2.8705674e-01, 4.8757398e-01, 8.8466209e-01,
        3.4356719e-01, 9.9034435e-01],
       [4.5909441e-01, 7.2474545e-01, 2.4293584e-01, 7.3560286e-01,
        3.2246715e-01, 7.6749289e-01, 3.6007798e-01, 3.0815858e-01,
        7.4665487e-01, 6.7713338e-01],
       [6.6836429e-01, 8.9111018e-01, 8.0427557e-01, 7.9984426e-01,
        6.5295666e-01, 8.1743485e-01, 8.8702154e-01, 3.6678237e-01,
        4.2774427e-01, 2.3170471e-02],
       [8.1350172e-01, 1.6834372e-01, 7.7932715e-02, 3.8021082e-01,
        9.7749555e-01, 5.6143039e-01, 7.9341477e-01, 3.7514049e-01,
        9.3114382e-01, 5.6820768e-01],
       [8.4002483e-01, 9.2273450e-01, 5.6649190e-01, 7.5385606e-01,
        9.1587120e-01, 3.9596200e-02, 8.9435184e-01, 5.6475997e-01,
        2.3288828e-01, 1.9652534e-01],
       [2.1682233e-01, 2.8950059e-01, 7.5310403e-01, 6.7648250e-01,
        5.1056564e-02, 1.6518539e-01, 5.8806950e-01, 9.4541669e-02,
        6.3110876e-01, 2.9048622e-01],
       [5.7742238e-02, 3.1502587e-01, 5.6935811e-01, 2.2748303e-01,
        4.8667991e-01, 6.4949030e-01, 6.1752105e-01, 3.9268762e-01,
        2.7897447e-01, 5.5806071e-01]], dtype=float32)

构建自定义边权重的GNN

胡乱定值的
代码修改自:https://zhuanlan.zhihu.com/p/426907570

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from torch_geometric.nn import GATConv
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = GCNConv(data.num_features, 16, cached=True,
normalize=True)
# self.conv1 = GATConv(data.num_features, 16)
#self.conv2 = GCNConv(16, data.num_classes, cached=True,
self.conv2 = GCNConv(16, 2, cached=True,
normalize=True)
# self.conv2 = GATConv(16, 2)
# self.conv1 = ChebConv(data.num_features, 16, K=2)
# self.conv2 = ChebConv(16, data.num_features, K=2)

def forward(self):
x, edge_index, edge_weight = data.x, data.edge_index, data.edge_attr
x = F.relu(self.conv1(x, edge_index, edge_weight))
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index, edge_weight)
return F.log_softmax(x, dim=1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv, ChebConv # noqa
from torch_geometric.data import data as D
from torch_geometric.data import dataset

x = torch.tensor([[1],[2],[3],[4],[5],[6],[7],[8],[9],[10]], dtype=torch.float) # N x emb(in)
print(x.shape)
x = torch.ones(10,dtype=torch.float).unsqueeze(-1)
#print(x.shape)
y = torch.randint(0,2,[10])
train_mask = torch.tensor([True, True, True,True,True,True,True,True,True,True], dtype=torch.bool)
val_mask=train_mask
test_mask=train_mask
data=D.Data()
data.x,data.y,data.edge_index,data.edge_attr,data.train_mask,data.val_mask,data.test_mask \
= x,y,edge_index,edge_attr,train_mask,val_mask,test_mask
torch.Size([10, 1])
1
2
3
4
5
6
7
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model, data = Net().to(device), data.to(device)
optimizer = torch.optim.Adam([
dict(params=model.conv1.parameters(), weight_decay=5e-4),
dict(params=model.conv2.parameters(), weight_decay=0)
], lr=0.01) # Only perform weight-decay on first convolution.

1
2
3
4
5
6
def train():
model.train()
optimizer.zero_grad()
F.nll_loss(model()[data.train_mask], data.y[data.train_mask]).backward()
#F.nll_loss(model()[data], data.y).backward() #不行!
optimizer.step()
1
2
3
4
5
6
7
8
9
@torch.no_grad()
def test():
model.eval()
logits, accs = model(), []
for _, mask in data('train_mask', 'val_mask', 'test_mask'):
pred = logits[mask].max(1)[1]
acc = pred.eq(data.y[mask]).sum().item() / mask.sum().item()
accs.append(acc)
return accs
1
2
3
4
5
6
7
8
9
best_val_acc = test_acc = 0
for epoch in range(1, 10):
train()
train_acc, val_acc, tmp_test_acc = test()
if val_acc > best_val_acc:
best_val_acc = val_acc
test_acc = tmp_test_acc
log = 'Epoch: {:03d}, Train: {:.4f}, Val: {:.4f}, Test: {:.4f}'
print(log.format(epoch, train_acc, best_val_acc, test_acc))
Epoch: 001, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 002, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 003, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 004, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 005, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 006, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 007, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 008, Train: 0.5000, Val: 0.5000, Test: 0.5000
Epoch: 009, Train: 0.5000, Val: 0.5000, Test: 0.5000

批量

单独传入,stack结果

1
2
3
4
5
6
7
8
9
10
11
12
13
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()

self.layer = GATConv(in_channels=16, out_channels=16)
self.layer2 = GATConv(in_channels=16, out_channels=1)

def forward(self,x,edg_index):
output = torch.stack([self.layer(graph, edge_index=edge_indexi) for graph,edge_indexi in zip(x,edg_index)], dim=0)
output = torch.stack([self.layer2(graph, edge_index=edge_indexi) for graph,edge_indexi in zip(output,edg_index)], dim=0)
#output = torch.sigmoid(output)
#print(output.shape)
return output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from torch_geometric.nn import GATConv
x = torch.randn((8, 207, 16))
y = torch.rand([8,207,1]).float()
edge_index = torch.randint(high=206, size=(2, 1200))
#print(edge_index.shape)

edge_index = edge_index.repeat(8,1,1)
#print(edge_index.shape)
model = Net()
optimizer = torch.optim.Adam(params=model.parameters(),lr=0.01) # Only perform weight-decay on first convolution.





model.train()
import time
s = time.time()
for e in range(3):
optimizer.zero_grad()
out = model(x,edge_index)
#print(out.shape)
#print(y.shape)
loss = F.mse_loss(out, y)
loss.backward()
optimizer.step()

print(loss.item())
print("time:",time.time()-s)
0.7729121446609497
0.41821303963661194
0.384408563375473
time: 0.09303927421569824

Batch+Data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from torch_geometric.nn import GATConv
from torch import nn
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()

self.layer = GATConv(in_channels=16, out_channels=16)
self.layer2 = GATConv(in_channels=16,out_channels=1)
self.dropout = nn.Dropout(0.2)

def forward(self,x,edge_index):
# print("input:",x.shape)
data_list = [Data(x=x_, edge_index=edge_indexi) for x_ , edge_indexi in zip(x,edge_index)]

batch = Batch.from_data_list(data_list)
output = self.layer(batch.x, edge_index=batch.edge_index)
# print("output:",output.shape)
output = self.dropout(output)
data_list = [Data(x=x_, edge_index=edge_indexi) for x_ , edge_indexi in zip(torch.split(output,x.shape[1]),edge_index)]
batch = Batch.from_data_list(data_list)
output = self.layer2(batch.x,batch.edge_index)
output = self.dropout(output)
return output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from torch_geometric.data import Data,Batch
from torch_geometric.nn import GATConv
import torch.nn.functional as F
import time
x = torch.randn((8, 207, 16))
y = torch.rand([8,207,1]).float()

edge_index = torch.randint(high=206, size=(2, 1200))
print(edge_index.shape)

edge_index = edge_index.repeat(8,1,1)
print(edge_index.shape)


model = Net()
optimizer = torch.optim.Adam(params=model.parameters(),lr=0.01) # Only perform weight-decay on first convolution.


model.train()
s = time.time()
for e in range(3):
optimizer.zero_grad()
result = model(x,edge_index)
# print(result.shape)
# print("output of model",result.shape)
# print(y.shape)
result = torch.stack(torch.split(result,x.shape[1]))
print("reshape the output:",result.shape)
loss = F.mse_loss(result, y)
loss.backward()
optimizer.step()

print(loss.item())
print("time:",time.time()-s)
torch.Size([2, 1200])
torch.Size([8, 2, 1200])
reshape the output: torch.Size([8, 207, 1])
2.3954498767852783
reshape the output: torch.Size([8, 207, 1])
1.1830278635025024
reshape the output: torch.Size([8, 207, 1])
0.9167585372924805
time: 0.05799269676208496
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from torch_geometric.data import Data,Batch
from torch_geometric.nn import GATConv
import torch.nn.functional as F
x = torch.randn((8, 207, 16))
y = torch.rand([8,207,1]).float()

edge_index = torch.randint(high=206, size=(2, 1200))
print(edge_index.shape)

edge_index = edge_index.repeat(8,1,1)
print(edge_index.shape)

data_list = [Data(x=x_, edge_index=edge_indexi) for x_ , edge_indexi in zip(x,edge_index)]
batch = Batch.from_data_list(data_list)
layer = GATConv(in_channels=16, out_channels=2)
result = layer(batch.x, edge_index=batch.edge_index)
print(result.shape)
torch.Size([2, 1200])
torch.Size([8, 2, 1200])
torch.Size([1656, 2])
1
2
3
x = torch.rand([2, 2, 40000])
for i in x:
print(i.shape)
torch.Size([2, 40000])
torch.Size([2, 40000])

批量邻接矩阵转换

转换实现

转换完stack

1
2
3
4
5
6
7
8
9
10
11
def adj2coo(self,Ab):
import scipy.sparse as sp
import numpy as np
adj = sp.coo_matrix(Ab) # 转换成coo_matrix矩阵
edge_attr = adj.data # 边权值
indices = np.vstack((adj.row, adj.col)) # 我们需要的coo形式的edge_index
edge_index = torch.LongTensor(indices) # PyG需要的edge_index

edge_attr = torch.FloatTensor(edge_attr) # to float tensor
print(edge_index.shape,edge_attr.shape)
return edge_index,edge_attr
1
2
edg_indexH, edge_attrH = torch.stack([self.adj2coo(i)[0] for i in scoadj], dim=0), torch.stack(
[self.adj2coo(i)[1] for i in adj], dim=0)

一次性解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def adj2edge_index(self,A):
import scipy.sparse as sp
import numpy as np
edg_indexAll = torch.zeros(0,dtype=torch.int64)
edg_attrAll = torch.zeros(0,dtype=torch.float32)

for b in A:
adj = sp.coo_matrix(b) # 转换成coo_matrix矩阵
edge_attr = adj.data # 边权值
indices = np.vstack((adj.row, adj.col)) # 我们需要的coo形式的edge_index
edge_index = torch.LongTensor(indices) # PyG需要的edge_index

edge_attr = torch.FloatTensor(edge_attr) # to float tensor
edg_indexAll = torch.cat((edg_indexAll, edge_index))
edg_attrAll = torch.cat((edg_attrAll, edge_attr))

#print("edg",edg_indexAll.view(A.shape[0],2,-1).shape)
#print(edg_attrAll.view(A.shape[0],-1).shape)
return edg_indexAll.view(A.shape[0],2,-1),edg_attrAll.view(A.shape[0],-1)

应用到模型

模型中传参

1
2
3
4
5
x3 = self.relu(
torch.stack(
[self.gc6(graph, edge_index=self.adj2coo(edge)[0], edge_attr=self.adj2coo(edge)[1]) for graph, edge in
zip(x3_h,A)],
dim=0))

Batch+Data

效率更高,如一个epoch前面是280s,后面是90s

1
2
3
4
5
6
from torch_geometric.data import Data,Batch
data_list = [Data(x = x_,edge_ index=self.adj2coo(edge)[0] ,edge_attr=self.adj2coo(edge)[1]) for
x_ ,edge in zip(x, A) ]
batchH = Batch.from_data_list(data_listata_list)
x1_h = self. relu(self. gc1(batchH.x, edge_index=batchH. edge_indexedge_attr=batchH.edge_attr ))