机器学习之鸢尾花-聚类

2020-05-22 00:00:00 算法 对象 样本 密度 兰德


将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类。由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异。“物以类聚,人以群分”,在自然科学和社会科学中,存在着大量的分类问题。聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法。聚类分析起源于分类学,但是聚类不等于分类。聚类与分类的不同在于,聚类所要求划分的类是未知的。聚类分析内容非常丰富,有系统聚类法、有序样品聚类法、动态聚类法、模糊聚类法、图论聚类法、聚类预报法等。

如下:

# 一.kmeans聚类
# 算法流程:
# 1.选择聚类的个数k.
# 2.任意产生k个聚类,然后确定聚类中心,或者直接生成k个中心。
# 3.对每个点确定其聚类中心点。
# 4.再计算其聚类新中心。
# 5.重复以上步骤直到满足收敛要求。(通常就是确定的中心点不再改变。
# 优点:
# 1.是解决聚类问题的一种经典算法,简单、快速
# 2.对处理大数据集,该算法保持可伸缩性和高效率
# 3.当结果簇是密集的,它的效果较好
# 缺点
# 1.在簇的平均值可被定义的情况下才能使用,可能不适用于某些应用
# 2.必须事先给出k(要生成的簇的数目),而且对初值敏感,对于不同的初始值,可能会导致不同结果。
# 3.不适合于发现非凸形状的簇或者大小差别很大的簇
# 4.对躁声和孤立点数据敏感

# DBSCAN聚类算法概述:
#         DBSCAN属于密度聚类算法,把类定义为密度相连对象的大集合,通过在样本空间中不断搜索大集合完成聚类。
#         DBSCAN能够在带有噪点的样本空间中发现任意形状的聚类并排除噪点。
#         DBSCAN算法不需要预先指定聚类数量,但对用户设定的参数非常敏感。
# 当空间聚类的密度不均匀、聚类间距差相差很大时,聚类质量较差。
# DBSCAN算法基本概念:
#         核心对象:如果给定对象的半径eps邻域内样本数量超过阈值min_samples,则称为核心对象。
#         边界对象:在半径eps内点的数量小于min_samples,但是落在核心点的邻域内。
#         噪声对象:既不是核心对象也不是边界对象的样本。
#         直接密度可达:如果对象q在核心对象p的eps邻域内,则称q从p出发是直接密度可达的。
#         密度可达:集合中的对象链p1、p2、p3、...、pn,如果每个对象pi+1从pi出发都是直接密度可达的,则称pn从p1出发是密度可达的。
#         密度相连:集合中如果存在对象o使得对象p和q从o出发都是密度可达的,则称对象p和q是互相密度相连的。
# DBSCAN聚类算法工作过程:
#         1)定义邻域半径eps和样本数量阈值min_samples。
#         2)从样本空间中抽取一个尚未访问过的样本p。
#         3)如果样本p是核心对象,进入第4)步;否则返回第2)步。
#         4)找出样本p出发的所有密度可达对象,构成一个聚类Cp(该聚类的边界对象都是非核心对象),并标记这些对象为已访问。
#         5)如果全部样本都已访问,算法结束;否则返回第2)步。
from sklearn import metrics
from sklearn.cluster import KMeans
from sklearn.cluster import DBSCAN
def test_clustering(X_train, X_test, y_train, y_test,X,y):
        # 设定聚类模型参数,并进行训练
        kmeans = KMeans(init="k-means++", n_clusters=3)
        kmeans.fit(X)

        # 在kmeans中就包含了K均值聚类的结果:聚类中心点和每个样本的类别
        labels = kmeans.labels_
        # [1 1 1 1 1 1 1 0 0 0 0 0 0 2 0 2 2 2 2]
        # 聚类中心点
        centers = kmeans.cluster_centers_
        # [[5.9016129  2.7483871  4.39354839 1.43387097]
        #  [5.006      3.428      1.462      0.246     ]
        #  [6.85       3.07368421 5.74210526 2.07105263]]
        # 样本到其近簇中心的平方距离之和。
        # #用来评估簇的个数是否合适,距离越小说明簇分的越好,选取临界点的簇个数
        inertia = kmeans.inertia_
        # 78.85144142614601

        # inertias:inertias是K均值模型对象的属性,表示样本距离近的聚类中心的总和,它是作为在没有真实分类结果标签下的非监督式评估指标。该值越小越好,值越小证明样本在类间的分布越集中,即类内的距离越小。
        # adjusted_rand_s:调整后的兰德指数(Adjusted Rand Index),
        #   兰德指数通过考虑在预测和真实聚类中在相同或不同聚类中分配的所有样本对和计数对来计算两个聚类之间的相似性度量。调整后的兰德指数通过对兰德指数的调整得到独立于样本量和类别的接近于0的值,其取值范围为[-1, 1],负数代表结果不好,越接近于1越好意味着聚类结果与真实情况越吻合。
        # mutual_info_s:互信息(Mutual Information, MI),
        #   互信息是一个随机变量中包含的关于另一个随机变量的信息量,在这里指的是相同数据的两个标签之间的相似度的量度,结果是非负值。
        # adjusted_mutual_info_s:调整后的互信息(Adjusted Mutual Information, AMI),
        #   调整后的互信息是对互信息评分的调整得分。它考虑到对于具有更大数量的聚类群,通常MI较高,而不管实际上是否有更多的信息共享,它通过调整聚类群的概率来纠正这种影响。当两个聚类集相同(即完全匹配)时,AMI返回值为1;随机分区(独立标签)平均预期AMI约为0,也可能为负数。
        # homogeneity_s:同质化得分(Homogeneity),
        #   如果所有的聚类都只包含属于单个类的成员的数据点,则聚类结果将满足同质性。其取值范围[0,1]值越大意味着聚类结果与真实情况越吻合。
        # completeness_s:完整性得分(Completeness),
        #   如果作为给定类的成员的所有数据点是相同集群的元素,则聚类结果满足完整性。其取值范围[0,1],值越大意味着聚类结果与真实情况越吻合。
        # v_measure_s:它是同质化和完整性之间的谐波平均值,
        #   v = 2 (均匀性完整性)/(均匀性+完整性)。其取值范围[0,1],值越大意味着聚类结果与真实情况越吻合。
        # silhouette_s:轮廓系数(Silhouette),
        #   它用来计算所有样本的平均轮廓系数,使用平均群内距离和每个样本的平均近簇距离来计算,它是一种非监督式评估指标。其高值为1,差值为-1,0附近的值表示重叠的聚类,负值通常表示样本已被分配到错误的集群。
        # calinski_harabaz_s:该分数定义为群内离散与簇间离散的比值,
        #   它是一种非监督式评估指标。
        pre_y=kmeans.predict(X)
        # 调整后的兰德指数
        adjusted_rand_s = metrics.adjusted_rand_score(y, pre_y)
        # 互信息
        mutual_info_s = metrics.mutual_info_score(y, pre_y)
        # 调整后的互信息
        adjusted_mutual_info_s = metrics.adjusted_mutual_info_score(y, pre_y)
        # 同质化得分
        homogeneity_s = metrics.homogeneity_score(y, pre_y)
        # 完整性得分
        completeness_s = metrics.completeness_score(y, pre_y)
        # V-measure得分
        v_measure_s = metrics.v_measure_score(y, pre_y)
        # 平均轮廓系数
        silhouette_s = metrics.silhouette_score(X, pre_y, metric='euclidean')
        # Calinski 和 Harabaz 得分
        calinski_harabaz_s = metrics.calinski_harabaz_score(X, pre_y)
        print('ine','tARI','tMI','tAMI','thomo','tcomp','tv_m','tsilh','tc&h')
        print(adjusted_rand_s,mutual_info_s, adjusted_mutual_info_s, homogeneity_s,completeness_s,v_measure_s, silhouette_s ,calinski_harabaz_s)
        # ine tARI tMI tAMI thomo tcomp tv_m tsilh tc&h
        # 0.7302382722834697 0.8255910976103356 0.7551191675800484 0.7514854021988338 0.7649861514489815 0.7581756800057784 0.5528190123564091 561.62775662962
        # 简单打印结果
        class_num = pd.Series(kmeans.labels_).value_counts()  # 统计各个类别的数目
        class_center = pd.DataFrame(kmeans.cluster_centers_)  # 找出聚类中心
        class_total = pd.concat([class_center, class_num], axis=1)  # 横向连接(0是纵向),得到聚类中心对应的类别下的数目
        class_total.columns = ['sepal length (cm)''sepal width (cm)''petal length (cm)''petal width (cm)','total']  # 重命名表头
        #    sepal length (cm)  sepal width (cm)  ...  petal width (cm)  total
        # 0           5.006000          3.428000  ...          0.246000     50
        # 1           5.901613          2.748387  ...          1.433871     62
        # 2           6.850000          3.073684  ...          2.071053     38

        # 详细输出原始数据及其类别
        df = pd.DataFrame(X)        # 讲numpy数组转为pandas
        df_y=pd.DataFrame(y)
        class_detail = pd.concat([df, pd.Series(kmeans.labels_, index = df.index)], axis=1)  # 将特征值和预测列组合起来
        class_detail = pd.concat([class_detail, df_y], axis=1)  # 将预测值和实际值
        class_detail.columns = ['sepal length (cm)''sepal width (cm)''petal length (cm)''petal width (cm)','class','actual_value']  # 重命名表头
        # 想尝试预期结果和实际值进行比对,得到准确率,不过两者的值不一致,无法进行转换
        class_detail['accuracy_score']=class_detail['class']==class_detail['actual_value']
        #      sepal length (cm)  sepal width (cm)  ...  class  actual value    accuracy_score
        # 0                  5.1               3.5  ...      1             0    False
        # 1                  4.9               3.0  ...      1             0    False
        # 2                  4.7               3.2  ...      1             0    False
        # for index, row in class_detail.iterrows():
        #     print(row['sepal length (cm)'], row['sepal width (cm)'],row[ 'petal length (cm)'], row['petal width (cm)'],row['class'],row['actual_value'],row['accuracy_score'])  # 输出每行的索引值
        # 5.1 3.5 1.4 0.2 1 0 False
        # 4.9 3.0 1.4 0.2 1 0 False
        # 4.7 3.2 1.3 0.2 1 0 False
        # 聚类结果可视化
        fig = plt.figure()
        ax = Axes3D(fig)
        ax.scatter3D(X[:, 3], X[:, ], X[:, 2],s=X[:,1]*10,alpha=.5,c=labels.astype(np.float), edgecolor='k')
        # 定位核心点,再进行标注
        for i, element in enumerate(centers):
            ax.scatter3D(element[3], element[], element[2],s=element[1]*10,c='#FF0000', edgecolor='k')
        ax.w_xaxis.set_ticklabels([])
        ax.w_yaxis.set_ticklabels([])
        ax.w_zaxis.set_ticklabels([])
        ax.set_xlabel('Petal width')
        ax.set_ylabel('Sepal length')
        ax.set_zlabel('Petal length')
        ax.set_title('K -mean class')
        ax.dist = 12
        plt.show()
        # 原始数据可视化比较
        fig = plt.figure()
        ax = Axes3D(fig)
        ax.scatter3D(X[:, 3], X[:, ], X[:, 2], s=X[:, 1] * 10, alpha=.5,c=y, edgecolor='k')
        ax.w_xaxis.set_ticklabels([])
        ax.w_yaxis.set_ticklabels([])
        ax.w_zaxis.set_ticklabels([])
        ax.set_xlabel('Petal width')
        ax.set_ylabel('Sepal length')
        ax.set_zlabel('Petal length')
        ax.set_title('original class')
        ax.dist = 12
        plt.show()
        # 设置半径为0.4,小样本量为9,建模
        db = DBSCAN(eps=0.4, min_samples=9)
        db.fit(X)
        labels = db.labels_
        # 构建一个y值大小矩阵
        core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
        # 将核心特征置为True
        core_samples_mask[db.core_sample_indices_] = True
        n_clusters_ = len(set(labels)) - (1 if -1 in labels else )
        n_noise_ = list(labels).count(-1)
        print('labels={}'.format(labels))   # =[ 0  0  0  0  0  0  0  0  0  0  0  0  0 -1 -1 -1  0  0  0  0  0  0 -1  0]
        print('Estimated number of clusters: %d' % n_clusters_) # 3
        print('Estimated number of noise points: %d' % n_noise_)    # 78
        print("Homogeneity: %0.3f" % metrics.homogeneity_score(y, labels)) # 0.603
        print("Completeness: %0.3f" % metrics.completeness_score(y, labels)) #0.584
        print("V-measure: %0.3f" % metrics.v_measure_score(y, labels))  #0.593
        print("Adjusted Rand Index: %0.3f" % metrics.adjusted_rand_score(y, labels))    #0.491
        print("Adjusted Mutual Information: %0.3f"  % metrics.adjusted_mutual_info_score(y, labels))    #0.585

        unique_labels = set(labels)
        colors = [plt.cm.Spectral(each) for each in np.linspace(1, len(unique_labels))]
        for k, col in zip(unique_labels, colors):
            if k == -1:
                col = [1]

            class_member_mask = (labels == k)
            xy = X[class_member_mask & core_samples_mask]
            plt.plot(xy[:, ], xy[:, 1], 'o', markerfacecolor=tuple(col),
                     markeredgecolor='k', markersize=14)
            xy = X[class_member_mask & ~core_samples_mask]
            plt.plot(xy[:, ], xy[:, 1], 'o', markerfacecolor=tuple(col),
                     markeredgecolor='k', markersize=6)

        plt.title('Estimated number of clusters: %d' % n_clusters_)
        plt.show()
if __name__=='__main__':
    X_train,X_test,y_train,y_test,X,y=load_data(iris)
    # -----------------------逻辑回归--------------------------------
    # test_LogisticRegression(X_train,X_test,y_train,y_test)
    # test_LogisticRegression_C(X_train, X_test, y_train, y_test)
    # test_LogisticRegression_Cpenaltyssolvers(X_train, X_test, y_train, y_test)
    # test_LogisticRegression_Cmulti_classsolvers(X_train, X_test, y_train, y_test)
    # test_LogisticRegression_penaltyssolvers(X_train, X_test, y_train, y_test)
    # test_LogisticRegression_multi_classssolvers(X_train, X_test, y_train, y_test)
    # test_LogisticRegression_best(X_train, X_test, y_train, y_test)
    # ---------------------K近邻算法-----------------------
    #test_KNeighborsClassifier(X_train, X_test, y_train, y_test, X, y)

    # ------------------朴素贝叶斯-----------------------
    # 高斯朴素贝叶斯
    # 多项分布朴素贝叶斯
    # 伯努利朴素贝叶斯
    # test_naive_bayes(X_train, X_test, y_train, y_test, X, y)
    # ---------------------决策树-----------------------
    # test_tree(X_train, X_test, y_train, y_test, X, y)
    # -------------------SVM支撑向量机-----------------------
    # test_svm(X_train, X_test, y_train, y_test, X, y)
    # -------------------降维-----------------------
    # test_reduce(X_train, X_test, y_train, y_test, X, y)
    # ---------------------K Means聚类-----------------------
    test_clustering(X_train, X_test, y_train, y_test, X, y)
    # ------------------高斯混合模型聚类-----------------------





相关文章