minibatch-node.rst 10 KB
Newer Older
Muhyun Kim's avatar
Muhyun Kim committed
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
35
36
37
38
39
40
41
42
.. _guide_ko-minibatch-node-classification-sampler:

6.1 이웃 샘플링을 사용한 노드 분류 GNN 모델 학습하기
-----------------------------------------

:ref:`(English Version) <guide-minibatch-node-classification-sampler>`

Stochastic 학습이 되도록 모델을 만들기 위해서는, 다음과 같은 것이 필요하다.

- 이웃 샘플러 정의하기
- 미니 배치 학습이 되도록 모델을 변경하기
- 학습  고치기

이제,  단계를 어떻게 구현하는 하나씩 살펴보자.

이웃 샘플러  데이터 로더 정의하기
~~~~~~~~~~~~~~~~~~~~~~~~~~~

DGL 계산하기를 원하는 노드들에 대해서  레이어에서 필요한 computation dependency들을 생성하는  가지 이웃 샘플러 클래스들을 가지고 있다.

가장 단순한 이웃 샘플러는 :class:`~dgl.dataloading.neighbor.MultiLayerFullNeighborSampler` , 노드가  노드의 모든 이웃들로부터 메시지를 수집하도록 해준다.

DGL 샘플러를 사용하기 위해서는 이를 미니배치에 있는 노드들의 집한은 iterate하는 :class:`~dgl.dataloading.pytorch.NodeDataLoader`  합쳐야한다.

다음 예제 코드는 배치들의 학습 노드 ID 배열 ``train_nids``  iterate하고, 생성된 MFG(Message Flow Graph)들의 목록을 GPU 옮기는 PyTorch DataLoader 만든다.

.. code:: python

    import dgl
    import dgl.nn as dglnn
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    sampler = dgl.dataloading.MultiLayerFullNeighborSampler(2)
    dataloader = dgl.dataloading.NodeDataLoader(
        g, train_nids, sampler,
        batch_size=1024,
        shuffle=True,
        drop_last=False,
        num_workers=4)

43
DataLoader iterate 하면서  레이어에 대한 computation dependency들을 대표하도록 특별하게 생성된 그래프들의 리스트를 얻을  있다. DGL에서 이것들을 *message flow graph* (MFG) 라고 부른다.
Muhyun Kim's avatar
Muhyun Kim committed
44
45
46
47
48
49
50
51
52
53
54
55
56
57

.. code:: python

    input_nodes, output_nodes, blocks = next(iter(dataloader))
    print(blocks)

Iterator 매번 세개의 아이템을 생성한다. ``input_nodes``  ``output_nodes``  representation 계산하는데 필요한 노드들을 담고 있다. ``block``  그것의 노드가 출력으로 계산되어야   GNN 레이어에 대해 어떤 노드 representation들이 입력으로 필요한지, 입력 노드들의 representation들이 출력 노드로 어떻게 전파되어야 하는지를 설명한다.

.. note::

   Message flow graph 개념은 :doc:`Stochastic Training Tutorial <tutorials/large/L0_neighbor_sampling_overview>`  참고하자.

   지원되는 빌드인 샘플러들의 전체 목록은 :ref:`neighborhood sampler API reference <api-dataloading-neighbor-sampling>` 에서 찾아볼  있다.

58
   :ref:`guide_ko-minibatch-customizing-neighborhood-sampler` 에는 여러분만의 이웃 샘플러 만드는 방법과 MFG 개념에 대한 보다 상세한 설명을 담고 있다.
Muhyun Kim's avatar
Muhyun Kim committed
59
60


61
.. _guide_ko-minibatch-node-classification-model:
Muhyun Kim's avatar
Muhyun Kim committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

모델을 미니-배치 학습에 맞게 만들기
~~~~~~~~~~~~~~~~~~~~~~~~~~~

만약 DGL에서 제공하는 메시지 전달 모듈만을 사용하고 있다면, 모델을 미니-배치 학습에 맞도록 수정할 것은 적다. 멀티-레이어 GCN 예로 들어보자. 그래프 전체에 대한 모델 구현은 아래와 같다.

.. code:: python

    class TwoLayerGCN(nn.Module):
        def __init__(self, in_features, hidden_features, out_features):
            super().__init__()
            self.conv1 = dglnn.GraphConv(in_features, hidden_features)
            self.conv2 = dglnn.GraphConv(hidden_features, out_features)
    
        def forward(self, g, x):
            x = F.relu(self.conv1(g, x))
            x = F.relu(self.conv2(g, x))
            return x

 , 변경해야할 것은 ``g``  앞에서 생성된 ``block``  교체하는 것이 전부이다.

.. code:: python

    class StochasticTwoLayerGCN(nn.Module):
        def __init__(self, in_features, hidden_features, out_features):
            super().__init__()
            self.conv1 = dgl.nn.GraphConv(in_features, hidden_features)
            self.conv2 = dgl.nn.GraphConv(hidden_features, out_features)
    
        def forward(self, blocks, x):
            x = F.relu(self.conv1(blocks[0], x))
            x = F.relu(self.conv2(blocks[1], x))
            return x

 DGL ``GraphConv`` 모듈들은 데이터 로더가 생성한 ``block``  원소를 argument 받는다.

:ref:`The API reference of each NN module <apinn>`  모듈이 MFG argument 받을  있는지 없는지를 알려주고 있다.

100
만약 여러분 자신의 메시지 전달 모듈을 사용하고 싶다면, :ref:`guide_ko-minibatch-custom-gnn-module`  참고하자.
Muhyun Kim's avatar
Muhyun Kim committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

학습 
~~~~~

단순하게 학습 룹은 커스터마이징된 배치 iterator 사용해서 데이터셋을 iterating하는 것으로 구성된다. MFG들의 리스트를 반환하는  iteration마다, 다음과 같은 일을 한다.

1. 입력 노드들의 노드 피처들을 GPU 로딩한다. 노드 피쳐들은 메모리나 외부 저장소에 저장되어 있을  있다. 그래프 전체 학습에서 모든 노드들의 피처를 로드하는 것과는 다르게, 입력 노드들의 피처만 로드하면 된다는 점을 유의하자.
   

   만약 피쳐들이 ``g.ndata``  저장되어 있다면,  피쳐들은 ``blocks[0].srcdata``  저장된 피쳐들,  첫번째 MFG 소스 노드들의 피처들을 접근해서 로드될  있다. 여기서 노드들은 최종 representation 계산하는데 필요한 모든 노드들을 의미한다.

2. MFG들의 리스트  입력 노드 피쳐들을 멀티-레이어 GNN 입력해서 결과를 
얻는다.

3. 출력 노드에 해당하는 노드 레이블을 GPU 로드한다. 비슷하게, 노드 레이블은 메모리나 외부 저장소에 저장되어 있을  있다. 역시, 그래프 전체 학습에서 모든 노드들의 레이블을 로드하는 것과는 다르게, 출력 노드들의 레이블만 로드한다는 점을 알아두자.
   
   피처가 ``g.ndata``  저장되어 있다면, 레이블은 ``blocks[-1].dstdata``  피쳐들 , 마지막 MFG 목적지 노드들의 피쳐들을 접근해서 로드될  있다. 이것들은 최종 representation 계산할 노드들과 같다.

4. loss 계산한 , backpropagate 수행한다.

.. code:: python

    model = StochasticTwoLayerGCN(in_features, hidden_features, out_features)
    model = model.cuda()
    opt = torch.optim.Adam(model.parameters())
    
    for input_nodes, output_nodes, blocks in dataloader:
        blocks = [b.to(torch.device('cuda')) for b in blocks]
        input_features = blocks[0].srcdata['features']
        output_labels = blocks[-1].dstdata['label']
        output_predictions = model(blocks, input_features)
        loss = compute_loss(output_labels, output_predictions)
        opt.zero_grad()
        loss.backward()
        opt.step()

DGL에서는 end-to-end stochastic 학습 예제인 `GraphSAGE
implementation <https://github.com/dmlc/dgl/blob/master/examples/pytorch/graphsage/train_sampling.py>`__  제공한다.

Heterogeneous 그래프의 경우
~~~~~~~~~~~~~~~~~~~~~~~~

Heterogeneous 그래프에 대한 노드 분류 그래프 뉴럴 네트워크를 학습하는 것은 간단하다.

145
:ref:`how to train a 2-layer RGCN on full graph <guide_ko-training-rgcn-node-classification>`  예로 들어보자. 미니-배치 학습을 하는 RGCN 구현 코드는  예제와 매우 비슷하다. (간단하게 하기 위해서 self-loop, non-linearity 기본적인 decomposition 제거했다.)
Muhyun Kim's avatar
Muhyun Kim committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

.. code:: python

    class StochasticTwoLayerRGCN(nn.Module):
        def __init__(self, in_feat, hidden_feat, out_feat, rel_names):
            super().__init__()
            self.conv1 = dglnn.HeteroGraphConv({
                    rel : dglnn.GraphConv(in_feat, hidden_feat, norm='right')
                    for rel in rel_names
                })
            self.conv2 = dglnn.HeteroGraphConv({
                    rel : dglnn.GraphConv(hidden_feat, out_feat, norm='right')
                    for rel in rel_names
                })
    
        def forward(self, blocks, x):
            x = self.conv1(blocks[0], x)
            x = self.conv2(blocks[1], x)
            return x

또한, DGL 제공하는 일부 샘플러들은 heterogeneous 그래프를 지원한다. 예를 들어, 제공되는 :class:`~dgl.dataloading.neighbor.MultiLayerFullNeighborSampler` 클래스  :class:`~dgl.dataloading.pytorch.NodeDataLoader` 클래스를 stochastic 학습에도 여전히 사용할  있다. 전체 이웃 샘플링에서 다른 점은 학습 셋에 노드 타입들과 노드 ID들의 사전을 명시해야한다는  뿐이다.

.. code:: python

    sampler = dgl.dataloading.MultiLayerFullNeighborSampler(2)
    dataloader = dgl.dataloading.NodeDataLoader(
        g, train_nid_dict, sampler,
        batch_size=1024,
        shuffle=True,
        drop_last=False,
        num_workers=4)

학습 룹은 homogeneous 그래프에 대한 학습 룹이랑 거의 유사하다. 다른 점은 ``compute_loss``  구현에서 노드 타입들와 예측 결과라는 두개의 dictionary들을 인자로 받는다는 것이다.

.. code:: python

    model = StochasticTwoLayerRGCN(in_features, hidden_features, out_features, etypes)
    model = model.cuda()
    opt = torch.optim.Adam(model.parameters())
    
    for input_nodes, output_nodes, blocks in dataloader:
        blocks = [b.to(torch.device('cuda')) for b in blocks]
        input_features = blocks[0].srcdata     # returns a dict
        output_labels = blocks[-1].dstdata     # returns a dict
        output_predictions = model(blocks, input_features)
        loss = compute_loss(output_labels, output_predictions)
        opt.zero_grad()
        loss.backward()
        opt.step()

End-to-end stochastic 학습 예제는 `RGCN
implementation <https://github.com/dmlc/dgl/blob/master/examples/pytorch/rgcn-hetero/entity_classify_mb.py>`__  참고하자.