高斯判别分析(Gaussian discriminant analysis)

原理

相关概率论知识(概率论)

在生成模型中,我们的学习目标是:

而在高斯判别分析中,我们有如下假设:

即:

其中 \mu 是高斯分布的均值向量\Sigma协方差矩阵.

然后,我们使用 极大似然估计 ,首先构造 l(\phi,\mu_0,\mu_1,\Sigma) :

于是得到:

于是我们只要将学习到的参数 \phi,\mu_0,\mu_1,\Sigma 代入 p(x|y)p(y) 的函数,在预测时,只需要代入数据,计算出不同类别中最大的 p(x|y)p(y),便可以得到预测的类别.

代码实现

import numpy as np
import random
import matplotlib.pyplot as plt

# 高斯判别分析(Gaussian discriminant analysis)


def load_data(gauss_1, gauss_2, point_num):
    """
    数据输入
    :param gauss_1: 类别0的μ和σ组成的数组
    :param gauss_2: 类别1的μ和σ组成的数组
    :param point_num: 样本总数
    :return: x_0,y_0 二维高斯分布样本点(x_0,y_0)
             x_1,y_1 二维高斯分布样本点(x_1,y_1)
             label 类别标签
    """
    x_0 = []
    x_1 = []
    y_0 = []
    y_1 = []
    label = []
    while len(label) < point_num:
        if random.random() > 0.5:
            x_0.append(random.gauss(gauss_1[0], gauss_1[1]))
            y_0.append(random.gauss(gauss_1[0], gauss_1[1]))
            label.append(0)
        else:
            x_1.append(random.gauss(gauss_2[0], gauss_2[1]))
            y_1.append(random.gauss(gauss_2[0], gauss_2[1]))
            label.append(1)
    return x_0, y_0, x_1, y_1, label


def train(x_train_0, x_train_1, label):
    """
    训练高斯判别分析模型
    :param x_train_0: 类别为0的样本
    :param x_train_1: 类别为1的样本
    :param label: 样本标签
    :return: phi: Φ
             mu_0: μ_0
             mu_1: μ_1
             sigma: Σ
    """
    m = len(label)
    label_cnt_0 = float(label.count(0))
    label_cnt_1 = float(label.count(1))
    phi = label_cnt_1 / m
    mu_0 = np.sum(x_train_0[0])/label_cnt_0, np.sum(x_train_0[1])/label_cnt_0
    mu_1 = np.sum(x_train_1[0])/label_cnt_1, np.sum(x_train_1[1])/label_cnt_1
    x0_u0 = np.mat(x_train_0.T - mu_0)
    x1_u1 = np.mat(x_train_1.T - mu_1)
    x_u = np.mat(np.concatenate([x0_u0, x1_u1]))
    sigma = (1.0 / m) * (x_u.T * x_u)
    '''
    print(phi)
    print(mu_0)
    print(mu_1)
    print(sigma_0)
    print(sigma_1)
    '''
    return phi, np.mat(mu_0), np.mat(mu_1), sigma


def predict(x, gauss):
    """
    预测数据
    :param x: 输入的预测样本
    :param gauss: 得到的高斯模型的数组
    :return: p_y0 类别为0的概率
             p_y1 类别为1的概率
    """
    p_y0 = (1-gauss[0]) * np.exp(-1/2 * (x-gauss[1]) * gauss[3].I * (x-gauss[1]).T)
    p_y1 = (gauss[0]) * np.exp(-1/2 * (x-gauss[2]) * gauss[3].I * (x-gauss[2]).T)
    if p_y1 > p_y0:
        print(str(x) + "is 1")
    else:
        print(str(x) + "is 0")
    return p_y0, p_y1


if __name__ == '__main__':
    x_0, y_0, x_1, y_1, label = load_data([15, 3], [30, 3], 5000)
    train_0 = np.vstack((x_0, y_0))
    train_1 = np.vstack((x_1, y_1))
    gauss = train(train_0, train_1, label)
    for i in range(10,40):
        pre_x = [i, i]
        p_0, p_1 =predict(pre_x, gauss)
    # 绘制训练样本点
    plt.scatter(x_0, y_0, 4, "lightblue")
    plt.scatter(x_1, y_1, 4, "red")
    # 绘制分隔曲线(取样本中心点连线的中垂线)
    x_point = []
    y_point = []
    x0 = ((gauss[2] + gauss[1]) /2).T
    # 直线的斜率
    tmp = (gauss[2] -gauss[1]).T
    k = float(- tmp[0] / tmp[1])
    for i in np.linspace(0, 40, 100):
        x_point.append(i)
        y_point.append(k*i - k*float(x0[0])+float(x0[1]))
    plt.plot(x_point, y_point)
    plt.show()
复制代码

实现后的图像如下:

高斯判别分析

猜你喜欢

转载自juejin.im/post/5b6d9796e51d45190f4b1a82