判别式模型

本文主要通过Logistics Regression讲解判别式模型

由上文生成式模型的讲解,我们大致了解了生成式模型,首先通过假设某些条件求出了联合概率密度分布,再通过贝叶斯公式求出相应的分类概率。

判别式模型则是完全通过数据进行分析,没有任何人为的假设。

首先我们看一下上文中最后推出的后验概率:

\[\begin{aligned} P(blue|x) &= \frac{P(x|blue)P(blue)}{P(x|blue)P(blue)+P(x|green)P(green)}\\ &= \frac{1}{1+\frac{P(x|green)P(green)}{P(x|blue)P(blue)}} \end{aligned} \]

此时我们令 \(z=ln\frac{P(x|blue)P(blue)}{P(x|green)P(green)}\),求出\(\frac{P(x|green)P(green)}{P(x|blue)P(blue)} = e^{-z}\)
带入\(P(blue|x)\)变为

\[P(blue|x) =\frac{1}{1+e^{-z}} \]

学过的同学一看就知道这就是Logistics distribution。这个图像估计都看腻了,我就不讲解了。
在这里插入图片描述
目前的问题就是需要知道我们假设的 \(z\) 是什么样的。\(z=ln\frac{P(x|blue)P(blue)}{P(x|green)P(green)}\)
此处我直接写出结论,不再进行推导了。说明一下如何推导,我们可以假设\(P(x|blue),P(x|green)\)服从某一种分布。将其分布带入到后验概率。即可求出

\[z = wx+b \]

这种样式。(无论用哪种分布,都会得到这样的形式,这样就不要人为假设服从哪种分布了
既然这样, 那我们直接将函数变为

\[P(blue|x) =\frac{1}{1+e^{-(wx+b)}} \]

目前我们的任务是如何求出 \(w,b\) 。我们只有样例数据,当然只能利用样例数据来求了。。那怎么求呢,因为数据有自变量取值,样例分类。—— 那我们就可以定义一个损失函数,利用梯度下降求出最优的 \(w,b\)

首先利用最大似然估计

\[H(w,b) = \prod_{i=1}^{N}(y^iP(blue|x^i)+(1-y^i)(1-P(blue|x^i))) \]

遇到连乘的问题首先取 \(ln\) 变为连加。

\[H(w,b) = \sum_{i=1}^{N} ln (y^iP(blue|x^i)+(1-y^i)(1-P(blue|x^i))) \]

目标函数变为:

\[w^{'},b^{'} = \mathop{\arg \max_{w,b} H(w,b)} \]

为了好看,改一下:

\[w^{'},b^{'} = \mathop{\arg \min_{w,b} -H(w,b)} \]

接下来就可以利用梯度下降了。

此处用梯度下降

\[\begin{aligned} w^{'} &= w - \eta \frac{\partial H(w,b)}{\partial w} \\ b^{'} &= b -\eta \frac{\partial H(w,b)}{\partial b} \end{aligned} \]

\(H(w,b)\)代入可得

\[\begin{aligned} w^{'} &= w - \eta \sum_{i=1}^{n} ( p(x^i)- y^i )*x^i \\ b^{'} &= b -\eta \sum_{i=1}^{n} p(x^i) - y^i \end{aligned} \]

最终求得 \(w^{*}\)\(b^{*}\)

迭代10000次得到的结果为

\[\begin{aligned} w &= [-1.48102123 1.37684754] \\ b &= 3.773931680340649 \end{aligned} \]

画出\(P(blue|x)\)的等高线可以看出在概率为0.5时还是能较好的分开两组数据
在这里插入图片描述

可以看出判别式模型中,完全是依据数据进行的分析,没有添加任何人为的假设(对于任意的分布\(z\)都满足\(z=wx+b\)的形式),直接根据贝叶斯后验概率进行的推导。

至此两种模型都讲完,这两者模型各有优缺点,当数据很少的时候,或许生成式模型中人为加入的限制更加有利于数据的分类,这会使得拟合效果更好。


附上代码:

# classification
# only use part[0] & part[1]
# @author Hongchuan CAO
# @date 2019-7-8

from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt


class SGD(object):

    def __init__(self):
        self.iris = datasets.load_iris()
        self.part = [[], [], []]

    def classify(self):
        for i in range(len(self.iris.target)):
            self.part[self.iris.target[i]].append(self.iris.data[i, :2])

        # change list to array
        for i in range(0, 3):
            self.part[i] = np.array(self.part[i])

        print(self.part[0][1])

    def gradient(self):
        w = np.array([1., 1.])
        b = 4
        learn_ratio = 0.001
        iteration = 10000

        for j in range(iteration):
            sum_w = np.array([0., 0.])
            sum_b = 0

            for i in range(len(self.part[0])):
                sum_w += (1.0 / (1 + np.exp(-1 * (np.dot(w, self.part[0][i].T) + b))) - 1) * self.part[0][i]
                sum_b += (1.0 / (1 + np.exp(-1 * (np.dot(w, self.part[0][i].T) + b))) - 1)

            for i in range(len(self.part[1])):
                sum_w += (1.0 / (1 + np.exp(-1 * (np.dot(w, self.part[1][i].T) + b)))) * self.part[1][i]
                sum_b += (1.0 / (1 + np.exp(-1 * (np.dot(w, self.part[1][i].T) + b))))

            w = w - learn_ratio * sum_w / (len(self.part[0]) + len(self.part[1]))
            b = b - learn_ratio * sum_b / (len(self.part[0]) + len(self.part[1]))
            print(j, '-----------')

        print(w,b)
        return w, b

    def ff(self, w, b, x):
        return 1.0 / (1 + np.exp(-1 * (np.dot(w, x.T) + b)))

    def plot1(self):
        w, b = self.gradient()

        xx = [x for x in np.arange(2, 8, 0.1)]
        yy = [y for y in np.arange(1, 7, 0.1)]
        Z = [[self.ff(w, b, np.array([x, y])) for x in xx] for y in yy]
        X, Y = np.meshgrid(xx, yy)
        cntr1 = plt.contourf(X, Y, Z)
        plt.clabel(cntr1, colors='k', inline_spacing=3, fmt='%.1f', fontsize=10)

        plt.plot(self.part[0][:, 0], self.part[0][:, 1], 'b.', label='0')
        plt.plot(self.part[1][:, 0], self.part[1][:, 1], 'g.', label='1')
        # plt.plot(self.part[2][:,0], self.part[2][:,1], 'r.', label='2')
        plt.legend()
        plt.xlabel('attribute0')
        plt.ylabel('attribute1')

        plt.show()


if __name__ == '__main__':
    obj = SGD()
    obj.classify()
    obj.plot1()

posted @ 2019-07-19 08:26  yingzhengttt  阅读(791)  评论(0编辑  收藏  举报