zoukankan      html  css  js  c++  java
  • 4、无监督学习笔记

    无监督学习

    1、简介

    无监督学习是一种对不含标记的数据建立模型的机器学习范式。最常见的无监督学习方法是聚类,就是讲无标记的数据分成几种集群,这些集群通常是根据某种相似度指标进行的,如欧氏距离(Euclidean distance),常用领域有:数据挖掘、医学影像、股票市场分析、计算机视觉、市场细分等。

    2、用k-means算法聚类数据

    k-means算法常用数据的不同属性将输入数据划分成k组。分组是使用最优化的技术实现的,即让各组的数据点与该组中心点的距离平方和最小化。例子如下:

    import matplotlib.pyplot as plt
    import numpy as np
    from sklearn.cluster import KMeans
    
    def load_data(input_file):
        X = []
        with open(input_file, 'r') as f:
            for line in f.readlines():
                data = [float(x) for x in line.split(',')]
                X.append(data)
        return np.array(X)
    
    
    # 1、获取数据并可视化
    input_file = 'data_multivar.txt'
    data = load_data(input_file)
    x_min,x_max=min(data[:,0])-1,max(data[:,0])+1
    y_min,y_max=min(data[:,1])-1,max(data[:,1])+1
    '''
    plt.figure()
    plt.scatter(data[:,0], data[:,1],
            facecolors='none', edgecolors='k')
    plt.xlim(x_min,x_max)
    plt.ylim(y_min,y_max)
    plt.show()
    '''
    # 2、获取k-means对象,并训练
    kmeans=KMeans(n_clusters=4,init='k-means++',n_init=10)
    kmeans.fit(data)
    # 3、获取边界
    step_size=0.01
    x_values,y_values=np.meshgrid(np.arange(x_min,x_max,step_size),np.arange(y_min,y_max,step_size))
    predict_labels=kmeans.predict(np.c_[x_values.ravel(),y_values.ravel()])
    predict_labels=predict_labels.reshape(x_values.shape)
    # 4、画出边界
    plt.figure()
    plt.clf()
    plt.imshow(predict_labels, interpolation='nearest',
               extent=(x_values.min(), x_values.max(), y_values.min(), y_values.max()),
               cmap=plt.cm.Paired,
               aspect='auto', origin='lower')
    plt.scatter(data[:,0], data[:,1],
            facecolors='none', edgecolors='k')
    
    centero=kmeans.cluster_centers_
    plt.scatter(centero[:,0],centero[:,1],linewidths=5,facecolor='black')
    
    plt.xlim(x_min,x_max)
    plt.ylim(y_min,y_max)
    plt.show()
    

    图片显示如下:

    3、用矢量量化压缩图片

    k-means聚类的主要应用之一就是矢量量化。矢量量化就是“四舍五入”(rounding off)的N维版本。在处理数字等一维数据时,会用四舍五入技术减少存储空间。矢量量化被广泛应用于图片压缩,用比原始图像更少的比特数来存储每个像素,从而实现图像图片。
    import argparse

    # 1、创建一个函数,用来解析输入参数,输入参数为图片和每个像素被压缩的比特数。
    def build_arg_parser():
        parser = argparse.ArgumentParser(description='输入图片')
        parser.add_argument('--input-file', dest='input_file', required=True, help='输入图片')
        parser.add_argument('--num-bits', dest='num_bits', type=int, required=False, help='比特数')
        return parser
    
    
    # 2、压缩输入图片
    def compress_img(img, num_cluster):
        print(img)
        X = img.reshape(-1, 1)
        print(X)
        kmeans = KMeans(n_clusters=num_cluster, n_init=4, random_state=5)
        kmeans.fit(X)
        contrid = kmeans.cluster_centers_.squeeze()
        labels = kmeans.labels_
        input_compress = np.choose(labels, contrid).reshape(img.shape)
        return input_compress
    
    # 3、查看压缩算法对图片质量的影响
    def plot_image(img,title):
        vmin=img.min()
        vmax=img.max()
        plt.figure()
        plt.title(title)
        plt.imshow(img,cmap=plt.cm.gray,vmin=vmin,vmax=vmax)
    
    if __name__ == '__main__':
        args = build_arg_parser().parse_args()
        input_file=args.input_file
        num_bits=args.num_bits
        if not 1<=num_bits<=8:
            raise TypeError('比特数应该在1和8之间')
        num_clusters=np.power(2,num_bits)
        compression_rate=round(100*(8.0-args.num_bits)/8.0,2)
        input_image=misc.imread(input_file,True).astype(np.uint8)
        plot_image(input_image,'image')
        input_compress=compress_img(input_image,num_clusters)
        plot_image(input_compress,'rate='+str(compression_rate)+'%')
        plt.show()
    

    4、建立均值漂移聚类模型

    均值漂移是一种非常强大的无监督学习算法,用于集群数据点。该算法把数据点的分布看成是概率密度函数(probability-density function),希望在特征空间中根据函数分布特征找出数据点的“模式”(mode),这些“模式”就对应于一群群局部最密集(local maxima)分布的点。该算法的优点在于它无需事先确定集群的数量。例子如下:

    # 均值漂移聚类模型
    from sklearn.cluster import MeanShift,estimate_bandwidth
    # 1、获取数据
    X=load_data('data_multivar.txt')
    # 2、通过指定输入参数创建均值漂移模型
    bandwidth=estimate_bandwidth(X,quantile=0.1,n_samples=len(X))
    meanshift=MeanShift(bandwidth=bandwidth,bin_seeding=True)
    # 3、训练模型
    meanshift.fit(X)
    # 4、提取标记
    labels=meanshift.labels_
    # 5、获取集群中心点,并打印数量
    centroids=meanshift.cluster_centers_
    num_clusters=len(np.unique(labels))
    print(labels)
    print(centroids)
    print(num_clusters,len(centroids))
    # 6、可视化
    markers='.*xv'
    plt.figure()
    for i,marker in zip(range(len(markers)),markers):
        plt.scatter(X[labels==i,0],X[labels==i,1],marker=marker,color='k')
        centroid=centroids[i]
        plt.plot(centroid[0],centroid[1],marker='o',markersize=15,markeredgecolor='k',markerfacecolor='k')
    plt.title('显示')
    plt.show()
    

    5、用凝聚层次聚类进行分组

    层次聚类:一组聚类算法,通过不断的分解或合并集群来构建树状集群(tree-like clusters),其结构可用一棵树表示。该算法可自上而下,也可自下而上。
    凝聚层次聚类:即自下而上的算法,每一个数据点被看做一个单独的子集,而让这些子集不断的合并,直到所有集合合并为一个巨型集群。相反,自上而下则是分解。直到所有集群变为一个单独的数据点。

    def get_spiral(t,noise_amplitude=0.5):# 获取呈螺旋状的数据
        r=t
        x=r*np.cos(t)
        y=r*np.sin(t)
        return add_noise(x,y,noise_amplitude)
    def get_rose(t,noise_amplitude=0.02):# 获取呈螺旋状的数据
        k=5
        r=np.cos(k*t)+0.25
        x=r*np.cos(t)
        y=r*np.sin(t)
        return add_noise(x,y,noise_amplitude)
    def get_hypotrochoid(t, noise_amplitude=0):
        a, b, h = 10.0, 2.0, 4.0
        x = (a - b) * np.cos(t) + h * np.cos((a - b) / b * t) 
        y = (a - b) * np.sin(t) - h * np.sin((a - b) / b * t) 
    
        return add_noise(x, y, 0)
    def add_noise(x,y,amplitude):# 添加噪音
        X=np.concatenate((x,y))
        X+=amplitude*np.random.randn(2,X.shape[1])
        return X.T
    from sklearn.cluster import AgglomerativeClustering
    
    def perform_clustering(X,connectivity,title,num_clusters=3,linkage='ward'):# 设置层次凝聚模型
        plt.figure()
        model=AgglomerativeClustering(linkage=linkage,n_clusters=num_clusters,connectivity=connectivity)
        model.fit(X)
    
        labels=model.labels_
    
        markers='.vx'
    
        for i,marker in zip(range(num_clusters),markers):
            plt.scatter(X[labels==i,0],X[labels==i,1],s=50,facecolor='none',marker=marker,color='k')
            plt.title(title)
    from sklearn.neighbors import kneighbors_graph
    if __name__=='__main__':
        # 生成样本数据
        n_samples=500
        np.random.seed(2)
        t=2.5*np.pi*(1+2*np.random.rand(1,n_samples))
        X=get_spiral(t)
        # X = get_rose(t)
        # X = get_hypotrochoid(t)
        connectivity=None
        perform_clustering(X,connectivity,'没有连接')
    
    
        connectivity=kneighbors_graph(X,10,include_self=False)
        perform_clustering(X,connectivity,'knei连接')# 可让连接在一起的数据组合在一起
    
        plt.show()
    

    6、评价聚类算法的聚类效果

    轮廓系数(Sihouette Coefficient)系数:得分=(x-y)/max(x,y),其中x表示在同一个集群中某个数据点与其他数据点的平均距离,y表示某个数据点与最近的另一个集群的所有点的平均距离,使用例子如下:

    from sklearn import metrics
    data=load_data('data_perf.txt')# 加载数据
    scores=[]
    range_values=np.arange(2,10)
    for i in range_values:# 分别分i个集群
        kmean=KMeans(n_clusters=i,n_init=10,init='k-means++')
        kmean.fit(data)
        score=metrics.silhouette_score(data,kmean.labels_,metric='euclidean',sample_size=len(data))
        scores.append(score)
    
    plt.figure()
    plt.bar(range_values,scores,width=0.6,color='k',align='center')
    plt.show()
    plt.figure()
    plt.scatter(data[:,0],data[:,1],color='k')
    xmin,xmax=min(data[:,0])-1,max(data[:,0])+1
    ymin,ymax=min(data[:,1])-1,max(data[:,1])+1
    plt.xlim(xmin,xmax)
    plt.ylim(ymin,ymax)
    plt.show()
    

    7、用DBSCAN算法自动估算集群数量

    DBSCAN(Density-Based Spatial Clustering of Applications with Noise):带噪声的基于密度的聚类方法,将数据点看成是紧密集群的若干组,若某个点属于一个集群,那会有许多点也属于同一个集群,该方法里面有一个epsilon参数,可控制该点到其他点的最大距离。若两点间距离超过epsilon,则他们不可能在一个集群中。该方法主要有点是它可以处理异常值,若某些点位于数据稀疏距离,则将其作为异常点,而不会强制将他们放入一个集群中。例子如下:

    # 1、获取数据
    X=load_data('data_perf.txt')
    # 2、初始化参数
    eps_grid=np.linspace(0.3,1.2,num=10)
    silhouette_scores=[]
    eps_best=eps_grid[0]
    silhouette_scores_max=-1
    model_best=None
    labels_best=None
    # 3、以此执行所有参数
    from sklearn.cluster import DBSCAN
    from sklearn import metrics
    for eps in eps_grid:
        model=DBSCAN(eps=eps,min_samples=5).fit(X)
        labels=model.labels_
        silhouette_score=round(metrics.silhouette_score(X,labels),4)
        silhouette_scores.append(silhouette_score)
        # 获取指标的最佳得分
        if silhouette_score>silhouette_scores_max:
            silhouette_scores_max=silhouette_score
            eps_best=eps
            model_best=model
            labels_best=labels
    
    # 4、画出条形图
    plt.figure()
    plt.bar(eps_grid,silhouette_scores,width=0.05,color='k',align='center')
    plt.show()
    # 5、由于可能会有某些点还没有分配集群,所以这里删除未分配而获取集群的数量
    offset=0
    if -1 in labels:
        offset=1
    num_clusters=len(set(labels))-offset
    # 6、提取核心样本
    model = model_best
    labels = labels_best
    mask_core=np.zeros(labels.shape,dtype=np.bool)# 初始化全部点的分配
    mask_core[model.core_sample_indices_]=True# model.core_sample_indices_表示分配后的数据位置为True
    
    # 7、数据可视化
    from itertools import cycle
    plt.figure()
    labels_uniq=set(labels)
    markers=cycle('vo^s<>')
    for cur_label,marker in zip(labels_uniq,markers):
        if cur_label==-1:
            marker='.'
        cur_mask=(labels==cur_label)# 获取当前某个数据集的集合的索引
        cur_data=X[cur_mask&mask_core]# 当前数据集中正常的数据
        plt.scatter(cur_data[:,0],cur_data[:,1],marker=marker,edgecolors='black',s=96,facecolors='none')
        cur_data=X[cur_mask&-mask_core]# 当前数据集中异常数据
        plt.scatter(cur_data[:,0],cur_data[:,1],marker=marker,edgecolors='black',s=32)
    plt.show()
    

    8、近邻传播聚类

    近邻传播聚类(Affinity Propagation):找出数据中每个集群的代表性数据点,找到数据点间的相似性度量值,并把所有数据点看成潜在的代表性数据点,也称取样器(exemplar)。具体查看如下链接:http://blog.csdn.net/u010161379/article/details/51636926

    9、建立客户细分模型

    市场细分对广告投放、库存管理、配送策略的实施、大众传媒等市场行为都非常有用。在不同类型商品的销售数据中,为客户提供最优的销售和分销策略,例子如下:

    # 1、获取数据
    import csv
    
    input_file='wholesale.csv'
    file_reader=csv.reader(open(input_file,'r'),delimiter=',')
    X=[]
    for count,row in enumerate(file_reader):
        if not count:
            names=row[2:]
            continue
        X.append([float(x) for x in row[2:]])
    X=np.array(X)
    # 2、使用均值漂移训练数据
    from sklearn.cluster import MeanShift,estimate_bandwidth
    
    bandwidth=estimate_bandwidth(X,quantile=0.8,n_samples=len(X))
    model=MeanShift(bandwidth=bandwidth,bin_seeding=True)
    model.fit(X)
    labels=model.labels_
    clucenters=model.cluster_centers_
    num_centers=len(clucenters)
    # 3、打印集群中心
    print('	'.join([name[:3] for name in names]))
    print('	'.join([str(clucenter) for clucenter in clucenters]))
    # 4、把milk与groceries的聚类结果可视化
    centriods_milk_groceries=clucenters[:,1:3]
    plt.figure()
    plt.scatter(centriods_milk_groceries[:,0],centriods_milk_groceries[:,1],color='k',s=100,facecolor='none')
    offset=0.2
    plt.xlim(centriods_milk_groceries[:,0].min()-offset*centriods_milk_groceries[:,0].ptp(),centriods_milk_groceries[:,0].max()+offset*centriods_milk_groceries[:,0].ptp())
    plt.xlim(centriods_milk_groceries[:,1].min()-offset*centriods_milk_groceries[:,1].ptp(),centriods_milk_groceries[:,1].max()+offset*centriods_milk_groceries[:,1].ptp())
    plt.show()
    文章来源:NSGUF,欢迎分享,转载请保留出处
  • 相关阅读:
    很简单的在Ubuntu系统下安装字体和切换默认字体的方法
    Qt添加驱动——Qt数据库之添加MySQL驱动插件
    qt 字体的相关问题
    qt configure参数配置介绍
    Qt封装QTcpServer参考资料--QT4中构建多线程的服务器
    Qt封装QTcpServer参考资料--QTcpServer多线程实现
    Qt封装QTcpServer参考资料--QT自带QTcpServer架构分析
    Qt Creator设置多核编译(-j8参数)
    QString::​arg的用法
    《Qt数据类型》--QByteArray,QString,int,hex之间的转化
  • 原文地址:https://www.cnblogs.com/NSGUF/p/8447929.html
Copyright © 2011-2022 走看看