3、聚类Kmeans

KMeans介绍

概念

1、无监督性问题
分类:有监督
聚类:无监督,能用分类,不用聚类
2、
分为多少簇,超参数K
质心:向量各维取平均即可

工作流程:

1、根据k值随意选取k个点作为初始的质心
2、进行分类
3、将已完成分类的点取平均数,作为质心
再次分类,求质心
初始点选择非常重要

查看过程:

1、数据

x,y = make_blobs(n_samples=2000,centers=blob_centers,
                     cluster_std = blob_std,random_state=7)

2、训练

kmeans_iter1 = KMeans(n_clusters = 5,init = 'random',
                      n_init = 1,max_iter=1,random_state=1)

kmeans_iter2 = KMeans(n_clusters = 5,init = 'random',
                      n_init = 1,max_iter=2,random_state=1)

kmeans_iter3 = KMeans(n_clusters = 5,init = 'random',
                      n_init = 1,max_iter=3,random_state=1)
#init:10默认,inherited(找最好的一次输出),k坐标初始随机位置
#max_iteration:最大迭代次数
kmeans_iter1.fit(x)
kmeans_iter2.fit(x)
kmeans_iter3.fit(x)

3、画图

def plot_data(x,y=None):#绘制无监督的图
    plt.plot(x[:,0],x[:,1],'k.')#绘制数据点
    
    
# 绘制中心点
def plot_centroids(centroids,weights=None,circle_color='w',
                   cross_color='r'):
    plt.scatter(centroids[:, 0], centroids[:, 1],
                marker='^', s=30, linewidths=8,
                color=circle_color, zorder=10, alpha=0.9)
    
    
#绘制决策边界
def plot_decision_boundaries(kmeans,x,resolution=1000,
                             show_centroids=True,
                            show_xlabels=True,show_ylabels=True):
    mins=x.min(axis=0)-0.1#x(2000,2)
    maxs=x.max(axis=0)+0.1#0:列,1:行;

    xx,yy=np.meshgrid(np.linspace(mins[0],maxs[0],resolution),
                      np.linspace(mins[1],maxs[1],resolution))
    z=kmeans.predict(np.c_[xx.ravel(),yy.ravel()]).reshape(xx.shape)
    #等高线加颜色
    plt.contour(z,extent=(mins[0],maxs[0],mins[1],maxs[1]),
                 linewidths=1,color='b')
    #等高线
    plt.contourf(z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
                cmap="Pastel2")
    
    
    plot_data(x)
    
    if show_centroids:
        plot_centroids(kmeans.cluster_centers_)

    if show_xlabels:
        plt.xlabel("$x_1$", fontsize=14)
    else:
        plt.tick_params(labelbottom='off')
        
    if show_ylabels:
        plt.ylabel("$x_2$", fontsize=14, rotation=0)
    else:
        plt.tick_params(labelleft='off')

plt.figure(figsize=(12,8))


plt.subplot(321)
plot_data(x)
plot_centroids(kmeans_iter1.cluster_centers_, 
               circle_color='w')
plt.title('Update cluster_centers')


plt.subplot(322)
plot_decision_boundaries(kmeans_iter1, x,show_xlabels=False, 
                         show_ylabels=False)
plt.title('Label')


plt.subplot(323)
plot_decision_boundaries(kmeans_iter1, x,show_xlabels=False, 
                         show_ylabels=False)
plot_centroids(kmeans_iter2.cluster_centers_,)


plt.subplot(324)
plot_decision_boundaries(kmeans_iter2, x,show_xlabels=False, 
                         show_ylabels=False)


plt.subplot(325)
plot_decision_boundaries(kmeans_iter2, x,show_xlabels=False, 
                         show_ylabels=False)
plot_centroids(kmeans_iter3.cluster_centers_,)


plt.subplot(326)
plot_decision_boundaries(kmeans_iter3, x,
                         show_xlabels=False, show_ylabels=False)

plt.show()

在这里插入图片描述

评价标准

1、inertia:

每个样本与其质心的最短距离的平方的总和
sum(每个样本与其质心的距离(样本到各个质心的最小值)**2)
?找找那个k值inertia最小

kmeans_per_k=[KMeans(n_clusters=k).fit(x) for k in range(1,10)]
inertial=[model.inertia_ for model in kmeans_per_k]

plt.figure(figsize=(8,4))
plt.plot(range(1,10),inertial,'bo-')
plt.axis([1,8.5,0,1500])

plt.show()

在这里插入图片描述

2、轮廓系数:

在这里插入图片描述
?对比那个k轮廓系数最小

from sklearn.metrics import silhouette_score
silhouette_score(x,kmeans.labels_)

silhouette_scores =[silhouette_score(x,model.labels_) for model in kmeans_per_k[1:]]
# Note that Silhouette Coefficient is only defined 
# if number of labels is 2 <= n_labels <= n_samples - 1.

plt.figure(figsize=(8,4))
plt.plot(range(2,10),silhouette_scores,'bo-')
plt.show()

在这里插入图片描述

kmeans初始点选择对比

1、数据

x1, y1 = make_blobs(n_samples=1000, centers=((4, -4), (0, 0)), 
                    random_state=42)
x1 = x1.dot(np.array([[0.374, 0.95], [0.732, 0.598]]))

x2, y2 = make_blobs(n_samples=250, centers=1, random_state=42)
x2 = x2 + [6, -8]

x = np.r_[x1, x2]
y = np.r_[y1, y2]

2、训练

kmeans_good = KMeans(n_clusters=3,init=np.array([[-1.5,2.5],[0.5,0],[4,0]]),n_init=1,random_state=42)
#
# init,k值的初始地址,可以指定

kmeans_bad = KMeans(n_clusters=3,random_state=42)

kmeans_good.fit(x)
kmeans_bad.fit(x)

3、画图:
在这里插入图片描述

plt.figure(figsize = (10,4))
plt.subplot(121)
plot_decision_boundaries(kmeans_good,x)
plt.title('Good - inertia = {}'.format(kmeans_good.inertia_))

plt.subplot(122)
plot_decision_boundaries(kmeans_bad,x)
plt.title('Bad - inertia = {}'.format(kmeans_bad.inertia_))

优劣势:

优:
简单,高效,时候常规数据集
缺:
k值难确定
复杂度与样本呈线性关系
很难发现任意形状的簇

DBSCAN算法

Density-Based Spatial Clustering of Applications with Noise
主要区别:不需要设置k值,当某个点的密度达到算法设定的阈值则将其设为核心点,需要两个参数,在r领域(半径为r)内点的数量不少于minPts

概念

1、直接密度可达:
若p在q的r领域内,则p,q称为直接密度可达
2、密度可达:
若有一个点序列q0,q1,,qk,对任意qi-qj-1是直接密度可达,则成q0-qk是密度可达
3、密度相连:
若q对p,r都是密度可达的,那么p-r是密度项链
4、边界点:
属于某一个类的非核心点,不能发展下线
5、噪声点:
不属于任何一个类簇的点,从任何一个核心点出发都是密度不可达的
6、过程

假代码:
D:数据集
r:半径大小
MinPts:密度阙值

标记所有对象为unvisited;
do
	随机选择一个unvisited对象p
	标记p为visited
	if p的r领域内至少有MinPts个对象
		创建一个新簇C,并将p添加到C中;
		令N为p的r领域中对象的集合
		for N中的对象p
			if p是unvisited
				标记p为visited
				if p的r领域内至少有MinPts个对象
					把这些对象添加到N
				if p不是任何簇的成员
					把p田间到C中
		end for
		输出C
	else
		标记p为噪声点
until 没有标为unvisite的对象

优劣势

优点:
1、不需要指定簇的个数
2、可以发现任意形状的簇
3、擅长找到离群点
4、一共需要两个参数
缺点
高维度较难
参数难以选择
sklearn效率较慢

代码实现:

对比查看r不同所产生的效果:
1、数据导入:

from sklearn.datasets import make_moons
x, y = make_moons(n_samples=1000, noise=0.05, random_state=42)

2、训练数据:

from sklearn.cluster import DBSCAN

dbscan = DBSCAN(eps = 0.05,min_samples=5)
#r=eps,min_samples=
dbscan.fit(x)

dbscan2 = DBSCAN(eps = 0.2,min_samples=5)
dbscan2.fit(x)

参数说明:
print(np.unique(dbscan.labels_))#7簇,-1为离群点
可以查看分为多少类,相当于k值
3、画图展示:

def plot_dbscan(dbscan, X, size, show_xlabels=True, show_ylabels=True):
    core_mask = np.zeros_like(dbscan.labels_, dtype=bool)
    core_mask[dbscan.core_sample_indices_] = True
    
    anomalies_mask = dbscan.labels_ == -1#噪声点
    non_core_mask = ~(core_mask | anomalies_mask)

    cores = dbscan.components_#含义(1000,2)
    anomalies = X[anomalies_mask]
    non_cores = X[non_core_mask]
    
    plt.scatter(cores[:, 0], cores[:, 1],
                c=dbscan.labels_[core_mask],
                marker='o', s=size, cmap="Paired")
    plt.scatter(cores[:, 0], cores[:, 1], 
                marker='*', s=20, c=dbscan.labels_[core_mask])
    
    plt.scatter(anomalies[:, 0], anomalies[:, 1],
                c="r", marker="x", s=100)
    
    plt.scatter(non_cores[:, 0], non_cores[:, 1], 
                c=dbscan.labels_[non_core_mask], marker=".")
    
    
    if show_xlabels:
        plt.xlabel("$x_1$", fontsize=14)
    else:
        plt.tick_params(labelbottom='off')
    if show_ylabels:
        plt.ylabel("$x_2$", fontsize=14, rotation=0)
    else:
        plt.tick_params(labelleft='off')
    plt.title("eps={:.2f}, min_samples={}".format(dbscan.eps, dbscan.min_samples), fontsize=14)


plt.figure(figsize=(9, 3.2))

plt.subplot(121)
plot_dbscan(dbscan, x, size=100)

plt.subplot(122)
plot_dbscan(dbscan2, x, size=600, show_ylabels=False)

plt.show()

在这里插入图片描述

分割颜色练习

1、图片作为数据:

from matplotlib.image import imread
image = imread('ladybug.png')
x = image.reshape(-1,3)#将长宽化成一维

2、训练模型

kmeans = KMeans(n_clusters = 8,random_state=42).fit(x)

3、用中心点进行聚类

segmented_img = kmeans.cluster_centers_[kmeans.labels_].reshape(533, 800, 3)
#kmeans.labels_预测的分类结果
#kmeans.cluster_centers_中心点的坐标表示

4、进行颜色分类

segmented_imgs=[]
n_colors=(10,8,6,4,2)
for n_cluster in n_colors:
    kmeans=KMeans(n_clusters=n_cluster,random_state=42).fit(x)#实例化
    print(np.unique(kmeans.labels_))
    segmented_img = kmeans.cluster_centers_[kmeans.labels_]
    segmented_imgs.append(segmented_img.reshape(image.shape))

5、展示:

plt.figure(figsize=(10,5))
plt.subplot(231)
plt.imshow(image)
plt.title('Original image')

for idx,n_clusters in enumerate(n_colors):
    plt.subplot(232+idx)
    plt.imshow(segmented_imgs[idx])
    plt.title('{}colors'.format(n_clusters))

在这里插入图片描述

半监督学习

部分有标签,部分无标签,所以称为半监督学习

# 1、导入数据,划分数据集
from sklearn.datasets import load_digits

x_digits,y_digits = load_digits(return_X_y = True)

from sklearn.model_selection import train_test_split

x_train,x_test,y_train,y_test = train_test_split(x_digits,y_digits,random_state=42)

1、监督学习

直接使用有标签的进行逻辑回归学习

from sklearn.linear_model import LogisticRegression
n_labeled = 50

log_reg = LogisticRegression(random_state=42)#逻辑回归
log_reg.fit(x_train[:n_labeled], y_train[:n_labeled])
log_reg.score(x_test, y_test)

0.8266666666666667

2、对质心进行人工监督学习

1、选取质心点
1、聚类

k = 50
kmeans = KMeans(n_clusters=k, random_state=42)
x_digits_dist = kmeans.fit_transform(x_train)

2、选取最小的点,距中心分类最小的就是质心点

representative_digits_idx = np.argmin(x_digits_dist,axis=0)#
x_representative_digits = x_train[representative_digits_idx]

3、显示:

plt.figure(figsize=(8, 2))
for index, x_representative_digit in enumerate(x_representative_digits):
    plt.subplot(k // 10, 10, index + 1)
    plt.imshow(x_representative_digit.reshape(8, 8), 
               cmap="binary", interpolation="bilinear")
    plt.axis('off')

plt.show()

在这里插入图片描述

4、看图,人工写出结果,进行监督学习

y_representative_digits = np.array([
    4, 8, 0, 6, 8, 3, 7, 7, 9, 2,
    5, 5, 8, 5, 2, 1, 2, 9, 6, 1,
    1, 6, 9, 0, 8, 3, 0, 7, 4, 1,
    6, 5, 2, 4, 1, 8, 6, 3, 9, 2,
    4, 2, 9, 4, 7, 6, 2, 3, 1, 1])
log_reg = LogisticRegression(random_state=42)
log_reg.fit(x_representative_digits, y_representative_digits)
log_reg.score(x_test, y_test)

0.92

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值