高斯判别分析GDA推导与代码实现

生成学习

处理分类问题,我们可以使用逻辑回归、Softmax。这两种方法都属于“判别学习”,也就是给定 \((x^{(i)}, y^{(i)})\),我们学习 \(P(y|x)\),并对于给定的 \(x\),计算 \(\operatorname{argmax}_{y}\{P(y|x)\}\)。

GDA属于另一种方法——生成学习。在判别学习中,我们并不关注 \(x\) 本身的分布,而在生成学习中,我们基于一些事实假设 \(x\) 的分布,例如在GDA中,我们假设对于相同的 \(y\),\(x\) 符合高斯分布。然后基于假设,学习 \(P(x|y)\) 的参数(高斯分布则学习均值 \(\mu\) 和协方差 \(\Sigma\)),以及 \(P(y)\) 的参数(例如两点分布的 \(\phi\)),从而得到联合概率 \(P(x,y)\)。在预测时,我们仍然是找到最大的 \(P(y|x)\),但是是用贝叶斯公式计算:

\[P(y|x) = \frac{P(x,y)}{P(x)}
\]

高斯判别分析

作出的假设

首先假设 \(Y\) 服从两点分布 \(Bernolli(\phi)\),于是可以写作 \(P(y)=\phi^{y}(1-\phi)^{1-y}\)。

(尽管可以直接用协方差定义多元变量的高斯分布,但是这里采用另一种方法,在特殊的情况下得到等式而不需要完全理解协方差矩阵。)

然后假设给定 \(y\) 后,\(x\) 的每一个分量 \(x_i\) 都服从高斯分布且相互独立。不妨设 \(y=0\),即 \(x_i|y=0\sim N(\mu_i,\sigma_i)\):

\[P(x_i|y=0)=\frac{1}{\sqrt{2\pi}\sigma_i}\exp\left(-\frac{(x_i-\mu_i)^2}{2\sigma_i^2}\right)
\]

又 \(x_i\) 相互独立,可以得到:

\[\begin{aligned}
P(x|y=0)&=\prod_{i=1}^n\frac{1}{\sqrt{2\pi}\sigma_i}\exp\left(-\frac{(x_i-\mu_i)^2}{2\sigma_i^2}\right)\\
&=\frac{1}{(2\pi)^{\frac{n}{2}}\sigma_1\dots\sigma_n}\exp\left(-\frac{1}{2}\sum_{i=1}^n\frac{(x_i-\mu_i)^2}{\sigma_i^2}\right)\\
\end{aligned}
\]

我们定义矩阵 \(\Sigma=\begin{pmatrix}\sigma_1^2\\&\ddots\\&&\sigma_n^2\end{pmatrix}\),可以将上式化简:

\[P(x|y=0)=\frac{1}{(2\pi)^{\frac{n}{2}}|\Sigma|^{\frac{1}{2}}}\exp\left(-\frac{1}{2}(x-\mu)\Sigma^{-1}(x-\mu)^{T}\right)
\]

同样,我们也假设 \(x|y=1\) 符合高斯分布 \(N(\mu',\Sigma)\),需要注意的是,两个分布都采用了同一个 \(\Sigma\)(存疑,不知道目的)。

但是实际上GDA并没有假设 \(\Sigma\)

最大似然估计

在判别学习中,我们以 \(P(y^{(i)}\mid x^{i})\) 为似然函数,而在GDA这一类生成学习中,我们以联合概率 \(P(x^{(i)},y^{(i)})\) 为似然函数。也即最大化如下对数似然函数:

\[\begin{aligned}
\mathcal{L}(\phi,\mu,\mu',\Sigma)&=\ln\prod_{i=1}^{m}P(x^{(i)},y^{(i)};\phi,\mu,\mu',\Sigma)\\
&=\ln\prod_{i=1}^{m}P(x^{(i)}\mid y^{(i)};\mu,\mu',\Sigma)P(y^{(i)};\phi)\\
&=\sum_{i=1}^{m}\ln P(x^{(i)}\mid y^{(i)};\mu,\mu',\Sigma)+\sum_{i=1}^m\ln P(y^{(i)};\phi)
\end{aligned}
\]

不同于逻辑回归,我们可以直接用导数为 \(0\) 求解参数。

计算 \(\phi\)

\[\begin{aligned}
\frac{\partial \mathcal{L}}{\partial \phi}&=\frac{\partial}{\partial\phi}\sum_{i=1}^m\ln P(y^{(i)};\phi)\\
&=\frac{\partial}{\partial\phi}\sum_{i=1}^my^{(i)}\ln\phi+(1-y^{(i)})\ln(1-\phi)\\
&=\sum_{i=1}^m\frac{y^{(i)}}{\phi}-\frac{1-y^{(i)}}{1-\phi}
\end{aligned}
\]

令上式为 \(0\),得 \(\phi=\frac{\sum y^{(i)}}{m}\)。

计算 \(\mu,\mu'\)

一些无关紧要的常数用 \(C\) 代替,比如密度函数中的系数。

\[\begin{aligned}
\nabla_{\mu}\mathcal{L}&=\nabla_{\mu}\sum_{i=1}^m(1-y^{(i)})\ln P(x^{(i)}\mid y=0;\mu,\Sigma)+y^{(i)}\ln P(x^{(i)}\mid y=1;\mu',\Sigma)
\end{aligned}
\]

其中

\[\begin{aligned}
\frac{\partial}{\partial \mu_j}\ln P(x^{(i)}\mid y=0;\mu,\Sigma)&=\frac{\partial}{\partial \mu_j}\left(C-\frac{1}{2}\ln|\Sigma|-\frac{1}{2}(x^{(i)}-\mu)\Sigma^{-1}(x^{(i)}-\mu)^T\right)\\
&=x^{(i)}_j-\mu_j
\end{aligned}
\]

则 \(\nabla_{\mu}\ln P(x^{(i)}\mid y=0;\mu,\Sigma)=x^{(i)}-\mu\),进而

\[\nabla_{\mu}\mathcal{L}=\sum_{i=1}^m(1-y^{(i)})(x^{(i)}-\mu)
\]

令上式为 \(0\),可得 \(\mu=\frac{\sum(1-y^{(i)})x^{(i)}}{\sum 1-y^{(i)}}\),同理可得 \(\mu'=\frac{\sum y^{(i)}x^{(i)}}{\sum y^{(i)}}\)。

计算 \(\Sigma\)

下面用到了两个 \(\nabla\) 算符的性质:

  • \(\nabla_{\Sigma}|\Sigma|=|\Sigma|\Sigma^{-1}\);
  • \(\nabla_{\Sigma}\Sigma^{-1}=-\Sigma^{-2}\)。
\[\begin{aligned}
\nabla_{\Sigma}\mathcal{L}&=\sum_{i=1}^m-\frac{1}{2|\Sigma|}\cdot\nabla_{\Sigma}|\Sigma|+\frac{1}{2}\nabla_{\Sigma}\left((x^{(i)}-\mu)\Sigma^{-1}(x^{(i)}-\mu)^{T}\right)\\
&=\sum_{i=1}^m-\frac{1}{2}\Sigma^{-1}+\frac{1}{2}(x^{(i)}-\mu)^T(x^{(i)}-\mu)\Sigma^{-2}
\end{aligned}
\]

同样地令上式为 \(0\),计算得

\[\Sigma=\frac{1}{m}\sum_{i=1}^m(x^{(i)}-\mu)^T(x^{(i)}-\mu)
\]

注意到,按照我们的假设,\(\Sigma\) 应该是一个对角矩阵(如果了解协方差矩阵的话,由 \(x_i\) 相互独立,可以推出 \(\Sigma\) 应该是对角矩阵,对角元就是每个变量的方差),但是这里非常显然不总是对角矩阵。

(以下仅是我个人的猜测)在GDA的实现中,我们并没有关注 \(x_i\) 相互独立的性质,而是直接学习了一个普遍的协方差矩阵。实际上这种定义的限制更低,更符合现实情况(现实中的变量之间存在联系比较普遍)。

代码实现

直接计算这几个参数的代码不需要解释:

m, n = xs.shape
# Calculate mu
self.mu = np.zeros((2, n))
classes_size = np.zeros(2)
for i in range(m):
self.mu[ys[i]] += xs[i]
classes_size[ys[i]] += 1
self.mu /= np.transpose([classes_size])
# Calculate Sigma
self.sigma = np.zeros((n, n))
for i in range(m):
temp_array = xs[i] - self.mu[ys[i]]
self.sigma += np.dot(temp_array.reshape(n, 1), temp_array.reshape(1, n))
self.sigma /= m
# Calculate phi
self.phi = np.sum(ys) / m

最后我们发现计算概率需要计算 \(\Sigma^{-1}\),然而我们算出来的可能是一个奇异矩阵。这时候可以对 \(\Sigma\) 进行微扰——将对角元加上一个较小的偏差。

最后我们对 \(y=0,1\) 分别计算出 \(P(x|y)\)。

\[P(x|y;\mu,\Sigma)=\frac{1}{(2\pi)^{\frac{n}{2}}|\Sigma|^{\frac{1}{2}}}\cdot\exp\left(-\frac{(x-\mu)\Sigma^{-1}(x-\mu)^T}{2}\right)
\]

但是实际上比较 \(P(x|y=0),P(x|y=1)\) 不需要真正计算出概率,而是比较两者不同的地方,也就是后面的 \(\exp\)。

(奇异矩阵的处理参考 https://blog.csdn.net/qq_30091945/article/details/81508055 ,对其中的 Gaussian 函数有修改)

最后是实现的一个类:

class GaussianDiscriminantAnalysis:
def __init__(self):
self.mu = None
self.phi = None
self.sigma = None def fit(self, xs, ys, **others):
m, n = xs.shape
# Calculate mu
self.mu = np.zeros((2, n))
classes_size = np.zeros(2)
for i in range(m):
self.mu[ys[i]] += xs[i]
classes_size[ys[i]] += 1
self.mu /= np.transpose([classes_size])
# Calculate Sigma
self.sigma = np.zeros((n, n))
for i in range(m):
temp_array = xs[i] - self.mu[ys[i]]
self.sigma += np.dot(temp_array.reshape(n, 1), temp_array.reshape(1, n))
self.sigma /= m
# Calculate phi
self.phi = np.sum(ys) / m def evaluate(self, x, mean, cov):
dim = np.shape(cov)[0]
# cov的行列式为零时的措施
cov_inv = np.linalg.inv(cov + np.eye(dim) * 0.001)
xdiff = (x - mean).reshape((1, dim))
# 概率密度
prob = np.exp(-0.5 * xdiff.dot(cov_inv).dot(xdiff.T))[0][0]
return prob def predict(self, xs):
predict = []
for x in xs:
evaluate_0 = self.evaluate(x, self.mu[0], self.sigma) * (1 - self.phi)
evaluate_1 = self.evaluate(x, self.mu[1], self.sigma) * self.phi
if evaluate_0 > evaluate_1:
predict.append(0)
else:
predict.append(1)
return predict

高斯判别分析GDA推导与代码实现的更多相关文章

  1. 【cs229-Lecture5】生成学习算法:1)高斯判别分析(GDA);2)朴素贝叶斯(NB)

    参考: cs229讲义 机器学习(一):生成学习算法Generative Learning algorithms:http://www.cnblogs.com/zjgtan/archive/2013/ ...

  2. Gaussian discriminant analysis 高斯判别分析

    高斯判别分析(附Matlab实现) 生成学习算法 高斯判别分析(Gaussian Discriminant analysis,GDA),与之前的线性回归和Logistic回归从方法上讲有很大的不同,G ...

  3. 高斯判别分析 Gaussian Discriminant Analysis

    如果在我们的分类问题中,输入特征xx是连续型随机变量,高斯判别模型(Gaussian Discriminant Analysis,GDA)就可以派上用场了. 以二分类问题为例进行说明,模型建立如下: ...

  4. [置顶] 生成学习算法、高斯判别分析、朴素贝叶斯、Laplace平滑——斯坦福ML公开课笔记5

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9285001 该系列笔记1-5pdf下载请猛击这里. 本篇博客为斯坦福ML公开 ...

  5. ML—高斯判别分析

    华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/12/11 高斯判别分析属于生成模型,模型终于学习一个特征-类别的联合概率. 0 多维正态分布 确定一个多维正态分布仅仅须要知道分布的均值 ...

  6. 《神经网络的梯度推导与代码验证》之FNN(DNN)的前向传播和反向推导

    在<神经网络的梯度推导与代码验证>之数学基础篇:矩阵微分与求导中,我们总结了一些用于推导神经网络反向梯度求导的重要的数学技巧.此外,通过一个简单的demo,我们初步了解了使用矩阵求导来批量 ...

  7. 《神经网络的梯度推导与代码验证》之FNN(DNN)前向和反向过程的代码验证

    在<神经网络的梯度推导与代码验证>之FNN(DNN)的前向传播和反向梯度推导中,我们学习了FNN(DNN)的前向传播和反向梯度求导,但知识仍停留在纸面.本篇章将基于深度学习框架tensor ...

  8. 《神经网络的梯度推导与代码验证》之CNN的前向传播和反向梯度推导

    在FNN(DNN)的前向传播,反向梯度推导以及代码验证中,我们不仅总结了FNN(DNN)这种神经网络结构的前向传播和反向梯度求导公式,还通过tensorflow的自动求微分工具验证了其准确性.在本篇章 ...

  9. 《神经网络的梯度推导与代码验证》之CNN前向和反向传播过程的代码验证

    在<神经网络的梯度推导与代码验证>之CNN的前向传播和反向梯度推导 中,我们学习了CNN的前向传播和反向梯度求导,但知识仍停留在纸面.本篇章将基于深度学习框架tensorflow验证我们所 ...

  10. 《神经网络的梯度推导与代码验证》之vanilla RNN的前向传播和反向梯度推导

    在本篇章,我们将专门针对vanilla RNN,也就是所谓的原始RNN这种网络结构进行前向传播介绍和反向梯度推导.更多相关内容请见<神经网络的梯度推导与代码验证>系列介绍. 注意: 本系列 ...

随机推荐

  1. 【分析笔记】Linux 4.9 backlight 子系统分析

    相关信息 内核版本:Linux version 4.9.56 驱动文件:lichee\linux-4.9\drivers\video\backlight\backlight.c 驱动作用 对上,面对应 ...

  2. Django-request、django连接数据库、ORM

    1.静态文件配置 1.静态文件:不经常变化的文件,主要针对html文件(CSS文件.js文件.img文件.第三方框架文件). 2.django针对静态文件资源需要单独开始一个目录统一存放:static ...

  3. 浅析 SeaweedFS 与 JuiceFS 架构异同

    SeaweedFS 是一款高效的分布式文件存储系统,最早的设计原型参考了 Facebook 的 Haystack,具有快速读写小数据块的能力.本文将通过对比 SeaweedFS 与 JuiceFS 在 ...

  4. 真正“搞”懂HTTPS协议15之安全的定义

    前面我们花了很大的篇幅来讲HTTP在性能上的改进,从1.0到1.1,再到2.0.3.0,HTTP通过替换底层协议,解决了一直阻塞性能提升的队头阻塞问题,在性能上达到了极致. 那么,接下来,我们来聊一聊 ...

  5. 尊重 respect

    尊重他人,这里面的门道. 明面上尊重他人要在自身有地位有身份的前提下,你身边的其他人 才能高效接收到你传递的信号,这叫礼贤下士. 暂时没地位的人更是应该无时无刻释放出尊重他人的信号,来向外界传达你是一 ...

  6. 亚马孙机器可能出现权限问题导致ssh无法秘钥登录的情况

    一般都是amazon会遇到,目前ali的机器没遇到过 情况是新机器,然后ssh脚本创建目录和用户和拷贝秘钥等等,后面用该新用户的秘钥登录发现一直无法登录. 把sshd的log改为debug,查看日志得 ...

  7. 国际财务系统基于ShardingSphere的数据分片和一主多从实践

    作者:京东物流 张广治 1 背景 传统的将数据集中存储至单一数据节点的解决方案,在性能和可用性方面已经难于满足海量数据的场景,系统最大的瓶颈在于单个节点读写性能,许多的资源受到单机的限制,例如连接数. ...

  8. Struts2文件配置介绍

    Struts2文件配置介绍 struts2 structs.xml文件配置 标签 package标签 <?xml version="1.0" encoding="U ...

  9. 通过 Blob 创建下载文件

    Blob 如上图所示,Blob 对象有三个部分组成,data:image/jpeg 表示该 Blob 是什么类型的文件.base64 是一个二进制到文本的编码,更多细节查看Base64 编码/解码.其 ...

  10. 从源码MessageSource的三个实现出发实战spring·i18n国际化

    1.前言 互联网业务出海,将已有的业务Copy to Global,并且开始对各个国家精细化,本土化的运营.对于开发人员来说,国际化很重要,在实际项目中所要承担的职责是按照客户指定的语言让服务端返回相 ...