前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文读懂Python复杂网络分析库networkx | CSDN博文精选

一文读懂Python复杂网络分析库networkx | CSDN博文精选

作者头像
AI科技大本营
发布2019-10-21 16:02:21
26.2K0
发布2019-10-21 16:02:21
举报
文章被收录于专栏:AI科技大本营的专栏
作者 | yyl424525

文章目录

1. 简介

  • 安装
  • 支持四种图
  • 绘制网络图基本流程

2. Graph-无向图

节点

属性

有向图和无向图互转

3. DiGraph-有向图

  • 一些精美的图例子
  • 环形树状图
  • 权重图
  • Giant Component
  • Random Geometric Graph 随机几何图
  • 节点颜色渐变
  • 边的颜色渐变
  • Atlas
  • 画个五角星
  • Club
  • 画一个多层感知机
  • 绘制一个DNN结构图
  • 一些图论算法
  • 最短路径

4. 问题

  • 一些其他神经网络绘制工具列表

5. 参考

1 简介

networkx是一个用Python语言开发的图论与复杂网络建模工具,内置了常用的图与复杂网络分析算法,可以方便的进行复杂网络数据分析、仿真建模等工作。

利用networkx可以以标准化和非标准化的数据格式存储网络、生成多种随机网络和经典网络、分析网络结构、建立网络模型、设计新的网络算法、进行网络绘制等。

networkx支持创建简单无向图、有向图和多重图(multigraph);内置许多标准的图论算法,节点可为任意数据;支持任意的边值维度,功能丰富,简单易用。

networkx以图(graph)为基本数据结构。图既可以由程序生成,也可以来自在线数据源,还可以从文件与数据库中读取。

安装

安装的话,跟其他包的安装差不多,用的是anaconda就不用装了。其他就用pip install networkx。

查看版本:

代码语言:javascript
复制
1>>> import networkx
2>>> networkx.__version__
3'1.11'

升级

代码语言:javascript
复制
1pip install --upgrade networkx

下面配合使用的一些库,可以选择性安装: 后面可能用到pygraphviz,安装方法如下(亲测有效):

代码语言:javascript
复制
1sudo apt-get install graphviz
2sudo apt-get install graphviz libgraphviz-dev pkg-config
3sudo apt-get install python-pip python-virtualenv
4pip install pygraphviz

windows的安装参考这篇博客:https://blog.csdn.net/fadai1993/article/details/82491657#2____linux_9

安装cv2:

代码语言:javascript
复制
1pip install opencv-python #安装非常慢,用下面的方式,从清华源下载
2pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

支持四种图

  • Graph:无多重边无向图
  • DiGraph:无多重边有向图
  • MultiGraph:有多重边无向图
  • MultiDiGraph:有多重边有向图

空图对象的创建方式

代码语言:javascript
复制
1import networkx as nx
2G=nx.Graph()
3G=nx.DiGraph()
4G=nx.MultiGraph()
5G=nx.MultiDiGraph()
6G.clear() #清空图

绘制网络图基本流程

  • 导入networkx,matplotlib包
  • 建立网络
  • 绘制网络 nx.draw()
  • 建立布局 pos = nx.spring_layout美化作用

最基本画图程序

代码语言:javascript
复制
1import import networkx as nx             #导入networkx包
2import matplotlib.pyplot as plt 
3G = nx.random_graphs.barabasi_albert_graph(100,1)   #生成一个BA无标度网络G
4nx.draw(G)                               #绘制网络G
5plt.savefig("ba.png")           #输出方式1: 将图像存为一个png格式的图片文件
6plt.show()                            #输出方式2: 在窗口中显示这幅图像 

networkx 提供画图的函数

代码语言:javascript
复制
 1draw(G,[pos,ax,hold])
 2draw_networkx(G,[pos,with_labels])
 3draw_networkx_nodes(G,pos,[nodelist])绘制网络G的节点图
 4draw_networkx_edges(G,pos[edgelist])绘制网络G的边图
 5draw_networkx_edge_labels(G, pos[, …]) 绘制网络G的边图,边有label
 6—有layout 布局画图函数的分界线—
 7draw_circular(G, **kwargs) Draw the graph G with a circular layout.
 8draw_random(G, **kwargs) Draw the graph G with a random layout.
 9draw_spectral(G, **kwargs)Draw the graph G with a spectral layout.
10draw_spring(G, **kwargs)Draw the graph G with a spring layout.
11draw_shell(G, **kwargs) Draw networkx graph with shell layout.
12draw_graphviz(G[, prog])Draw networkx graph with graphviz layout.

networkx 画图函数里的一些参数

  • pos(dictionary, optional): 图像的布局,可选择参数;如果是字典元素,则节点是关键字,位置是对应的值。如果没有指明,则会是spring的布局;也可以使用其他类型的布局,具体可以查阅networkx.layout
  • arrows :布尔值,默认True; 对于有向图,如果是True则会画出箭头
  • with_labels: 节点是否带标签(默认为True)
  • ax:坐标设置,可选择参数;依照设置好的Matplotlib坐标画图
  • nodelist:一个列表,默认G.nodes(); 给定节点
  • edgelist:一个列表,默认G.edges();给定边
  • node_size: 指定节点的尺寸大小(默认是300,单位未知,就是上图中那么大的点)
  • node_color: 指定节点的颜色 (默认是红色,可以用字符串简单标识颜色,例如’r’为红色,'b’为绿色等,具体可查看手册),用“数据字典”赋值的时候必须对字典取值(.values())后再赋值
  • node_shape: 节点的形状(默认是圆形,用字符串’o’标识,具体可查看手册)
  • alpha: 透明度 (默认是1.0,不透明,0为完全透明)
  • cmap:Matplotlib的颜色映射,默认None; 用来表示节点对应的强度
  • vmin,vmax:浮点数,默认None;节点颜色映射尺度的最大和最小值
  • linewidths:[None|标量|一列值];图像边界的线宽
  • width: 边的宽度 (默认为1.0)
  • edge_color: 边的颜色(默认为黑色)
  • edge_cmap:Matplotlib的颜色映射,默认None; 用来表示边对应的强度
  • edge_vmin,edge_vmax:浮点数,默认None;边的颜色映射尺度的最大和最小值
  • style: 边的样式(默认为实现,可选:solid|dashed|dotted,dashdot)
  • labels:字典元素,默认None;文本形式的节点标签
  • font_size: 节点标签字体大小 (默认为12)
  • font_color: 节点标签字体颜色(默认为黑色)
  • node_size:节点大小
  • font_weight:字符串,默认’normal’
  • font_family:字符串,默认’sans-serif’

布局指定节点排列形式

  • circular_layout:节点在一个圆环上均匀分布
  • random_layout:节点随机分布shell_layout:节点在同心圆上分布
  • spring_layout:用Fruchterman-Reingold算法排列节点,中心放射状分布
  • spectral_layout:根据图的拉普拉斯特征向量排列节点
  • 布局也可用pos参数指定,例如,nx.draw(G, pos = spring_layout(G)) 这样指定了networkx上以中心放射状分布.

2 Graph-无向图

如果添加的节点和边是已经存在的,是不会报错的,NetworkX会自动忽略掉已经存在的边和节点的添加。

节点

常用函数

  • nodes(G):在图节点上返回一个迭代器
  • number_of_nodes(G):返回图中节点的数量
  • all_neighbors(graph, node):返回图中节点的所有邻居
  • non_neighbors(graph, node):返回图中没有邻居的节点
  • common_neighbors(G, u, v):返回图中两个节点的公共邻居
代码语言:javascript
复制
 1import networkx as nx
 2import matplotlib.pyplot as plt
 3G = nx.Graph()  # 建立一个空的无向图G
 4#增加节点
 5G.add_node('a')  # 添加一个节点1
 6G.add_nodes_from(['b', 'c', 'd', 'e'])  # 加点集合
 7G.add_cycle(['f', 'g', 'h', 'j'])  # 加环
 8H = nx.path_graph(10)  # 返回由10个节点的无向图
 9G.add_nodes_from(H)  # 创建一个子图H加入G
10G.add_node(H)  # 直接将图作为节点
11
12nx.draw(G, with_labels=True,node_color='red')
13plt.show()
14
15#访问节点
16print('图中所有的节点', G.nodes())
17#图中所有的节点 [0, 1, 2, 3, 'a', 'c', 'f', 7, 8, 9, <networkx.classes.graph.Graph object at 0x7fdf7d0d2780>, 'g', 'e', 'h', 'b', 4, 6, 5, 'j', 'd']
18
19print('图中节点的个数', G.number_of_nodes())
20#图中节点的个数 20
21
22#删除节点
23G.remove_node(1)    #删除指定节点
24G.remove_nodes_from(['b','c','d','e'])    #删除集合中的节点

边常用函数

  • edges(G[, nbunch]):返回与nbunch中的节点相关的边的视图
  • number_of_edges(G):返回图中边的数目
  • non_edges(graph):返回图中不存在的边
代码语言:javascript
复制
 1import networkx as nx
 2import matplotlib.pyplot as plt
 3
 4#添加边方法1
 5
 6F = nx.Graph() # 创建无向图
 7F.add_edge(11,12)   #一次添加一条边
 8
 9#添加边方法2
10e=(13,14)        #e是一个元组
11F.add_edge(*e) #这是python中解包裹的过程
12
13#添加边方法3
14F.add_edges_from([(1,2),(1,3)])     #通过添加list来添加多条边
15
16H = nx.path_graph(10)          #返回由10个节点的无向图
17#通过添加任何ebunch来添加边
18F.add_edges_from(H.edges()) #不能写作F.add_edges_from(H)
19
20nx.draw(F, with_labels=True)
21plt.show()
22
23#访问边
24print('图中所有的边', F.edges())
25# 图中所有的边 [(0, 1), (1, 2), (1, 3), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (11, 12), (13, 14)]
26
27print('图中边的个数', F.number_of_edges()) 
28# 图中边的个数 12
29
30
31
32#删除边
33F.remove_edge(1,2)
34F.remove_edges_from([(11,12), (13,14)])
35
36nx.draw(F, with_labels=True)
37plt.show()

使用邻接迭代器遍历每一条边

代码语言:javascript
复制
 1import networkx as nx
 2import matplotlib.pyplot as plt
 3
 4#快速遍历每一条边,可以使用邻接迭代器实现,对于无向图,每一条边相当于两条有向边
 5FG = nx.Graph()
 6FG.add_weighted_edges_from([(1,2,0.125), (1,3,0.75), (2,4,1.2), (3,4,0.275)])
 7for n, nbrs in FG.adjacency_iter():
 8    for nbr, eattr in nbrs.items():
 9        data = eattr['weight']
10        print('(%d, %d, %0.3f)' % (n,nbr,data))
11        # (1, 2, 0.125)
12        # (1, 3, 0.750)
13        # (2, 1, 0.125)
14        # (2, 4, 1.200)
15        # (3, 1, 0.750)
16        # (3, 4, 0.275)
17        # (4, 2, 1.200)
18        # (4, 3, 0.275)
19
20print('***********************************')
21
22#筛选weight小于0.5的边:
23FG = nx.Graph()
24FG.add_weighted_edges_from([(1,2,0.125), (1,3,0.75), (2,4,1.2), (3,4,0.275)])
25for n, nbrs in FG.adjacency_iter():
26    for nbr, eattr in nbrs.items():
27        data = eattr['weight']
28        if data < 0.5:
29            print('(%d, %d, %0.3f)' % (n,nbr,data))
30            # (1, 2, 0.125)
31            # (2, 1, 0.125)
32            # (3, 4, 0.275)
33            # (4, 3, 0.275)
34
35print('***********************************')
36
37#一种方便的访问所有边的方法:
38for u,v,d in FG.edges(data = 'weight'):
39    print((u,v,d))
40    # (1, 2, 0.125)
41    # (1, 3, 0.75)
42    # (2, 4, 1.2)
43    # (3, 4, 0.275)

属性

属性诸如weight,labels,colors,或者任何对象,都可以附加到图、节点或边上。

对于每一个图、节点和边都可以在关联的属性字典中保存一个(多个)键-值对。

默认情况下这些是一个空的字典,但是可以增加或者是改变这些属性。

图的属性

代码语言:javascript
复制
 1#图的属性
 2
 3import networkx as nx
 4
 5G = nx.Graph(day='Monday')    #可以在创建图时分配图的属性
 6print(G.graph)
 7
 8G.graph['day'] = 'Friday'     #也可以修改已有的属性
 9print(G.graph)
10
11G.graph['name'] = 'time'      #可以随时添加新的属性到图中
12print(G.graph)
13
14输出:
15{'day': 'Monday'}
16{'day': 'Friday'}
17{'day': 'Friday', 'name': 'time'}

节点的属性

代码语言:javascript
复制
 1#节点的属性
 2import networkx as nx
 3
 4G = nx.Graph(day='Monday')
 5G.add_node(1, index='1th')             #在添加节点时分配节点属性
 6# print(G.node(data=True))  #TypeError: 'dict' object is not callable
 7print(G.node) 
 8#{1: {'index': '1th'}}
 9
10
11G.node[1]['index'] = '0th'             #通过G.node[][]来添加或修改属性
12print(G.node)
13# {1: {'index': '0th'}}
14
15
16G.add_nodes_from([2,3], index='2/3th') #从集合中添加节点时分配属性
17print(G.node)
18# {1: {'index': '0th'}, 2: {'index': '2/3th'}, 3: {'index': '2/3th'}}

边的属性

代码语言:javascript
复制
 1#边的属性
 2import networkx as nx
 3
 4G = nx.Graph(day='manday')
 5G.add_edge(1,2,weight=10)                    #在添加边时分配属性
 6print(G.edges(data=True))
 7#[(1, 2, {'weight': 10})]
 8
 9G.add_edges_from([(1,3), (4,5)], len=22)     #从集合中添加边时分配属性
10print(G.edges(data='len'))
11# [(1, 2, None), (1, 3, 22), (4, 5, 22)]
12
13G.add_edges_from([(3,4,{'hight':10}),(1,4,{'high':'unknow'})])
14print(G.edges(data=True))
15# [(1, 2, {'weight': 10}), (1, 3, {'len': 22}), (1, 4, {'high': 'unknow'}), (3, 4, {'hight': 10}), (4, 5, {'len': 22})]
16
17
18G[1][2]['weight'] = 100000                   #通过G[][][]来添加或修改属性
19print(G.edges(data=True))
20# [(1, 2, {'weight': 100000}), (1, 3, {'len': 22}), (1, 4, {'high': 'unknow'}), (3, 4, {'hight': 10}), (4, 5, {'len': 22})]

有向图和无向图互转

有向图和多重图的基本操作与无向图一致。

无向图与有向图之间可以相互转换,转化方法如下:

代码语言:javascript
复制
 1#有向图转化成无向图
 2
 3H=DG.to_undirected()
 4#或者
 5H=nx.Graph(DG)
 6
 7#无向图转化成有向图
 8
 9F = H.to_directed()
10#或者
11F = nx.DiGraph(H)

3、DiGraph-有向图

代码语言:javascript
复制
 1import networkx as nx
 2import matplotlib.pyplot as plt
 3
 4G = nx.DiGraph()
 5G.add_node(1)
 6G.add_node(2)
 7G.add_nodes_from([3,4,5,6])
 8G.add_cycle([1,2,3,4])
 9G.add_edge(1,3)
10G.add_edges_from([(3,5),(3,6),(6,7)])
11nx.draw(G,node_color = 'red')
12plt.savefig("youxiangtu.png")
13plt.show()
代码语言:javascript
复制
 1from __future__ import division
 2import matplotlib.pyplot as plt
 3import networkx as nx
 4
 5G = nx.generators.directed.random_k_out_graph(10, 3, 0.5)
 6pos = nx.layout.spring_layout(G)
 7
 8node_sizes = [3 + 10 * i for i in range(len(G))]
 9M = G.number_of_edges()
10edge_colors = range(2, M + 2)
11edge_alphas = [(5 + i) / (M + 4) for i in range(M)]
12
13nodes = nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color='blue')
14edges = nx.draw_networkx_edges(G, pos, node_size=node_sizes, arrowstyle='->',
15                               arrowsize=10, edge_color=edge_colors,
16                               edge_cmap=plt.cm.Blues, width=2)
17# set alpha value for each edge
18for i in range(M):
19    edges[i].set_alpha(edge_alphas[i])
20
21ax = plt.gca()
22ax.set_axis_off()
23plt.savefig("directed.jpg")
24plt.show()

一些精美的图例子

环形树状图

代码语言:javascript
复制
 1import matplotlib.pyplot as plt
 2import networkx as nx
 3
 4try:
 5    import pygraphviz
 6    from networkx.drawing.nx_agraph import graphviz_layout
 7except ImportError:
 8    try:
 9        import pydot
10        from networkx.drawing.nx_pydot import graphviz_layout
11    except ImportError:
12        raise ImportError("This example needs Graphviz and either "
13                          "PyGraphviz or pydot")
14
15G = nx.balanced_tree(3, 5)
16pos = graphviz_layout(G, prog='twopi', args='')
17plt.figure(figsize=(8, 8))
18nx.draw(G, pos, node_size=20, alpha=0.5, node_color="blue", with_labels=False)
19plt.axis('equal')
20plt.show()

权重图

代码语言:javascript
复制
 1import matplotlib.pyplot as plt
 2import networkx as nx
 3
 4G = nx.Graph()
 5
 6G.add_edge('a', 'b', weight=0.6)
 7G.add_edge('a', 'c', weight=0.2)
 8G.add_edge('c', 'd', weight=0.1)
 9G.add_edge('c', 'e', weight=0.7)
10G.add_edge('c', 'f', weight=0.9)
11G.add_edge('a', 'd', weight=0.3)
12
13elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]
14esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]
15
16pos = nx.spring_layout(G)  # positions for all nodes
17
18# nodes
19nx.draw_networkx_nodes(G, pos, node_size=700)
20
21# edges
22nx.draw_networkx_edges(G, pos, edgelist=elarge,
23                       width=6)
24nx.draw_networkx_edges(G, pos, edgelist=esmall,
25                       width=6, alpha=0.5, edge_color='b', style='dashed')
26
27# labels
28nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')
29
30plt.axis('off')
31plt.savefig("weight.jpg")
32plt.show()

Giant Component

代码语言:javascript
复制
 1import math
 3
 4import matplotlib.pyplot as plt
 5import networkx as nx
 6
 7try:
 8    import pygraphviz
 9    from networkx.drawing.nx_agraph import graphviz_layout
10    layout = graphviz_layout
11except ImportError:
12    try:
13        import pydot
14        from networkx.drawing.nx_pydot import graphviz_layout
15        layout = graphviz_layout
16    except ImportError:
17        print("PyGraphviz and pydot not found;\n"
18              "drawing with spring layout;\n"
19              "will be slow.")
20        layout = nx.spring_layout
21
22n = 150  # 150 nodes
23# p value at which giant component (of size log(n) nodes) is expected
24p_giant = 1.0 / (n - 1)
25# p value at which graph is expected to become completely connected
26p_conn = math.log(n) / float(n)
27
28# the following range of p values should be close to the threshold
29pvals = [0.003, 0.006, 0.008, 0.015]
30
31region = 220  # for pylab 2x2 subplot layout
32plt.subplots_adjust(left=0, right=1, bottom=0, top=0.95, wspace=0.01, hspace=0.01)
33for p in pvals:
34    G = nx.binomial_graph(n, p)
35    pos = layout(G)
36    region += 1
37    plt.subplot(region)
38    plt.title("p = %6.3f" % (p))
39    nx.draw(G, pos,
40            with_labels=False,
41            node_size=10
42           )
43    # identify largest connected component
44    Gcc = sorted(nx.connected_component_subgraphs(G), key=len, reverse=True)
45    G0 = Gcc[0]
46    nx.draw_networkx_edges(G0, pos,
47                           with_labels=False,
48                           edge_color='r',
49                           width=6.0
50                          )
51    # show other connected components
52    for Gi in Gcc[1:]:
53        if len(Gi) > 1:
54            nx.draw_networkx_edges(Gi, pos,
55                                   with_labels=False,
56                                   edge_color='r',
57                                   alpha=0.3,
58                                   width=5.0
59                                  )
60plt.show()

Random Geometric Graph 随机几何图

代码语言:javascript
复制
 1import matplotlib.pyplot as plt
 2import networkx as nx
 3
 4G = nx.random_geometric_graph(200, 0.125)
 5# position is stored as node attribute data for random_geometric_graph
 6pos = nx.get_node_attributes(G, 'pos')
 7
 8# find node near center (0.5,0.5)
 9dmin = 1
10ncenter = 0
11for n in pos:
12    x, y = pos[n]
13    d = (x - 0.5)**2 + (y - 0.5)**2
14    if d < dmin:
15        ncenter = n
16        dmin = d
17
18# color by path length from node near center
19p = dict(nx.single_source_shortest_path_length(G, ncenter))
20
21plt.figure(figsize=(8, 8))
22nx.draw_networkx_edges(G, pos, nodelist=[ncenter], alpha=0.4)
23nx.draw_networkx_nodes(G, pos, nodelist=list(p.keys()),
24                       node_size=80,
25                       node_color=list(p.values()),
26                       cmap=plt.cm.Reds_r)
27
28plt.xlim(-0.05, 1.05)
29plt.ylim(-0.05, 1.05)
30#plt.axis('off')
31plt.show()

节点颜色渐变

代码语言:javascript
复制
1import networkx as nx
2import matplotlib.pyplot as plt
3G = nx.cycle_graph(24)
4pos = nx.spring_layout(G, iterations=200)
5nx.draw(G, pos, node_color=range(24), node_size=800, cmap=plt.cm.Blues)
6plt.savefig("node.jpg")
7plt.show()

边的颜色渐变

代码语言:javascript
复制
1import matplotlib.pyplot as plt
2import networkx as nx
3
4G = nx.star_graph(20)
5pos = nx.spring_layout(G) #布局为中心放射状
6colors = range(20)
7nx.draw(G, pos, node_color='#A0CBE2', edge_color=colors,
8        width=4, edge_cmap=plt.cm.Blues, with_labels=False)
9plt.show()

Atlas

代码语言:javascript
复制
 1import random
 2
 3try:
 4    import pygraphviz
 5    from networkx.drawing.nx_agraph import graphviz_layout
 6except ImportError:
 7    try:
 8        import pydot
 9        from networkx.drawing.nx_pydot import graphviz_layout
10    except ImportError:
11        raise ImportError("This example needs Graphviz and either "
12                          "PyGraphviz or pydot.")
13
14import matplotlib.pyplot as plt
15
16import networkx as nx
17from networkx.algorithms.isomorphism.isomorph import graph_could_be_isomorphic as isomorphic
18from networkx.generators.atlas import graph_atlas_g
19
20
21def atlas6():
22    """ Return the atlas of all connected graphs of 6 nodes or less.
23        Attempt to check for isomorphisms and remove.
24    """
25
26    Atlas = graph_atlas_g()[0:208]  # 208
27    # remove isolated nodes, only connected graphs are left
28    U = nx.Graph()  # graph for union of all graphs in atlas
29    for G in Atlas:
30        zerodegree = [n for n in G if G.degree(n) == 0]
31        for n in zerodegree:
32            G.remove_node(n)
33        U = nx.disjoint_union(U, G)
34
35    # iterator of graphs of all connected components
36    C = (U.subgraph(c) for c in nx.connected_components(U))
37
38    UU = nx.Graph()
39    # do quick isomorphic-like check, not a true isomorphism checker
40    nlist = []  # list of nonisomorphic graphs
41    for G in C:
42        # check against all nonisomorphic graphs so far
43        if not iso(G, nlist):
44            nlist.append(G)
45            UU = nx.disjoint_union(UU, G)  # union the nonisomorphic graphs
46    return UU
47
48
49def iso(G1, glist):
50    """Quick and dirty nonisomorphism checker used to check isomorphisms."""
51    for G2 in glist:
52        if isomorphic(G1, G2):
53            return True
54    return False
55
56
57if __name__ == '__main__':
58    G = atlas6()
59
60    print("graph has %d nodes with %d edges"
61          % (nx.number_of_nodes(G), nx.number_of_edges(G)))
62    print(nx.number_connected_components(G), "connected components")
63
64    plt.figure(1, figsize=(8, 8))
65    # layout graphs with positions using graphviz neato
66    pos = graphviz_layout(G, prog="neato")
67    # color nodes the same in each connected subgraph
68    C = (G.subgraph(c) for c in nx.connected_components(G))
69    for g in C:
70        c = [random.random()] * nx.number_of_nodes(g)  # random color...
71        nx.draw(g,
72                pos,
73                node_size=40,
74                node_color=c,
75                vmin=0.0,
76                vmax=1.0,
77                with_labels=False
78               )
79    plt.show()

画个五角星

代码语言:javascript
复制
 1import networkx as nx
 2import matplotlib.pyplot as plt
 3#画图!
 4G=nx.Graph()
 5G.add_node(1)
 6G.add_nodes_from([2,3,4,5])
 7for i in range(5):
 8    for j in range(i):
 9        if (abs(i-j) not in (1,4)):
10            G.add_edge(i+1, j+1)
11nx.draw(G,
12        with_labels=True, #这个选项让节点有名称
13        edge_color='b', # b stands for blue!
14        pos=nx.circular_layout(G), # 这个是选项选择点的排列方式,具体可以用 help(nx.drawing.layout) 查看
15     # 主要有spring_layout  (default), random_layout, circle_layout, shell_layout
16     # 这里是环形排布,还有随机排列等其他方式
17        node_color='r', # r = red
18        node_size=1000, # 节点大小
19        width=3, # 边的宽度
20       )
21plt.savefig("star.jpg")
22plt.show()

Club

代码语言:javascript
复制
 1import matplotlib.pyplot as plt
 2import networkx as nx
 3import networkx.algorithms.bipartite as bipartite
 4
 5G = nx.davis_southern_women_graph()
 6women = G.graph['top']
 7clubs = G.graph['bottom']
 8
 9print("Biadjacency matrix")
10print(bipartite.biadjacency_matrix(G, women, clubs))
11
12# project bipartite graph onto women nodes
13W = bipartite.projected_graph(G, women)
14print('')
15print("#Friends, Member")
16for w in women:
17    print('%d %s' % (W.degree(w), w))
18
19# project bipartite graph onto women nodes keeping number of co-occurence
20# the degree computed is weighted and counts the total number of shared contacts
21W = bipartite.weighted_projected_graph(G, women)
22print('')
23print("#Friend meetings, Member")
24for w in women:
25    print('%d %s' % (W.degree(w, weight='weight'), w))
26
27nx.draw(G,node_color="red")
28plt.savefig("club.jpg")
29plt.show()

画一个多层感知机

代码语言:javascript
复制
 1import matplotlib.pyplot as plt
 2import networkx as nx
 3left, right, bottom, top, layer_sizes = .1, .9, .1, .9, [4, 7, 7, 2]
 4# 网络离上下左右的距离
 5# layter_sizes可以自己调整
 6import random
 7G = nx.Graph()
 8v_spacing = (top - bottom)/float(max(layer_sizes))
 9h_spacing = (right - left)/float(len(layer_sizes) - 1)
10node_count = 0
11for i, v in enumerate(layer_sizes):
12    layer_top = v_spacing*(v-1)/2. + (top + bottom)/2.
13    for j in range(v):
14        G.add_node(node_count, pos=(left + i*h_spacing, layer_top - j*v_spacing))
15        node_count += 1
16# 这上面的数字调整我想了好半天,汗
17for x, (left_nodes, right_nodes) in enumerate(zip(layer_sizes[:-1], layer_sizes[1:])):
18    for i in range(left_nodes):
19        for j in range(right_nodes):
20            G.add_edge(i+sum(layer_sizes[:x]), j+sum(layer_sizes[:x+1]))
21
22pos=nx.get_node_attributes(G,'pos')
23# 把每个节点中的位置pos信息导出来
24nx.draw(G, pos,
25        node_color=range(node_count),
26        with_labels=True,
27        node_size=200,
28        edge_color=[random.random() for i in range(len(G.edges))],
29        width=3,
30        cmap=plt.cm.Dark2, # matplotlib的调色板,可以搜搜,很多颜色
31        edge_cmap=plt.cm.Blues
32       )
33plt.savefig("mlp.jpg")
34plt.show()

绘制一个DNN结构图

代码语言:javascript
复制
 1# -*- coding:utf-8 -*-
 2import networkx as nx
 3import matplotlib.pyplot as plt
 4
 5# 创建DAG
 6G = nx.DiGraph()
 7
 8# 顶点列表
 9vertex_list = ['v'+str(i) for i in range(1, 22)]
10# 添加顶点
11G.add_nodes_from(vertex_list)
12
13# 边列表
14edge_list = [
15             ('v1', 'v5'), ('v1', 'v6'), ('v1', 'v7'),('v1', 'v8'),('v1', 'v9'),
16             ('v2', 'v5'), ('v2', 'v6'), ('v2', 'v7'),('v2', 'v8'),('v2', 'v9'),
17             ('v3', 'v5'), ('v3', 'v6'), ('v3', 'v7'),('v3', 'v8'),('v3', 'v9'),
18             ('v4', 'v5'), ('v4', 'v6'), ('v4', 'v7'),('v4', 'v8'),('v4', 'v9'),
19             ('v5','v10'),('v5','v11'),('v5','v12'),('v5','v13'),('v5','v14'),('v5','v15'),
20             ('v6','v10'),('v6','v11'),('v6','v12'),('v6','v13'),('v6','v14'),('v6','v15'),
21             ('v7','v10'),('v7','v11'),('v7','v12'),('v7','v13'),('v7','v14'),('v7','v15'),
22             ('v8','v10'),('v8','v11'),('v8','v12'),('v8','v13'),('v8','v14'),('v8','v15'),
23             ('v9','v10'),('v9','v11'),('v9','v12'),('v9','v13'),('v9','v14'),('v9','v15'),
24             ('v10','v16'),('v10','v17'),('v10','v18'),
25             ('v11','v16'),('v11','v17'),('v11','v18'),
26             ('v12','v16'),('v12','v17'),('v12','v18'),
27             ('v13','v16'),('v13','v17'),('v13','v18'),
28             ('v14','v16'),('v14','v17'),('v14','v18'),
29             ('v15','v16'),('v15','v17'),('v15','v18'),
30             ('v16','v19'),
31             ('v17','v20'),
32             ('v18','v21')
33            ]
34# 通过列表形式来添加边
35G.add_edges_from(edge_list)
36
37# 绘制DAG图
38plt.title('DNN for iris')    #图片标题
39
40nx.draw(
41        G,
42        node_color = 'red',             # 顶点颜色
43        edge_color = 'black',           # 边的颜色
44        with_labels = True,             # 显示顶点标签
45        font_size =10,                  # 文字大小
46        node_size =300                  # 顶点大小
47       )
48# 显示图片
49plt.show()

可以看到,在代码中已经设置好了这22个神经元以及它们之间的连接情况,但绘制出来的结构如却是这样的:

这显然不是想要的结果,因为各神经的连接情况不明朗,而且很多神经都挤在了一起,看不清楚。之所以出现这种情况,是因为没有给神经元设置坐标,导致每个神经元都是随机放置的。

接下来,引入坐标机制,即设置好每个神经元节点的坐标,使得它们的位置能够按照事先设置好的来放置,其Python代码如下:

代码语言:javascript
复制
 1# -*- coding:utf-8 -*-
 2import networkx as nx
 3import matplotlib.pyplot as plt
 4
 5# 创建DAG
 6G = nx.DiGraph()
 7
 8# 顶点列表
 9vertex_list = ['v'+str(i) for i in range(1, 22)]
10# 添加顶点
11G.add_nodes_from(vertex_list)
12
13# 边列表
14edge_list = [
15             ('v1', 'v5'), ('v1', 'v6'), ('v1', 'v7'),('v1', 'v8'),('v1', 'v9'),
16             ('v2', 'v5'), ('v2', 'v6'), ('v2', 'v7'),('v2', 'v8'),('v2', 'v9'),
17             ('v3', 'v5'), ('v3', 'v6'), ('v3', 'v7'),('v3', 'v8'),('v3', 'v9'),
18             ('v4', 'v5'), ('v4', 'v6'), ('v4', 'v7'),('v4', 'v8'),('v4', 'v9'),
19             ('v5','v10'),('v5','v11'),('v5','v12'),('v5','v13'),('v5','v14'),('v5','v15'),
20             ('v6','v10'),('v6','v11'),('v6','v12'),('v6','v13'),('v6','v14'),('v6','v15'),
21             ('v7','v10'),('v7','v11'),('v7','v12'),('v7','v13'),('v7','v14'),('v7','v15'),
22             ('v8','v10'),('v8','v11'),('v8','v12'),('v8','v13'),('v8','v14'),('v8','v15'),
23             ('v9','v10'),('v9','v11'),('v9','v12'),('v9','v13'),('v9','v14'),('v9','v15'),
24             ('v10','v16'),('v10','v17'),('v10','v18'),
25             ('v11','v16'),('v11','v17'),('v11','v18'),
26             ('v12','v16'),('v12','v17'),('v12','v18'),
27             ('v13','v16'),('v13','v17'),('v13','v18'),
28             ('v14','v16'),('v14','v17'),('v14','v18'),
29             ('v15','v16'),('v15','v17'),('v15','v18'),
30             ('v16','v19'),
31             ('v17','v20'),
32             ('v18','v21')
33            ]
34# 通过列表形式来添加边
35G.add_edges_from(edge_list)
36
37# 指定绘制DAG图时每个顶点的位置
38pos = {
39        'v1':(-2,1.5),
40        'v2':(-2,0.5),
41        'v3':(-2,-0.5),
42        'v4':(-2,-1.5),
43        'v5':(-1,2),
44        'v6': (-1,1),
45        'v7':(-1,0),
46        'v8':(-1,-1),
47        'v9':(-1,-2),
48        'v10':(0,2.5),
49        'v11':(0,1.5),
50        'v12':(0,0.5),
51        'v13':(0,-0.5),
52        'v14':(0,-1.5),
53        'v15':(0,-2.5),
54        'v16':(1,1),
55        'v17':(1,0),
56        'v18':(1,-1),
57        'v19':(2,1),
58        'v20':(2,0),
59        'v21':(2,-1)
60       }
61# 绘制DAG图
62plt.title('DNN for iris')    #图片标题
63plt.xlim(-2.2, 2.2)                     #设置X轴坐标范围
64plt.ylim(-3, 3)                     #设置Y轴坐标范围
65nx.draw(
66        G,
67        pos = pos,                      # 点的位置
68        node_color = 'red',             # 顶点颜色
69        edge_color = 'black',           # 边的颜色
70        with_labels = True,             # 显示顶点标签
71        font_size =10,                  # 文字大小
72        node_size =300                  # 顶点大小
73       )
74# 显示图片
75plt.show()

可以看到,在代码中,通过pos字典已经规定好了每个神经元节点的位置。

接下来,需要对这个框架图进行更为细致地修改,需要修改的地方为:

  • 去掉神经元节点的标签;
  • 添加模型层的文字注释(比如Input layer)

其中,第二步的文字注释,我们借助opencv来完成。完整的Python代码如下:

代码语言:javascript
复制
  1# -*- coding:utf-8 -*-
  2import cv2
  3import networkx as nx
  4import matplotlib.pyplot as plt
  5
  6# 创建DAG
  7G = nx.DiGraph()
  8
  9# 顶点列表
 10vertex_list = ['v'+str(i) for i in range(1, 22)]
 11# 添加顶点
 12G.add_nodes_from(vertex_list)
 13
 14# 边列表
 15edge_list = [
 16             ('v1', 'v5'), ('v1', 'v6'), ('v1', 'v7'),('v1', 'v8'),('v1', 'v9'),
 17             ('v2', 'v5'), ('v2', 'v6'), ('v2', 'v7'),('v2', 'v8'),('v2', 'v9'),
 18             ('v3', 'v5'), ('v3', 'v6'), ('v3', 'v7'),('v3', 'v8'),('v3', 'v9'),
 19             ('v4', 'v5'), ('v4', 'v6'), ('v4', 'v7'),('v4', 'v8'),('v4', 'v9'),
 20             ('v5','v10'),('v5','v11'),('v5','v12'),('v5','v13'),('v5','v14'),('v5','v15'),
 21             ('v6','v10'),('v6','v11'),('v6','v12'),('v6','v13'),('v6','v14'),('v6','v15'),
 22             ('v7','v10'),('v7','v11'),('v7','v12'),('v7','v13'),('v7','v14'),('v7','v15'),
 23             ('v8','v10'),('v8','v11'),('v8','v12'),('v8','v13'),('v8','v14'),('v8','v15'),
 24             ('v9','v10'),('v9','v11'),('v9','v12'),('v9','v13'),('v9','v14'),('v9','v15'),
 25             ('v10','v16'),('v10','v17'),('v10','v18'),
 26             ('v11','v16'),('v11','v17'),('v11','v18'),
 27             ('v12','v16'),('v12','v17'),('v12','v18'),
 28             ('v13','v16'),('v13','v17'),('v13','v18'),
 29             ('v14','v16'),('v14','v17'),('v14','v18'),
 30             ('v15','v16'),('v15','v17'),('v15','v18'),
 31             ('v16','v19'),
 32             ('v17','v20'),
 33             ('v18','v21')
 34            ]
 35# 通过列表形式来添加边
 36G.add_edges_from(edge_list)
 37
 38# 指定绘制DAG图时每个顶点的位置
 39pos = {
 40        'v1':(-2,1.5),
 41        'v2':(-2,0.5),
 42        'v3':(-2,-0.5),
 43        'v4':(-2,-1.5),
 44        'v5':(-1,2),
 45        'v6': (-1,1),
 46        'v7':(-1,0),
 47        'v8':(-1,-1),
 48        'v9':(-1,-2),
 49        'v10':(0,2.5),
 50        'v11':(0,1.5),
 51        'v12':(0,0.5),
 52        'v13':(0,-0.5),
 53        'v14':(0,-1.5),
 54        'v15':(0,-2.5),
 55        'v16':(1,1),
 56        'v17':(1,0),
 57        'v18':(1,-1),
 58        'v19':(2,1),
 59        'v20':(2,0),
 60        'v21':(2,-1)
 61       }
 62# 绘制DAG图
 63plt.title('DNN for iris')    #图片标题
 64plt.xlim(-2.2, 2.2)                     #设置X轴坐标范围
 65plt.ylim(-3, 3)                     #设置Y轴坐标范围
 66nx.draw(
 67        G,
 68        pos = pos,                      # 点的位置
 69        node_color = 'red',             # 顶点颜色
 70        edge_color = 'black',           # 边的颜色
 71        font_size =10,                  # 文字大小
 72        node_size =300                  # 顶点大小
 73       )
 74
 75# 保存图片,图片大小为640*480
 76plt.savefig('DNN_sketch.png')
 77
 78# 利用opencv模块对DNN框架添加文字注释
 79
 80# 读取图片
 81imagepath = 'DNN_sketch.png'
 82image = cv2.imread(imagepath, 1)
 83
 84# 输入层
 85cv2.rectangle(image, (85, 130), (120, 360), (255,0,0), 2)
 86cv2.putText(image, "Input Layer", (15, 390), 1, 1.5, (0, 255, 0), 2, 1)
 87
 88# 隐藏层
 89cv2.rectangle(image, (190, 70), (360, 420), (255,0,0), 2)
 90cv2.putText(image, "Hidden Layer", (210, 450), 1, 1.5, (0, 255, 0), 2, 1)
 91
 92# 输出层
 93cv2.rectangle(image, (420, 150), (460, 330), (255,0,0), 2)
 94cv2.putText(image, "Output Layer", (380, 360), 1, 1.5, (0, 255, 0), 2, 1)
 95
 96# sofrmax层
 97cv2.rectangle(image, (530, 150), (570, 330), (255,0,0), 2)
 98cv2.putText(image, "Softmax Func", (450, 130), 1, 1.5, (0, 0, 255), 2, 1)
 99
100# 保存修改后的图片
101cv2.imwrite('DNN.png', image)

一些图论算法

最短路径

函数调用:

代码语言:javascript
复制
 1dijkstra_path(G, source, target, weight=‘weight’) ————求最短路径
 2dijkstra_path_length(G, source, target, weight=‘weight’) ————求最短距离
 3
 4import networkx as nx
 5import pylab 
 6import numpy as np
 7#自定义网络
 8row=np.array([0,0,0,1,2,3,6])
 9col=np.array([1,2,3,4,5,6,7])
10value=np.array([1,2,1,8,1,3,5])
11
12print('生成一个空的有向图')
13G=nx.DiGraph()
14print('为这个网络添加节点...')
15for i in range(0,np.size(col)+1):
16    G.add_node(i)
17print('在网络中添加带权中的边...')
18for i in range(np.size(row)):
19    G.add_weighted_edges_from([(row[i],col[i],value[i])])
20
21print('给网路设置布局...')
22pos=nx.shell_layout(G)
23print('画出网络图像:')
24nx.draw(G,pos,with_labels=True, node_color='white', edge_color='red', node_size=400, alpha=0.5 )
25pylab.title('Self_Define Net',fontsize=15)
26pylab.show()
27
28
29'''
30Shortest Path with dijkstra_path
31'''
32print('dijkstra方法寻找最短路径:')
33path=nx.dijkstra_path(G, source=0, target=7)
34print('节点0到7的路径:', path)
35print('dijkstra方法寻找最短距离:')
36distance=nx.dijkstra_path_length(G, source=0, target=7)
37print('节点0到7的距离为:', distance)

输出:

代码语言:javascript
复制
1生成一个空的有向图
2为这个网络添加节点...
3在网络中添加带权中的边...
4给网路设置布局...
5画出网络图像:
6dijkstra方法寻找最短路径:
7节点0到7的路径: [0, 3, 6, 7]
8dijkstra方法寻找最短距离:
9节点0到7的距离为: 9

问题

本人在pycharm中运行下列程序:

代码语言:javascript
复制
 1import networkx as nx
 2import matplotlib.pyplot as plt
 3
 4G = nx.Graph()  # 建立一个空的无向图G
 5G.add_node('a')  # 添加一个节点1
 6G.add_nodes_from(['b', 'c', 'd', 'e'])  # 加点集合
 7G.add_cycle(['f', 'g', 'h', 'j'])  # 加环
 8H = nx.path_graph(10)  # 返回由10个节点挨个连接的无向图,所以有9条边
 9G.add_nodes_from(H)  # 创建一个子图H加入G
10G.add_node(H)  # 直接将图作为节点
11
12nx.draw(G, with_labels=True)
13plt.show()

发现在Pycharm下使用matploylib库绘制3D图的时候,在最后需要显示图像的时候,每当输入plt.show() 都会报错

代码语言:javascript
复制
1plt.show()
2/yyl/Python/3.6/lib/python/site-packages/matplotlib/figure.py:1743: UserWarning: This figure includes Axes that are not compatible with tight_layout, so its results might be incorrect.
3warnings.warn("This figure includes Axes that are not "
4...
5ValueError: max() arg is an empty sequence

网上的解决方案:File -> Setting -> Tools -> Python Scientific中去掉对Show plots in tool window的勾选就好了

一些其他神经网络绘制工具列表

上面都是一些这个网络库使用的一点总结,更多内容可以参考下面的官方链接。

参考

官方教程:https://networkx.github.io/documentation/stable/_downloads/networkx_reference.pdf

官方网站:https://networkx.github.io/documentation/latest/index.html

官方githu博客:http://networkx.github.io/

用Python的networkx绘制精美网络图:https://blog.csdn.net/qq951127336/article/details/54586869

networkx整理:https://www.cnblogs.com/minglex/p/9205160.html

Networkx使用指南:https://blog.csdn.net/Zhili_wang/article/details/89368177

论文中绘制神经网络工具汇总:https://blog.csdn.net/WZZ18191171661/article/details/87886588

networkx + Cytoscape构建及可视化网络图:https://www.jianshu.com/p/f62991aa1f8a

用python+graphviz/networkx画目录结构树状图:https://blog.csdn.net/XiaoPANGXia/article/details/53043664

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技大本营 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一些其他神经网络绘制工具列表
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档