机器学习之高斯混合模型——基于Scikit-Learn

《Python数据科学手册》笔记

一、高斯混合模型(GMM)的由来

       首先回顾一下k-means模型:它在每一个簇中心放置一个圆圈(在更高维空间中是一个超空间),圆圈半径根据最远的点与簇中心点的距离算出,在圆圈之外的任何点都不是该簇的成员。这里最核心的一点是,k-means要求这些簇的模型必须是圆形,k-算法没有内置的方法来实现椭圆形的簇。因此,拟合非圆形的分类数据时,效果不好。如图1和图2。

           

                                  图1 原始数据                                                        图2 用k-means聚类的结果

效果不好的原因在于k-means两个缺点:类的形状确实灵活性、缺少簇分配的概率。为了解决这两个问题,便产生了高斯混合模型。 

二、高斯混合模型聚类特点

针对k-means暴露出的两个大问题,高斯混合模型提出了两个解决方案:

通过比较所有簇中心点的距离来度量簇分配的不确定性,而不仅仅是关注最近的簇

将簇的边界由圆形放宽至椭圆形,从而得到非圆形的簇

因此分簇的方式相比于k-means有一定的变化,这里将高斯混合模型(图3)和k-means模型(图4)分簇的过程一并给出:

            

                               图3 高斯混合模型                                                       图4 k-means模型

对比两个过程可知,高斯混合模型中增加了权重(概率)这一因素,使得每个簇的结果并不与硬边缘的空间有关,而是通过高斯平滑模型实现。 

以图1为例,应用高斯混合模型对其进行聚类,结果如下(图5):

                                        图5

可以看出,突破了前面k-means算法的两个局限。 

三、相应代码

1.生成原始数据(图1)

%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
#生成数据
from sklearn.datasets.samples_generator import make_blobs
X,y_true = make_blobs(n_samples=400,centers=4,cluster_std=0.60,random_state=0)
X = X[:,::-1]
#用k-means标签画出数据
from sklearn.cluster import KMeans
kmeans = KMeans(4,random_state=0)
labels = kmeans.fit(X).predict(X)
rng = np.random.RandomState(13)
X_stretched = np.dot(X,rng.randn(2,2))
plt.scatter(X_stretched[:,0],X_stretched[:,1],c=labels,s=40,cmap='viridis')

2.应用k-means对其进行聚类(图2)

from scipy.spatial.distance import cdist
def plot_kmeans(kmeans,X,n_clusters=4,rseed=0,ax=None):
    labels = kmeans.fit_predict(X)
    #画出输入数据
    ax = ax or plt.gca()
    ax.axis('equal')
    ax.scatter(X[:,0],X[:,1],c=labels,s=40,cmap='viridis',zorder=2)
    #画出k-means模型的表示
    centers = kmeans.cluster_centers_
    radii = [cdist(X[labels == i],[center]).max() for i,center in enumerate(centers)]
    for c,r in zip(centers,radii):
        ax.add_patch(plt.Circle(c,r,fc='#CCCCCC',lw=3,alpha=0.5,zorder=1))
        
kmeans = KMeans(n_clusters=4,random_state=0)
plot_kmeans(kmeans,X_stretched)

3.应用高斯混合模型对其进行聚类(图5) 

from matplotlib.patches import Ellipse
def draw_ellipse(position,covariance,ax=None,**kwargs):
    #用给定的位置和协方差画一个椭圆
    ax = ax or plt.gca()
    #将协方差转化成主轴
    if covariance.shape == (2,2):
        U,s,Vt = np.linalg.svd(covariance)
        angle = np.degrees(np.arctan2(U[1,0],U[0,0]))
        width,height = 2*np.sqrt(s)
    else:
        angle = 0
        width,height = 2*np.sqrt(covariance)
    #画出椭圆
    for nsig in range(1,4):
        ax.add_patch(Ellipse(position,nsig*width,nsig*height,angle,**kwargs))
        
def plot_gmm(gmm,X,label=True,ax=None):
    ax = ax or plt.gca()
    labels = gmm.fit(X).predict(X)
    if label:
        ax.scatter(X[:,0],X[:,1],c=labels,s=40,cmap='viridis',zorder=2)
    else:
        ax.scatter(X[:,0],X[:,1],s=40,zorder=2)
    ax.axis('equal')
    w_factor = 0.2 / gmm.weights_.max()
    for pos,covar,w in zip(gmm.means_,gmm.covariances_,gmm.weights_):
        draw_ellipse(pos,covar,alpha=w*w_factor)
        
gmm = GaussianMixture(n_components=4,random_state=42)
plot_gmm(gmm,X)

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值