#第28篇分享:数据聚类及降维(python语言:sklearn 聚类算法KMeans)(4)

#聚类算法是一种无监督学习算法,也就是只有特征而没有标签,我们要做的就是把特征相似的聚类到一起:实际应用可以做图片颜色特征的降维:

a.K-means聚类算法(无监督学习:):

①算法概念
KMeans算法是将N个样本的特征矩阵划分为K个无交集的簇;簇中的均值通常被称为这个簇的质心;随机/有选择的抽取K个质心-》开始循环-》将每个样本点分配到离他们最近的质心,生成K个簇-》对每个簇计算所有被分到该簇的样本点平均值作为新的质心-》当质心不再变化,迭代停止,聚类完成;

从上面可以看出,质心的选择及K的选择会影响最终的聚类效果。

②.算法思路:视频讲解
要求:组内差异小,组间差异大;欧式距离(质心均值),曼哈顿距离(质心中位数),余弦距离(质心均值);簇内平方和:inertia,KMeans追求的是求解能让inertia(簇内平方和)最小化的质心;我们一般使用欧氏距离,见下图:
#第28篇分享:数据聚类及降维(python语言:sklearn 聚类算法KMeans)(4)_第1张图片
#1.轮廓系数(主要使用的方式:越接近1越好):评价聚类的效果的方式:b簇外差异,a簇内差异:
#第28篇分享:数据聚类及降维(python语言:sklearn 聚类算法KMeans)(4)_第2张图片
#2.除轮廓系数还有很多评估指标,主要介绍卡林斯基-哈拉巴斯指数:越大越好,比轮廓系数的优势是计算快,缺点是无上限:
#第28篇分享:数据聚类及降维(python语言:sklearn 聚类算法KMeans)(4)_第3张图片
③优缺点:
优点:算法容易理解,聚类效果不错;具有出色的速度;当簇近似高斯分布时,效果比较好
缺点:需要自己确定K值,k值的选定是比较难确定;对初始中心点敏感
不适合发现非凸形状的簇或者大小差别较大的簇;特殊值/离群值对模型的影响比较大。

④.代码实例1(基于轮廓系数来寻找合适的质心个数):


#1.基于轮廓系数来选择质心个数:n_clusters
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples,silhouette_score

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

#首先设定我们要分的簇数:
n_clusters = 4

#创建一个画布,画布上面有一行两列:
fig,(ax1,ax2) = plt.subplots(1,2)
#画布尺寸:
fig.set_size_inches(18,7)

from sklearn.datasets import make_blobs
#a.自己创建数据集:
x,y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)

#要做什么:
'''
第一个图是我们轮廓系数的图像,是由各个簇的轮廓系数组成的横向条形图;
横坐标是轮廓系数的值,纵坐标是我们每个样本
'''
#x轴取值[-0.1,1]
ax1.set_xlim([-0.1,1])
#y轴取值:[0,x.shape[0]],每个簇的间隔:(n_clusters+1)*10
ax1.set_ylim(0,x.shape[0]+(n_clusters+1)*10)

#建模:调整好聚类的标签:
clusterer = KMeans(n_clusters=n_clusters,random_state=10).fit(x)
cluster_labels = clusterer.labels_

#调整轮廓系数:
silhoustte_avg = silhouette_score(x,cluster_labels)
print("For n_clusters = ",n_clusters,"The average silhouette_score is:",silhoustte_avg)

#调用silhouette_samples,返回每个样本点的轮廓系数,这就是我们的横坐标:
sample_silhouette_values = silhouette_samples(x,cluster_labels)

#设定y轴上的初始值:
y_lower = 10

#接下来对每个簇进行循环:
for i in range(n_clusters):
    #从每个样本的轮廓系数取出第i个簇的轮廓系数,并对他们进行排序
    ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels==i]
    #注意,.sort()这个命令会直接改变原数据顺序
    ith_cluster_silhouette_values.sort()

    #可以查看这个簇中究竟有多少个样本:
    size_cluster_i = ith_cluster_silhouette_values.shape[0]

    #这一个簇在y轴的取值,应该由y_lower开始,到初始值+这个簇中的样本数量结束y_upper
    y_upper = y_lower + size_cluster_i

    #每个簇生成不同的颜色:nipy_spectral中任意小数代表一个颜色
    color = cm.nipy_spectral(float(i)/n_clusters)

    # 开始填充子图1:参数:纵坐标下线,横坐标上线,柱状图颜色
    ax1.fill_betweenx(np.arange(y_lower, y_upper)
                      , ith_cluster_silhouette_values
                      , facecolor=color
                      , alpha=0.7
                      )

    #为每个簇的轮廓系数上写上簇的编号,并显示在坐标轴的中间位置
    #text用法:显示编号位置的横坐标,显示编号位置的纵坐标,要显示的编号内容
    ax1.text(-0.05
             ,y_lower+0.5*size_cluster_i
             ,str(i)
             )

    #保证每个簇之间存在空隙:
    y_lower = y_upper + 10

#给图一加上标题,横坐标,纵坐标标签:
ax1.set_title("The silhouette plot for the various clusters.")
ax1.set_xlabel("The silhouette coefficient values")
ax1.set_ylabel("Cluster label")

#把整个数据集上的轮廓系数的均值以虚线的形式放入我们的图中:
ax1.axvline(x=silhoustte_avg,color="red",linestyle="--")

#让y轴不显示刻度:
ax1.set_yticks([])

#让x轴上的刻度显示为我们规定的列表:
ax1.set_xticks([-0.1,0,0.2,0.4,0.6,0.8,1.0])

#########开始处理第二个图:

#首先获取颜色:
colors = cm.nipy_spectral(cluster_labels.astype(float)/n_clusters)

#首先绘制点的分布:
ax2.scatter(x[:,0],x[:,1]
            ,marker="o"
            ,s=8
            ,c=colors
            )
#把质心放入图片:
centers = clusterer.cluster_centers_

ax2.scatter(centers[:,0],centers[:,1]
            ,marker="x"
            ,c="red"
            ,alpha=1
            ,s=200
            )

#为图二设置标题,横坐标,纵坐标标题:
ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")

#为整个图设置标题:
plt.suptitle(("Silhouette analysis for KMeans clustering on sample data"
             "with n_clusters = %d"% n_clusters)
             ,fontsize=14,fontweight="bold")
plt.show()

#第28篇分享:数据聚类及降维(python语言:sklearn 聚类算法KMeans)(4)_第4张图片
代码实例2(聚类算法的实际应用:降维):

#5,聚类算法用于降维:
#导库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
#对两个序列中的点进行距离匹配的函数
from sklearn.metrics import pairwise_distances_argmin
#导入图片数据所需要的类:
from sklearn.datasets import load_sample_image
#对数据尽心重新随机排列
from sklearn.utils import shuffle

#实例化,导入颐和园的图片
china = load_sample_image("china.jpg")
#uint8 (427, 640, 3):长度-宽度-像素; [174 201 231] :这里图像使用RGB编码,每个像素由三个数字定义。
# print(china.dtype,china.shape,china[0][0],china)

#包含多少种不同颜色呢,三维变成二维:
newimage = china.reshape((427*640,3))

#查看一下数据的个数:
import pandas as pd
'''
在pandas中如何使用drop_duplicates进行去重。
df.drop_duplicates(subset=['A','B'],keep='first',inplace=True)
subset: 输入要进行去重的列名,默认为None
keep: 可选参数有三个:‘first’、 ‘last’、 False, 默认值 ‘first’。其中,
first表示: 保留第一次出现的重复行,删除后面的重复行。
last表示: 删除重复项,保留最后一次出现。
False表示: 删除所有重复项。
inplace:布尔值,默认为False,是否直接在原数据上删除重复项或删除重复项后返回副本。
'''
newimage = pd.DataFrame(newimage).drop_duplicates().shape

# #图像可视化:
# plt.figure(figsize=(15,15))
# plt.imshow(china)
# plt.show()
# print(newimage)


# #查看另一张图片:
# flower = load_sample_image("flower.jpg")
# #图像可视化:
# plt.figure(figsize=(15,15))
# plt.imshow(flower)
# plt.show()

'''
目的:颐和园图片有9W种颜色,我们要做的事情,就是
通过聚类,把图片颜色缩减为64种,看图片是否能正确
显示。
'''
n_clusters = 64

#plt.imshow在浮点数上表现优异,我们先转换为浮点数;
#然后对浮点数进行压缩至[0-1]之间处理;
china = np.array(china,dtype=np.float64)/china.max()

#把China从图像格式转化为矩阵格式:
w,h,d = original_shape = tuple(china.shape)
assert d == 3 #要求必须等于3,如果不等于就报错
image_array = np.reshape(china,(w*h,d))

#可以训练数据了,先用1000个数据寻找质心
image_array_sample = shuffle(image_array,random_state=0)[:1000]
kmeans = KMeans(n_clusters=n_clusters,random_state=0).fit(image_array_sample)

# print(kmeans.cluster_centers_.shape)

#找出质心后,按照已存在的质心对所有数据进行聚类:
labels = kmeans.predict(image_array)
print(labels.shape)

#使用质心代替原来的样本:
image_kmeans = image_array.copy()

for i in range(w*h):
    image_kmeans[i] = kmeans.cluster_centers_[labels[i]]

#数据还原为图片格式:
image_kmeans = image_kmeans.reshape(w,h,d)
print(image_kmeans.shape)
plt.figure(figsize=(15,15))
plt.imshow(image_kmeans)
plt.show()


#另一种方式实现随机矢量量化:
centroid_random = shuffle(image_array,random_state=0)[:n_clusters]
#pairwise_distances_argmin用来计算image_array中到centroid_random点的距离,并返回image_array形状相同的,centroid_random中最近样本点的值。
labels_random = pairwise_distances_argmin(centroid_random,image_array,axis=0)

#使用随机质心替换所有样本:
image_random = image_array.copy()
for i in range(w*h):
    image_random[i] = centroid_random[labels_random[i]]

#恢复图片结构:
image_random = image_random.reshape(w,h,d)

plt.figure(figsize=(15,15))
plt.imshow(image_random)
plt.show()

原图:

K-Means聚类后的图片:颜色特征聚类后被压缩:

另一种方式聚类降维:
#对两个序列中的点进行距离匹配的函数
from sklearn.metrics import pairwise_distances_argmin
pairwise_distances_argmin用来计算image_array中到centroid_random点的距离,并返回image_array形状相同的,centroid_random中最近样本点的值:使用随机质心替换所有样本:可以看出K-Means聚类的效果还是不错的:

以上就介绍了聚类的实例及聚类的一些概念,相信看完之后会有一点点感觉了。

持续更新,,,

你可能感兴趣的:(Skicit-learn,python,python,机器学习,kmeans算法,聚类)