混合高斯模型和EM算法
于2021年5月15日2021年5月15日由Sukuna发布
一些概率的解释
在这个条件下,我们把图片上没有动物的角的概率作为先验概率,图片上有动物的角并且是犀牛称为类条件概率
类条件概率是就是已知一个条件下,结果发生的概率。条件概率实际上把一个完整的问题集合S通过特征进行了划分,划分成S1/S2/S3…。类条件概率中的类指的是把造成结果的所有原因一一进行列举,分别讨论。
先验概率:事情还没有发生,根据以往经验和分析得到的概率,在事情发生之前,得到的事情(结果)发生的概率。比如,一次抛硬币实验,我们认为正面朝上的概率是0.5,这就是一种先验概率,在抛硬币前,我们只有常识。
后验概率:事情已经发生了,结果的发生的原因有很多,判断结果的发生是由哪个原因引起的概率
贝叶斯决策论
假设有N种判别标记,
,
为将一个真实的标记
错误地分成了
地的损失,基于后验概率可以定义把x分到
所产生的期望损失
于是有:
在这里我们一般当i=j的时候,
,i≠j的时候,
所以说可以写出总体风险的表达式:
对于每个样本x,如果我们能最小化条件风险,我们就可以让总体风险减小,这个时候判定的准则就是最优的,因为我们的风险比较低,用数学式子表达一下:
计算后验概率是我们需要考虑的,这里有两个模型需可以考虑,一个是判别模型,就是直接构造概率分布:
,一个是生成模型,下面进行叙述:
在收到某个消息之后,接收端所了解到的该消息发送的概率称为后验概率。 随机变量X的概率分布为
,先验概率分布为
(样本空间中各类样本所占的比例),根据贝叶斯定理,后验概率分布为
:这里的逻辑内涵是:
是输出(分类的标准),
是输入,那么
是类条件概率,我们又称作似然.
极大似然估计
现在我们已经有训练集
,并且
可以用一组向量进行表示,训练集的样本是独立同分布的:
现在我我们要利用训练集来估计参数,假设参数我们用
表示:,这个时候我们定义似然:
,这个时候我们就可以找到使得似然值最大的
注意:这个时候
是类先验概率里面的一个参数,不能完全等同于c,这里只是说明方便把它替换了一下而已(因为贝叶斯学派认为
也是有分布的)
朴素贝叶斯分类器
从上面的分析中我们知道,我们很难得到
,因为P(x|c)是需要我们构建复杂的模型进行生成的,我们假设x是独立同分布的,那么有:
,朴素贝叶斯分类器就是基于训练集D来估计先验概率和类条件概率
首先是先验概率:
对于离散属性:我们让其条件概率为c类的所有元素之和和c类上取值为
的集合 对于连续属性:默认其为Gauss分布
根据独立同分布原理,我们可以把类条件概率刻画为
贝叶斯分类器的实践
下面用周志华的西瓜分类器3.0来作为例子:
代码语言:javascript复制编号,色泽,根蒂,敲声,纹理,脐部,触感,密度,含糖率,好瓜
1,青绿,蜷缩,浊响,清晰,凹陷,硬滑,0.697,0.46,是
2,乌黑,蜷缩,沉闷,清晰,凹陷,硬滑,0.774,0.376,是
3,乌黑,蜷缩,浊响,清晰,凹陷,硬滑,0.634,0.264,是
4,青绿,蜷缩,沉闷,清晰,凹陷,硬滑,0.608,0.318,是
5,浅白,蜷缩,浊响,清晰,凹陷,硬滑,0.556,0.215,是
6,青绿,稍蜷,浊响,清晰,稍凹,软粘,0.403,0.237,是
7,乌黑,稍蜷,浊响,稍糊,稍凹,软粘,0.481,0.149,是
8,乌黑,稍蜷,浊响,清晰,稍凹,硬滑,0.437,0.211,是
9,乌黑,稍蜷,沉闷,稍糊,稍凹,硬滑,0.666,0.091,否
10,青绿,硬挺,清脆,清晰,平坦,软粘,0.243,0.267,否
11,浅白,硬挺,清脆,模糊,平坦,硬滑,0.245,0.057,否
12,浅白,蜷缩,浊响,模糊,平坦,软粘,0.343,0.099,否
13,青绿,稍蜷,浊响,稍糊,凹陷,硬滑,0.639,0.161,否
14,浅白,稍蜷,沉闷,稍糊,凹陷,硬滑,0.657,0.198,否
15,乌黑,稍蜷,浊响,清晰,稍凹,软粘,0.36,0.37,否
16,浅白,蜷缩,浊响,模糊,平坦,硬滑,0.593,0.042,否
17,青绿,蜷缩,沉闷,稍糊,稍凹,硬滑,0.719,0.103,否
代码语言:javascript复制import numpy as np
import pandas as pd
dataset = pd.read_csv('3.0.csv', delimiter=",")
del dataset['编号']
print(dataset)
#X保存了所有除了是和否的元素
X = dataset.values[:, :-1]
m, n = np.shape(X)
print(m,n)
#做四舍五入计算
for i in range(m):
X[i, n - 1] = round(X[i, n - 1], 3)
X[i, n - 2] = round(X[i, n - 2], 3)
#y保存了结果
y = dataset.values[:, -1]
columnName = dataset.columns
colIndex = {}
#每一列的元素进行编号
for i in range(len(columnName)):
colIndex[columnName[i]] = i
Pmap = {} # 函数P很耗时间,而且经常会求一样的东西,因此我加了个记忆化搜索,用map存一下,避免重复计算,这里保存的是离散值
kindsOfAttribute = {} # kindsOfAttribute[0] = 3,因为有3种不同的类型的"色泽"
for i in range(n):
kindsOfAttribute[i] = len(set(X[:, i]))
continuousPara = {} # 记忆一些参数的连续数据,以避免重复计算
#保存好的和不好的元素
goodList = []
badList = []
for i in range(len(y)):
if y[i] == '是':
goodList.append(i)
else:
badList.append(i)
import math
def P(colID, attribute, C): # P(colName=attribute|C) P(色泽=青绿|是)
#已经预测过了,就直接返回一个三元组就行了
if (colID, attribute, C) in Pmap:
return Pmap[(colID, attribute, C)]
curJudgeList = []
if C == '是':
curJudgeList = goodList
else:
curJudgeList = badList
ans = 0
#colID>=6代表的是连续型变量
if colID >= 6:
mean = 1
std = 1
if (colID, C) in continuousPara:
curPara = continuousPara[(colID, C)]
mean = curPara[0]
std = curPara[1]
else:
#求平均值和方差
curData = X[curJudgeList, colID]
mean = curData.mean()
std = curData.std()
# print(mean,std)
#保存元素
continuousPara[(colID, C)] = (mean, std)
#返回要测试的密度
ans = 1 / (math.sqrt(math.pi * 2) * std) * math.exp((-(attribute - mean) ** 2) / (2 * std * std))
else:
for i in curJudgeList:
if X[i, colID] == attribute:
ans = 1
ans = (ans 1) / (len(curJudgeList) kindsOfAttribute[colID])
Pmap[(colID, attribute, C)] = ans
# print(ans)
return ans
def predictOne(single):
#先验概率
ansYes = math.log2((len(goodList) 1) / (len(y) 2))
ansNo = math.log2((len(badList) 1) / (len(y) 2))
for i in range(len(single)): # 书上是连乘,但在实践中要把“连乘”通过取对数的方式转化为“连加”以避免数值下溢
ansYes = math.log2(P(i, single[i], '是'))
ansNo = math.log2(P(i, single[i], '否'))
# print(ansYes,ansNo,math.pow(2,ansYes),math.pow(2,ansNo))
if ansYes > ansNo:
return '是'
else:
return '否'
def predictAll(iX):
predictY = []
for i in range(m):
predictY.append(predictOne(iX[i]))
return predictY
predictY = predictAll(X)
print(y)
print(np.array(predictAll(X)))
#输出测试结果
confusionMatrix = np.zeros((2, 2))
for i in range(len(y)):
if predictY[i] == y[i]:
if y[i] == '否':
confusionMatrix[0, 0] = 1
else:
confusionMatrix[1, 1] = 1
else:
if y[i] == '否':
confusionMatrix[0, 1] = 1
else:
confusionMatrix[1, 0] = 1
print(confusionMatrix)
acc = (confusionMatrix[0][0] confusionMatrix[1][1])/17
acc = str(acc)
print('acc: ' acc)
输出:
混合高斯分布
一维高斯分布函数
(多元)高斯分布
混合高斯分布
GMM是一个生成模型,它假设数据是从多个高斯分布中生成的,可以这样理解生成流程:有
个高斯分布,赋予每一个分布一个权重,每当生成一个数据时,就按权重的比例随机选择一个分布,然后按照该分布生成数据,就是隐变量,所以对于样本在给定参数
的条件下边际概率
首先,明确变量与参数
其中参数
包含隐变量Z的概率分布,各个高斯的均值与协方差矩阵:
就是输入,就是隐变量的值
协方差矩阵:左对角线是变量自己的相关系数,这个数越大圈里面的点扩散得越厉害。矩阵其他的数值就是变量本身跟其他变量的相关系数,这个数越大这个方向的椭圆就越尖。(矩阵的行列式就是协方差)
且样本的条件概率分布服从于
我们用概率的角度来思考这个问题,我们发现:
,
其实我们最终的目的已经知道了,对应一些输入,我们要分成给定的类,求出每一个类的核心,隐变量的离散分布,求出协方差矩阵来
总的来说:
高斯混合模型的概率分布为:
对于这个模型而言,参数
,也就是每个子模型的期望、方差(或协方差)、在混合模型中发生的概率。现在我们要求每个字模型的这些参数来作为分类手段
EM算法
还是上面的吃西瓜,对于一个西瓜的数据集,我们很难观察出所有西瓜的数据集成分,所以说我们就假设一个没有观测到的变量,我们把这个变量称为隐变量,现在我们想求隐变量的分布,就要用到EM算法,下面简要介绍其做法
1、根据已有的模型变量,推断出最佳的隐变量的参数 2、再根据已有的隐变量的参数,最大化模型变量
下面列出EM算法的数学表达:,我们假设大theta
是模型的表面参数,
是模型的隐参数,那么我们有:
E步:根据以前参数
推导出隐变量分布,并且计算出对树似然关于Z的期望
M步:
根据参数推导出新的变量的极大似然值
对于GMM的EM算法
数学推导暂缺
- E-step:依据当前参数,计算每个数据
来自子模型
的可能性
- M-step:计算新一轮迭代的模型参数
(用这一轮更新后的
)