Advertisement

聚类实践(无监督学习)

阅读量:

该文本介绍了使用TensorFlow进行聚类分析的知识体系与实现方法:
无监督学习基础

  • 聚类方法适用于无标签数据(无监督学习),通过计算样本间距离找到自然存在的簇结构。
  • 聚类核心是将不同特征的数据点分组到相似的簇中,并通过距离度量评估簇内的相似性与簇间的差异性。
    K-means算法
  • 初始化随机选择质心(cluster centroids)。
  • 样本被分配到最近质心所属的簇中。
  • 重新计算各簇的新质心并迭代更新直至收敛或达到最大迭代次数。
  • 停止条件包括质心不再变化或达到预设的最大迭代次数。
    KNN半监督学习
  • 采用半监督方式结合少量标签数据提升聚类性能。
  • 训练集包含样本及其类别信息。
  • 测试样本通过计算与训练集中样本的距离找到最近邻并推断类别。
    TensorFlow实现
  • 使用tf.unsortedsegmentsum等函数处理数据分割与质心更新。
  • 构建图节点表示数据操作并执行Session进行模型训练与预测。
  • 提供可视化结果以展示簇结构与分类效果。
    性能优化与停止条件
  • 设置合理的最大迭代次数或质心稳定性的停止标准以避免冗余计算。
  • 通过精度指标(如准确率)评估模型性能并优化参数设置。
  • TensorFlow 聚类分析相关知识掌握
    • 一、基于数据的学习 === > 无监督学习

      • 1.1 概念阐述
      • 1.2 具体实施步骤
    • 1.2.1 K均值聚类方法

    • 1.2.2 Knn(K近邻方法,在此我们采用半监督学习策略进行优化)

    • 二、算法实现

      • 2.1 Kmeans 算法实现
      • 2.2 Knn 算法实现

TensorFlow 聚类算法相关的实践应用研究

该领域作为无监督学习的重要组成部分涉及多种聚类算法及其原理。其中包括经典的K-means方法、优化版本的K-means++、层次聚类技术、基于密度分布的空间聚类方法以及谱聚方法等。本节重点介绍如何利用TensorFlow框架实现K-means算法(采用半监督学习方法实现目标是以期快速掌握TensorFlow API的具体操作细节)。至于其他具体算法的详细讲解,请参阅其他资源。


一、从数据中学习 === > 无监督学习


1.1 概念简介

  • 无监督学习可以通过给定的数据集识别感兴趣的行为模式(pattern),无需预先指定标签或模式信息;系统需自主解析数据构成方式并发现数据中的潜在结构。
  • 聚类分析涉及对未标记化(unlabeled)数据集进行分组处理,并依据相似特征将它们归类至具有共同属性的不同组别或簇中。
  • 在将不同元素分配至同一簇的过程中,在确定各元素间距离(distance)时变得尤为关键。
  • 同时,在实际应用中通常会根据具体情况定义多种距离计算方法。

1.2 算法实现流程

1.2.1 K 均值算法

初始化阶段中,默认会随机选取K个数据点来充当初始质心。此外,在实际应用中为了简化流程可以选择使用数据集头K个实例直接构成初始聚类中心;当然你也可以根据自己的研究特点设计独特的初始化策略。
计算每个样本与当前所有质心中最邻近的那个中心点之间的距离,并将其归入该中心点所属的簇类中。这一操作完成后就需要重新评估并更新各个簇类的核心代表——即聚类中心的位置。
当计算后的新的聚类中心位置确定后,则会引发各个旧有簇类与其他潜在数据点之间距离的变化;因此必须立即对所有数据进行重新分类以适应新的空间分布情况。
只有当系统检测到当前迭代过程中的停止条件得到满足时,则算法程序才会终止运行。

对于停止条件我们可以有不同的选择:如下

为了提高效率并减少不必要的计算开销,在算法实现时应选择一个较大的迭代次数。
当算法达到稳定状态时(即所有元素均停留在各自的类别中),意味着迭代过程完成。

1.2.2 Knn(K 近邻,这里采用半监督学习方式实现)
  1. 明确训练数据集中的各类别特征。
  2. 获取待分类样本并计算其与训练集中每个样本之间的欧几里得距离。
  3. 基于最小欧氏距离找到最邻近的同类样本来识别待分类样品所属类别。
  4. 循环上述操作直至所有待分类测试样例都被正确归类为止。

二、算法实现


2.1 Kmeans 算法实现

复制代码
    # coding: utf-8
    
    import tensorflow as tf 
    import numpy as np  
    import time 
    
    import matplotlib as mpl 
    import matplotlib.pyplot as plt 
    
    from sklearn.datasets.samples_generator import make_blobs
    from sklearn.datasets.samples_generator import make_circles
    
    def bucket_mean(data,bucker_ids,num_buckers):
    # 各自按照不同的类别(即bucker_ids)进行相加,且bucker_ids 不保证顺序
    total = tf.unsorted_segment_sum(data,bucker_ids,num_buckers)
    count = tf.unsorted_segment_sum(tf.ones_like(data),bucker_ids,num_buckers)
    return total / count 
    
    
    if __name__ == '__main__':
    # 首先第一步就是构造数据
    DATA_TYPE = 'blobs'
    N = 200 
    # 首先确定聚类的 K 值,即聚类个数
    # Number of clusters, if we choose circles, only 2 will be enough
    if (DATA_TYPE == 'circle'):
        K = 2 
    else:
        K = 4 
    
    # 开始计时
    start = time.time()
    
    # 迭代次数 
    MAX_ITERS = 1000 
    
    # 聚类中心
    centers = [(-2,-2),(-2,1.5),(1.5,-2),(2,1.5)]
    if (DATA_TYPE == 'circle'):
        # make_circles 函数创建两个一大一下的圆环(由200个点构成),noise 是高斯噪声,factor 是内外圆之间的放大因子
        data, features = make_circles(n_samples=200,shuffle=True,noise=0.01,factor=0.4)
    else:
        # 注意这里构造的是同方差 cluster_std 为一个值
        data, features = make_blobs(n_samples=200,centers=centers,n_features=2,cluster_std=0.8,shuffle=False,random_state=42)
    
    # print type(data), data.shape, '\n'
    # print features
    
    fig, ax = plt.subplots()
    plt.figure(figsize=(10,8),facecolor='w')
    if DATA_TYPE == 'blobs':
        # plt.subplot(1,2,1)
        ax.scatter(np.asarray(centers).T[0],np.asarray(centers).T[1],marker = 'o',s=250)
        # 当需要将四组不同的类别的样本着上不同的颜色时,便需要将 c = features 有多少类别传入作为依据
        # plt.subplot(1,2,2)
        ax.scatter(data.T[0],data.T[1],marker='*',s=100,c=features,cmap=plt.cm.coolwarm)
        # plt.show()
    
    # 接着,第二步便是给初值,计算样本与质心的距离,更新质心,迭代
    points = tf.Variable(data)   # point 用来存放数据集点的集合
    # 用来存储样本被聚到哪一类,初始置为 0 
    cluster_assignments = tf.Variable(tf.zeros([N],dtype=tf.int64))
    # centroids 用于保存质心坐标,初始化为任意k个点,这里取data 的前K个
    centroids = tf.Variable(tf.slice(points.initialized_value(),[0,0],[K,2]))
    
    # 开启 TensorFlow 会话
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    sess.run(centroids)
    
    # 第三步,便是定义损失函数以及优化,及停止条件等
    # print centroids,'\n'
    # print tf.tile(centroids,[2,1])
    # 将质心做 N 次复制,对每个样本做 K 次复制,这样样本的和质心形状都是 N*K*2 ,即 N个样本,K个簇
    # 于是,我们便可以计算每个样本到每个质心点之间的所有维度的距离
    rep_centroids = tf.reshape(tf.tile(centroids,[N,1]),[N,K,2])
    # print rep_centroids
    rep_points = tf.reshape(tf.tile(points,[1,K]),[N,K,2])
    # print tf.square(rep_points - rep_centroids)
    sum_squares = tf.reduce_sum(tf.square(rep_points - rep_centroids),
    reduction_indices=2)
    # print sum_squares
    
    # 寻找距离最小的中心,返回其最小距离的序号,即哪一个簇
    best_centroids = tf.argmin(sum_squares,1)
    
    # 这里采用当所有质心不再发生变化作为停止条件,以下为是否更新质心得 flag
    did_assignments_change = tf.reduce_any(tf.not_equal(best_centroids,cluster_assignments))
    
    # bucket_mean 函数用来更新新的质心
    means = bucket_mean(points,best_centroids,K)
    
    # 然后,根据 control_dependencies 来判别是否更新质心,
    # 可以用tf.control_dependencies(control_inputs)来实现指定某些操作执行的依赖关系,
    # 它会返回一个控制依赖的上下文管理器,使用with关键字可以让在这个上下文环境中
    # 的操作都在 control_inputs 执行
    with tf.control_dependencies([did_assignments_change]):
        # assign 赋值的意思
        do_updates = tf.group(centroids.assign(means),cluster_assignments.assign(best_centroids))
    
    changed = True 
    iters = 0 
    
    fig, ax = plt.subplots()
    if DATA_TYPE == 'blobs':
        colourindexes = [2,1,4,3]
    else:
        colourindexes = [2,1] 
    
    while changed and iters < MAX_ITERS:
        fig, ax = plt.subplots()
        iters += 1
        [chagned, _] = sess.run([did_assignments_change,do_updates])
        [centers,assignments] = sess.run([centroids,cluster_assignments])
        ax.scatter(sess.run(points).T[0],sess.run(points).T[1],marker='o',s=200,c=assignments,cmap=plt.cm.coolwarm)
        # ax.scatter(np.asarray(centers).T[0],np.asarray(centers).T[1], marker = '^', s = 550, c = colourindexes, cmap=plt.cm.plasma)
        ax.scatter(centers[:,0],centers[:,1],marker='^',s=550,c=colourindexes,cmap=plt.cm.plasma)
        ax.set_title('Iteration' + str(iters))
        plt.savefig('./My_pratise/Kmean_pic/kmeans' + str(iters) + '.png')
    
    ax.scatter(sess.run(points).T[0],sess.run(points).T[1],marker = 'o',s = 200,c=assignments,cmap=plt.cm.coolwarm)
    # plt.show()
    
    end = time.time()
    print 'Found in %.2f seconds'% (end - start), iters,'iterations'
    print 'Centroids:'
    print centers
    print 'Cluster assignments:',assignments

2.2 Knn 算法实现

复制代码
    # coding:utf-8
    import tensorflow as tf 
    import numpy as np 
    import time 
    
    import matplotlib as mpl 
    import matplotlib.pyplot as plt 
    from sklearn.cross_validation import train_test_split
    from sklearn.datasets.samples_generator import make_circles 
    from sklearn.metrics import accuracy_score
    
    if __name__ == '__main__':
    # 样本点个数
    N = 210
    # 类别个数
    K = 2
    # 最大迭代次数
    MAX_ITERS = 1000
    # cut = int(N * 0.7)
    start = time.time()
    
    # 生成数据,划分数据
    # noise 的取值较大,kmeans不擅长的非线性,的圆形数据集,这里使用 knn
    data, features = make_circles(n_samples=N,shuffle=True,noise=0.12,factor=.4)
    data_train, data_test, features_train, features_test = train_test_split(data,features,test_size=0.3,random_state=1)
    
    fig, ax = plt.subplots()
    ax.scatter(data_train[:,0],data_train[:,1],marker='o',s=100, c=features_train,cmap=plt.cm.coolwarm)
    plt.plot()
    plt.grid(True)
    # plt.show()
    
    # point 用来存放数据集点的集合
    points = tf.Variable(data)
    # 用来存储样本被聚到哪一类,初始置为 0 
    cluster_assignments = tf.Variable(tf.zeros([N],dtype=tf.int64))
    
    # 创建会话
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    
    test = []
    
    for i, j in zip(data_test,features_test):
        distances = tf.reduce_sum(tf.square(tf.subtract(i, data_train)),reduction_indices=1)
        neighbor = tf.arg_min(distances,0)
        # 下面语句可以粗略观察一下
        # print 'neighbor: ',features_train[sess.run(neighbor)]
        # print  'Real_value: ',j 
        test.append(features_train[sess.run(neighbor)])
    print test 
    # 可以通过此语句查看 knn 的正确率
    
    fig, ax = plt.subplots()
    ax.scatter(data_test[:,0],data_test[:,1],marker='o',s=100,c=test,cmap=plt.cm.coolwarm)
    plt.plot()
    
    # final
    end = time.time()
    print ("Found in %.2f seconds" % (end-start))
    print 'clusster assignment:', test 
    print '准确率:',accuracy_score(features_test,test)
    
    plt.show()

全部评论 (0)

还没有任何评论哟~