目录
1.2计算spatio-structural differential efficiency
0、简介
数据分类是一种机器学习和数据挖掘任务,被广泛应用在生物信息、模式识别、机器人等领域。目前,众多算法相继被提出:人工神经网络、贝叶斯、决策树、支持向量机等。当然了,虽然数据分类已经被广泛的研究,但仍然存在着问题。
问题1:传统的技术都是基于数据的物理特征(相似性、距离、分布)来达到分类的任务,但在实际中,无论数据样本之间的物理差异如何,我们都能够识别数据的组织结构(organizational structure),这个特征对分类任务会有很大的帮助,所以就出现这样一个问题:怎样利用计算机实现对数据组织结构特征的使用?
问题2:传统的分类算法平等的对待每一个样本,要对数据集有一个正确的理解就不能忽略每个样本个体的重要性。
在这里,为大家介绍一种基于复杂网络的新型分类器,可以从一定程度上缓解上述问题。
原文链接:https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7999257
1、算法原理
1.1构造复杂网络
所有训练样本组成了有向复杂网络的节点。每个节点将充当源节点,其目标节点满足两个条件:1.类标和源节点相同;2.目标节点属于源节点的kNN(即属于距离源节点最近的k个节点)。显然,对于具有两个类的分类问题,至少要创建两个组件(满足第一个条件)。换句话说,可以为一个类生成多个组件。如图1(a)中蓝色的那一类就形成了两个组件,而红色的那一类只有一个组件。
1.2计算spatio-structural differential efficiency
首先我们先计算单个节点的local efficiency(我们用e来表示),它代表的含义就是以某个节点为源节点,从源节点到其目标节点的平均距离。例如图1(b)中最上面的那个蓝色节点,分别到它的两个目标节点(有向边指向的两个节点)的距离为0.24,0.22,那么它的local efficiency就是0.23.
然后,我们再来计算spatio-structural differential efficiency(我们用ε来表示),它代表一个组件中所有节点的local efficiency的平均值,例如图1(b)中右下角的那个包含三个节点的蓝色组件,三个节点的local efficiency分别为0.09,0.10,0.11,那么这个组件的spatio-structural differential efficiency值为0.10
1.3计算PageRank
直接将PageRank的计算公式给出来,至于这个公式的含义可以到百度上搜索,有很多。
1.4建立测试节点与训练集中节点的临时边
测试节点与训练集中的一个节点之间是否建立临时边由下面的这个公式公式决定(公式成立建立连接):
给大家解释一下,D表示测试节点和训练节点之间的距离,ε表示训练节点所在组件的spatio-structural differential efficiency,γ是个参数,我们可以自己设定,设定的值越大,建立的临时边也就会越多,对决定测试节点的类别起作用的训练节点也就越多。
不过对于有些测试节点,对任意训练节点,上式都不成立,那么我们怎么建立临时连接呢?这时候,我们只建立一条边,这条边的一头是测试节点,另一头是最可能使上式成立的训练节点(使得最大的训练节点,虽然是个负数)。
注:测试节点与测试节点之间不会建立连接
1.5计算测试节点对每一类的重要性
对于一个测试节点,将它的邻节点且属于同一类的PageRank值加起来,加起来的和就是这个测试节点对某一类的重要性,例如图1(e),测试节点对红色的重要性就是0.06+0.13=0.19,对蓝色的重要性就是0.14+0.14=0.28.
1.6预测测试节点的类标
最后一步就是,完成分类了,我们利用上一步的重要性计算的结果,测试节点对哪类的重要性最高,它就属于哪一类。如图1(f),测试节点属于蓝色的那一类。
2、代码示例
我们可以从上面的介绍看到,总共只有两个参数可以调节一个k近邻中的k值,一个建立临时边时用到的γ值。
import numpy as np
import networkx as nx
def graph(dist_map,y_train,k):
graph=[]
Lenth=len(y_train)
weight=dict()
for i in range(Lenth):
weight[i]=0
for i in range(Lenth):
dist=dist_map[i]
rank_dist=np.argsort(dist)
knn=rank_dist[1:k+1]
for j in range(k):
if y_train[knn[j]]==y_train[rank_dist[0]]:
graph.append((rank_dist[0],knn[j]))
weight[rank_dist[0]]+=dist[knn[j]]
print('Graph is done!')
return [graph,weight]
def effi_comp(graph,weight):
G=nx.Graph()
G.add_edges_from(graph)
components=sorted(nx.connected_components(G), key = len, reverse=True)
G=nx.DiGraph()
G.add_edges_from(graph)
out_degree=G.out_degree()
components_num=len(components)
print('Total have '+str(components_num)+' components!')
for i in range(components_num):
components[i]=list(components[i])
effi=np.zeros(components_num,np.float32)
for i in range(components_num):
for j in components[i]:
if out_degree[j]>0:
effi[i]+=weight[j]/out_degree[j]
effi[i] = effi[i] / len(components[i])
print('Effi_Comp is done!')
return [effi,components,G]
def PageRank(G,y_train):
pr=nx.pagerank(G,alpha=0.85)
Lenth=len(y_train)
Pr=np.zeros(Lenth,np.float32)
for i in range(len(y_train)):
if i not in pr:
Pr[i]=0
else:
Pr[i]=pr[i]
print('PageRank is done!')
return Pr
def predict(dist_map,y_train,pr,gamma,effi,components):
ga_effi=effi*gamma
Lenth,Lenth_=dist_map.shape
P=np.zeros((Lenth,2),np.float32)
pre=np.zeros(Lenth,np.int8)
for i in range(Lenth_):
for component in components:
if i in component:
Index=components.index(component)
break
dist_map[:,i]=ga_effi[Index]-dist_map[:,i]
for i in range(Lenth):
if np.max(dist_map[i])<=0:
Index=np.argmax(dist_map[i])
if y_train[Index]==1:
P[i,1]=pr[Index]
else:
P[i,0]=pr[Index]
else:
Index=np.argwhere(dist_map[i]>0)
Pr=np.take(pr,Index)
y_label=np.take(y_train,Index)
P[i,1]=np.sum(Pr*y_label)
P[i,0]=np.sum(Pr)-P[i,1]
if P[i,0]<P[i,1]:
pre[i]=1
print('Predict is done!')
return pre
if __name__=='__main__':
k=15 #knn中的k值
gamma=1 #γ值
y_train=np.load('train_lable.npy') #训练集的标签
dist_map = np.load('dist_map_1.npy') #训练集数据之间的距离,例如dist_map[1,2]就表示第2个训练样本和第3个训练样本间的距离
#(这个预先准备好,另外也不不只能是欧式距离,也可以是其它的相似度计算的结果)
print('Trainset distance is done!')
Graph=graph(dist_map,y_train,k) #构建复杂网络
Effi_comp=effi_comp(Graph[0],Graph[1]) #计算spatio-structural differential efficiency
pr=PageRank(Effi_comp[2],y_train) #计PageRank
dist_map=np.load('dist_map_2.npy') #训练集和测试集数据之间的距离,变量重新使用减少内存,例如dist_map[1,2]表示
#第2条测试样本和第3条训练样本之间的距离
print('Testset distance is done!')
pre=predict(dist_map,y_train,pr,gamma,Effi_comp[0],Effi_comp[1]) #预测结果,我的预测函数是针对的二分类,至于多分类的没写,大家可以尝试着去修改