Skip to content

Commit 3a3f74b

Browse files
authored
Merge pull request #271 from FluxML/doc
Update docs
2 parents 87c2dcf + 757d2cc commit 3a3f74b

25 files changed

+329
-116
lines changed

README.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,32 +28,35 @@ Suggestions, issues and pull requsts are welcome.
2828
* Variable graph inputs are supported. You use it when diverse graph structures are prepared as inputs to the same model.
2929
* Integrate GNN benchmark datasets (WIP)
3030

31-
## Featured Graphs
31+
### Featured Graphs
3232

3333
GeometricFlux handles graph data (the topology plus node/vertex/graph features)
34-
thanks to the type `FeaturedGraph`.
34+
thanks to `FeaturedGraph` type.
3535

36-
A `FeaturedGraph` can be constructed out of
36+
A `FeaturedGraph` can be constructed from various graph structures, including
3737
adjacency matrices, adjacency lists, Graphs' types...
3838

3939
```julia
4040
fg = FeaturedGraph(adj_list)
4141
```
42-
## Graph convolutional layers
42+
43+
### Graph convolutional layers
4344

4445
Construct a GCN layer:
4546

4647
```julia
47-
GCNConv([fg,] input_dim => output_dim, relu)
48+
GCNConv(input_dim => output_dim, relu)
4849
```
4950

5051
## Use it as you use Flux
5152

5253
```julia
53-
model = Chain(GCNConv(fg, 1024 => 512, relu),
54-
Dropout(0.5),
55-
GCNConv(fg, 512 => 128),
56-
Dense(128, 10))
54+
model = Chain(
55+
WithGraph(fg, GCNConv(fg, 1024 => 512, relu)),
56+
Dropout(0.5),
57+
WithGraph(fg, GCNConv(fg, 512 => 128)),
58+
Dense(128, 10)
59+
)
5760
## Loss
5861
loss(x, y) = logitcrossentropy(model(x), y)
5962
accuracy(x, y) = mean(onecold(model(x)) .== onecold(y))

docs/bibliography.bib

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,9 @@ @inproceedings{node2vec2016
1515
location = {San Francisco, California, USA},
1616
series = {KDD '16}
1717
}
18+
19+
@misc{google_word2vec,
20+
title = {Google code archive - long-term storage for google code project hosting.},
21+
url = {https://code.google.com/archive/p/word2vec/},
22+
publisher = {Google}
23+
}

docs/make.jl

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,32 @@ makedocs(
1313
analytics = "G-M61P0B2Y8E",
1414
),
1515
clean = false,
16-
modules = [GeometricFlux],
16+
modules = [GeometricFlux,GraphSignals],
1717
pages = ["Home" => "index.md",
18-
"Get started" => "start.md",
19-
"Basics" =>
20-
["Graph convolutions" => "basics/conv.md",
21-
"Building layers" => "basics/layers.md",
22-
"Graph passing" => "basics/passgraph.md"],
23-
"Cooperate with Flux layers" => "cooperate.md",
24-
"Tutorials" =>
25-
[
26-
"Semi-supervised learning with GCN" => "tutorials/semisupervised_gcn.md",
18+
"Introduction" => "introduction.md",
19+
"Basics" => [
20+
"Graph Convolutions" => "basics/conv.md",
21+
"Graph Passing" => "basics/passgraph.md",
22+
"Building Layers" => "basics/layers.md",
23+
"Subgraph" => "basics/subgraph.md",
24+
"Batch Learning" => "basics/batch.md",
25+
],
26+
"Cooperate with Flux Layers" => "cooperate.md",
27+
"Tutorials" => [
28+
"Semi-Supervised Learning with GCN" => "tutorials/semisupervised_gcn.md",
2729
"GCN with Fixed Graph" => "tutorials/gcn_fixed_graph.md",
2830
],
29-
"Abstractions" =>
30-
["Message passing scheme" => "abstractions/msgpass.md",
31-
"Graph network block" => "abstractions/gn.md"],
32-
"Manual" =>
33-
["Convolutional Layers" => "manual/conv.md",
34-
"Pooling Layers" => "manual/pool.md",
35-
"Models" => "manual/models.md",
36-
"Linear Algebra" => "manual/linalg.md"],
31+
"Abstractions" => [
32+
"Message passing scheme" => "abstractions/msgpass.md",
33+
"Graph network block" => "abstractions/gn.md"],
34+
"Manual" => [
35+
"FeaturedGraph" => "manual/featuredgraph.md",
36+
"Convolutional Layers" => "manual/conv.md",
37+
"Pooling Layers" => "manual/pool.md",
38+
"Embeddings" => "manual/embedding.md",
39+
"Models" => "manual/models.md",
40+
"Linear Algebra" => "manual/linalg.md"
41+
],
3742
"References" => "references.md",
3843
]
3944
)

docs/src/abstractions/msgpass.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@ update(mp, m, x) = m
1111

1212
`mp` denotes a message passing layer. `message` accepts node state `x_i` for node `i` and its neighbor state `x_j` for node `j`, as well as corresponding edge state `e_ij` for edge `(i,j)`. The default message function gives all the neighbor state `x_j` for neighbor of node `i`. `update` takes aggregated message `m` and current node state `x`, and then outputs `m`.
1313

14+
```@docs
15+
GeometricFlux.MessagePassing
16+
```
17+
1418
## Message function
1519

1620
A message function accepts feature vector representing node state `x_i`, feature vectors for neighbor state `x_j` and corresponding edge state `e_ij`. A vector is expected to output from `message` for message. User can override `message` for customized message passing layer to provide desired behavior.
1721

22+
```@docs
23+
GeometricFlux.message
24+
```
25+
1826
## Aggregate messages
1927

2028
Messages from message function are aggregated by an aggregate function. An aggregated message is passed to update function for node-level computation. An aggregate function is given by the following:
@@ -38,3 +46,7 @@ The following `aggr` are available aggregate functions:
3846
## Update function
3947

4048
An update function takes aggregated message `m` and current node state `x` as arguments. An output vector is expected to be the new node state for next layer. User can override `update` for customized message passing layer to provide desired behavior.
49+
50+
```@docs
51+
GeometricFlux.update
52+
```

docs/src/assets/bypass_graph.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/src/assets/geometry.svg

Lines changed: 4 additions & 0 deletions
Loading

docs/src/assets/graph signals.svg

Lines changed: 4 additions & 0 deletions
Loading

docs/src/basics/batch.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Batch Learning
2+
3+
## Batch Learning for Variable Graph Strategy
4+
5+
Batch learning for variable graph strategy can be prepared as follows:
6+
7+
```julia
8+
train_data = [(FeaturedGraph(g, nf=train_X), train_y) for _ in 1:N]
9+
train_batch = Flux.batch(train_data)
10+
```
11+
12+
It batches up `FeaturedGraph` objects into specified mini-batch. A batch is passed to a GNN model and trained/inferred one by one. It is hard for `FeaturedGraph` objects to train or infer in real batch for GPU.
13+
14+
## Batch Learning for Static Graph Strategy
15+
16+
A efficient batch learning should use static graph strategy. Batch learning for static graph strategy can be prepared as follows:
17+
18+
```julia
19+
train_data = (repeat(train_X, outer=(1,1,N)), repeat(train_y, outer=(1,1,N)))
20+
train_loader = DataLoader(train_data, batchsize=batch_size, shuffle=true)
21+
```
22+
23+
An efficient batch learning should feed array to a GNN model. In the example, the mini-batch dimension is the third dimension for `train_X` array. The `train_X` array is split by `DataLoader` into mini-batches and feed a mini-batch to GNN model at a time. This strategy leverages the advantage of GPU training by accelerating training GNN model in a real batch learning.

docs/src/basics/conv.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# Graph convolutions
1+
# Graph Convolutions
22

3-
Graph convolution can be classified into spectral-based graph convolution and spatial-based graph convolution. Spectral-based graph convolution, such as `GCNConv` and `ChebConv`, performs operation on features of *whole* graph at one time. Spatial-based graph convolution, such as `GraphConv` and `GATConv`, performs operation on features of *local* graph instead. Message-passing scheme is an abstraction for spatial-based graph convolutional layers. Any spatial-based graph convolutional layer can be implemented under the framework of message-passing scheme.
3+
Graph convolution can be classified into *spectral-based graph convolution* and *spatial-based graph convolution*. Spectral-based graph convolution, such as `GCNConv` and `ChebConv`, performs operation on features of *whole* graph at one time. Spatial-based graph convolution, such as `GraphConv` and `GATConv`, performs operation on features of *local* subgraph instead. Message-passing scheme is an abstraction for spatial-based graph convolutional layers. Any spatial-based graph convolutional layer can be implemented under the framework of message-passing scheme.

docs/src/basics/layers.md

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,85 @@
1-
# Building graph neural networks
1+
# Building Graph Neural Networks
22

33
Building GNN is as simple as building neural network in Flux. The syntax here is the same as Flux. `Chain` is used to stack layers into a GNN. A simple example is shown here:
44

55
```julia
6-
model = Chain(GCNConv(adj_mat, feat=>h1),
7-
GCNConv(adj_mat, h1=>h2, relu))
6+
model = Chain(
7+
GCNConv(feat=>h1),
8+
GCNConv(h1=>h2, relu),
9+
)
810
```
911

10-
In the example above, The first argument `adj_mat` is the representation of a graph in form of adjacency matrix. The feature dimension in first layer is mapped from `feat` to `h1`. In second layer, `h1` is then mapped to `h2`. Default activation function is given as identity if it is not specified by users.
12+
In the example above, the feature dimension in first layer is mapped from `feat` to `h1`. In second layer, `h1` is then mapped to `h2`. Default activation function is given as `identity` if it is not specified by users.
1113

12-
The initialization function `GCNConv(...)` constructs a `GCNConv` layer. For most of the layer types in GeometricFlux, a layer can be initialized in at least two ways:
14+
The initialization function `GCNConv(...)` constructs a `GCNConv` layer. For most of the layer types in GeometricFlux, a layer can be initialized in two ways:
1315

14-
* Initializing *with* a predefined adjacency matrix or `FeaturedGraph`, followed by the other parameters. For most of the layer types, this is for datasets where each input has the same graph structure.
15-
* Initializing *without* an initial graph argument, only supplying the relevant parameters. This allows the layer to accept different graph structures.
16+
* GNN layer without graph: initializing *without* a predefined graph topology. This allows the layer to accept different graph topology.
17+
* GNN layer with static graph: initializing *with* a predefined graph topology, e.g. graph wrapped in `FeaturedGraph`. This strategy is suitable for datasets where each input requires the same graph structure and it has better performance than variable graph strategy.
1618

17-
# Applying layers
19+
The example above demonstrate the variable graph strategy. The equivalent GNN architecture but with static graph strategy is shown as following:
20+
21+
```julia
22+
model = Chain(
23+
WithGraph(fg, GCNConv(feat=>h1)),
24+
WithGraph(fg, GCNConv(h1=>h2, relu)),
25+
)
26+
```
27+
28+
```@docs
29+
GeometricFlux.WithGraph
30+
```
31+
32+
## Applying Layers
1833

1934
When using GNN layers, the general guidelines are:
2035

21-
* If you pass in a ``n \times d`` matrix of node features, and the layer maps node features ``\mathbb{R}^d \rightarrow \mathbb{R}^k`` then the output will be in matrix with dimensions ``n \times k``. The same ostensibly goes for edge features but as of now no layer type supports outputting new edge features.
22-
* If you pass in a `FeaturedGraph`, the output will be also be a `FeaturedGraph` with modified node (and/or edge) features. Add `node_feature` as the following entry in the Flux chain (or simply call `node_feature()` on the output) if you wish to subsequently convert them to matrix form.
36+
* With static graph strategy: you should pass in a ``d \times n \times batch`` matrix for node features, and the layer maps node features ``\mathbb{R}^d \rightarrow \mathbb{R}^k`` then the output will be in matrix with dimensions ``k \times n \times batch``. The same ostensibly goes for edge features but as of now no layer type supports outputting new edge features.
37+
* With variable graph strategy: you should pass in a `FeaturedGraph`, the output will be also be a `FeaturedGraph` with modified node (and/or edge) features. Add `node_feature` as the following entry in the Flux chain (or simply call `node_feature()` on the output) if you wish to subsequently convert them to matrix form.
38+
39+
## Define Your Own GNN Layer
40+
41+
Customizing your own GNN layers are the same as defining a layer in Flux. You may want to check [Flux documentation](https://fluxml.ai/Flux.jl/stable/models/basics/#Building-Layers-1) first.
42+
43+
To define a customized GNN layer, for example, we take a simple `GCNConv` layer as example here.
44+
45+
```julia
46+
struct GCNConv <: AbstractGraphLayer
47+
weight
48+
bias
49+
σ
50+
end
51+
52+
@functor GCNConv
53+
```
54+
55+
We first should define a `GCNConv` type and let it be the subtype of `AbstractGraphLayer`. In this type, it holds parameters that a layer operate on. Don't forget to add `@functor` macro to `GCNConv` type.
56+
57+
```julia
58+
(l::GCNConv)(Ã::AbstractMatrix, x::AbstractMatrix) = l.σ.(l.weight * x *.+ l.bias)
59+
```
2360

24-
## Create custom layers
61+
Then, we can define the operation for `GCNConv` layer.
62+
63+
```julia
64+
function (l::GCNConv)(fg::AbstractFeaturedGraph)
65+
nf = node_feature(fg)
66+
= Zygote.ignore() do
67+
GraphSignals.normalized_adjacency_matrix(fg, eltype(nf); selfloop=true)
68+
end
69+
return ConcreteFeaturedGraph(fg, nf = l(Ã, nf))
70+
end
71+
```
2572

26-
Customizing your own GNN layers are the same as customizing layers in Flux. You may want to reference [Flux documentation](https://fluxml.ai/Flux.jl/stable/models/basics/#Building-Layers-1).
73+
Here comes to the GNN-specific behaviors. A GNN layer should accept object of subtype of `AbstractFeaturedGraph` to support variable graph strategy. A variable graph strategy should fetch node/edge/global features from `fg` and transform graph in `fg` into required form for layer operation, e.g. `GCNConv` layer needs a normalized adjacency matrix with self loop. Then, normalized adjacency matrix `` and node features `nf` are pass through `GCNConv` layer `l(Ã, nf)` to give a new node feature. Finally, a `ConcreteFeaturedGraph` wrap graph in `fg` and new node features into a new object of subtype of `AbstractFeaturedGraph`.
74+
75+
```julia
76+
layer = GCNConv(10=>5, relu)
77+
new_fg = layer(fg)
78+
gradient(() -> sum(node_feature(layer(fg))), Flux.params(layer))
79+
```
80+
81+
Now we complete a simple version of `GCNConv` layer. One can test the forward pass and gradient if they work properly.
82+
83+
```@docs
84+
GeometricFlux.AbstractGraphLayer
85+
```

0 commit comments

Comments
 (0)