Recently contacted with graph neural network, I feel that this device can provide multi granularity perspective. After abstracting the research object, we can classify the nodes, the edges and the whole graph. Graph neural network provides the ability to describe specific objects with multi granularity. It's pretty good to think about.

So we'll figure out the neural network.

At present, the theoretical learning routes of graph neural network are as follows:

- Basic knowledge of graph theory. This one is very familiar. You don't need to learn it.
- Linear algebra, especially the matrix form of Fourier transform. As long as I go back to the book, I read the theoretical basis of graph convolution network, which is actually the application of Fourier transform matrix form. This is very common in matrix analysis class, and it is not a new knowledge point. But to contact the graph neural network, this part needs to be mastered carefully!
- Knowledge of neural network.

After about one time "deep and simple map neural network", I feel almost the same, or mainly practice. So I wrote about practice.

# Figure neural network library

My library is DGL: https://docs.dgl.ai/index.html

GitHub address: https://github.com/dmlc/dgl

This library seems to have been written by New York University. In it, the common graph neural network model is realized, and the network is constructed directly like building blocks, and then the data can be constructed.

# Install DGL Library

Installation without cuda:

```
pip3 install dgl -i https://mirrors.aliyun.com/pypi/simple/
```

cuda10 installation:

```
python3 -m pip install dgl-cu100 -i https://mirrors.aliyun.com/pypi/simple/
```

By default, pytorch is used as the underlying neural network library in DGL

# course

## Add node, add edge, and visualization diagram

The edges in DGL are all directed edges. For undirected edges, the opposite edges can be created at the same time.

__author__ = 'dk' #Building diagrams, adding nodes and edges import networkx as nx import dgl import matplotlib.pyplot as plt #Build star chart u=[0,0,0,0,0] v=[1,2,3,4,5] #The first way is to array u and v. they are the same length star1 = dgl.DGLGraph((u,v)) nx.draw(star1.to_networkx(),with_labels=True)#Visualization chart plt.show() star2 = dgl.DGLGraph((0,v)) #For a star, it can be broadcast nx.draw(star2.to_networkx(),with_labels=True) plt.show() star3= dgl.DGLGraph([(0,1),(0,2),(0,3),(0,4),(0,5)]) #Direct enumeration nx.draw(star3.to_networkx(),with_labels=True) plt.show()

You can also add an edge later, instead of adding an edge in the constructor:

#You can also add an edge while composing, instead of adding an edge in the constructor g = dgl.DGLGraph()#This is a blank picture g.add_nodes(9)#When adding nodes, be sure to add nodes first and then add edges for i in range(1,8): g.add_edge(0,i) nx.draw(g.to_networkx(),with_labels=True) plt.show()

be careful! When edge (u,v) is added, u and v cannot exceed the maximum node ID that the network already has (the number of nodes is reduced by 1). For redundant nodes without access, DGL considers them isolated.

For example, node 8 is not connected to it.

## Assignment and extraction of node features

After the graph is established, the nodes can be characterized.

In DGL, the characteristics of nodes are treated as dictionaries. Users can get a token key for the characteristics of nodes_ Name. At the same time, users can define multiple features for a node at the same time.

For example, the star model above:

import numpy as np features = np.random.normal(0,1,(9,5)) #Random generation of a 9x5 normal distribution matrix print(features) g.ndata['features'] = features

Output:

[[-0.73241917 0.78738566 1.21160063 -0.83944648 -0.15739715] [-0.05520377 0.83418124 -0.68477259 -1.29054549 -1.2375015 ] [-0.23807425 -0.40030208 1.74318389 -0.70699831 -0.61449034] [-0.48597221 0.65284435 -0.27101916 -0.69242791 -0.83134013] [-0.00580359 1.29773141 1.28545031 -0.41703836 0.97254182] [-1.19173936 1.18409306 -0.24284504 -1.93560515 -1.1080128 ] [-0.4854841 0.06257814 -1.3432515 -0.53297016 -0.01270537] [-0.16906863 0.17349874 1.0057332 1.85554737 0.13355367] [-1.45619866 0.77784642 1.52454762 -0.86608947 0.28595569]]

The ndata attribute is short for node data. It's a dict.

Note that the number of rows in features needs to be consistent with the number of nodes currently owned by the graph.

Otherwise, an error is reported:

dgl._ffi.base.DGLError: Expect number of features to match number of nodes (len(u)). Got 7 and 9 instead.

Access node characteristics:

Directly g.ndata [feature name] [node ID] can:

For example: access to the characteristics of node 3

print(g.ndata['features'][3])

Output: the third line of features matrix

tensor([-0.4860, 0.6528, -0.2710, -0.6924, -0.8313], dtype=torch.float64)

Of course, you can modify the characteristics of a node:

g.ndata['features'][3]=th.zeros(1,5) print(g.ndata['features'][3])

Output:

tensor([0., 0., 0., 0., 0.], dtype=torch.float64)

It can be seen that DGL uses a tensor to store node features. The modification and access of node features are finally implemented to the modification and access of this matrix.

print(g.ndata)

Output:

{'features': tensor([[-0.4771, 1.7900, -1.1160, 0.2916, -0.7986], [-1.6190, -0.5006, -0.0437, 1.6412, -1.6979], [ 1.8872, 0.5236, 0.5123, -0.7658, -0.5050], [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000], [-0.3382, -0.4218, 0.8622, 1.1720, 0.3460], [-0.1710, 0.2713, -0.1639, -1.1159, -0.3623], [-0.9241, 1.2943, 0.1137, 1.5348, 0.1791], [-1.0372, 1.4145, -2.0653, -0.1469, -0.6041], [ 0.1035, -1.4215, 0.3288, -0.5195, -1.4120]], dtype=torch.float64)}

## Assignment, access and modification of edge features

Like node features, edges can specify features and access and modify features

Assignment:

g.edata['w']=th.randn(len(g.edges),2)

Note that the row function of the assignment matrix needs to be equal to the number of sides

To access the feature of an edge, you need to implement it to a row in the access edge matrix. And the line is the ID of the side.

So we need to determine what the ID of the side we are visiting is.

For example: get the ID of the (0,7) side:

g.edge_id(0,7)

Access the features of this edge:

g.edata(g.edge_id(0,7))

Then you can also delete features: This is actually a dictionary operation

g.ndata.pop('features') g.edata.pop('w')