R || 高斯混合模型GMM

好久不见. 提交于 2019-12-06 01:51:08

GMM模型的R实现

预备知识:

EM算法原理

GMM算法原理

友情提示:本代码配合GMM算法原理中的步骤阅读更佳哦!

本文分为一元高斯分布的EM算法以及多元高斯分布的EM算法,分别采用两本书上的数据《统计学习方法》和《机器学习》。

一元高斯混合模型

步骤:

1、设置模型参数的初始值,以及给出测试的数据

data <- c(-67,-48,6,8,14,16,23,24,28,29,41,49,56,60,75)
a = c(0.5,0.5) #系数
u = c(0,1)     #初始均值
sigma2 =c(9,9) #初始方差

data数据来自《统计机器学习》

2:E步 迭代计算gamma值,也就是响应度

首先利用dnorm()计算高斯公式的密度值,sapply()来向量化带入函数计算

p <- t(sapply(data,dnorm,u,sigma))
amatrix <- matrix(rep(a,N),nrow=N,byrow = T) #便于计算
r = (p * amatrix) / rowSums(p * amatrix)     
#r(gamma):分模型k对观测数据data的响应度

M步 迭代更新均值、方差和模型系数

u <-  colSums(data*r)/colSums(r)
umatrix <- matrix(rep(u,N),nrow=N,byrow = T)
sigma2 <- colSums(r*(mat-umatrix)^2)/colSums(r) 
a <- colSums(r)/length(data)

3:设置迭代停止条件

根据自己需要设置,这里设置为均值和方差变化不大则停止(也可以设置迭代最大轮数)

4:根据每个观测值对每个高斯分布的响应度,响应度大则归为该分布(也就是簇)。

 cluster <- which(r == apply(r,1,max),arr.ind = T)

将上述过程写成函数

GaussCluster <- function(data,k,a,u,sigma2){
  #data:数据集,向量
  #k:聚类的个数,或高斯分布的个数
  #a0:高斯分布的先验概率,选择各个高斯分布的概率,向量
  #u0:高斯分布的初始均值
  #sigma2:一元高斯分布即为方差,sigma为标准差

  mat = matrix(rep(data,k),ncol = k) #方便后续计算
  N = length(data)
  i=0
  while(TRUE){
    u0 <- u
    sigma  = sqrt(sigma2)
    sigma0 <- sigma
    umatrix <- matrix(rep(u,N),nrow=N,byrow = T)
    p <- t(sapply(data,dnorm,u,sigma)) 
    amatrix <- matrix(rep(a,N),nrow=N,byrow = T) 
    r = (p * amatrix) / rowSums(p * amatrix)     
    u <-  colSums(data*r)/colSums(r)
    sigma2 <- colSums(r*(mat-umatrix)^2)/colSums(r) 
    a <- colSums(r)/length(data)
    sumU <- sum((u-u0)^2)
    sumsigma <- sum((sigma-sigma0)^2)
    if((sumU <= 1e-4) & (sumsigma <= 1e-4)){
      break
    }
  }
  cluster <- which(r == apply(r,1,max),arr.ind = T)
  return(list(u = u,d = sigma2,a = a,cluster = cluster))
}

调用函数

GaussCluster(data,2,c(0.5,0.5),c(0,1),c(9,9))

最终得到的结果

多元高斯混合模型

多元高斯混合模型采用的是《机器学习》中的西瓜数据集。

多元高斯分布中的密度值需要用mvtnorm包中的dmvnorm()来计算。

library(mvtnorm)
mulGaussCluster <- function(data,k,a,u,cov0){
  #data:数据集,向量或数据框
  #k:聚类的个数,或高斯分布的个数
  #a:高斯分布的先验概率,选择各个高斯分布的概率,向量
  #u:高斯分布的初始均值
  #cov0:多元高斯分布的初始协方差阵
  N = nrow(data)
  covList = list()
  for(i in 1:k){
    covList[[i]] <- cov0
  }
  count=1
  while(TRUE){
    u0 <- u
    p = c()
    for(j in 1:k){
      prob = apply(data,1,dmvnorm,mean=u[j,],sigma = covList[[j]])
      p = cbind(p,prob)
    }
    amatrix <- matrix(rep(a,N),nrow=N,byrow = T)
    r = (p * amatrix) / rowSums(p * amatrix)  
    u <- t(r) %*% data / colSums(r) #求和可以转化为向量相乘的形式,简化计算
    for(j in 1:k){
      sigma = matrix(rep(0,4),ncol=2)
      for(i in 1:N){
        sigma = sigma + r[i,j] * (data[i,]-u0[j,]) %*% t(data[i,]-u0[j,])  #R中向量默认为列向量
      }
      covList[[j]]= sigma/sum(r[,j]) 
    }
    a <- colSums(r)/N
    count = count + 1
    if(count == 100){
      break
    }
  }
  cluster <- which(r == apply(r,1,max),arr.ind = T)
  cluster <- cluster[order(cluster[,1]),]
  return(list(u = u,covList = covList,a = a,cluster = cluster))
}

调用:

wamellondata <- read.csv('watermelon.csv')
data = as.matrix(wamellondata[,2:3])
a = c(1/3,1/3,1/3)
u = rbind(data[6,],data[22,],data[27,])
cov0 <- matrix(c(0.1,0,0,0.1),ncol = 2)
list=mulGaussCluster(data,k=3,a,u,cov0)
cluster = list$cluster

结果:

当然这时候还可以用ggplot2来绘制聚类图

library(ggplot2)
ggplot(data=NULL,mapping=aes(x=data[,1],y=data[,2],group = cluster[,2])) + 
  geom_point(colour = cluster[,2]) + xlab('density')+ylab('sugarContent')+
  theme_minimal()

得到的图:

参考网址:

R实现一维高斯分布混合模型

python实现多维高斯分布模型

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!