Skip to content

Commit

Permalink
Merge branch 'master' into new-multidocs
Browse files Browse the repository at this point in the history
  • Loading branch information
aurorarossi committed Nov 3, 2024
2 parents d40a3d4 + 15055d8 commit 2b51334
Show file tree
Hide file tree
Showing 22 changed files with 302 additions and 44 deletions.
2 changes: 1 addition & 1 deletion GNNGraphs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "GNNGraphs"
uuid = "aed8fd31-079b-4b5a-b342-a13352159b8c"
authors = ["Carlo Lucibello and contributors"]
version = "1.2.1"
version = "1.3.0"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
Expand Down
5 changes: 3 additions & 2 deletions GNNGraphs/src/sampling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ function Graphs.induced_subgraph(graph::GNNGraph, nodes::Vector{Int})

node_map = Dict(node => i for (i, node) in enumerate(nodes))

edge_list = [collect(t) for t in zip(edge_index(graph)[1],edge_index(graph)[2])]

# Collect edges to add
source = Int[]
target = Int[]
Expand All @@ -187,8 +189,7 @@ function Graphs.induced_subgraph(graph::GNNGraph, nodes::Vector{Int})
if neighbor in keys(node_map)
push!(target, node_map[node])
push!(source, node_map[neighbor])

eindex = findfirst(x -> x == [neighbor, node], edge_index(graph))
eindex = findfirst(x -> x == [neighbor, node], edge_list)
push!(eindices, eindex)
end
end
Expand Down
2 changes: 1 addition & 1 deletion GNNlib/docs/src/messagepassing.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function (l::GCN)(g::GNNGraph, x::AbstractMatrix{T}) where T
end
```

See the `GATConv` implementation [here](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/blob/master/src/layers/conv.jl) for a more complex example.
See the `GATConv` implementation [here](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/blob/master/src/layers/conv.jl) for a more complex example.


## Built-in message functions
Expand Down
4 changes: 3 additions & 1 deletion GraphNeuralNetworks/Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
name = "GraphNeuralNetworks"
uuid = "cffab07f-9bc2-4db1-8861-388f63bf7694"
authors = ["Carlo Lucibello and contributors"]
version = "0.6.21"
version = "0.6.22"

[deps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
GNNGraphs = "aed8fd31-079b-4b5a-b342-a13352159b8c"
GNNlib = "a6a84749-d869-43f8-aacc-be26a1996e48"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54"
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
Expand All @@ -28,6 +29,7 @@ CUDA = "4, 5"
ChainRulesCore = "1"
Flux = "0.14"
Functors = "0.4.1"
Graphs = "1.12"
GNNGraphs = "1.0"
GNNlib = "0.2"
LinearAlgebra = "1"
Expand Down
16 changes: 8 additions & 8 deletions GraphNeuralNetworks/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<img align="right" width="300px" src="https://raw.githubusercontent.com/CarloLucibello/GraphNeuralNetworks.jl/master/docs/src/assets/logo.svg">
<img align="right" width="300px" src="https://raw.githubusercontent.com/JuliaGraphs/GraphNeuralNetworks.jl/master/docs/src/assets/logo.svg">


# GraphNeuralNetworks.jl

[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://CarloLucibello.github.io/GraphNeuralNetworks.jl/stable)
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://CarloLucibello.github.io/GraphNeuralNetworks.jl/dev)
![](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/actions/workflows/ci.yml/badge.svg)
[![codecov](https://codecov.io/gh/CarloLucibello/GraphNeuralNetworks.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/CarloLucibello/GraphNeuralNetworks.jl)
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaGraphs.github.io/GraphNeuralNetworks.jl/stable)
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaGraphs.github.io/GraphNeuralNetworks.jl/dev)
![](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/actions/workflows/ci.yml/badge.svg)
[![codecov](https://codecov.io/gh/JuliaGraphs/GraphNeuralNetworks.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaGraphs/GraphNeuralNetworks.jl)


GraphNeuralNetworks.jl is a graph neural network library written in Julia and based on the deep learning framework [Flux.jl](https://github.com/FluxML/Flux.jl).
Expand All @@ -18,7 +18,7 @@ Among its features:
* Easy to define custom layers.
* CUDA support.
* Integration with [Graphs.jl](https://github.com/JuliaGraphs/Graphs.jl).
* [Examples](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/tree/master/examples) of node, edge, and graph level machine learning tasks.
* [Examples](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/examples) of node, edge, and graph level machine learning tasks.
* Heterogeneous and temporal graphs.

## Installation
Expand All @@ -31,7 +31,7 @@ pkg> add GraphNeuralNetworks

## Usage

Usage examples can be found in the [examples](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/tree/master/examples) and in the [notebooks](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/tree/master/notebooks) folder. Also, make sure to read the [documentation](https://CarloLucibello.github.io/GraphNeuralNetworks.jl/dev) for a comprehensive introduction to the library.
Usage examples can be found in the [examples](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/examples) and in the [notebooks](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/notebooks) folder. Also, make sure to read the [documentation](https://JuliaGraphs.github.io/GraphNeuralNetworks.jl/dev) for a comprehensive introduction to the library.


## Citing
Expand All @@ -43,7 +43,7 @@ If you use GraphNeuralNetworks.jl in a scientific publication, we would apprecia
author = {Carlo Lucibello and other contributors},
title = {GraphNeuralNetworks.jl: a geometric deep learning library for the Julia programming language},
year = 2021,
url = {https://github.com/CarloLucibello/GraphNeuralNetworks.jl}
url = {https://github.com/JuliaGraphs/GraphNeuralNetworks.jl}
}
```

Expand Down
7 changes: 3 additions & 4 deletions GraphNeuralNetworks/docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ makedocs(;
"Home" => "index.md",
"Developer guide" => "dev.md",
"Google Summer of Code" => "gsoc.md",


],
"GraphNeuralNetworks.jl" =>[
"Home" => "home.md",
Expand All @@ -38,7 +36,8 @@ makedocs(;
"Convolutional layers" => "api/conv.md",
"Pooling layers" => "api/pool.md",
"Temporal Convolutional layers" => "api/temporalconv.md",
"Hetero Convolutional layers" => "api/heteroconv.md"
"Hetero Convolutional layers" => "api/heteroconv.md",
"Samplers" => "api/samplers.md",


],
Expand All @@ -49,4 +48,4 @@ makedocs(;



deploydocs(;repo = "https://github.com/CarloLucibello/GraphNeuralNetworks.jl.git", dirname= "GraphNeuralNetworks")
deploydocs(;repo = "https://github.com/CarloLucibello/GraphNeuralNetworks.jl.git", dirname= "GraphNeuralNetworks")
14 changes: 14 additions & 0 deletions GraphNeuralNetworks/docs/src/api/samplers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```@meta
CurrentModule = GraphNeuralNetworks
```

# Samplers


## Docs

```@autodocs
Modules = [GraphNeuralNetworks]
Pages = ["samplers.jl"]
Private = false
```
9 changes: 9 additions & 0 deletions GraphNeuralNetworks/docs/src/datasets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Datasets

GraphNeuralNetworks.jl doesn't come with its own datasets, but leverages those available in the Julia (and non-Julia) ecosystem. In particular, the [examples in the GraphNeuralNetworks.jl repository](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/examples) make use of the [MLDatasets.jl](https://github.com/JuliaML/MLDatasets.jl) package. There you will find common graph datasets such as Cora, PubMed, Citeseer, TUDataset and [many others](https://juliaml.github.io/MLDatasets.jl/dev/datasets/graphs/).

GraphNeuralNetworks.jl provides the [`mldataset2gnngraph`](@ref) method for interfacing with MLDatasets.jl.

```@docs
mldataset2gnngraph
```
4 changes: 2 additions & 2 deletions GraphNeuralNetworks/docs/src/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ julia> compare(dfpr, dfmaster)

Tutorials in GraphNeuralNetworks.jl are written in Pluto and rendered using [DemoCards.jl](https://github.com/JuliaDocs/DemoCards.jl) and [PlutoStaticHTML.jl](https://github.com/rikhuijzer/PlutoStaticHTML.jl). Rendering a Pluto notebook is time and resource-consuming, especially in a CI environment. So we use the [caching functionality](https://huijzer.xyz/PlutoStaticHTML.jl/dev/#Caching) provided by PlutoStaticHTML.jl to reduce CI time.

If you are contributing a new tutorial or making changes to the existing notebook, generate the docs locally before committing/pushing. For caching to work, the cache environment(your local) and the documenter CI should have the same Julia version (e.g. "v1.9.1", also the patch number must match). So use the [documenter CI Julia version](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/blob/master/.github/workflows/docs.yml#L17) for generating docs locally.
If you are contributing a new tutorial or making changes to the existing notebook, generate the docs locally before committing/pushing. For caching to work, the cache environment(your local) and the documenter CI should have the same Julia version (e.g. "v1.9.1", also the patch number must match). So use the [documenter CI Julia version](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/blob/master/.github/workflows/docs.yml#L17) for generating docs locally.

```console
julia --version # check julia version before generating docs
Expand All @@ -95,6 +95,6 @@ During the doc generation process, DemoCards.jl stores the cache notebooks in do
git add docs/pluto_output # add generated cache
```

Check the [documenter CI logs](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/actions/workflows/docs.yml) to ensure that it used the local cache:
Check the [documenter CI logs](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/actions/workflows/docs.yml) to ensure that it used the local cache:

![](https://user-images.githubusercontent.com/55111154/210061301-c84b7274-9e66-46fd-b272-d45b1c681d00.png)
20 changes: 10 additions & 10 deletions GraphNeuralNetworks/docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# GraphNeuralNetworks Monorepo

This repository is a monorepo that contains all the code for the GraphNeuralNetworks project. The project is organized as a monorepo to facilitate code sharing and reusability across different components of the project. The monorepo contains the following packages:
This is the documentation page for [GraphNeuralNetworks.jl](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl), a graph neural network library written in Julia and based on the deep learning framework [Flux.jl](https://github.com/FluxML/Flux.jl).
GraphNeuralNetworks.jl is largely inspired by [PyTorch Geometric](https://pytorch-geometric.readthedocs.io/en/latest/), [Deep Graph Library](https://docs.dgl.ai/),
and [GeometricFlux.jl](https://fluxml.ai/GeometricFlux.jl/stable/).

- `GraphNeuralNetwork.jl`: Package that contains stateful graph convolutional layers based on the machine learning framework [Flux.jl](https://fluxml.ai/Flux.jl/stable/). This is fronted package for Flux users. It depends on GNNlib.jl, GNNGraphs.jl, and Flux.jl packages.

- `GNNLux.jl`: Package that contains stateless graph convolutional layers based on the machine learning framework [Lux.jl](https://lux.csail.mit.edu/stable/). This is fronted package for Lux users. It depends on GNNlib.jl, GNNGraphs.jl, and Lux.jl packages.

- `GNNlib.jl`: Package that contains the core graph neural network layers and utilities. It depends on GNNGraphs.jl and GNNlib.jl packages and serves for code base for GraphNeuralNetwork.jl and GNNLux.jl packages.

- `GNNGraphs.jl`: Package that contains the graph data structures and helper functions for working with graph data. It depends on Graphs.jl package.

Here is a schema of the dependencies between the packages:

![Monorepo schema](assets/schema.png)
* Implements common graph convolutional layers.
* Supports computations on batched graphs.
* Easy to define custom layers.
* CUDA support.
* Integration with [Graphs.jl](https://github.com/JuliaGraphs/Graphs.jl).
* [Examples](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/examples) of node, edge, and graph level machine learning tasks.




Usage examples on real datasets can be found in the [examples](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/examples) folder.

2 changes: 1 addition & 1 deletion GraphNeuralNetworks/docs/src/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ X = randn(Float32, din, 10)
y = model(X)
```

An example of `WithGraph` usage is given in the graph neural ODE script in the [examples](https://github.com/CarloLucibello/GraphNeuralNetworks.jl/tree/master/examples) folder.
An example of `WithGraph` usage is given in the graph neural ODE script in the [examples](https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/tree/master/examples) folder.
2 changes: 1 addition & 1 deletion GraphNeuralNetworks/notebooks/gnn_intro.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"\\mathbf{x}_i^{(\\ell + 1)} = f^{(\\ell + 1)}_{\\theta} \\left( \\mathbf{x}_i^{(\\ell)}, \\left\\{ \\mathbf{x}_j^{(\\ell)} : j \\in \\mathcal{N}(i) \\right\\} \\right)\n",
"$$\n",
"\n",
"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)**.\n",
"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/JuliaGraphs/GraphNeuralNetworks.jl)**.\n",
"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.\n",
"\n",
"Let's first import the packages we need:"
Expand Down
2 changes: 1 addition & 1 deletion GraphNeuralNetworks/notebooks/graph_classification.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@
"# Exercise 2 \n",
"\n",
"Define your own convolutional layer drawing inspiration from any of the already existing ones:\n",
"https://github.com/CarloLucibello/GraphNeuralNetworks.jl/blob/master/src/layers/conv.jl\n",
"https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/blob/master/src/layers/conv.jl\n",
"\n",
"You can try to:\n",
"- use MLPs instead of linear operators\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@
"# Exercise 2 \n",
"\n",
"Define your own convolutional layer drawing inspiration from any of the already existing ones:\n",
"https://github.com/CarloLucibello/GraphNeuralNetworks.jl/blob/master/src/layers/conv.jl\n",
"https://github.com/JuliaGraphs/GraphNeuralNetworks.jl/blob/master/src/layers/conv.jl\n",
"\n",
"You can try to:\n",
"- use MLPs instead of linear operators\n",
Expand Down
4 changes: 4 additions & 0 deletions GraphNeuralNetworks/src/GraphNeuralNetworks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ using NNlib: scatter, gather
using ChainRulesCore
using Reexport
using MLUtils: zeros_like
using Graphs: Graphs

using GNNGraphs: COO_T, ADJMAT_T, SPARSE_T,
check_num_nodes, check_num_edges,
Expand Down Expand Up @@ -66,4 +67,7 @@ export GlobalPool,

include("deprecations.jl")

include("samplers.jl")
export NeighborLoader

end
103 changes: 103 additions & 0 deletions GraphNeuralNetworks/src/samplers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""
NeighborLoader(graph; num_neighbors, input_nodes, num_layers, [batch_size])
A data structure for sampling neighbors from a graph for training Graph Neural Networks (GNNs).
It supports multi-layer sampling of neighbors for a batch of input nodes, useful for mini-batch training
originally introduced in "Inductive Representation Learning on Large Graphs" paper.
[see https://arxiv.org/abs/1706.02216]
# Fields
- `graph::GNNGraph`: The input graph.
- `num_neighbors::Vector{Int}`: A vector specifying the number of neighbors to sample per node at each GNN layer.
- `input_nodes::Vector{Int}`: A vector containing the starting nodes for neighbor sampling.
- `num_layers::Int`: The number of layers for neighborhood expansion (how far to sample neighbors).
- `batch_size::Union{Int, Nothing}`: The size of the batch. If not specified, it defaults to the number of `input_nodes`.
# Usage
```jldoctest
julia> loader = NeighborLoader(graph; num_neighbors=[10, 5], input_nodes=[1, 2, 3], num_layers=2)
julia> batch_counter = 0
julia> for mini_batch_gnn in loader
batch_counter += 1
println("Batch ", batch_counter, ": Nodes in mini-batch graph: ", nv(mini_batch_gnn))
```
"""
struct NeighborLoader
graph::GNNGraph # The input GNNGraph (graph + features from GraphNeuralNetworks.jl)
num_neighbors::Vector{Int} # Number of neighbors to sample per node, for each layer
input_nodes::Vector{Int} # Set of input nodes (starting nodes for sampling)
num_layers::Int # Number of layers for neighborhood expansion
batch_size::Union{Int, Nothing} # Optional batch size, defaults to the length of input_nodes if not given
neighbors_cache::Dict{Int, Vector{Int}} # Cache neighbors to avoid recomputation
end

function NeighborLoader(graph::GNNGraph; num_neighbors::Vector{Int}, input_nodes::Vector{Int}=nothing,
num_layers::Int, batch_size::Union{Int, Nothing}=nothing)
return NeighborLoader(graph, num_neighbors, input_nodes === nothing ? collect(1:graph.num_nodes) : input_nodes, num_layers,
batch_size === nothing ? length(input_nodes) : batch_size, Dict{Int, Vector{Int}}())
end

# Function to get cached neighbors or compute them
function get_neighbors(loader::NeighborLoader, node::Int)
if haskey(loader.neighbors_cache, node)
return loader.neighbors_cache[node]
else
neighbors = Graphs.neighbors(loader.graph, node, dir = :in) # Get neighbors from graph
loader.neighbors_cache[node] = neighbors
return neighbors
end
end

# Function to sample neighbors for a given node at a specific layer
function sample_nbrs(loader::NeighborLoader, node::Int, layer::Int)
neighbors = get_neighbors(loader, node)
if isempty(neighbors)
return Int[]
else
num_samples = min(loader.num_neighbors[layer], length(neighbors)) # Limit to required samples for this layer
return rand(neighbors, num_samples) # Randomly sample neighbors
end
end

# Iterator protocol for NeighborLoader with lazy batch loading
function Base.iterate(loader::NeighborLoader, state=1)
if state > length(loader.input_nodes)
return nothing # End of iteration if batches are exhausted (state larger than amount of input nodes or current batch no >= batch number)
end

# Determine the size of the current batch
batch_size = min(loader.batch_size, length(loader.input_nodes) - state + 1) # Conditional in case there is not enough nodes to fill the last batch
batch_nodes = loader.input_nodes[state:state + batch_size - 1] # Each mini-batch uses different set of input nodes

# Set for tracking the subgraph nodes
subgraph_nodes = Set(batch_nodes)

for node in batch_nodes
# Initialize current layer of nodes (starting with the node itself)
sampled_neighbors = Set([node])

# For each GNN layer, sample the neighborhood
for layer in 1:loader.num_layers
new_neighbors = Set{Int}()
for n in sampled_neighbors
neighbors = sample_nbrs(loader, n, layer) # Sample neighbors of the node for this layer
new_neighbors = union(new_neighbors, neighbors) # Avoid duplicates in the neighbor set
end
sampled_neighbors = new_neighbors
subgraph_nodes = union(subgraph_nodes, sampled_neighbors) # Expand the subgraph with the new neighbors
end
end

# Collect subgraph nodes and their features
subgraph_node_list = collect(subgraph_nodes)

if isempty(subgraph_node_list)
return GNNGraph(), state + batch_size
end

mini_batch_gnn = Graphs.induced_subgraph(loader.graph, subgraph_node_list) # Create a subgraph of the nodes

# Continue iteration for the next batch
return mini_batch_gnn, state + batch_size
end
1 change: 1 addition & 0 deletions GraphNeuralNetworks/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ tests = [
"layers/temporalconv",
"layers/pool",
"examples/node_classification_cora",
"samplers"
]

!CUDA.functional() && @warn("CUDA unavailable, not testing GPU support")
Expand Down
Loading

0 comments on commit 2b51334

Please sign in to comment.