k-means算法是经典的聚类算法. 我自己手写了一个k-means++的放在后面, 效果似乎不太好 , 希望大佬指点
sklearn实现
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets.samples_generator import make_blobs
原始数据
# 绘图函数
def plot_img(x,y=True):
fig=plt.figure(figsize=(7,5))
if y:
plt.scatter(x[:,0],x[:,1],c=x[:,2],cmap=plt.cm.Spectral,marker='o')
else:
plt.scatter(x[:,0],x[:,1],marker='o')
plt.title('Scatter')
plt.xlabel('feature 2')
plt.ylabel('feature 1')
plt.show()
'''构造数据'''
# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本2个特征,共4个簇,
#簇中心在[-1,-1], [0,0],[1,1], [2,2], 簇方差分别为[0.4, 0.2, 0.2]
X,Y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.2, 0.2, 0.2],
random_state =9)
# 可视化
data=np.c_[X,Y]
plot_img(data,y=True)
传统的k-means聚类
from sklearn.cluster import KMeans
from sklearn import metrics
plt.figure(figsize=(10,10))
for i,k in enumerate([2,3,4,5]):
km=KMeans(n_clusters=k,# 即k值,即要形成的质心数
max_iter=300,# 凸数据集不用管这个,如果是非凸数据集可能会无法收敛,设置最大迭代次数
n_init=10,# 用不同的初始化质心运行算法的次数. 默认是10,不需要改.如果k值较大,
# 则可以适当增大这个值。
init='k-means++',# 初始化质心的方法,可以选择'random'随机,推荐用默认'k-means ++'
algorithm='auto',)# 优化方法,推荐使用默认'auto',通过数据的稀疏性,自动选择合适的方法
km.fit(X)
y_pred=km.predict(X)
'''calinske_harbaz_score是聚类算法的衡量标准,值越大越好'''
score=metrics.calinski_harabaz_score(X, y_pred)
plt.subplot(2,2,i+1)
plt.scatter(X[:,0],X[:,1],c=y_pred,cmap=plt.cm.Spectral)
plt.title('Clusters=%d\nScore=%f'%(k,score))
MiniBatchKMeans
应用于大数据集,选取一部分合适的数据集来迭代质心
from sklearn.cluster import MiniBatchKMeans
plt.figure(figsize=(10,10))
for i,k in enumerate((2,3,4,5)):
y_pred=MiniBatchKMeans(n_clusters=k,
batch_size = 200,# 即用来跑Mini Batch KMeans算法的采样集的大小,
#默认是100.如果发现数据集的类别较多或者噪音点较多,
#需要增加这个值以达到较好的聚类效果。
random_state=9).fit_predict(X)
score= metrics.calinski_harabaz_score(X, y_pred)
plt.subplot(2,2,i+1)
plt.scatter(X[:,0],X[:,1],c=y_pred,cmap=plt.cm.Spectral)
plt.title("Clusters={0}\nScore={1}".format(k,score))
手动实现
class K_mean(object):
def __init__(self,c,n_iterations):
self.n_iterations=n_iterations
self.c=c
def init_params(self,X):
self.X=X
self.init_u()
def init_u(self):
all_u=[]
for i in range(self.c):
uid=np.random.choice(self.X.shape[0],1)
u=self.X[uid]
delta=u-self.X
d_delta=np.apply_along_axis(lambda x:np.dot(x,x),1,delta)
best_u=X[np.argmax(d_delta)]
all_u.append(best_u)
self.U=np.array(all_u)
def get_label(self):
labels=[]
for i in range(len(self.X)):
di=self.X[i].reshape(1,-1)-self.U
di=np.apply_along_axis(lambda x:x.dot(x),1,di)
k=di.argmin()
labels.append(k)
return labels
def update_u(self):
U_up=[]
labels=self.get_label()
X_new=np.c_[self.X,labels]
self.X_complete=X_new
label_map=set(labels)
for i in label_map:
group=X[labels==i]
u=group.sum(axis=0)/len(group)
U_up.append(u)
self.U=np.array(U_up)
def fit_transform(self,X):
self.init_params(X)
old_u=None
iters=0
for iter in range(self.n_iterations):
self.update_u()
iters+=1
self.iters=iters
return self.X_complete
c=4
n_iters=100
km=K_mean(c,n_iters)
X_show=km.fit_transform(X)
plot_img(X_show)
完整代码:https://github.com/TaoistNie/The-road-to-ML/blob/master/K-means/readme.md