又是自闭的一天,一个下标没对找错误找的我怀疑人生`,一开始是下面这样的,就是因为更新质点的时候我将下标,i,j没区分开,导致的质点越算越少,到了最后只有一个质点,后面改掉才好的
import numpy as np
import matplotlib.pyplot as plt
# 载入数据
data = np.genfromtxt("kmeans.txt", delimiter=" ")
#样本总量和纬度
numsample,dim=data.shape
#计算距离
def eudistance(x,y):
return np.sqrt(sum((x-y)**2))
#随机初始化K个类别的质心
def center(data,k):
centers=np.zeros((k,dim))
for i in range(k):
index=int(np.random.uniform(0,numsample))
centers[i,:]=data[index,:]
return centers
'''
np.random.uniform()
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
low: 采样下界,float类型,默认值为0;
high: 采样上界,float类型,默认值为1;
size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出m*n*k个样本,缺省时输出1个值。
这里一开始没有int,然后系统报错,说.....整数或布尔数组是有效的索引
'''
#对于每个样本,将其标记为距离类别中心Aj最近的类别j
def kmeans(data,k):
#簇数据,存储样本属性,二列数据,第一列保存样本属于哪个簇,第二列保存样本和簇之间的误差,即欧氏距离
clusterdata=np.array(np.zeros((numsample,2)))
cluster_change=True #决定后续是否改变质心
centers=center(data,k)#调用随机初始化质心的函数
print('初始化质心:')
print(centers)
while cluster_change:
cluster_change=False
for i in range(numsample):
minidistance=1000.0 #定义一个很大的初始距离,方便后续更新
minindex=0 #定义初始化的类别都是0类
for j in range(k): #调用上面的函数计算每一个质点和该样本的距离
distance=eudistance(data[j,:],centers[j,:])
if distance<minidistance:
minidistance=distance #更新最小距离,根据距离判断属于哪个簇
clusterdata[i,1]=minidistance
minindex=j #更新簇
#当当前样本i,与k个质点比较距离之后,判断出他当前属于J簇,现在更新簇
if clusterdata[i,0]!=minindex:
cluster_change=True#只要有一个样本的所属簇发生变化,其质心就需要从新计算
clusterdata[i,0]=minindex
#这样第i个样本与簇之间的误差和所属簇都更新完毕,下面进行第I+1的样本更新
#当遍历完当前样本之后,就要对K个质点更新
for j in range(k):
#获取第j个簇的所有样本的索引
centers_index=np.nonzero(clusterdata[:,0]==j)
#j簇的所有的样本点
allpoint=data[centers_index]
#更新质点为每个簇的所有样本的均值
centers[j,:]=np.mean(allpoint,axis=0)
#返回质点和样本属性
return centers,clusterdata
def showCluster(data,k,centers,clusterdata):
# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
# 画样本点
for i in range(numsample):
markIndex = int(clusterdata[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])
# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centers[i, 0], centers[i, 1], mark[i], markersize=20)
plt.show()
k=4
centers, clusterdata= kmeans(data,k)
showCluster(data,k,centers,clusterdata)
这里是改正后的
import numpy as np
import matplotlib.pyplot as plt
# 载入数据
data = np.genfromtxt("kmeans.txt", delimiter=" ")
#样本总量和纬度
numsample,dim=data.shape
#计算距离
def eudistance(x,y):
return np.sqrt(sum((x-y)**2))
#随机初始化K个类别的质心
def center(data,k):
centers=np.zeros((k,dim))
for i in range(k):
index=int(np.random.uniform(0,numsample))
centers[i,:]=data[index,:]
return centers
'''
np.random.uniform()
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
low: 采样下界,float类型,默认值为0;
high: 采样上界,float类型,默认值为1;
size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出m*n*k个样本,缺省时输出1个值。
这里一开始没有int,然后系统报错,说.....整数或布尔数组是有效的索引
'''
#对于每个样本,将其标记为距离类别中心Aj最近的类别j
def kmeans(data,k):
#簇数据,存储样本属性,二列数据,第一列保存样本属于哪个簇,第二列保存样本和簇之间的误差,即欧氏距离
clusterdata=np.array(np.zeros((numsample,2)))
cluster_change=True #决定后续是否改变质心
centers=center(data,k)#调用随机初始化质心的函数
print('初始化质心:')
print(centers)
while cluster_change:
cluster_change=False
for i in range(numsample):
minidistance=1000.0 #定义一个很大的初始距离,方便后续更新
minindex=0 #定义初始化的类别都是0类
for j in range(k): #调用上面的函数计算每一个质点和该样本的距离
distance=eudistance(data[i,:],centers[j,:])
if distance<minidistance:
minidistance=distance #更新最小距离,根据距离判断属于哪个簇
clusterdata[i,1]=minidistance
minindex=j #更新簇
#当当前样本i,与k个质点比较距离之后,判断出他当前属于J簇,现在更新簇
if clusterdata[i,0]!=minindex:
cluster_change=True#只要有一个样本的所属簇发生变化,其质心就需要从新计算
clusterdata[i,0]=minindex
#这样第i个样本与簇之间的误差和所属簇都更新完毕,下面进行第I+1的样本更新
#当遍历完当前样本之后,就要对K个质点更新
for j in range(k):
#获取第j个簇的所有样本的索引
centers_index=np.nonzero(clusterdata[:,0]==j)
#j簇的所有的样本点
allpoint=data[centers_index]
#更新质点为每个簇的所有样本的均值
centers[j,:]=np.mean(allpoint,axis=0)
#返回质点和样本属性
return centers,clusterdata
def showCluster(data,k,centers,clusterdata):
# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
# 画样本点
for i in range(numsample):
markIndex = int(clusterdata[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])
# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centers[i, 0], centers[i, 1], mark[i], markersize=20)
plt.show()
k=4
centers, clusterdata= kmeans(data,k)
showCluster(data,k,centers,clusterdata)