GMM模型的R实现
预备知识:
友情提示:本代码配合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()
得到的图:
参考网址:
来源:CSDN
作者:Clytze_yy
链接:https://blog.csdn.net/qq_29737811/article/details/78836427