• 机器学习


    聚类算法

    概述

    无监督问题  手中无标签

    聚类  将相似的东西分到一组

    难点  如何 评估, 如何 调参

    基本概念

    要得到的簇的个数   - 需要指定 K 值

    质心   - 均值, 即向量各维度取平均

    距离的度量  - 常用 欧几里得距离余弦线相似度 ( 先标准化 )

    优化目标  - 

    需求每个簇中的点, 到质心的距离尽可能的加和最小, 从而得到最优 

    K - MEANS 算法

    工作流程

    - (a)    初始图

    - (b)   在指定了 K 值之后, 会在图中初始化两个点 红点, 蓝点( 随机质心 )    这里 K 指定为 2 

    - (c)   然后对图中的每一个点计算是分别到红点以及蓝点的距离, 谁短就算谁的

    - (d)   重新将红色蓝色区域计算质心

    - (e)   根据重新计算的质心, 再次遍历所有点计算到两个新质点的距离对比划分

    - (f)    按照之前的套路再次更新质点

    就这样不断的更新下去, 直到所有的样本点都不再发生变化的时候则表示划分成功

    优势

    简单快速, 适合常规数据集

    劣势

    K 值难以决定

    复杂度与样本呈线性关系

    很难发现任意形状的簇 ,  如下图

    非常依赖初始点, 如果初始点设定很不好会影响迭代次数甚至无法达到最优解

      实际操作很不稳定, 需要多次设定初始点进行操作对比

    图像压缩实例

    将彩色 三通道 RGB 0~255 的青取值压缩成 单通道 0~128 的取值

    解压缩

    DBSCAN 算法

    基本概念

    核心对象  

    若某个点的密度达到算法设定的阈值则其为核心点 ( 即 r 邻域内点的数量不小于 minPts )

    即这点画一个半径为 r 的圆, 圆内的点的数量不小于我们设定的最小数量, 这个点就是核心点

    € - 领域的距离阈值

    设定的半径 r, 就是上面画圈用的半径

    直接密度可达 

    若某点 p 在点 q 的 r 邻域内, 且 q 是核心点则 p-q 直接密度可达

    密度可达

    若有一个点的序列 q0.q1,.....qk, 对任意 qi - qi -1 是直接密度可达, 则称 q0 到 qk 密度可达

    这实际上是直接密度可达的 '传播' 

    如图, q1 对 q0 是直接密度可达

    q2 对 q1 是直接密度可达, 

    因此 尽管 q2 并不在 q0 的 r 半径的区域内

    q2 还是可以通过 q1 对 q0 密度可达

    密度相连

    若从某核心点 p 出发, 点 q 和点 k 都是密度可达的, 则称点 q 和点 k 是 密度相连的

    边界点

    属于某一个类的非核心点, 不能发展下线了

    噪声点

    不属于任何一个类簇的点, 从任何一个核心点出发都是密度不可达

     

    参数

    参数 D   数据集

    参数 €  指定半径

    MinPts  密度阈值

    流程

    1.   标记所有的对象为 unvsited 

    2.  随机选择一个对象为 p 为 visited

    3.  if  p 的 € 半径内的领域至少有 MinPts 个对象

      3.1  创建一个 新簇 C 并把 这些对象添加到 N

      3.2  for N 中的每个点 p

        3.2.1  if p 是 unvsited :

          3.2.1.1  标记 p 为 visited

          3.2.1.2  if p 的  € 半径内的领域至少有 MinPts 个对象, 把这些对象添加到 N 

          3.2.1.3  if p 不是任何 簇的成员, 把 p 添加到 C

      3.3  输出 C

    4.  标记 p 为噪声 

    5.   为 unvsited  在创建新的 簇 C2 

    6.  不断循环直到所有的 对象都成为 visited

    参数选择

    优势

    不需要指定 簇的个数

    可以发现任意形状的簇

    擅长找出离群点 ( 检测任务 )

    两个参数就够了

    劣势

    高维度数据有些困难 ( 可以做降为 )

    参数难以选择 ( 参数对结果的影响非常大 )

    Sklearn 中效率很慢 ( 数据削减策略 )

    聚类算法对比

     DBSCAN 是有着绝对大的优势比起其他的算法,  其他三个算法中值得一提的是 BIRCH 的增量更新的速度是最快的, 对于结果最高要求的话还是推荐 DBSCAN 对于速度要求的话就 BIRCH 好了

    聚类练习实例

    数据集

    # beer dataset
    import pandas as pd
    
    beer = pd.read_csv('data.txt', sep=' ')
    beer

     

    X = beer[["calories","sodium","alcohol","cost"]]

    KMeans 算法

    模型

    训练两个模型做对比, 只需要指定堆的数量即可

    from sklearn.cluster import KMeans
    
    km = KMeans(n_clusters=3).fit(X)
    km2 = KMeans(n_clusters=2).fit(X)

    数据展示

    训练完后就可以拿到标签, 这里因为指定了三个类别, 因此 取值为 0,1,2 

    km.labels_
    array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 2, 0, 0, 2, 1])

    方便查看重新组合一下数据

    beer['cluster'] = km.labels_
    beer['cluster2'] = km2.labels_
    beer.sort_values('cluster')

     

    查看数据的均值

    beer.groupby("cluster").mean()

     

     取出中心点位置

    centers = beer.groupby("cluster").mean().reset_index()

     画图展示

    %matplotlib inline
    import matplotlib.pyplot as plt
    plt.rcParams['font.size'] = 14
    import numpy as np
    colors = np.array(['red', 'green', 'blue', 'yellow'])
    plt.scatter(beer["calories"], beer["alcohol"],c=colors[beer["cluster"]])
    
    plt.scatter(centers.calories, centers.alcohol, linewidths=3, marker='+', s=300, c='black')
    
    plt.xlabel("Calories")
    plt.ylabel("Alcohol")

     

    混淆矩阵展示 所有的特征之间的关系展示

    from pandas.plotting import scatter_matrix
    %matplotlib inline
    
    cluster_centers = km.cluster_centers_
    
    cluster_centers_2 = km2.cluster_centers_
    scatter_matrix(beer[["calories","sodium","alcohol","cost"]],s=100, alpha=1, c=colors[beer["cluster"]], figsize=(10,10))
    plt.suptitle("With 3 centroids initialized")

     

    scatter_matrix(beer[["calories","sodium","alcohol","cost"]],s=100, alpha=1, c=colors[beer["cluster2"]], figsize=(10,10))
    plt.suptitle("With 2 centroids initialized")

    两个簇的混淆矩阵

     

    标准化处理

    在 sklearn 中的 预处理模块中使用标准化方法将数据处理一下

    将原来的数据浮动大小转变成差不多的大小, 从而消除数值之间的差异性

    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    X_scaled
    array([[ 0.38791334,  0.00779468,  0.43380786, -0.45682969],
           [ 0.6250656 ,  0.63136906,  0.62241997, -0.45682969],
           [ 0.82833896,  0.00779468, -3.14982226, -0.10269815],
           [ 1.26876459, -1.23935408,  0.90533814,  1.66795955],
           [ 0.65894449, -0.6157797 ,  0.71672602,  1.95126478],
           [ 0.42179223,  1.25494344,  0.3395018 , -1.5192243 ],
           [ 1.43815906,  1.41083704,  1.1882563 , -0.66930861],
           [ 0.55730781,  1.87851782,  0.43380786, -0.52765599],
           [-1.1366369 , -0.7716733 ,  0.05658363, -0.45682969],
           [-0.66233238, -1.08346049, -0.5092527 , -0.66930861],
           [ 0.25239776,  0.47547547,  0.3395018 , -0.38600338],
           [-1.03500022,  0.00779468, -0.13202848, -0.24435076],
           [ 0.08300329, -0.6157797 , -0.03772242,  0.03895447],
           [ 0.59118671,  0.63136906,  0.43380786,  1.88043848],
           [ 0.55730781, -1.39524768,  0.71672602,  2.0929174 ],
           [-2.18688263,  0.00779468, -1.82953748, -0.81096123],
           [ 0.21851887,  0.63136906,  0.15088969, -0.45682969],
           [ 0.38791334,  1.41083704,  0.62241997, -0.45682969],
           [-2.05136705, -1.39524768, -1.26370115, -0.24435076],
           [-1.20439469, -1.23935408, -0.03772242, -0.17352445]])
    km = KMeans(n_clusters=3).fit(X_scaled)
    beer["scaled_cluster"] = km.labels_
    beer.sort_values("scaled_cluster")

     

    聚类评估 - 轮廓系数

     

    • 计算样本i到同簇其他样本的平均距离ai
      • ai 越小,说明样本i越应该被聚类到该簇
      • 将ai 称为样本i的簇内不相似度
    • 计算样本i到其他某簇Cj 的所有样本的平均距离bij
      • bi 越大, 表示离其他簇越远
      • 称为样本i与簇Cj 的不相似度
      • 定义为样本i的簇间不相似度:bi =min{bi1, bi2, ..., bik}
    • si接近1,则说明样本i聚类合理
    • si接近-1,则说明样本i更应该分类到另外的簇
    • 若si 近似为0,则说明样本i在两个簇的边界上
    from sklearn import metrics
    score_scaled = metrics.silhouette_score(X,beer.scaled_cluster)
    score = metrics.silhouette_score(X,beer.cluster)
    print(score_scaled, score)

    结果做了标准化的结果居然比没做标准化结果的更差了. 所以标准化有时候也需要取舍

    0.1797806808940007 0.6731775046455796

    参数选择

     K 参数的不知道怎么选那就利用上面的评测分别评测一遍试下

    scores = []
    for k in range(2,20):
        labels = KMeans(n_clusters=k).fit(X).labels_
        score = metrics.silhouette_score(X, labels)
        scores.append(score)
    
    scores
    [0.6917656034079486,
     0.6731775046455796,
     0.5857040721127795,
     0.422548733517202,
     0.39888288049162546,
     0.43776116697963124,
     0.38946337473125997,
     0.39746405172426014,
     0.3915697409245163,
     0.32472080133848924,
     0.3459775237127248,
     0.31221439248428434,
     0.30707782144770296,
     0.2736836031737978,
     0.2849514001174898,
     0.23498077333071996,
     0.1588091017496281,
     0.08423051380151177]

     可见 k = 2 的时候 0.69 是最高的

    画图展示更加直观

    plt.plot(list(range(2,20)), scores)
    plt.xlabel("Number of Clusters Initialized")
    plt.ylabel("Sihouette Score")

    DBSCAN 算法 

    对于不规则的更推荐 DBSCAN 算法, 但是简单的数据集上可能还不如 KMEANS 

    创建模型

    from sklearn.cluster import DBSCAN
    db = DBSCAN(eps=10, min_samples=2).fit(X)

     取出分类结果

    labels = db.labels_

     组合数据

    beer['cluster_db'] = labels
    beer.sort_values('cluster_db')

     

     查看数据

    beer.groupby('cluster_db').mean()

     画图展示

    scatter_matrix(X, c=colors[beer.cluster_db], figsize=(10,10), s=100)

     

  • 相关阅读:
    ConcurrentHashMap使用示例
    vss的ss.ini丢失或损坏导致的vss无法登录错误
    Arcgis中用滚轮做放大缩小为什么和一般软件反向
    MapControl控件
    string截取字符串
    C# CheckedListBox控件用法总结(怎样得到多选的值)
    通信串口中报ObjectDisposedException错误时怎么解决
    C#串口SerialPort常用属性方法
    SerialPort.DataReceived 事件
    C#的串口编程
  • 原文地址:https://www.cnblogs.com/shijieli/p/11925823.html
Copyright © 2020-2023  润新知