PRML-4.1 判别函数

1.概念

判别式是一个使用输入向量\(x\)并把它分配给\(K\)种分类的其中一种\(C_k\)的函数。本章中,我们把我们的讨论局限于线性判别式(linear discriminants),即那些决策面是超平面的判别函数。为了简化讨论,我们首先考虑二分类的情况,再推广到\(K > 2\)的情形。

2 二分类

线性判别式的最简单形式是取输入向量的线性函数,即
$ y(x) = w^Tx + w_0 \tag{4.4} $

如果\(y(x) \geq 0\)则把输入向量\(x\)分到类\(C_1\)中,否则分到\(C_2\)中。因此,对应的决策边界由\(y(x) = 0\)确定,它对应着\(D\)维空间中的一个\((D-1)\)维超平面。

原点到决策面的标准距离由
$ \frac{w^Tx}{\Vert w \Vert} = -\frac{w_0}{\Vert w \Vert} \tag{4.5} $


解释一下
设点\(x\)在决策面上,\(w\)是法向量
\(\frac{w^Tx}{\Vert w \Vert} 代表向量x在w上的投影,=\frac{||w||||x||cos\theta}{\Vert w \Vert}=||x||cos\theta\)
因为x在决策面上,\(w^Tx + w_0=0 ,w^Tx = - w_0\)


3 多分类

现在把线性判别式推广到\(K > 2\)个类别的情况,我们可能会尝试组合多个二分类判别式来构造一个\(K\)类判别式。然而这会导致一些现在要展示的严重问题(Duda and Hart, 1973)。

考虑一个包含\(K-1\)个把属于类别\(C_k\)的点与其它的区分开的分类器(本类和其他类)。这被称为一对其他(one-versus-the-rest)分类器。图4.2的左手边展示了一个涉及三个类别的例子,这种方法会导致空间中有一块类别含糊不清的区域。

另一种方法是引入\(K(K-1)/2\)个二元判别函数,对每一对类别都设置一个。这被称为一对一(one-versus-one)分类器。然后根据这些判别函数的大多数投票来确定每个点的类别。然而这也会引起类别含糊不清的区域的问题,图4.2的右手边展示。

所以,引入包含\(K\)个形式为
\(y_k(x) = w_k^Tx + w_{k0} \tag{4.9}\)
的线性函数的单个\(K\)类判别式,并把\(x\)分入对于所有\(j \neq k\)都有\(y_k(x) > y_j(x)\)的类\(C_k\),就可以避免这些问题。类\(C_k, C_j\)间的决策边界由\(y_k(x) = y_j(x)\)给出,它对应形式为

$ (w_k - w_j)^Tx + (w_{k0} - w_{j0}) = 0 \tag{4.10} $

\((D-1)\)维的超平面。这与4.1.1节讨论的二分类情况下的决策边界具有相同的形式,因此也有类似的几何性质。

这样的判别式得到的决策区域总是单连通且凸的。为了证明这个,让我们考虑图4.3中展示的,两个都位于决策区域\(R_k\)中的点\(x_A,x_B\)

任何一个在连接\(x_A,x_B\)线段上的点\(\hat{x}\)可以表示为

$ \hat{x}=\lambda x_A + (1-\lambda)x_B \tag{4.11} $

其中\(0 \leq \lambda \leq 1\)。根据判别函数的线性性,可以得到

$ y_k(\hat{x}) = \lambda y_k(x_A) + (1-\lambda)y_k(x_B) \tag{4.12} $

因为\(x_A, x_B\)都在\(R_k\)中,所以对于所有\(j \neq k\)都满足\(y_k(x_A) > y_j(x_A), y_k(x_B) > y_j(x_B)\),所以\(y_k(\hat{x}) > y_j(\hat{x})\),所以\(\bar{x}\)\(R_k\)中。因此\(R_k\)是单连通且凸的(我理解是如果两个点都属于第k类,它们之间的点也都是属于k类别)。
注意,对于二分类的情形,我们既可以使用这里讨论的基于两个判别函数\(y_1(x), y_2(x)\)方法,也可以使用4.1.1节给出基于单一的判别函数\(y(x)\)的更简单的但等价的方法。

现在,我们开始探讨三种线性判别函数的参数学习方法,即基于最小二乘、Fisher线性判别式,以及感知器算法

4.判别函数1-最小平方法法

每个类别\(C_k\)通过它自己的线性模型

$ y_k(x) = w_k^Tx + w_{k0} \tag{4.13} $

可以很容易地把这些量聚集在一起表示,即
$ y(x) = \widetilde{W}^T\tilde{x} \tag{4.14} $

其中

\[\widetilde{W} 是第 k^{th} 列构成 D+1 维向量 \tilde{w}k = (w_{k0}, w_k^T)^T 的矩阵 \]

\(\tilde{x}\)

\[\tilde{x} 对应的是通过虚输入x_0=1扩张后的输入向量(1,x^T)^T \]

训练数据集

\[{x_n,t_n} n = 1,...,N \]

\(矩阵T\),y_test

\[定义一个第 n^{th} 行是向量t_n^T 矩阵T \]

\(矩阵X\),x_test

\[行是\tilde{x}_n^T的矩阵\tilde{X} \]

平方和误差函数就可以写成

\[E_{D}(\tilde{\boldsymbol{W}})=\frac{1}{2} \operatorname{Tr}\left\{(\tilde{\boldsymbol{X}} \tilde{\boldsymbol{W}}-\boldsymbol{T})^{T}(\tilde{\boldsymbol{X}} \tilde{\boldsymbol{W}}-\boldsymbol{T})\right\}\tag{4.15} \]


证明 4.15

先详细展开一些标记
\(\tilde x =\begin{pmatrix} 1 \\ x_1\\ .\\ x_D\\ \end{pmatrix}_{D+1 \times 1},\tilde X =\begin{pmatrix} \tilde x_1^T\\ .\\ \tilde x_N^T\\ \end{pmatrix}_{N \times D+1},T =\begin{pmatrix} t_1^T \\ t_2^T\\ .\\ t_N^T\\ \end{pmatrix}_{N\times K},\tilde W = \begin{pmatrix} w_{10} & ... & w_{K0} \\ ... & ... & ... \\ w_{1D} & ... & w_{KD} \\ \end{pmatrix}_{D+1 \times K},每一列都是\begin{pmatrix} w_{k0} \\ ... \\ w_{kD} \\ \end{pmatrix} = \tilde w_k,\tilde W^T = \begin{pmatrix} w_{10} & ... & w_{1D} \\ ... & ... & ... \\ w_{K0} & ... & w_{KD} \\ \end{pmatrix}_{K \times D+1}\)

\(y(x) = \widetilde{W}^T\tilde{x}= \begin{pmatrix} w_{10} & ... & w_{1D} \\ ... & ... & ... \\ w_{K0} & ... & w_{KD} \\ \end{pmatrix}_{K \times D+1}\begin{pmatrix} 1 \\ x_1\\ . x_D\\ \end{pmatrix}_{ D+1 \times 1}\)
\(y(x)=\begin{pmatrix} y_1(x) \\ ... \\ y_K(x) \\ \end{pmatrix}_{K\times 1}=\begin{pmatrix} p_1(x) & 表示数据x归类于类别1的概率\\ ... \\ p_K(x) & 表示数据x归类于类别K的概率\\ \end{pmatrix}_{K\times 1}\)
然后开始计算
\(\tilde X \tilde W = \begin{pmatrix} \tilde x_1^T\\ .\\ \tilde x_N^T\\ \end{pmatrix}\begin{pmatrix} w_{10} & ... & w_{K0} \\ ... & ... & ... \\ w_{1D} & ... & w_{KD} \\ \end{pmatrix}=\begin{pmatrix} p_1(x_1) & ... & p_k(x_1) \\ ... & ... & ... \\ p_1(x_N) & ... & p_k(x_N) \\ \end{pmatrix}(这里参看上面的y(x)) = \begin{pmatrix} p(c_1|x_1) & ... & p(c_k|x_1) \\ ... & ... & ... \\ p(c_1|x_N) & ... & p(c_k|x_N) \\ \end{pmatrix}(写的正规点),\color{red}{这步很重要}\)

\(\tilde X \tilde W - T = \begin{pmatrix} p(c_1|x_1)-t_{11} & ... & p(c_k|x_1)-t_{1K} \\ ... & ... & ... \\ p(c_1|x_N)-t_{1N} & ... & p(c_k|x_N) -t_{NK}\\ \end{pmatrix}\)

\(令\tilde X \tilde W - T = A,a_{ij}=p(c_j|c_i) - t_{ij}\)
\((\tilde X \tilde W - T)^T(\tilde X \tilde W - T)=\begin{pmatrix} a_{11} & ... & a_{N1} \\ ... & ... & ... \\ a_{1K} & ... & a_{KN}\\ \end{pmatrix}\begin{pmatrix} a_{11} & ... & a_{1K} \\ ... & ... & ... \\ a_{N1} & ... & a_{KN}\\ \end{pmatrix}=\begin{pmatrix} a_{11}^2 + a_{21}^2+...+a_{N1}^2 & ... & ... \\ ... & ... & ... \\ ... & ... & a_{1K}^2 + a_{2K}^2+...+a_{NK}^2\\ \end{pmatrix}_{K\times K}\)

\(TR(A^TA)=(a_{11}^2 + a_{21}^2+...+a_{N1}^2) + ... + (a_{1K}^2 + a_{2K}^2+...+a_{NK}^2)=C_1分类误差之和+...+C_K分类误差之和\)

证毕


令关于\(\widetilde{W}\)的导数等于零,整理,可得\(\widetilde{W}\)的解

\[\widetilde{W} = (\tilde{X}^T\tilde{X})^{-1}\tilde{X}^TT=\tilde{X}^+T \tag{4.16} \]

其中\(\tilde{X}^+\)是3.1.1节中讨论过的\(\tilde{X}\)的伪逆。然后我们得到形式为

\[\color{red}{y(x) = \widetilde{W}^T\tilde{x} = T^T\left(\tilde{X}^+\right)^T\tilde{x} }\tag{4.17} \]

的判别函数。


多目标变量的最小二乘解的一个有趣性质是,如果训练集合中的每个目标向量对于某些常数\(a, b\)都满足线性约束

$ a^Tt_n + b = 0 \tag{4.18} $

那么,模型对于任意的\(x\)值预测也满足这个约束,即

$ a^Ty(x) + b = 0 \tag{4.19} $


证明 4.18 习题4.2


python 最小二乘法分类

点击查看代码

# 二分类
x_train, y_train = create_toy_data()
x1_test, x2_test = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
x_test = np.array([x1_test, x2_test]).reshape(2, -1).T

feature = PolynomialFeature(1)
X_train = feature.transform(x_train)
X_test = feature.transform(x_test)

model = LeastSquaresClassifier()
model.fit(X_train, y_train)
y = model.classify(X_test)

plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.contourf(x1_test, x2_test, y.reshape(100, 100), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()

点击查看代码

import numpy as np
from prml.linear.classifier import Classifier
from prml.preprocess.label_transformer import LabelTransformer


class LeastSquaresClassifier(Classifier):
    """
    Least squares classifier model

    X : (N, D)
    W : (D, K)
    y = argmax_k X @ W
    """

    def __init__(self, W:np.ndarray=None):
        self.W = W

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        least squares fitting for classification

        Parameters
        ----------
        X : (N, D) np.ndarray
            training independent variable
        t : (N,) or (N, K) np.ndarray
            training dependent variable
            in class index (N,) or one-of-k coding (N,K)
        """
        if t.ndim == 1:
            t = LabelTransformer().encode(t)
        self.W = np.linalg.pinv(X) @ t

    def classify(self, X:np.ndarray):
        """
        classify input data

        Parameters
        ----------
        X : (N, D) np.ndarray
            independent variable to be classified

        Returns
        -------
        (N,) np.ndarray
            class index for each input
        """
        return np.argmax(X @ self.W, axis=-1)


点击查看代码

import numpy as np


class LabelTransformer(object):
    """
    Label encoder decoder

    Attributes
    ----------
    n_classes : int
        number of classes, K
    """

    def __init__(self, n_classes:int=None):
        self.n_classes = n_classes

    @property
    def n_classes(self):
        return self.__n_classes

    @n_classes.setter
    def n_classes(self, K):
        self.__n_classes = K
        self.__encoder = None if K is None else np.eye(K)

    @property
    def encoder(self):
        return self.__encoder

    def encode(self, class_indices:np.ndarray):
        """
        encode class index into one-of-k code

        Parameters
        ----------
        class_indices : (N,) np.ndarray
            non-negative class index
            elements must be integer in [0, n_classes)

        Returns
        -------
        (N, K) np.ndarray
            one-of-k encoding of input
        """
        if self.n_classes is None:
            self.n_classes = np.max(class_indices) + 1

        return self.encoder[class_indices]

    def decode(self, onehot:np.ndarray):
        """
        decode one-of-k code into class index

        Parameters
        ----------
        onehot : (N, K) np.ndarray
            one-of-k code

        Returns
        -------
        (N,) np.ndarray
            class index
        """

        return np.argmax(onehot, axis=1)

点击查看代码

x_train, y_train = create_toy_data(add_outliers=True)
x1_test, x2_test = np.meshgrid(np.linspace(-5, 15, 100), np.linspace(-5, 15, 100))
x_test = np.array([x1_test, x2_test]).reshape(2, -1).T

feature = PolynomialFeature(1)
X_train = feature.transform(x_train)
X_test = feature.transform(x_test)

least_squares = LeastSquaresClassifier()
least_squares.fit(X_train, y_train)
y_ls = least_squares.classify(X_test)

logistic_regression = LogisticRegression()
logistic_regression.fit(X_train, y_train)
y_lr = logistic_regression.classify(X_test)

plt.subplot(1, 2, 1)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.contourf(x1_test, x2_test, y_ls.reshape(100, 100), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.xlim(-5, 15)
plt.ylim(-5, 15)
plt.gca().set_aspect('equal', adjustable='box')
plt.title("Least Squares")
plt.subplot(1, 2, 2)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.contourf(x1_test, x2_test, y_lr.reshape(100, 100), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.xlim(-5, 15)
plt.ylim(-5, 15)
plt.gca().set_aspect('equal', adjustable='box')
plt.title("Logistic Regression")
plt.show()

python 最小二乘法三分类

点击查看代码

# 三分类
x_train, y_train = create_toy_data(add_class=True)
x1_test, x2_test = np.meshgrid(np.linspace(-5, 10, 100), np.linspace(-5, 10, 100))
x_test = np.array([x1_test, x2_test]).reshape(2, -1).T

feature = PolynomialFeature(1)
X_train = feature.transform(x_train)
X_test = feature.transform(x_test)

least_squares = LeastSquaresClassifier()
least_squares.fit(X_train, y_train)
y_ls = least_squares.classify(X_test)

logistic_regression = SoftmaxRegression()
logistic_regression.fit(X_train, y_train, max_iter=1000, learning_rate=0.01)
y_lr = logistic_regression.classify(X_test)

plt.subplot(1, 2, 1)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.contourf(x1_test, x2_test, y_ls.reshape(100, 100), alpha=0.2, levels=np.array([0., 0.5, 1.5, 2.]))
plt.xlim(-5, 10)
plt.ylim(-5, 10)
plt.gca().set_aspect('equal', adjustable='box')
plt.title("Least squares")
plt.subplot(1, 2, 2)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.contourf(x1_test, x2_test, y_lr.reshape(100, 100), alpha=0.2, levels=np.array([0., 0.5, 1.5, 2.]))
plt.xlim(-5, 10)
plt.ylim(-5, 10)
plt.gca().set_aspect('equal', adjustable='box')
plt.title("Softmax Regression")
plt.show()


5-Fisher线性判别函数

我们可以从降维的角度来观察线性分类模型。首先考虑二分类的情形,并假设有\(D\)维输入向量\(x\)并使用

$ y=w^Tx \tag{4.20} $

把它投影到一维空间。如果我们在\(y\)上放一个阈值,并把\(y \geq -w_0\)分到类别\(C_1\)中,其余的分到类别\(C_2\),那么我们就得到了前一小节讨论的标准的线性分类器。通常来说,投影在一维空间会造成大程度的信息损失,所以能够在原来的\(D\)维空间中完全分开的样本在一维空间中可能会相互重叠。不过通过调节分量的权向量\(w\),我们可以选择使类别最分散的一个投影。首先,考虑一个包含\(N_1\)\(C_1\)点和\(N_2\)\(C_2\)点的二分类问题,那么两个类别的均值向量为:

\[\textbf{m}_1 = \frac{1}{N_1}\sum\limits_{n \in C_1}x_n , \textbf{m}_2 = \frac{1}{N_2}\sum\limits_{n \in C_2}x_n \tag{4.21} \]

当投影到\(w\)上后,最简单的度量类别之间分开程度的方法就是投影之后的的类别均值的距离。这要求我们去选择那个使得

$ m_2-m_1 = w^T(\textbf{m}_2 - \textbf{m}_1) \tag{4.22} $

\(\textbf{m}_2 , \textbf{m}_1投影在y=w^Tx上的点的距离相减\)

最大的\(w\)的值。 其中

$ m_k = w^T\textbf{m}_k \tag{4.23} $

类别\(C_k\)的数据投影后的均值。但是,可以通过增大\(w\)来使这个表达式无穷大。为了解决这个问题,我们现在\(w\)为单位长的,即\(\sum_i w_i^2 = 1\)。使用拉格朗日乘数法来求解限制条件下的最大化问题,得到\(w \propto (m_2 - m_1)\)。但是这个方法还有图4.6展示的问题。


证明 \(w \propto (m_2 - m_1)\) ,习题4.4
\(有m_2 -m_1= w^T(\textbf{m}_2 - \textbf{m}_1)\)
\(有w^Tw=1,求w \propto (m_2 - m_1)\)
\(L(w,\lambda)=w^T(m2-m1)+\lambda(w^Tw-1)\)
\(\frac{\partial L }{\partial w}=m_2-m_1 +2\lambda w=0\)
\(w=-\frac{1}{2\lambda}(m_2-m_1)\)
\(w \propto (m_2 - m_1)\)


图4.6,它展示了在原来二维空间\((x1, x2)\)中可以完全分开的两个类别,当投影到连接它们的均值的直线上时,有一定程度的重叠。这是由于类别分布的协方差强非对角引起的(概率分布的协方差矩阵与对角化矩阵差距较大(暂且没有推导))。Fisher提出了最大化一种在给出大的投影均值的距离的同时,给出较小的每个类别内部的方差的函数的主意,来最小化类别重叠。(类内小,类间大

投影公式(4.20)把通过\(x\)标记的数据点转换为通过一维空间\(y\)标记的点。转换后的类别\(C_k\)的内部方差由

$ s_k^2 = \sum\limits_{n \in C_k}(y_n - m_k)^2 \tag{4.24} $

其中\(y_n = w^Tx_n\)。我们可以简单的定义整个数据集总的类别内部的方差为\(s_1^2 + s_2^2\)。Fisher准则是由类别间的方差与类别内部的方差比例定义的,即

\[J(w) = \frac{(m_2 - m_1)^2}{s_1^2 + s_2^2} \tag{4.25} \]

使用式(4.20)、式(4.23)和式(4.24)对它重写得到

\[J(w) = \frac{w^TS_Bw}{w^TS_Ww} \tag{4.26} \]

来显示的表达对\(w\)的依赖。其中\(S_B\)是类别间的协方差矩阵。\(\color{red}{S_B 类间方差,B代表Between}\),由

\[S_B = (m_2 - m_1)(m_2 - m_1)^T \tag{4.27} \]

给出,\(S_W\)是总得类别内部方差矩阵,\(\color{red}{S_W,类内方差,W代表 within}\),由

$ S_W = \sum\limits_{n \in C_1}(x_n - m_1)(x_n - m_1)^T + \sum\limits_{n \in C_2}(x_n - m_2)(x_n - m_2)^T \tag{4.28} $


证明 4.26式 习题 4.5

4.20
\(y=w^Tx\)
4.23
\(m_k = w^T\textbf{m}_k\)
4.24
\(s_k^2 = \sum\limits_{n \in C_k}(y_n - m_k)^2\)

\(m_1=w^T\textbf{m}_1\)
\(m_2=w^T\textbf{m}_2\)
\(s_1^2 = \sum\limits_{n \in C_1}(w^Tx_n - w^Tm_1)^2\)
\(s_2^2 = \sum\limits_{n \in C_2}(w^Tx_n - w^Tm_2)^2\)
\(J(w)=\frac{(w^T(m_2-m_1))((m_2-m_1)^Tw)}{\sum\limits_{n \in C_1}(w^T(x_n-m_1))((x_n-m_1)^Tw) \sum\limits_{n \in C_2}(w^T(x_n-m_2))((x_n-m_2)^Tw)}\)
\(S_B=(m_2-m_1)(m_2-m_1)^T\)
\(S_W=\sum\limits_{n \in C_1}((x_n-m_1))((x_n-m_1)^T) \sum\limits_{n \in C_2}((x_n-m_2))((x_n-m_2)^T)\)

\[J(w) = \frac{w^TS_Bw}{w^TS_Ww} \tag{4.26} \]


对式(4.26)对于\(w\)求导,得到当

$ (w^TS_Bw)S_Ww = (w^TS_Ww)S_Bw \tag{4.29} $

使得\(J(w)\)最大。从式(4.27)我们得到\(S_Bw\)总是在\((m_2 - m_1)\)的方向上。更重要的是我们只在乎\(w\)的方向,而不在乎它的大小,因此我们可以去掉标量因子\((w^TS_Bw) (w^TS_Ww)\) 。在式(4.29)两边都乘以\(S_W^{-1}\)得到

$ w \propto S_W^{-1}(m_2 - m_1) \tag{4.30} $

注意,如果类别内部的协方差是各向同性的,那么\(S_W\)正比于单位矩阵,然后得到和之前讨论的一样,\(w\)正比于类均值的差。

尽管严格来说式(4.30)并不是一个判别式,而是对于数据向一维投影的方向的一个具体选择(得到方向w),但是仍习惯把它称为Fisher线性判别式。然而,投影的数据可以通过选择一个阈值\(y_0\),使得当\(y(x) \geq y_0\)时,我们把它分到\(C_1\)中,否则把它分到\(C_2\),来构造后面的判别式。

例如,我们可以使用高斯概率分布对类条件密度$ p(y|C_k) $建模,然后使用1.2.4节(高斯分布)的技术通过最大似然找到高斯分布的参数值。

当找到投影类别的高斯近似之后,1.5.1节的方法给出了最优的阈值的形式化解(最小化错误分类率)。注意,$ y = w^Tx $是一组随机变量的和,因此根据中心极限定理,我们可以作出高斯分布的假设。


这里提下,在多元统计分析中,获得了方向\(w\)就可以了,偏置\(w_0\)无所谓,见https://www.cnblogs.com/boyknight/p/16047144.html


4.26求导
借用公式
\(\frac{\partial}{\partial x}\frac{(Ax)^TAx}{(Bx)^TBx}=2\frac{A^TAx}{(Bx)^TBx}-2\frac{(x^TA^TAx)B^TBx}{(x^TB^TBx)^2}--这个公式不知道哪里得到的,哎,还是要一些数学的基础功底的\)
\(\frac{\partial}{\partial w}J(w)=2\frac{S_Bw}{w^TS_ww}-2\frac{(w^TS_Bw)S_ww}{(w^TS_ww)^2}\)
\((w^TS_Bw)S_ww =(w^TS_ww)S_Bw\)


Fisher判别 python实现

点击查看代码

# Fisher
x_train, y_train = create_toy_data()
x1_test, x2_test = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
x_test = np.array([x1_test, x2_test]).reshape(2, -1).T

model = FishersLinearDiscriminant()
model.fit(x_train, y_train)
y = model.classify(x_test)

plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.contourf(x1_test, x2_test, y.reshape(100, 100), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()

点击查看代码

import numpy as np
from prml.linear.classifier import Classifier
from prml.rv.gaussian import Gaussian


class FishersLinearDiscriminant(Classifier):
    """
    Fisher's Linear discriminant model
    """

    def __init__(self, w:np.ndarray=None, threshold:float=None):
        self.w = w
        self.threshold = threshold

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        estimate parameter given training dataset

        Parameters
        ----------
        X : (N, D) np.ndarray
            training dataset independent variable
        t : (N,) np.ndarray
            training dataset dependent variable
            binary 0 or 1
        """
        X0 = X[t == 0]
        X1 = X[t == 1]
        m0 = np.mean(X0, axis=0)
        m1 = np.mean(X1, axis=0)
        cov_inclass = np.cov(X0, rowvar=False) + np.cov(X1, rowvar=False)
        self.w = np.linalg.solve(cov_inclass, m1 - m0)
        self.w /= np.linalg.norm(self.w).clip(min=1e-10)

        g0 = Gaussian()
        g0.fit((X0 @ self.w))
        g1 = Gaussian()
        g1.fit((X1 @ self.w))
        root = np.roots([
            g1.var - g0.var,
            2 * (g0.var * g1.mu - g1.var * g0.mu),
            g1.var * g0.mu ** 2 - g0.var * g1.mu ** 2
            - g1.var * g0.var * np.log(g1.var / g0.var)
        ])
        if g0.mu < root[0] < g1.mu or g1.mu < root[0] < g0.mu:
            self.threshold = root[0]
        else:
            self.threshold = root[1]

    def transform(self, X:np.ndarray):
        """
        project data

        Parameters
        ----------
        X : (N, D) np.ndarray
            independent variable

        Returns
        -------
        y : (N,) np.ndarray
            projected data
        """
        return X @ self.w

    def classify(self, X:np.ndarray):
        """
        classify input data

        Parameters
        ----------
        X : (N, D) np.ndarray
            independent variable to be classified

        Returns
        -------
        (N,) np.ndarray
            binary class for each input
        """
        return (X @ self.w > self.threshold).astype(np.int)


6-最小平方和Fisher判别的关系

确定线性判别式的最小二乘方法是基于使模型预测尽可能的接近目标值的目的的。相反,Fisher准则的目标是最大化输出空间中类别的区分度。这两种方法之间的关系是很有趣的。特别的,我们会证明,在二分类问题中,Fisher准则可以看成最小二乘的一个特例
目前为止,我们一直采用“1-of-K”编码来表示目标值。然而,如果我们采用一种稍微不同的编码方式,那么权重的最小二乘解会等价于Fisher判别式的解(Duda and Hart, 1973)。特别的,我们让属于\(C_1\)的目标值等于\(N/N_1\),其中\(N_1\)是类别\(C_1\)的模式的数量,\(N\)是总的模式数量。这个目标值近似于类别\(C_1\)的先验概率的倒数,同时令\(C_2\)目标值等于\(−N/N_2\),其中\(N_2\)是类别\(C_2\)的模式的数量
平方和误差函数可以写成

\[E = \frac{1}{2}\sum\limits_{n=1}^N\left(w^Tx_n + w_0 - t_n \right)^2 \tag{4.31} \]

分别关于\(w_0, w\)\(E\)的导数,并使其等于0,得到

\[\begin{eqnarray} \sum\limits_{n=1}^N\left(w^Tx_n + w_0 - t_n \right) = 0 \tag{4.32} \\ \sum\limits_{n=1}^N\left(w^Tx_n + w_0 - t_n \right)x_n = 0 \tag{4.33} \end{eqnarray} \]

根据式(4.32),并按选择的目标编码方式来编码\(t_n\),就可得到偏置的表示式

$ w_0 = -w^Tm \tag{4.34} $

其中我们使用了

$ \sum\limits_{n=1}^Nt_n = N_1\frac{N}{N_1} - N_2\frac{N}{N_2} = 0 \tag{4.35} $

\(m\)是由

$ m = \frac{1}{N}\sum\limits_{n=1}^Nx_n = \frac{1}{N}(N_1m_1 + N_2m_2) \tag{4.36} $

给出的全部数据的均值


说白了就是两个算法的编码方式不一样

posted @ 2022-03-27 16:59  筷点雪糕侠  阅读(219)  评论(0编辑  收藏  举报