围绕特定节点的图形集群节点
cluster nodes of graph around specific nodes
考虑来自 networkx 的节点图,我如何应用所有节点的 kmean 集群,其中特定节点被视为集群的质心。换句话说,假设我们有这个图:
import networkx as nx
s = [0,3,2,3,4,5,1]
t = [1,2,7,4,6,6,5]
dist = [3,2,5,1,5,4,2]
G = nx.Graph()
for i in range(len(s)):
G.add_edge(s[i],t[i],weight=dist[i])
我想在网络上应用 kmean 聚类,例如我选择质心为 3 和 6,图形将相应地聚类以生成两个子图(或与我输入的一样多的质心)
我一直在看这里的 kmean 聚类https://www.learndatasci.com/tutorials/k-means-clustering-algorithms-python-intro/,它没有涵盖输入的质心,而是它只考虑没有质心节点的簇数。
请注意,您不能直接将 k-means 聚类应用于网络,因为不一定存在测量节点和质心之间距离的度量。 但是...
.. 如果你假设:
- 加权最短路径的路径长度是一对节点之间的距离度量。
- 质心是节点。注意:在传统的 k 均值聚类中,centroids 不一定是数据点本身。
在这些假设下,如果您将质心与最短加权最短路径关联到每个节点,则到质心的距离总和最小。
所以程序可以是:
- 将每个节点与一个质心相关联,使得每个节点到其质心的距离总和最小(即距离的聚类总和)
- 更新质心
- 重复前两个步骤,直到质心稳定。
这个过程大致对应于k-mean clustering的过程,即最小化簇内平方和(WCSS)。
尽管此过程类似于度量中数据点的 k-均值聚类-space,但我不会将其称为 k-均值聚类。特别是因为质心的位置仅限于网络中的节点。
以下是您如何使用 python:
来解决这个问题
1. 定义初始质心:
centroids = [3, 6]
2.对于每个节点,获取到所有质心的所有最短路径 .
例如:
shortest_paths = [[(cent, nx.shortest_path(
G, source=n ,target=cent, weight='weight'
)) for cent in centroids] for n in G.nodes
]
这给出(这里它们与质心的 id 一起报告):
In [26]: shortest_paths
Out[26]:
[[(3, [0, 1, 5, 6, 4, 3]), (6, [0, 1, 5, 6])],
[(3, [1, 5, 6, 4, 3]), (6, [1, 5, 6])],
[(3, [3]), (6, [3, 4, 6])],
[(3, [2, 3]), (6, [2, 3, 4, 6])],
[(3, [7, 2, 3]), (6, [7, 2, 3, 4, 6])],
[(3, [4, 3]), (6, [4, 6])],
[(3, [6, 4, 3]), (6, [6])],
[(3, [5, 6, 4, 3]), (6, [5, 6])]]
3. 计算实际距离,即对所有节点的所有最短路径求和路径上的权重:
例如:
distances = [
[
(
sp[0], # this is the id of the centroid
sum([
G[sp[1][i]][sp[1][i+1]]['weight']
for i in range(len(sp[1]) - 1)
]) if len(sp[1]) > 1 else 0
) for sp in sps
] for sps in shortest_paths
]
所以距离是:
In [28]: distances
Out[28]:
[[(3, 15), (6, 9)],
[(3, 12), (6, 6)],
[(3, 0), (6, 6)],
[(3, 2), (6, 8)],
[(3, 7), (6, 13)],
[(3, 1), (6, 5)],
[(3, 6), (6, 0)],
[(3, 10), (6, 4)]]
4. 获取所有节点距离最小的质心:
例如:
closest_centroid = [
min(dist, key=lambda d: d[1])[0] for dist in distances
]
根据质心进行分组:
In [30]: closest_centroid
Out[30]: [6, 6, 3, 3, 3, 3, 6, 6]
5. 更新质心,因为当前质心可能不再是组的实际质心:
方法:
# for each group
# for each member of the group
# get the distance of shortest paths to all the other members of the group
# sum this distances
# find the node with the minimal summed distance > this is the new centroid of the group
Iteration:如果新的centroids和旧的不一样,就用新的centroids重复步骤 2.- 5.
最后一步:如果在步骤 5. 中找到的新质心与旧质心相同,或者您已经达到迭代限制,将最近的质心关联到每个节点:
例如:
nodes = [n for n in G] # the actual id of the nodes
cent_dict = {nodes[i]: closest_centroid[i] for i in range(len(nodes))}
nx.set_node_attributes(G, cent_dict, 'centroid')
或nx.set_node_attributes(G, 'centroid', cent_dict)
如果你还在v1.x。
这将是一种为网络执行某种 k 均值聚类的方法。
希望对您有所帮助,编码愉快!
考虑来自 networkx 的节点图,我如何应用所有节点的 kmean 集群,其中特定节点被视为集群的质心。换句话说,假设我们有这个图:
import networkx as nx
s = [0,3,2,3,4,5,1]
t = [1,2,7,4,6,6,5]
dist = [3,2,5,1,5,4,2]
G = nx.Graph()
for i in range(len(s)):
G.add_edge(s[i],t[i],weight=dist[i])
我想在网络上应用 kmean 聚类,例如我选择质心为 3 和 6,图形将相应地聚类以生成两个子图(或与我输入的一样多的质心)
我一直在看这里的 kmean 聚类https://www.learndatasci.com/tutorials/k-means-clustering-algorithms-python-intro/,它没有涵盖输入的质心,而是它只考虑没有质心节点的簇数。
请注意,您不能直接将 k-means 聚类应用于网络,因为不一定存在测量节点和质心之间距离的度量。 但是...
.. 如果你假设:
- 加权最短路径的路径长度是一对节点之间的距离度量。
- 质心是节点。注意:在传统的 k 均值聚类中,centroids 不一定是数据点本身。
在这些假设下,如果您将质心与最短加权最短路径关联到每个节点,则到质心的距离总和最小。
所以程序可以是:
- 将每个节点与一个质心相关联,使得每个节点到其质心的距离总和最小(即距离的聚类总和)
- 更新质心
- 重复前两个步骤,直到质心稳定。
这个过程大致对应于k-mean clustering的过程,即最小化簇内平方和(WCSS)。
尽管此过程类似于度量中数据点的 k-均值聚类-space,但我不会将其称为 k-均值聚类。特别是因为质心的位置仅限于网络中的节点。
以下是您如何使用 python:
来解决这个问题1. 定义初始质心:
centroids = [3, 6]
2.对于每个节点,获取到所有质心的所有最短路径 .
例如:
shortest_paths = [[(cent, nx.shortest_path(
G, source=n ,target=cent, weight='weight'
)) for cent in centroids] for n in G.nodes
]
这给出(这里它们与质心的 id 一起报告):
In [26]: shortest_paths
Out[26]:
[[(3, [0, 1, 5, 6, 4, 3]), (6, [0, 1, 5, 6])],
[(3, [1, 5, 6, 4, 3]), (6, [1, 5, 6])],
[(3, [3]), (6, [3, 4, 6])],
[(3, [2, 3]), (6, [2, 3, 4, 6])],
[(3, [7, 2, 3]), (6, [7, 2, 3, 4, 6])],
[(3, [4, 3]), (6, [4, 6])],
[(3, [6, 4, 3]), (6, [6])],
[(3, [5, 6, 4, 3]), (6, [5, 6])]]
3. 计算实际距离,即对所有节点的所有最短路径求和路径上的权重:
例如:
distances = [
[
(
sp[0], # this is the id of the centroid
sum([
G[sp[1][i]][sp[1][i+1]]['weight']
for i in range(len(sp[1]) - 1)
]) if len(sp[1]) > 1 else 0
) for sp in sps
] for sps in shortest_paths
]
所以距离是:
In [28]: distances
Out[28]:
[[(3, 15), (6, 9)],
[(3, 12), (6, 6)],
[(3, 0), (6, 6)],
[(3, 2), (6, 8)],
[(3, 7), (6, 13)],
[(3, 1), (6, 5)],
[(3, 6), (6, 0)],
[(3, 10), (6, 4)]]
4. 获取所有节点距离最小的质心:
例如:
closest_centroid = [
min(dist, key=lambda d: d[1])[0] for dist in distances
]
根据质心进行分组:
In [30]: closest_centroid
Out[30]: [6, 6, 3, 3, 3, 3, 6, 6]
5. 更新质心,因为当前质心可能不再是组的实际质心:
方法:
# for each group
# for each member of the group
# get the distance of shortest paths to all the other members of the group
# sum this distances
# find the node with the minimal summed distance > this is the new centroid of the group
Iteration:如果新的centroids和旧的不一样,就用新的centroids重复步骤 2.- 5.
最后一步:如果在步骤 5. 中找到的新质心与旧质心相同,或者您已经达到迭代限制,将最近的质心关联到每个节点:
例如:
nodes = [n for n in G] # the actual id of the nodes
cent_dict = {nodes[i]: closest_centroid[i] for i in range(len(nodes))}
nx.set_node_attributes(G, cent_dict, 'centroid')
或nx.set_node_attributes(G, 'centroid', cent_dict)
如果你还在v1.x。
这将是一种为网络执行某种 k 均值聚类的方法。
希望对您有所帮助,编码愉快!