Skip to content

Commit 3d73a59

Browse files
authored
Change GNN.jl in GraphNeuralNetworks.jl (#229)
1 parent 0364a98 commit 3d73a59

File tree

4 files changed

+24
-24
lines changed

4 files changed

+24
-24
lines changed

docs/pluto_output/gnn_intro_pluto.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<p>Recently, deep learning on graphs has emerged to one of the hottest research fields in the deep learning community. Here, <strong>Graph Neural Networks &#40;GNNs&#41;</strong> aim to generalize classical deep learning concepts to irregular structured data &#40;in contrast to images or texts&#41; and to enable neural networks to reason about objects and their relations.</p>
3434
<p>This is done by following a simple <strong>neural message passing scheme</strong>, where node features <span class="tex">$\mathbf&#123;x&#125;_i^&#123;&#40;\ell&#41;&#125;$</span> of all nodes <span class="tex">$i \in \mathcal&#123;V&#125;$</span> in a graph <span class="tex">$\mathcal&#123;G&#125; &#61; &#40;\mathcal&#123;V&#125;, \mathcal&#123;E&#125;&#41;$</span> are iteratively updated by aggregating localized information from their neighbors <span class="tex">$\mathcal&#123;N&#125;&#40;i&#41;$</span>:</p>
3535
<p class="tex">$$\mathbf&#123;x&#125;_i^&#123;&#40;\ell &#43; 1&#41;&#125; &#61; f^&#123;&#40;\ell &#43; 1&#41;&#125;_&#123;\theta&#125; \left&#40; \mathbf&#123;x&#125;_i^&#123;&#40;\ell&#41;&#125;, \left\&#123; \mathbf&#123;x&#125;_j^&#123;&#40;\ell&#41;&#125; : j \in \mathcal&#123;N&#125;&#40;i&#41; \right\&#125; \right&#41;$$</p>
36-
<p>This tutorial will introduce you to some fundamental concepts regarding deep learning on graphs via Graph Neural Networks based on the <strong><a href="https://github.com/CarloLucibello/GraphNeuralNetworks.jl">GraphNeuralNetworks.jl library</a></strong>. GNN.jl is an extension library to the popular deep learning framework <a href="https://fluxml.ai/Flux.jl/stable/">Flux.jl</a>, and consists of various methods and utilities to ease the implementation of Graph Neural Networks.</p>
36+
<p>This tutorial will introduce you to some fundamental concepts regarding deep learning on graphs via Graph Neural Networks based on the <strong><a href="https://github.com/CarloLucibello/GraphNeuralNetworks.jl">GraphNeuralNetworks.jl library</a></strong>. GraphNeuralNetworks.jl is an extension library to the popular deep learning framework <a href="https://fluxml.ai/Flux.jl/stable/">Flux.jl</a>, and consists of various methods and utilities to ease the implementation of Graph Neural Networks.</p>
3737
<p>Let&#39;s first import the packages we need:</p>
3838
</div>
3939
@@ -70,7 +70,7 @@ end;</code></pre>
7070
7171
7272
<div class="markdown"><p>Following <a href="https://arxiv.org/abs/1609.02907">Kipf et al. &#40;2017&#41;</a>, let&#39;s dive into the world of GNNs by looking at a simple graph-structured example, the well-known <a href="https://en.wikipedia.org/wiki/Zachary&#37;27s_karate_club"><strong>Zachary&#39;s karate club network</strong></a>. This graph describes a social network of 34 members of a karate club and documents links between members who interacted outside the club. Here, we are interested in detecting communities that arise from the member&#39;s interaction.</p>
73-
<p>GNN.jl provides utilities to convert <a href="https://github.com/JuliaML/MLDatasets.jl">MLDatasets.jl</a>&#39;s datasets to its own type:</p>
73+
<p>GraphNeuralNetworks.jl provides utilities to convert <a href="https://github.com/JuliaML/MLDatasets.jl">MLDatasets.jl</a>&#39;s datasets to its own type:</p>
7474
</div>
7575
7676
<pre class='language-julia'><code class='language-julia'>dataset = MLDatasets.KarateClub()</code></pre>
@@ -163,7 +163,7 @@ Is undirected: true
163163
164164
165165
166-
<div class="markdown"><p>Each graph in GNN.jl is represented by a <code>GNNGraph</code> object, which holds all the information to describe its graph representation. We can print the data object anytime via <code>print&#40;g&#41;</code> to receive a short summary about its attributes and their shapes.</p>
166+
<div class="markdown"><p>Each graph in GraphNeuralNetworks.jl is represented by a <code>GNNGraph</code> object, which holds all the information to describe its graph representation. We can print the data object anytime via <code>print&#40;g&#41;</code> to receive a short summary about its attributes and their shapes.</p>
167167
<p>The <code>g</code> object holds 3 attributes:</p>
168168
<ul>
169169
<li><p><code>g.ndata</code> contains node related information;</p>
@@ -183,9 +183,9 @@ Is undirected: true
183183
<pre id='var-hash182682' class='code-output documenter-example-output'>([1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 34, 34, 34, 34, 34, 34, 34, 34, 34, 34], [2, 3, 4, 5, 6, 7, 8, 9, 11, 12 … 21, 23, 24, 27, 28, 29, 30, 31, 32, 33])</pre>
184184
185185
186-
<div class="markdown"><p>By printing <code>edge_index&#40;g&#41;</code>, we can understand how GNN.jl represents graph connectivity internally. We can see that for each edge, <code>edge_index</code> holds a tuple of two node indices, where the first value describes the node index of the source node and the second value describes the node index of the destination node of an edge.</p>
187-
<p>This representation is known as the <strong>COO format &#40;coordinate format&#41;</strong> commonly used for representing sparse matrices. Instead of holding the adjacency information in a dense representation <span class="tex">$\mathbf&#123;A&#125; \in \&#123; 0, 1 \&#125;^&#123;|\mathcal&#123;V&#125;| \times |\mathcal&#123;V&#125;|&#125;$</span>, GNN.jl represents graphs sparsely, which refers to only holding the coordinates/values for which entries in <span class="tex">$\mathbf&#123;A&#125;$</span> are non-zero.</p>
188-
<p>Importantly, GNN.jl does not distinguish between directed and undirected graphs, and treats undirected graphs as a special case of directed graphs in which reverse edges exist for every entry in the edge_index.</p>
186+
<div class="markdown"><p>By printing <code>edge_index&#40;g&#41;</code>, we can understand how GraphNeuralNetworks.jl represents graph connectivity internally. We can see that for each edge, <code>edge_index</code> holds a tuple of two node indices, where the first value describes the node index of the source node and the second value describes the node index of the destination node of an edge.</p>
187+
<p>This representation is known as the <strong>COO format &#40;coordinate format&#41;</strong> commonly used for representing sparse matrices. Instead of holding the adjacency information in a dense representation <span class="tex">$\mathbf&#123;A&#125; \in \&#123; 0, 1 \&#125;^&#123;|\mathcal&#123;V&#125;| \times |\mathcal&#123;V&#125;|&#125;$</span>, GraphNeuralNetworks.jl represents graphs sparsely, which refers to only holding the coordinates/values for which entries in <span class="tex">$\mathbf&#123;A&#125;$</span> are non-zero.</p>
188+
<p>Importantly, GraphNeuralNetworks.jl does not distinguish between directed and undirected graphs, and treats undirected graphs as a special case of directed graphs in which reverse edges exist for every entry in the edge_index.</p>
189189
<p>Since a <code>GNNGraph</code> is an <code>AbstractGraph</code> from the <code>Graphs.jl</code> library, it supports graph algorithms and visualization tools from the wider julia graph ecosystem:</p>
190190
</div>
191191
@@ -198,11 +198,11 @@ Is undirected: true
198198
```@raw html
199199
<div class="markdown">
200200
201-
<p>After learning about GNN.jl&#39;s data handling, it&#39;s time to implement our first Graph Neural Network&#33;</p>
201+
<p>After learning about GraphNeuralNetworks.jl&#39;s data handling, it&#39;s time to implement our first Graph Neural Network&#33;</p>
202202
<p>For this, we will use on of the most simple GNN operators, the <strong>GCN layer</strong> &#40;<a href="https://arxiv.org/abs/1609.02907">Kipf et al. &#40;2017&#41;</a>&#41;, which is defined as</p>
203203
<p class="tex">$$\mathbf&#123;x&#125;_v^&#123;&#40;\ell &#43; 1&#41;&#125; &#61; \mathbf&#123;W&#125;^&#123;&#40;\ell &#43; 1&#41;&#125; \sum_&#123;w \in \mathcal&#123;N&#125;&#40;v&#41; \, \cup \, \&#123; v \&#125;&#125; \frac&#123;1&#125;&#123;c_&#123;w,v&#125;&#125; \cdot \mathbf&#123;x&#125;_w^&#123;&#40;\ell&#41;&#125;$$</p>
204204
<p>where <span class="tex">$\mathbf&#123;W&#125;^&#123;&#40;\ell &#43; 1&#41;&#125;$</span> denotes a trainable weight matrix of shape <code>&#91;num_output_features, num_input_features&#93;</code> and <span class="tex">$c_&#123;w,v&#125;$</span> refers to a fixed normalization coefficient for each edge.</p>
205-
<p>GNN.jl implements this layer via <code>GCNConv</code>, which can be executed by passing in the node feature representation <code>x</code> and the COO graph connectivity representation <code>edge_index</code>.</p>
205+
<p>GraphNeuralNetworks.jl implements this layer via <code>GCNConv</code>, which can be executed by passing in the node feature representation <code>x</code> and the COO graph connectivity representation <code>edge_index</code>.</p>
206206
<p>With this, we are ready to create our first Graph Neural Network by defining our network architecture:</p>
207207
</div>
208208

docs/pluto_output/graph_classification_pluto.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,15 @@ end</code></pre>
141141
<div class="markdown">
142142
143143
<p>Since graphs in graph classification datasets are usually small, a good idea is to <strong>batch the graphs</strong> before inputting them into a Graph Neural Network to guarantee full GPU utilization. In the image or language domain, this procedure is typically achieved by <strong>rescaling</strong> or <strong>padding</strong> each example into a set of equally-sized shapes, and examples are then grouped in an additional dimension. The length of this dimension is then equal to the number of examples grouped in a mini-batch and is typically referred to as the <code>batchsize</code>.</p>
144-
<p>However, for GNNs the two approaches described above are either not feasible or may result in a lot of unnecessary memory consumption. Therefore, GNN.jl opts for another approach to achieve parallelization across a number of examples. Here, adjacency matrices are stacked in a diagonal fashion &#40;creating a giant graph that holds multiple isolated subgraphs&#41;, and node and target features are simply concatenated in the node dimension &#40;the last dimension&#41;.</p>
144+
<p>However, for GNNs the two approaches described above are either not feasible or may result in a lot of unnecessary memory consumption. Therefore, GraphNeuralNetworks.jl opts for another approach to achieve parallelization across a number of examples. Here, adjacency matrices are stacked in a diagonal fashion &#40;creating a giant graph that holds multiple isolated subgraphs&#41;, and node and target features are simply concatenated in the node dimension &#40;the last dimension&#41;.</p>
145145
<p>This procedure has some crucial advantages over other batching procedures:</p>
146146
<ol>
147147
<li><p>GNN operators that rely on a message passing scheme do not need to be modified since messages are not exchanged between two nodes that belong to different graphs.</p>
148148
</li>
149149
<li><p>There is no computational or memory overhead since adjacency matrices are saved in a sparse fashion holding only non-zero entries, <em>i.e.</em>, the edges.</p>
150150
</li>
151151
</ol>
152-
<p>GNN.jl can <strong>batch multiple graphs into a single giant graph</strong>:</p>
152+
<p>GraphNeuralNetworks.jl can <strong>batch multiple graphs into a single giant graph</strong>:</p>
153153
</div>
154154
155155
<pre class='language-julia'><code class='language-julia'>vec_gs, _ = first(train_loader)</code></pre>
@@ -185,7 +185,7 @@ end</code></pre>
185185
</ol>
186186
<p>There exists multiple <strong>readout layers</strong> in literature, but the most common one is to simply take the average of node embeddings:</p>
187187
<p class="tex">$$\mathbf&#123;x&#125;_&#123;\mathcal&#123;G&#125;&#125; &#61; \frac&#123;1&#125;&#123;|\mathcal&#123;V&#125;|&#125; \sum_&#123;v \in \mathcal&#123;V&#125;&#125; \mathcal&#123;x&#125;^&#123;&#40;L&#41;&#125;_v$$</p>
188-
<p>GNN.jl provides this functionality via <code>GlobalPool&#40;mean&#41;</code>, which takes in the node embeddings of all nodes in the mini-batch and the assignment vector <code>graph_indicator</code> to compute a graph embedding of size <code>&#91;hidden_channels, batchsize&#93;</code>.</p>
188+
<p>GraphNeuralNetworks.jl provides this functionality via <code>GlobalPool&#40;mean&#41;</code>, which takes in the node embeddings of all nodes in the mini-batch and the assignment vector <code>graph_indicator</code> to compute a graph embedding of size <code>&#91;hidden_channels, batchsize&#93;</code>.</p>
189189
<p>The final architecture for applying GNNs to the task of graph classification then looks as follows and allows for complete end-to-end training:</p>
190190
</div>
191191
@@ -263,7 +263,7 @@ end</code></pre>
263263
<h2>&#40;Optional&#41; Exercise</h2>
264264
<p>Can we do better than this? As multiple papers pointed out &#40;<a href="https://arxiv.org/abs/1810.00826">Xu et al. &#40;2018&#41;</a>, <a href="https://arxiv.org/abs/1810.02244">Morris et al. &#40;2018&#41;</a>&#41;, applying <strong>neighborhood normalization decreases the expressivity of GNNs in distinguishing certain graph structures</strong>. An alternative formulation &#40;<a href="https://arxiv.org/abs/1810.02244">Morris et al. &#40;2018&#41;</a>&#41; omits neighborhood normalization completely and adds a simple skip-connection to the GNN layer in order to preserve central node information:</p>
265265
<p class="tex">$$\mathbf&#123;x&#125;_i^&#123;&#40;\ell&#43;1&#41;&#125; &#61; \mathbf&#123;W&#125;^&#123;&#40;\ell &#43; 1&#41;&#125;_1 \mathbf&#123;x&#125;_i^&#123;&#40;\ell&#41;&#125; &#43; \mathbf&#123;W&#125;^&#123;&#40;\ell &#43; 1&#41;&#125;_2 \sum_&#123;j \in \mathcal&#123;N&#125;&#40;i&#41;&#125; \mathbf&#123;x&#125;_j^&#123;&#40;\ell&#41;&#125;$$</p>
266-
<p>This layer is implemented under the name <code>GraphConv</code> in GNN.jl.</p>
266+
<p>This layer is implemented under the name <code>GraphConv</code> in GraphNeuralNetworks.jl.</p>
267267
<p>As an exercise, you are invited to complete the following code to the extent that it makes use of <code>GraphConv</code> rather than <code>GCNConv</code>. This should bring you close to <strong>82&#37; test accuracy</strong>.</p>
268268
</div>
269269

docs/tutorials/introductory_tutorials/gnn_intro_pluto.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ This is done by following a simple **neural message passing scheme**, where node
5757
```
5858
5959
This tutorial will introduce you to some fundamental concepts regarding deep learning on graphs via Graph Neural Networks based on the **[GraphNeuralNetworks.jl library](https://github.com/CarloLucibello/GraphNeuralNetworks.jl)**.
60-
GNN.jl is an extension library to the popular deep learning framework [Flux.jl](https://fluxml.ai/Flux.jl/stable/), and consists of various methods and utilities to ease the implementation of Graph Neural Networks.
60+
GraphNeuralNetworks.jl is an extension library to the popular deep learning framework [Flux.jl](https://fluxml.ai/Flux.jl/stable/), and consists of various methods and utilities to ease the implementation of Graph Neural Networks.
6161
6262
Let's first import the packages we need:
6363
"""
@@ -66,7 +66,7 @@ Let's first import the packages we need:
6666
md"""
6767
Following [Kipf et al. (2017)](https://arxiv.org/abs/1609.02907), let's dive into the world of GNNs by looking at a simple graph-structured example, the well-known [**Zachary's karate club network**](https://en.wikipedia.org/wiki/Zachary%27s_karate_club). This graph describes a social network of 34 members of a karate club and documents links between members who interacted outside the club. Here, we are interested in detecting communities that arise from the member's interaction.
6868
69-
GNN.jl provides utilities to convert [MLDatasets.jl](https://github.com/JuliaML/MLDatasets.jl)'s datasets to its own type:
69+
GraphNeuralNetworks.jl provides utilities to convert [MLDatasets.jl](https://github.com/JuliaML/MLDatasets.jl)'s datasets to its own type:
7070
"""
7171

7272
# ╔═╡ 4ba372d4-7a6a-41e0-92a0-9547a78e2898
@@ -129,7 +129,7 @@ end
129129

130130
# ╔═╡ 1e362709-a0d0-45d5-b2fd-a91c45fa317a
131131
md"""
132-
Each graph in GNN.jl is represented by a `GNNGraph` object, which holds all the information to describe its graph representation.
132+
Each graph in GraphNeuralNetworks.jl is represented by a `GNNGraph` object, which holds all the information to describe its graph representation.
133133
We can print the data object anytime via `print(g)` to receive a short summary about its attributes and their shapes.
134134
135135
The `g` object holds 3 attributes:
@@ -154,13 +154,13 @@ edge_index(g)
154154

155155
# ╔═╡ 98bb86d2-a7b9-4110-8851-8829a9f9b4d0
156156
md"""
157-
By printing `edge_index(g)`, we can understand how GNN.jl represents graph connectivity internally.
157+
By printing `edge_index(g)`, we can understand how GraphNeuralNetworks.jl represents graph connectivity internally.
158158
We can see that for each edge, `edge_index` holds a tuple of two node indices, where the first value describes the node index of the source node and the second value describes the node index of the destination node of an edge.
159159
160160
This representation is known as the **COO format (coordinate format)** commonly used for representing sparse matrices.
161-
Instead of holding the adjacency information in a dense representation ``\mathbf{A} \in \{ 0, 1 \}^{|\mathcal{V}| \times |\mathcal{V}|}``, GNN.jl represents graphs sparsely, which refers to only holding the coordinates/values for which entries in ``\mathbf{A}`` are non-zero.
161+
Instead of holding the adjacency information in a dense representation ``\mathbf{A} \in \{ 0, 1 \}^{|\mathcal{V}| \times |\mathcal{V}|}``, GraphNeuralNetworks.jl represents graphs sparsely, which refers to only holding the coordinates/values for which entries in ``\mathbf{A}`` are non-zero.
162162
163-
Importantly, GNN.jl does not distinguish between directed and undirected graphs, and treats undirected graphs as a special case of directed graphs in which reverse edges exist for every entry in the edge_index.
163+
Importantly, GraphNeuralNetworks.jl does not distinguish between directed and undirected graphs, and treats undirected graphs as a special case of directed graphs in which reverse edges exist for every entry in the edge_index.
164164
165165
Since a `GNNGraph` is an `AbstractGraph` from the `Graphs.jl` library, it supports graph algorithms and visualization tools from the wider julia graph ecosystem:
166166
"""
@@ -173,7 +173,7 @@ md"""
173173
174174
## Implementing Graph Neural Networks
175175
176-
After learning about GNN.jl's data handling, it's time to implement our first Graph Neural Network!
176+
After learning about GraphNeuralNetworks.jl's data handling, it's time to implement our first Graph Neural Network!
177177
178178
For this, we will use on of the most simple GNN operators, the **GCN layer** ([Kipf et al. (2017)](https://arxiv.org/abs/1609.02907)), which is defined as
179179
@@ -183,7 +183,7 @@ For this, we will use on of the most simple GNN operators, the **GCN layer** ([K
183183
184184
where ``\mathbf{W}^{(\ell + 1)}`` denotes a trainable weight matrix of shape `[num_output_features, num_input_features]` and ``c_{w,v}`` refers to a fixed normalization coefficient for each edge.
185185
186-
GNN.jl implements this layer via `GCNConv`, which can be executed by passing in the node feature representation `x` and the COO graph connectivity representation `edge_index`.
186+
GraphNeuralNetworks.jl implements this layer via `GCNConv`, which can be executed by passing in the node feature representation `x` and the COO graph connectivity representation `edge_index`.
187187
188188
With this, we are ready to create our first Graph Neural Network by defining our network architecture:
189189
"""

0 commit comments

Comments
 (0)