24/11/14 算法条记 GMM高斯混淆模子

打印 上一主题 下一主题

主题 1118|帖子 1118|积分 3354

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
高斯混淆模子(Gaussian Mixture Model,简称 GMM)是一种概率模子,用于表示具有多个子群体的数据集,其中每个子群体的数据分布可以用高斯分布(正态分布)来形貌。GMM 是一种软聚类方法,意味着它为每个数据点分配一个属于每个聚类的概率分布,而不是硬聚类方法中的严酷分类。
GMM 的构成

一个 GMM 由以下几个部分构成:

  • 聚类数量(K):模子中高斯分布(聚类)的数量。
  • 均值向量(μkμk​):每个高斯分布的均值向量,其中 kk 表示聚类索引。
  • 协方差矩阵(ΣkΣk​):每个高斯分布的协方差矩阵,形貌了数据在各个维度上的分布范围和形状。
  • 混淆系数(πkπk​):每个高斯分布的权重,表示数据属于该聚类的概率,全部混淆系数之和为1。
GMM 的数学表达

GMM 的概率密度函数(PDF)可以表示为:


GMM 的学习

GMM 的参数学习通常使用 EM 算法举行,EM算法前面有将,是一个策略优化算法
24/11/14 算法条记 EM算法期望最大化算法-CSDN博客
我们来看一下简朴的GMM源代码
  1. import numpy as np
  2. from scipy.stats import multivariate_normal
  3. class GaussianMixture:
  4.     def __init__(self, n_components, covariance_type='full', n_iter=100, random_state=None):
  5.         self.n_components = n_components  # 聚类数量
  6.         self.covariance_type = covariance_type  # 协方差类型
  7.         self.n_iter = n_iter  # 迭代次数
  8.         self.random_state = random_state  # 随机种子
  9.         self.weights_ = None  # 混合系数
  10.         self.means_ = None  # 均值
  11.         self.covariances_ = None  # 协方差
  12.     def _initialize_parameters(self, X):
  13.         """随机初始化均值、协方差和权重"""
  14.         n_samples, n_features = X.shape
  15.         self.weights_ = np.ones(self.n_components) / self.n_components  # 初始化权重
  16.         random_indices = np.random.choice(n_samples, self.n_components, replace=False)
  17.         self.means_ = X[random_indices]  # 随机选择均值
  18.         self.covariances_ = np.array([np.eye(n_features)] * self.n_components)  # 初始化协方差为单位矩阵
  19.     def _e_step(self, X):
  20.         """E步骤:计算每个数据点属于每个高斯分布的责任"""
  21.         n_samples = X.shape[0]
  22.         responsibilities = np.zeros((n_samples, self.n_components))
  23.         
  24.         for k in range(self.n_components):
  25.             rv = multivariate_normal(mean=self.means_[k], cov=self.covariances_[k])
  26.             responsibilities[:, k] = self.weights_[k] * rv.pdf(X)
  27.         
  28.         # 归一化责任
  29.         responsibilities /= responsibilities.sum(axis=1, keepdims=True)
  30.         return responsibilities
  31.     def _m_step(self, X, responsibilities):
  32.         """M步骤:更新均值、协方差和权重"""
  33.         n_samples = X.shape[0]
  34.         effective_n = responsibilities.sum(axis=0)  # 每个聚类的有效样本数量
  35.         
  36.         # 更新权重
  37.         self.weights_ = effective_n / n_samples
  38.         
  39.         # 更新均值
  40.         self.means_ = np.dot(responsibilities.T, X) / effective_n[:, np.newaxis]
  41.         
  42.         # 更新协方差
  43.         for k in range(self.n_components):
  44.             diff = X - self.means_[k]
  45.             self.covariances_[k] = np.dot(responsibilities[:, k] * diff.T, diff) / effective_n[k]
  46.     def fit(self, X):
  47.         """训练模型"""
  48.         self._initialize_parameters(X)  # 初始化参数
  49.         for _ in range(self.n_iter):  # 迭代更新
  50.             responsibilities = self._e_step(X)  # E步骤
  51.             self._m_step(X, responsibilities)  # M步骤
  52.     def predict(self, X):
  53.         """预测数据点的聚类标签"""
  54.         responsibilities = self._e_step(X)  # 计算责任
  55.         return np.argmax(responsibilities, axis=1)  # 返回最大责任的聚类索引
  56.     def sample(self, n_samples):
  57.         """从模型中生成新样本"""
  58.         samples = np.zeros((n_samples, self.means_.shape[1]))
  59.         for i in range(n_samples):
  60.             k = np.random.choice(self.n_components, p=self.weights_)  # 根据权重选择聚类
  61.             samples[i] = np.random.multivariate_normal(self.means_[k], self.covariances_[k])  # 生成样本
  62.         return samples
复制代码
接下来让我们分析下每段代码
1.初始化函数 __init__
  1. def __init__(self, n_components, covariance_type='full', n_iter=100, random_state=None):
  2.     self.n_components = n_components  # 聚类数量
  3.     self.covariance_type = covariance_type  # 协方差类型
  4.     self.n_iter = n_iter  # 迭代次数
  5.     self.random_state = random_state  # 随机种子
  6.     self.weights_ = None  # 混合系数
  7.     self.means_ = None  # 均值
  8.     self.covariances_ = None  # 协方差
复制代码
这是类的构造函数,用于初始化GMM模子的参数:


  • n_components:模子中高斯分布(聚类)的数量。
  • covariance_type:协方差矩阵的类型,可以是'full'、'diag'或'spherical',分别表示全协方差、对角协方差和球面协方差。
  • n_iter:EM算法的最大迭代次数。
  • random_state:随机数生成器的种子,用于结果的可重复性。
  • weights_、means_和covariances_:这些属性将在模子训练后存储模子参数。
2.参数初始化函数 _initialize_parameters
  1. def _initialize_parameters(self, X):
  2.     """随机初始化均值、协方差和权重"""
  3.     n_samples, n_features = X.shape
  4.     self.weights_ = np.ones(self.n_components) / self.n_components  # 初始化权重
  5.     random_indices = np.random.choice(n_samples, self.n_components, replace=False)
  6.     self.means_ = X[random_indices]  # 随机选择均值
  7.     self.covariances_ = np.array([np.eye(n_features)] * self.n_components)  # 初始化协方差为单位矩阵
复制代码
这个函数用于随机初始化模子参数:


  • self.weights_:权重初始化为均平分布。
  • self.means_:均值初始化为数据会合随机选择的点。
  • self.covariances_:协方差矩阵初始化为单位矩阵,实用于全协方差情况。
  • 协方差可以告诉我们两个变量是怎样一起变革的。如果两个变量的协方差是正的,那么它们倾向于朝相同的方向变革;如果协方差是负的,那么一个变量增加时,另一个变量倾向于淘汰。
3.E步调函数 _e_step
  1. def _e_step(self, X):
  2.     """E步骤:计算每个数据点属于每个高斯分布的责任"""
  3.     n_samples = X.shape[0]
  4.     responsibilities = np.zeros((n_samples, self.n_components))
  5.    
  6.     for k in range(self.n_components):
  7.         #函数用于生成符合多元正态分布的随机样本。
  8.         rv = multivariate_normal(mean=self.means_[k], cov=self.covariances_[k])
  9.         responsibilities[:, k] = self.weights_[k] * rv.pdf(X)
  10.    
  11.     # 归一化责任
  12.     responsibilities /= responsibilities.sum(axis=1, keepdims=True)
  13.     return responsibilities
复制代码
E步调计算每个数据点属于每个高斯分布的责任(后验概率):


  • 使用multivariate_normal.pdf计算每个高斯分布的PDF值。
  • 将每个高斯分布的PDF值乘以相应的权重,得到未归一化的责任。
  • 通过将每个数据点的责任除以其总和来归一化责任,确保每个数据点的责任之和为1。
PDF值通常指的是概率密度函数(Probability Density Function)的值。概率密度函数是连续概率分布的一个焦点概念,它形貌了随机变量在给定区间内取值的概率密度。对于连续随机变量,其概率密度函数的图形可以告诉我们随机变量取某个特定值的可能性。
4.M步调函数 _m_step
  1. def _m_step(self, X, responsibilities):
  2.     """M步骤:更新均值、协方差和权重"""
  3.     n_samples = X.shape[0]
  4.     effective_n = responsibilities.sum(axis=0)  # 每个聚类的有效样本数量
  5.    
  6.     # 更新权重
  7.     self.weights_ = effective_n / n_samples
  8.    
  9.     # 更新均值
  10.     self.means_ = np.dot(responsibilities.T, X) / effective_n[:, np.newaxis]
  11.    
  12.     # 更新协方差
  13.     for k in range(self.n_components):
  14.         diff = X - self.means_[k]
  15.         self.covariances_[k] = np.dot(responsibilities[:, k] * diff.T, diff) / effective_n[k]
复制代码

M步调根据E步调计算的责任更新模子参数:


  • self.weights_:权重更新为每个聚类的有效样本数量除以总样本数量。
  • self.means_:均值更新为加权均匀,权重是每个数据点对每个聚类的责任。
  • self.covariances_:协方差更新为加权的样本偏差的外积,权重是每个数据点对每个聚类的责任。
5.训练函数 fit
  1. def fit(self, X):
  2.     """训练模型"""
  3.     self._initialize_parameters(X)  # 初始化参数
  4.     for _ in range(self.n_iter):  # 迭代更新
  5.         responsibilities = self._e_step(X)  # E步骤
  6.         self._m_step(X, responsibilities)  # M步骤
复制代码



  • 首先调用_initialize_parameters函数初始化参数。
  • 然后举行指定次数的迭代,每次迭代都包括E步调和M步调。
6.预测函数 predict
  1. def predict(self, X):
  2.     """预测数据点的聚类标签"""
  3.     responsibilities = self._e_step(X)  # 计算责任
  4.     return np.argmax(responsibilities, axis=1)  # 返回最大责任的聚类索引
复制代码


  • 首先调用_e_step函数计算新数据点对每个聚类的责任。
  • 然后返回责任最大的聚类索引作为预测标签。
7.采样函数 sample
  1. def sample(self, n_samples):
  2.     """从模型中生成新样本"""
  3.     samples = np.zeros((n_samples, self.means_.shape[1]))
  4.     for i in range(n_samples):
  5.         k = np.random.choice(self.n_components, p=self.weights_)  # 根据权重选择聚类
  6.         samples[i] = np.random.multivariate_normal(self.means_[k], self.covariances_[k])  # 生成样本
  7.     return samples
复制代码


  • 首先初始化一个空的样本数组。
  • 然后根据每个聚类的权重随机选择一个聚类。
  • 从选定的聚类对应的高斯分布中生成一个样本。
  • 重复上述过程,直到生成所需数量的样本。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表