前言
这篇文章总结一个生成模型——高斯判别分析。
1. 判别模型和生成模型
?在监督学习中,模型训练成功后,我们往往会得到一个决策函数
f
(
x
)
f(x)
f(x) 或者一个概率分布
P
(
y
∣
x
)
P(y|x)
P(y∣x) ,当需要预测时,我们通过给定的
x
x
x ,使用
f
(
x
)
f(x)
f(x) 作为
y
y
y 的预测值或者使用
P
(
y
∣
x
)
P(y|x)
P(y∣x) 计算出概率。
?在之前总结的线性回归、逻辑回归等模型都是判别模型(discriminative model),判别模型是根据训练集学习,直接得到
f
(
x
)
f(x)
f(x) 或者
P
(
y
∣
x
)
P(y|x)
P(y∣x) ,它只是关心对于给定的
x
x
x 需要预测出什么样的
y
y
y 。
?还有一种模型是生成模型(generative model),这个模型大致思想是这样的,对于给定的训练集
{
(
x
(
i
)
,
y
(
i
)
)
}
1
m
\left\{ \left( x^{\left( i \right)},y^{\left( i \right)} \right) \right\} _{1}^{m}
{(x(i),y(i))}1m? ,我们它是由某一个概率分布 “生成” 的,这样我们就要估计出那个概率分布。这些数据既然会出现,那么也就是说出现这些数据的可能性很大,我们就通过最大化联合概率分布
P
(
x
(
1
)
,
y
(
1
)
,
?
?
,
x
(
m
)
,
y
(
m
)
)
P\left( x^{\left( 1 \right)},y^{\left( 1 \right)},\cdots ,x^{\left( m \right)},y^{\left( m \right)} \right)
P(x(1),y(1),?,x(m),y(m)) 来估计原来的分布。也就是利用最大似然估计法估计。估计原分布的过程就是训练的过程。预测时,通过条件概率公式
P
(
y
∣
x
)
=
P
(
x
,
y
)
/
P
(
x
)
P\left( y|x \right) =P\left( x,y \right) /P\left( x \right)
P(y∣x)=P(x,y)/P(x) 得到给定特征向量
x
x
x 条件下
y
y
y 的概率。
2. 高斯判别分析模型
?高斯判别分析(Gaussian Discriminant Analysis,GDA) 是一种生成模型。假设一个分类任务中,类别有
K
K
K 个,记为
{
0
,
1
,
?
?
,
K
?
1
}
\left\{ 0,1,\cdots ,K-1 \right\}
{0,1,?,K?1} ,特征向量为
x
=
(
x
1
,
x
2
,
?
?
,
x
n
)
T
x=\left( x_1,x_2,\cdots ,x_n \right)^T
x=(x1?,x2?,?,xn?)T ,输出变量为
y
∈
{
0
,
1
,
?
?
,
K
?
1
}
y\in \left\{ 0,1,\cdots ,K-1 \right\}
y∈{0,1,?,K?1} ,现有训练集
{
(
x
(
i
)
,
y
(
i
)
)
}
1
m
\left\{ \left( x^{\left( i \right)},y^{\left( i \right)} \right) \right\} _{1}^{m}
{(x(i),y(i))}1m? 。
?高斯判别分析需对每一个类别
i
i
i 作出这样的假设:
P
(
x
∣
y
=
i
)
=
1
(
2
π
)
n
/
2
∣
Σ
∣
1
/
2
exp
?
(
?
1
2
(
x
?
μ
i
)
T
Σ
?
1
(
x
?
μ
i
)
)
P\left( x|y=i \right) =\frac{1}{\left( 2\pi \right) ^{n/2}\left| \Sigma \right|^{1/2}}\exp \left( -\frac{1}{2}\left( x-\mu _i \right) ^T\Sigma ^{-1}\left( x-\mu _i \right) \right)
P(x∣y=i)=(2π)n/2∣Σ∣1/21?exp(?21?(x?μi?)TΣ?1(x?μi?)) 也就是说,每一类别
i
(
i
=
0
,
1
,
?
?
,
K
?
1
)
i\left( i=0,1,\cdots ,K-1 \right)
i(i=0,1,?,K?1) 的特征向量服从
n
n
n 元高斯分布。
μ
i
\mu_i
μi? 是
n
n
n 维期望向量,第
j
j
j 个分量是类别
i
i
i 的特征向量
x
x
x 的第
j
j
j 个分量
x
j
x_j
xj? 的期望。
Σ
\Sigma
Σ 是
n
×
n
n\times n
n×n 维协方差矩阵,
Σ
i
j
\Sigma_{ij}
Σij? 是
x
i
x_i
xi? 和
x
j
x_j
xj? 的协方差,
Σ
\Sigma
Σ 并不区分类别,这里假设所有类别的
Σ
\Sigma
Σ 相同。
?需要对类别的概率分布作出这样的假设:
P
(
y
)
=
?
0
I
{
y
=
0
}
?
1
I
{
y
=
1
}
?
?
K
?
1
I
{
y
=
K
?
1
}
P\left( y \right) =\phi _{0}^{I\left\{ y=0 \right\}}\phi _{1}^{I\left\{ y=1 \right\}}\cdots \phi _{K-1}^{I\left\{ y=K-1 \right\}}
P(y)=?0I{y=0}??1I{y=1}???K?1I{y=K?1}? 其中
∑
i
=
0
K
?
1
?
i
=
1
\sum_{i=0}^{K-1}{\phi _i}=1
∑i=0K?1??i?=1 ,也就是说
y
y
y 是类别
i
(
i
=
0
,
1
,
?
?
,
K
?
1
)
i\left( i=0,1,\cdots ,K-1 \right)
i(i=0,1,?,K?1) 的概率为
?
i
\phi_i
?i? 。
?这个模型训练时就是要求解这些参数:
{
?
0
,
?
1
,
?
?
,
?
K
?
1
,
μ
0
,
μ
1
,
?
?
,
μ
K
?
1
,
Σ
}
\left\{ \phi _0,\phi _1,\cdots ,\phi _{K-1},\mu _0,\mu _1,\cdots ,\mu _{K-1},\Sigma \right\}
{?0?,?1?,?,?K?1?,μ0?,μ1?,?,μK?1?,Σ} ,实际上,对于每一个类别很可能有不同的协方差矩阵
Σ
\Sigma
Σ ,但这个模型中仍然假设
Σ
\Sigma
Σ 相同,这样做可以使得分类决策面是线性的。但是如果每个类别的协方差矩阵相差很大时,那么这样做可能使模型预测效果变差。
?模型预测时,对于所给的特征向量
x
x
x ,计算出条件概率:
P
(
y
=
i
∣
x
)
=
P
(
x
,
y
=
i
)
P
(
x
)
=
P
(
x
∣
y
=
i
)
P
(
y
=
i
)
P
(
x
)
??
(
i
=
0
,
1
,
?
?
,
K
?
1
)
P\left( y=i|x \right) =\frac{P\left( x,y=i \right)}{P\left( x \right)}=\frac{P\left( x|y=i \right) P\left( y=i \right)}{P\left( x \right)} \\ \,\, \left( i=0,1,\cdots ,K-1 \right)
P(y=i∣x)=P(x)P(x,y=i)?=P(x)P(x∣y=i)P(y=i)?(i=0,1,?,K?1) ?预测结果是
y
=
a
r
g
max
?
i
??
P
(
y
=
i
∣
x
)
y=arg\max_i \,\,P\left( y=i|x \right)
y=argmaxi?P(y=i∣x) 。
?无论
i
i
i 取值如何,概率
P
(
x
)
P(x)
P(x) 都是相同的,因此预测时可以不必计算
P
(
x
)
P(x)
P(x) ,只需要计算
P
(
x
∣
y
=
i
)
P
(
y
=
i
)
P(x|y=i)P(y=i)
P(x∣y=i)P(y=i) ,然后求出哪一类
i
i
i 使得
P
(
x
∣
y
=
i
)
P
(
y
=
i
)
P(x|y=i)P(y=i)
P(x∣y=i)P(y=i) 最大即可。这也就是说预测结果可以简化为:
y
=
a
r
g
max
?
i
??
P
(
y
=
i
∣
x
)
=
a
r
g
max
?
i
??
P
(
x
∣
y
=
i
)
P
(
y
=
i
)
y=arg\max_i \,\,P\left( y=i|x \right) =arg\max_i \,\,P\left( x|y=i \right) P\left( y=i \right)
y=argmaxi?P(y=i∣x)=argmaxi?P(x∣y=i)P(y=i) 。
?如果想要得到每个类别的概率,这时只需要将每一个
P
(
x
∣
y
=
i
)
P
(
y
=
i
)
P(x|y=i)P(y=i)
P(x∣y=i)P(y=i) 归一化即可,也就是说:
P
(
y
=
i
∣
x
)
=
P
(
x
∣
y
=
i
)
P
(
y
=
i
)
∑
j
=
0
K
?
1
P
(
x
∣
y
=
j
)
P
(
y
=
j
)
??
(
i
=
0
,
1
,
?
?
,
K
?
1
)
P\left( y=i|x \right) =\frac{P\left( x|y=i \right) P\left( y=i \right)}{\sum_{j=0}^{K-1}{P\left( x|y=j \right) P\left( y=j \right)}}\,\,\left( i=0,1,\cdots ,K-1 \right)
P(y=i∣x)=∑j=0K?1?P(x∣y=j)P(y=j)P(x∣y=i)P(y=i)?(i=0,1,?,K?1) ?实际上,通过全概率公式也可以得到:
P
(
x
)
=
∑
j
=
0
K
?
1
P
(
x
∣
y
=
j
)
P
(
y
=
j
)
P\left( x \right) =\sum_{j=0}^{K-1}{P\left( x|y=j \right) P\left( y=j \right)}
P(x)=∑j=0K?1?P(x∣y=j)P(y=j) 。
3. 参数估计
?模型中提到,训练时要估计这些参数:
{
?
0
,
?
1
,
?
?
,
?
K
?
1
,
μ
0
,
μ
1
,
?
?
,
μ
K
?
1
,
Σ
}
\left\{ \phi _0,\phi _1,\cdots ,\phi _{K-1},\mu _0,\mu _1,\cdots ,\mu _{K-1},\Sigma \right\}
{?0?,?1?,?,?K?1?,μ0?,μ1?,?,μK?1?,Σ} ,采用最大似然法估计,对数似然函数为:
l
(
μ
0
,
?
?
,
μ
K
?
1
,
?
0
,
?
?
,
?
K
?
1
,
Σ
)
=
∑
i
=
1
m
ln
?
P
(
x
(
i
)
,
y
(
i
)
)
=
∑
i
=
1
m
ln
?
P
(
x
(
i
)
∣
y
(
i
)
)
P
(
y
(
i
)
)
l\left( \mu _0,\cdots ,\mu _{K-1},\phi _0,\cdots ,\phi _{K-1},\Sigma \right) \\ =\sum_{i=1}^m{\ln P\left( x^{\left( i \right)},y^{\left( i \right)} \right)}=\sum_{i=1}^m{\ln P\left( x^{\left( i \right)}|y^{\left( i \right)} \right) P\left( y^{\left( i \right)} \right)}
l(μ0?,?,μK?1?,?0?,?,?K?1?,Σ)=i=1∑m?lnP(x(i),y(i))=i=1∑m?lnP(x(i)∣y(i))P(y(i)) 最大化该对数自然函数,求出的结果为:
μ
i
=
∑
j
=
1
m
x
(
j
)
I
{
y
(
j
)
=
i
}
∑
j
=
1
m
I
{
y
(
j
)
=
i
}
??
(
i
=
0
,
1
,
?
?
,
K
?
1
)
\mu _i=\frac{\sum_{j=1}^m{x^{\left( j \right)}I\left\{ y^{\left( j \right)}=i \right\}}}{\sum_{j=1}^m{I\left\{ y^{\left( j \right)}=i \right\}}}\,\,\left( i=0,1,\cdots ,K-1 \right)
μi?=∑j=1m?I{y(j)=i}∑j=1m?x(j)I{y(j)=i}?(i=0,1,?,K?1)
?
i
=
1
m
∑
j
=
1
m
I
{
y
(
j
)
=
i
}
\phi _i=\frac{1}{m}\sum_{j=1}^m{I\left\{ y^{\left( j \right)}=i \right\}}
?i?=m1?j=1∑m?I{y(j)=i}
Σ
=
1
m
∑
j
=
1
m
(
x
(
j
)
?
μ
y
(
j
)
)
(
x
(
j
)
?
μ
y
(
j
)
)
T
\Sigma =\frac{1}{m}\sum_{j=1}^m{\left( x^{\left( j \right)}-\mu _{y^{\left( j \right)}} \right) \left( x^{\left( j \right)}-\mu _{y^{\left( j \right)}} \right) ^T}
Σ=m1?j=1∑m?(x(j)?μy(j)?)(x(j)?μy(j)?)T
?最大似然估计最终得出的结果是上述公式。这个计算过程是稍微有些繁琐的(所以我也就不想写了),但是这个最终结果却是非常棒的,看起来很合理,直接使用矩估计也可以得出同样的结果。
4. 代码实现
?实现高斯判别分析的类:
class GDA(object):
mu, Sigma, phi, n_class = 0, 0, 0, 0
def fit(self, X_train, y_train):
self.n_class = y_train.max() + 1
self.mu = np.empty([self.n_class, X_train.shape[1]])
for i in range(self.n_class):
idx = np.argwhere(y == i)
idx = idx.squeeze(axis = 1)
self.mu[i] = X[idx].mean(axis = 0)
self.Sigma = np.corrcoef(X_train, rowvar = False)
self.phi = np.empty(self.n_class)
for i in range(self.n_class):
self.phi[i] = (y_train == i).sum() / y_train.shape[0]
def probability(self, X):
mu, Sigma, phi, n_class = self.mu, self.Sigma, self.phi, self.n_class
p = np.empty([X.shape[0], n_class])
for i in range(X.shape[0]):
for j in range(n_class):
fenzi = np.exp(-np.dot(np.dot(X[i]-mu[j], np.linalg.inv(Sigma)), X[i]-mu[j]) / 2)
p[i,j] = phi[j] * fenzi
p = (p.T / p.sum(axis = 1)).T
return p
def predict(self, X):
mu, Sigma, phi, n_class = self.mu, self.Sigma, self.phi, self.n_class
p = np.empty([X.shape[0], n_class])
for i in range(X.shape[0]):
for j in range(n_class):
tmp = np.exp(-np.dot(np.dot(X[i]-mu[j], np.linalg.inv(Sigma)), X[i]-mu[j]) / 2)
p[i, j] = phi[j] * tmp
pred = np.argmax(p, axis = 1)
return pred
? 自己创造数据并使用高斯判别分析训练并预测:
if __name__ == '__main__':
X, y = make_blobs(n_samples = 200, n_features = 2, centers = 2, cluster_std = (1,1), random_state = 0)
plt.scatter(X[:,0], X[:,1], c = y, s = 6)
X_train, X_test, y_train, y_test = train_test_split(
X, y, train_size = 0.7, random_state = 0)
clf = GDA()
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
y_prob = clf.probability(X_test)
conf_mat = confusion_matrix(y_test, y_pred)
print("混淆矩阵为:\n", conf_mat)
x1, x2 = np.mgrid[X[:,0].min() - 1:X[:,0].max() + 1:0.05,X[:,1].min() - 1:X[:,1].max() + 1:0.05]
area = np.stack([x1.flat,x2.flat],axis=1)
area_pred = clf.predict(area)
area_pred = area_pred.reshape(x1.shape)
plt.pcolormesh(x1, x2, area_pred, alpha = 0.2)
plt.show()
模型划分测试集与训练集,训练后在测试集上预测,预测结果的混淆矩阵为:
模型在区域上的分类结果为:
模型训练后在测试集上预测,预测结果的混淆矩阵为:
模型在区域上的预测效果为:
?从上述两个实例中可以看到,模型大致成功分类了样本,且分类决策面是线性的,这是因为
Σ
\Sigma
Σ 选取一致。
|