混合高斯模型和EM算法

2022-12-08 14:21:09 浏览数 (1)

混合高斯模型和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:计算新一轮迭代的模型参数

 (用这一轮更新后的 

 )

0 人点赞