机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

 K-means聚类算法的探索

import  numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import matplotlib.colors
from sklearn.cluster import  KMeans,MiniBatchKMeans

def expand(a,b):
    d=(b-a)*0.1
    return a-d,b+d
if __name__ == '__main__':
    N=400               #创建400个样本
    centers=4           #创建4组数据
    # n_features=2 样本含有2个维度  centers这样样本分布到4个簇中
    # 返回值 data 数据,y的含义是 因为我们是通过ds创建的数据  其实是知道数据在那个标签中的
    data,y=ds.make_blobs(N,n_features=2,centers=centers,random_state=2)
    # 指定四个组的方差创建数据
    data2,y2 = ds.make_blobs(N, n_features=2, centers=centers,cluster_std=(1,2.5,0.5,2),random_state=2)
    #把第一组数据的所有数据 第二组数据到额前50个 第三组数据的前20个  第四组数据的前5个
    data3=np.vstack((data[y==0][:],data[y==1][:50],data[y==2][:20],data[y==3][:5]))
    # 为拿出来的data3 数据打标签
    y3=np.array([0]*100+[1]*50+[2]*20+[3]*5)
    #  创建KMeans 对象
    cls=KMeans(n_clusters=4,init='k-means++')  #初始
    y_hat=cls.fit_predict(data)  #训练并与预测data
    y2_hat = cls.fit_predict(data2) #训练并与预测data2
    y3_hat = cls.fit_predict(data3) #训练并与预测data3

    m=np.array(((1,1),(1,3)))  #创建一个矩阵
    data_r=data.dot(m)         #用创建的矩阵对data进行线性变换
    y_r_hat=cls.fit_predict(data_r)  #训练并与预测data_r
    matplotlib.rcParams['font.sans-serif']=[u'SimHei'] #可以显示中文
    matplotlib.rcParams['axes.unicode_minus'] = False
    cm=matplotlib.colors.ListedColormap(list('rgbm'))
    plt.figure(figsize=(9,10),facecolor='w')
    plt.subplot(421)
    plt.title(u'原始数据')
    plt.scatter(data[:,0],data[:,1],c=y,s=30,cmap=cm,edgecolors='none')
    x1_min, x2_min = np.min(data, axis=0)
    x1_max, x2_max = np.max(data, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(422)
    plt.title(u'KMeans++聚类')
    plt.scatter(data[:, 0], data[:, 1], c=y_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(423)
    plt.title(u'旋转后数据')
    plt.scatter(data_r[:, 0], data_r[:, 1], c=y, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data_r, axis=0)
    x1_max, x2_max = np.max(data_r, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(424)
    plt.title(u'旋转后KMeans++聚类')
    plt.scatter(data_r[:, 0], data_r[:, 1], c=y_r_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(425)
    plt.title(u'方差不相等数据')
    plt.scatter(data2[:, 0], data2[:, 1], c=y2, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data2, axis=0)
    x1_max, x2_max = np.max(data2, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(426)
    plt.title(u'方差不相等KMeans++聚类')
    plt.scatter(data2[:, 0], data2[:, 1], c=y2_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(427)
    plt.title(u'数量不相等数据')
    plt.scatter(data3[:, 0], data3[:, 1], s=30, c=y3, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data3, axis=0)
    x1_max, x2_max = np.max(data3, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(428)
    plt.title(u'数量不相等KMeans++聚类')
    plt.scatter(data3[:, 0], data3[:, 1], c=y3_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.tight_layout(2, rect=(0, 0, 1, 0.97))
    plt.suptitle(u'数据分布对KMeans聚类的影响', fontsize=18)
    # https://github.com/matplotlib/matplotlib/issues/829
    # plt.subplots_adjust(top=0.92)
    plt.show()
    # plt.savefig('cluster_kmeans')



机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

 相关指标的探索

# !/usr/bin/python
# -*- coding:utf-8 -*-

from sklearn import metrics


if __name__ == "__main__":
    y = [0, 0, 0, 1, 1, 1]
    y_hat = [0, 0, 1, 1, 2, 2]
    h = metrics.homogeneity_score(y, y_hat)
    c = metrics.completeness_score(y, y_hat)
    print(u'同一性(Homogeneity):', h)
    print(u'完整性(Completeness):', c)
    v2 = 2 * c * h / (c + h)
    v = metrics.v_measure_score(y, y_hat)
    print(u'V-Measure:', v2, v)

    y = [0, 0, 0, 1, 1, 1]
    y_hat = [0, 0, 1, 3, 3, 3]
    h = metrics.homogeneity_score(y, y_hat)
    c = metrics.completeness_score(y, y_hat)
    v = metrics.v_measure_score(y, y_hat)
    print(u'同一性(Homogeneity):', h)
    print(u'完整性(Completeness):', c)
    print(u'V-Measure:', v)

    # 允许不同值
    y = [0, 0, 0, 1, 1, 1]
    y_hat = [1, 1, 1, 0, 0, 0]
    h = metrics.homogeneity_score(y, y_hat)
    c = metrics.completeness_score(y, y_hat)
    v = metrics.v_measure_score(y, y_hat)
    print(u'同一性(Homogeneity):', h)
    print(u'完整性(Completeness):', c)
    print(u'V-Measure:', v)

    y = [0, 0, 1, 1]
    y_hat = [0, 1, 0, 1]
    ari = metrics.adjusted_rand_score(y, y_hat)
    print(ari)

    y = [0, 0, 0, 1, 1, 1]
    y_hat = [0, 0, 1, 1, 2, 2]
    ari = metrics.adjusted_rand_score(y, y_hat)
    print(ari)

结果

同一性(Homogeneity): 0.6666666666666669
完整性(Completeness): 0.420619835714305
V-Measure: 0.5158037429793889 0.5158037429793889
同一性(Homogeneity): 1.0
完整性(Completeness): 0.6853314789615865
V-Measure: 0.8132898335036762
同一性(Homogeneity): 1.0
完整性(Completeness): 1.0
V-Measure: 1.0
-0.5
0.24242424242424243

Process finished with exit code 0

层次聚类

• 解决了k-means k值选择和初始中心点选择的问题 • 分为 分裂法 和 凝聚法

分裂法

• 1.将所有样本归为一个簇         • While 不满足条件(k个数或距离阈值):                 • 在同一个簇C中计算样本间距离,选最远的距离的两个样本ab(终止条件检测)                 • 将样本a,b划入c1 c2(终止条件检测)                 • 计算原簇c中样本离谁近 划入谁 机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

 

凝聚法 

1.将所有点看做一个独立的簇         • While 不满足条件:                 • 计算两两簇之间的距离,找到最小距离的簇C1 和C2(多种计算方式)                 • 合并C1 C2          •合并C1  C2 的方式 :         • 1. 两个簇间距离最小的样本距离         • 2 两个簇间最远的两个点的距离         • 3. 两个簇之间两两求距离的平局值         • 4. 两个粗之间两两求距离的中位数         • 5. 求每个集合的中心点 中心点的距离代表簇的距离

层次聚类对比 k-means

        机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

密度聚类-DBSCAN

 

• DBSCAN(Density-Based Spatial Clustering of Applications with Noise)

 

• 一个基于密度聚类的算法 ,与层次聚类不同 ,它将簇定义为密度相连的点的最大集合,能够把具 有高密度的区域划分为簇,并可有效地对抗噪声 问:将簇定义为密度相连的点的最大集合? 概念一:直接密度可达:         • 对象的e邻域:给定对象在半径e内的区域;         • 核心对象 :给定一个数目m,如果对象的e邻域中有至少m个对象,               该对象为核心对象         • 直接密度可达:给定一个对象集合D, 如果p在q的e邻域内,而q是一个核心对象,p从q                                         出发是直接密度可达的 机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

         • 密度可达:如果存在一个对象链p1p2…pn ,令p1=p,pn=q,pi+1是关于e和m直接密度可达的,则对象p是从对象q关于e和m密度可达的。

       • 密度相连:如果集合D中存在一个对象o,使o->p 密度可达,o->q 密度可达,那么p和q就是关 于e和m密度相连的 机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

 

DB SCAN算法

• DB-SCAN 通过检查数据集中每个对象的e邻域来寻找聚类 • 如果一个点p的e邻域中多余m 个对象,则创建一个p为核心的新 簇,依据p来反复寻找密度相连的集合(有可能合并原有已经生成的簇)当没有任何新的点可以被添加到簇中的时候,寻找结束。

DB_SCAN探索

# !/usr/bin/python
# -*- coding:utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import matplotlib.colors
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler


def expand(a, b):
    d = (b - a) * 0.1
    return a-d, b+d


if __name__ == "__main__":
    N = 1000
    centers = [[1, 2], [-1, -1], [1, -1], [-1, 1]]
    data, y = ds.make_blobs(N, n_features=2, centers=centers, cluster_std=[0.5, 0.25, 0.7, 0.5], random_state=0)
    data = StandardScaler().fit_transform(data)
    # 数据的参数:(epsilon, min_sample)  #epsilon 半径大小  min_sample 在半径内最小的样本个数,用于判断是否是核心对象
    params = ((0.2, 5), (0.2, 10), (0.2, 15), (0.3, 5), (0.3, 10), (0.3, 15))

    matplotlib.rcParams['font.sans-serif'] = [u'SimHei']
    matplotlib.rcParams['axes.unicode_minus'] = False

    plt.figure(figsize=(12, 8), facecolor='w')
    plt.suptitle(u'DBSCAN聚类', fontsize=20)

    for i in range(6):
        eps, min_samples = params[i]
        model = DBSCAN(eps=eps, min_samples=min_samples)
        model.fit(data)
        y_hat = model.labels_

        core_indices = np.zeros_like(y_hat, dtype=bool)
        core_indices[model.core_sample_indices_] = True

        y_unique = np.unique(y_hat)
        n_clusters = y_unique.size - (1 if -1 in y_hat else 0)
        print(y_unique, '聚类簇的个数为:', n_clusters)

        plt.subplot(2, 3, i+1)
        clrs = plt.cm.Spectral(np.linspace(0, 0.8, y_unique.size))
        print(clrs)
        for k, clr in zip(y_unique, clrs):
            cur = (y_hat == k)
            if k == -1:
                plt.scatter(data[cur, 0], data[cur, 1], s=20, c='k')
                continue
            plt.scatter(data[cur, 0], data[cur, 1], s=30, c=clr, edgecolors='k')
            plt.scatter(data[cur & core_indices][:, 0], data[cur & core_indices][:, 1], s=60, c=clr, marker='o', edgecolors='k')
        x1_min, x2_min = np.min(data, axis=0)
        x1_max, x2_max = np.max(data, axis=0)
        x1_min, x1_max = expand(x1_min, x1_max)
        x2_min, x2_max = expand(x2_min, x2_max)
        plt.xlim((x1_min, x1_max))
        plt.ylim((x2_min, x2_max))
        plt.grid(True)
        plt.title(u'epsilon = %.1f  m = %d,聚类数目:%d' % (eps, min_samples, n_clusters), fontsize=16)
    plt.tight_layout()
    plt.subplots_adjust(top=0.9)
    plt.show()

机器学习算法 08 聚类探索(04 K-means聚类算法的探索,层次聚类概念,密度聚类-DBSCAN探索)

 

上一篇:C语言笔记(翁凯老师)


下一篇:力扣 373. 查找和最小的K对数字