#coding utf-8
#python 3.4
#2015-4-3
#Fitz Yin
#yinruyi.hm@gmail.com
from sklearn.cluster importKMeansimportnumpy as npdefmakedict(f):#建立行号和每行数据间的字典关系
a = [line.split() for line inf]
data_dict={}for i inrange(len(a)):
data_dict[i]=a[i]returndata_dictdefkmeans(data):#kmeans算法
data =np.array(data)
computer=KMeans(n_clusters=2)
computer.fit(data)
labels=computer.labels_
one_class=[]
zero_class=[]for i inrange(len(labels)):if labels[i] == 1:
one_class.append(i)#0类的行号
else:
zero_class.append(i)#1类的行号
centers = computer.cluster_centers_#找到中心
cohesion_0,cohesion_1 = -1,-1#初始化,自己和自己的cos是1
for i inzero_class:
cohesion_0+= judge_cos(data[i],centers[0])#0类cos评价
for i inone_class:
cohesion_1+= judge_cos(data[i],centers[1])#1类cos评价
returnzero_class,one_class,cohesion_0,cohesion_1defjudge_cos(x,y):#cos评价函数
af,bf,ab =0,0,0for i inrange(len(x)):
af= float(x[i])*float(x[i])
bf= float(y[i])*float(y[i])
ab= float(x[i])*float(y[i])if af == 0 or bf ==0:print('error')return0#本例中不出现全是0情况
else:
cos_value= ab/(np.sqrt(af)*np.sqrt(bf))returncos_valuedefgettransdict(split_set,split_number):#建立kmeans计算的矩阵和原来矩阵 两个行号之间的字典关系
a =split_set[split_number][0]
transdict={}for i inrange(len(a)):
transdict[i]=a[i]returntransdictdefgetsplitset(split_set,split_number):#簇中去掉要分的簇
new_split_set =[]for i inrange(len(split_set)):if i ==split_number:pass
else:
new_split_set.append(split_set[i])returnnew_split_setdefgetsplitnumber(split_set):#找寻待分簇的编号
split_number =0
temp=[]for i inrange(len(split_set)):
temp.append(split_set[i][1])for i inrange(len(temp)):if temp[split_number]
split_number=ireturnsplit_numberdefmain():
f= open('train.txt','r',encoding='utf-8').readlines()
data_dict=makedict(f)
k= 3#分类个数
#sse = 0.001
split_set = [[[i for i in range(1000)],0]]#此处1000是行号
split_number = 0#需要分类的簇标号
while len(split_set) !=k:
transdict= gettransdict(split_set,split_number)#转换字典
array2kmeans = [data_dict[i] for i in split_set[split_number][0]]#获取二分kmeans计算矩阵
zero_class,one_class,cohesion_0,cohesion_1 =kmeans(array2kmeans)
real_zero_class= [transdict[i] for i in zero_class]#分裂后的簇0
real_one_class = [transdict[i] for i in one_class]#分裂后的簇1
split_set = getsplitset(split_set,split_number)#将总的簇中去掉分的大的簇
split_set.append([real_zero_class,cohesion_0])
split_set.append([real_one_class,cohesion_1])#总的簇中加入分完的小簇
split_number = getsplitnumber(split_set)#获取下一个循环待分的簇编号
print(split_set)#[[[行号1类],sse1],[[行号2类],sse2],[[行号三类],sse3]]
if __name__ == '__main__':
main()