深度学习理论推导--二分类逻辑回归

文章目录

当你迷茫的时候,请回头看看 目录大纲,也许有你意想不到的收获

前言

前面讲到几篇,都是 线性回归问题 的求解,目标是找到一条 直线来拟合,求解方式有 最小二乘法正规方程梯度下降法

现在讲讲另一种回归问题,就是 逻辑回归,也就是分类问题,分类问题也包括二分类多分类 问题。

  1. 二分类:输出是(1)否(0),例如逻辑门,与门、或门、非门、异或门等等。

  2. 多分类:输出的是多个值,对应着每个分类的概率,是小于或等于 1 的值。最经典的例子莫过于手写数字的识别,给出一张手写的数字图片,最后输出是各个数字(1~9)的概率,比如我手写了一个 7,像 7 又像 1,那么多分类输出可能为:7 有 0.9 概率,1 有 0.1 的概率,其他数字概率接近于 0。

二分类问题

先简单点,讨论二分类问题,例如 异或门

真值表为:

样本 i 样本 i 样本i x i 1 x_{i1} xi1 x i 2 x_{i2} xi2 y i y_i yi
i=1 0 0 0
i=2 0 1 1
i=3 1 0 1
i=4 1 1 0

可以把真值表中的每一行都看作是一个样本, x i 1 x_{i1} xi1 与 x i 2 x_{i2} xi2 为异或门的 第 i 个样本输入, y i y_i yi 为第 i 个样本的输出。

多元线性函数

u = w 1 x 1 + w 2 x 2 + . . . + b u=w_1x_1+w_2x_2+...+b u=w1x1+w2x2+...+b

σ \sigma σ 函数

σ ( x ) = 1 1 + e − x = e x 1 + e x \sigma(x)=\frac{1}{1+e^{-x}}=\frac{e^x}{1+e^x}\\[10pt] σ(x)=1+e−x1=1+exex

可以看出: σ ( x ) ∈ ( 0 , 1 ) \sigma(x) \in (0,1) σ(x)∈(0,1),如果令 P = σ ( x ) P=\sigma(x) P=σ(x),那么有 x = ln ⁡ P 1 − P x=\ln{\frac{P}{1-P}} x=ln1−PP,这个也比较好推导:

∵ σ ( x ) = 1 1 + e − x = P ∴ 1 + e − x = 1 P ∴ e − x = 1 P − 1 = 1 − P P ∴ x = − ln ⁡ 1 − P P = ln ⁡ P 1 − P \because\sigma(x)=\frac{1}{1+e^{-x}}=P\\[10pt] \therefore 1+e^{-x}=\frac{1}{P}\\[10pt] \therefore e^{-x}=\frac{1}{P}-1=\frac{1-P}{P}\\[10pt] \therefore x=-\ln{\frac{1-P}{P}}=\ln{\frac{P}{1-P}} ∵σ(x)=1+e−x1=P∴1+e−x=P1∴e−x=P1−1=P1−P∴x=−lnP1−P=ln1−PP

σ ( x ) \sigma(x) σ(x) 导数:

σ ′ ( x ) = − 1 ( 1 + e − x ) 2 ⋅ ( 1 + e − x ) ′ = e − x ( 1 + e − x ) 2 = 1 1 + e − x ⋅ e − x 1 + e − x = 1 1 + e − x ⋅ ( 1 − 1 1 + e − x ) ∴ σ ′ ( x ) = σ ( x ) ⋅ ( 1 − σ ( x ) ) \sigma'(x)=-\frac{1}{(1+e^{-x})^2} \cdot (1+e^{-x})'=\frac{e^{-x}}{(1+e^{-x})^2}\\[10pt] =\frac{1}{1+e^{-x}} \cdot \frac{e^{-x}}{1+e^{-x}} =\frac{1}{1+e^{-x}} \cdot (1- \frac{1}{1+e^{-x}})\\[10pt] \therefore \sigma'(x)= \sigma(x)\cdot (1-\sigma(x))\\[10pt] σ′(x)=−(1+e−x)21⋅(1+e−x)′=(1+e−x)2e−x=1+e−x1⋅1+e−xe−x=1+e−x1⋅(1−1+e−x1)∴σ′(x)=σ(x)⋅(1−σ(x))

输出函数

将线性函数与 σ \sigma σ 函数结合在一起,得到一个函数 σ ( u ) \sigma(u) σ(u),这里把 b 也看作是 w n w_n wn,相应地 x n x_n xn 也就为 1

σ ( u ) = 1 1 + e − u = 1 1 + e − ( w 1 x 1 + w 2 x 2 + . . . + w n x n ) \sigma(u)=\frac{1}{1+e^{-u}}=\frac{1}{1+e^{-(w_1x_1+w_2x_2+...+w_nx_n)}} σ(u)=1+e−u1=1+e−(w1x1+w2x2+...+wnxn)1

这里我令输出函数 z = σ ( u ) z=\sigma(u) z=σ(u),即

z = σ ( u ) = 1 1 + e − u = 1 1 + e − ( w 1 x 1 + w 2 x 2 + . . . + w n x n ) z=\sigma(u)=\frac{1}{1+e^{-u}}=\frac{1}{1+e^{-(w_1x_1+w_2x_2+...+w_nx_n)}}\\[10pt] z=σ(u)=1+e−u1=1+e−(w1x1+w2x2+...+wnxn)1

根据 σ \sigma σ 函数导数性质有:

z ′ = σ ′ ( u ) = σ ( u ) ⋅ ( 1 − σ ( u ) ) = z ( 1 − z ) z'=\sigma'(u)=\sigma(u)\cdot (1-\sigma(u))=z(1-z)\\[10pt] z′=σ′(u)=σ(u)⋅(1−σ(u))=z(1−z)

上面我们提到过 σ ( u ) ∈ ( 0 , 1 ) \sigma(u) \in (0,1) σ(u)∈(0,1),令 P = σ ( u ) P=\sigma(u) P=σ(u),那么有 u = ln ⁡ P 1 − P u=\ln{\frac{P}{1-P}} u=ln1−PP,P 可以看作是某个类别的概率,对于二分类来说,概率要么是 0,要么是 1,那么从概率的角度上看:

∵ P = σ ( u ) ∴ u = ln ⁡ P 1 − P = ln ⁡ P ( y = 1 ∣ x ) P ( y = 0 ∣ x ) \because P=\sigma(u)\\[10pt] \therefore u=\ln{\frac{P}{1-P}}=\ln{\frac{P(y=1|x)}{P(y=0|x)}} ∵P=σ(u)∴u=ln1−PP=lnP(y=0∣x)P(y=1∣x)

y 为真实标签,u 的含义为 事件为1的概率 P ( y = 1 ∣ x ) P(y=1|x) P(y=1∣x) 与 事件为0的概率 P ( y = 0 ∣ x ) P(y=0|x) P(y=0∣x) 比值再取对数。

似然函数

似然(likelihood),一听这个名字就知道是以前的老前辈翻译的,带有文言色彩

似然:相似的样子

假设总共有 m 个样本,第 i 个样本, 二分类 的似然函数如下,其中 z i z_i zi 为预测输出, y i y_i yi 为实际输出:

L ( w ) = ∏ i = 1 m z i y i ( 1 − z i ) ( 1 − y i ) % 似然函数 L(w)=\prod\limits_{i=1}^{m} z_i^{y_i}(1-z_i)^{(1-y_i)}\\[10pt] L(w)=i=1∏mziyi(1−zi)(1−yi)

要注意的是,这里 y i y_i yi 与 1 − y i 1-y_i 1−yi 其中有一个为 0, y i y_i yi 要么为 0,要么为 1(二分类),令:

w = [ w 1 w 2 ... w n ] , x i = [ x i 1 x i 2 ... x i n ] z i = σ ( w T x i ) % w 参数 w=\begin{bmatrix} w_1\\w_2\\\dots\\ w_n \end{bmatrix}, % x 输入 x_i=\begin{bmatrix} x_{i1}\\x_{i2}\\\dots\\ x_{in} \end{bmatrix}\\[10pt] z_i=\sigma(w^Tx_i)\\[10pt] w= w1w2...wn ,xi= xi1xi2...xin zi=σ(wTxi)

为了方便,可以对似然函数取对数,就由乘法转为了加法,称之为 对数似然函数

ℓ ( w ) = ln ⁡ L ( w ) = ln ⁡ ( ∏ i = 1 m z i y i ( 1 − z i ) ( 1 − y i ) ) = ∑ i = 1 m [ y i ln ⁡ z i + ( 1 − y i ) ln ⁡ ( 1 − z i ) ] \ell(w)=\ln{L(w)}=\ln{(\prod\limits_{i=1}^{m} z_i^{y_i}(1-z_i)^{(1-y_i)})}\\[10pt] =\sum\limits_{i=1}^{m}[{y_i\ln{z_i}}+{(1-y_i)\ln{(1-z_i)}}] ℓ(w)=lnL(w)=ln(i=1∏mziyi(1−zi)(1−yi))=i=1∑m[yilnzi+(1−yi)ln(1−zi)]

因为输出 z i ∈ ( 0 , 1 ) z_i \in(0,1) zi∈(0,1),所以 ln ⁡ z i \ln{z_i} lnzi 或者 ln ⁡ ( 1 − z i ) \ln(1-z_i) ln(1−zi) 都是负数,因此 负对数似然 为正数:

L N L L ( w ) = − ∑ i = 1 m [ y i ln ⁡ z i + ( 1 − y i ) ln ⁡ ( 1 − z i ) ] \mathcal{L}{NLL}(w)= - \sum\limits{i=1}^{m}[{y_i\ln{z_i}}+{(1-y_i)\ln{(1-z_i)}}] LNLL(w)=−i=1∑m[yilnzi+(1−yi)ln(1−zi)]

极大似然估计

还记得我们前面的最小二乘法吗?目标是最小残差平方和(RSS),通过 RSS 来判断函数拟合的优劣,那么对于回归回题,目标则是求极大似然估计,似然函数或对数似然函数越大,等效于负对数似然越小,函数拟合的就越好。

极大似然估计,等效于要求负对数似然极小。这就和最小化残差平方和有点相似了,都是求最小,就可以采用梯度下降法进行求解。

梯度下降法

函数准备

令 i 为样本号,eg. z i z_{i} zi 为第 i 个样本预测概率, y i y_{i} yi 为真实概率,有:

u i = w 1 x i 1 + w 2 x i 2 + . . . + b = [ x i 1 x i 2 ... 1 ] [ w 1 w 2 ... b ] z i = σ ( u i ) = 1 1 + e − u i u_{i}=w_{1}x_{i1}+w_{2}x_{i2}+...+b\\[10pt] =\begin{bmatrix} x_{i1}& x_{i2}&\dots& 1 \end{bmatrix} \begin{bmatrix} w_{1}\\ w_{2}\\\dots\\ b \end{bmatrix} \\[10pt] z_{i}=\sigma(u_{i})=\frac{1}{1+e^{-u_{i}}}\\[10pt] ui=w1xi1+w2xi2+...+b=[xi1xi2...1] w1w2...b zi=σ(ui)=1+e−ui1

可以把 b 作为 w n w_{n} wn,那么 x n = 1 x_{n}=1 xn=1 它们的偏导为:

∂ u i ∂ w k = x i k ∂ z i ∂ u i = z i ( 1 − z i ) \frac{\partial u_{i}}{\partial w_{k}} =x_{ik}\\[10pt] \frac{\partial z_{i}}{\partial u_{i}} =z_{i}(1-z_{i})\\[10pt] ∂wk∂ui=xik∂ui∂zi=zi(1−zi)

负对数似然函数为

L N L L ( w ) = − ∑ i = 1 m [ y i ln ⁡ z i + ( 1 − y i ) ln ⁡ ( 1 − z i ) ] \mathcal{L}{NLL}(w)= - \sum\limits{i=1}^{m}[{y_i\ln{z_i}}+{(1-y_i)\ln{(1-z_i)}}] LNLL(w)=−i=1∑m[yilnzi+(1−yi)ln(1−zi)]

令:

E i = − [ y i ln ⁡ z i + ( 1 − y i ) ln ⁡ ( 1 − z i ) ] ∴ L N L L ( w ) = ∑ i = 1 m E i E_{i}=-[{y_i\ln{z_i}}+{(1-y_i)\ln{(1-z_i)}}]\\[10pt] %% \therefore \mathcal{L}{NLL}(w)= \sum\limits{i=1}^{m}E_{i}\\[10pt] Ei=−[yilnzi+(1−yi)ln(1−zi)]∴LNLL(w)=i=1∑mEi

求偏导

∂ E i ∂ z i = − ( y i z i − 1 − y i 1 − z i ) = z i − y i z i ( 1 − z i ) %% \frac{\partial E_{i}}{\partial z_{i}} =-(\frac{y_{i}}{z_{i}}-\frac{1-y_{i}}{1-z_{i}})\\[10pt] =\frac{z_{i}-y_{i}}{z_{i}(1-z_{i})} \\[10pt] ∂zi∂Ei=−(ziyi−1−zi1−yi)=zi(1−zi)zi−yi

所以有:

∂ E i ∂ w k = ∂ E i ∂ z i ⋅ ∂ z i ∂ u i ⋅ ∂ u i ∂ w k = z i − y i z i ( 1 − z i ) ⋅ z i ( 1 − z i ) ⋅ x i k = ( z i − y i ) ⋅ x i k ∴ ∂ L N L L ∂ w k = ∑ i = 1 m ∂ E i ∂ w k = ∑ i = 1 m ( z i − y i ) ⋅ x i k \frac{\partial E_{i}}{\partial w_{k}} =\frac{\partial E_{i}}{\partial z_{i}} \cdot \frac{\partial z_{i}}{\partial u_{i}}\cdot \frac{\partial u_{i}}{\partial w_{k}}\\[10pt] =\frac{z_{i}-y_{i}}{z_{i}(1-z_{i})} \cdot z_{i}(1-z_{i}) \cdot x_{ik}\\[10pt] =(z_{i}-y_{i}) \cdot x_{ik}\\[10pt] %% \therefore\frac{\partial \mathcal{L}{NLL}}{\partial w{k}} =\sum\limits_{i=1}^{m}\frac{\partial E_{i}}{\partial w_{k}} =\sum\limits_{i=1}^{m}(z_{i}-y_{i}) \cdot x_{ik}\\[10pt] ∂wk∂Ei=∂zi∂Ei⋅∂ui∂zi⋅∂wk∂ui=zi(1−zi)zi−yi⋅zi(1−zi)⋅xik=(zi−yi)⋅xik∴∂wk∂LNLL=i=1∑m∂wk∂Ei=i=1∑m(zi−yi)⋅xik

损失函数

项目上多用均值作为损失函数,即:

E = 1 m L N L L ( w ) = 1 m ∑ i = 1 m E i = − 1 m ∑ i = 1 m [ y i ln ⁡ z i + ( 1 − y i ) ln ⁡ ( 1 − z i ) ] E=\frac{1}{m}\mathcal{L}{NLL}(w)=\frac{1}{m}\sum\limits{i=1}^{m}E_{i}\\[10pt] =-\frac{1}{m}\sum\limits_{i=1}^{m}[{y_i\ln{z_i}}+{(1-y_i)\ln{(1-z_i)}}]\\[10pt] E=m1LNLL(w)=m1i=1∑mEi=−m1i=1∑m[yilnzi+(1−yi)ln(1−zi)]

所以有:

∂ E ∂ w k = 1 m ∂ L N L L ∂ w k = 1 m ∑ i = 1 m ( z i − y i ) ⋅ x i k \frac{\partial E}{\partial w_{k}} =\frac{1}{m}\frac{\partial \mathcal{L}{NLL}}{\partial w{k}} =\frac{1}{m}\sum\limits_{i=1}^{m}(z_{i}-y_{i}) \cdot x_{ik}\\[10pt] ∂wk∂E=m1∂wk∂LNLL=m1i=1∑m(zi−yi)⋅xik

梯度更新

上面我们求出了偏导,是为了求梯度准备的。

再来翻译一下, 梯度:梯子的斜度,也就是斜率,对于多维度的梯度,就是每个维度方向上的斜率。

那么 E 的梯度为:

∂ E ∂ w ⃗ = [ ∂ E ∂ w 1 ∂ E ∂ w 2 ... ∂ E ∂ w n ] = [ 1 m ∑ i = 1 m ( z i − y i ) ⋅ x i 1 1 m ∑ i = 1 m ( z i − y i ) ⋅ x i 2 ... 1 m ∑ i = 1 m ( z i − y i ) ⋅ x i n ] \frac{\partial E}{\partial \vec{w}}=\begin{bmatrix} \frac{\partial E}{\partial w_{1}}\\[10pt] \frac{\partial E}{\partial w_{2}}\\[10pt] \dots\\[10pt] \frac{\partial E}{\partial w_{n}}\\[10pt] \end{bmatrix} =\begin{bmatrix} \frac{1}{m}\sum\limits_{i=1}^{m}(z_{i}-y_{i}) \cdot x_{i1}\\[10pt] \frac{1}{m}\sum\limits_{i=1}^{m}(z_{i}-y_{i}) \cdot x_{i2}\\[10pt] \dots\\[10pt] \frac{1}{m}\sum\limits_{i=1}^{m}(z_{i}-y_{i}) \cdot x_{in}\\[10pt] \end{bmatrix} ∂w ∂E= ∂w1∂E∂w2∂E...∂wn∂E = m1i=1∑m(zi−yi)⋅xi1m1i=1∑m(zi−yi)⋅xi2...m1i=1∑m(zi−yi)⋅xin

前面我们推导出沿着 梯度 方向下降最快:

Δ w k = η Δ r ∂ E ∂ w k w k ( t + 1 ) = w k ( t ) − η Δ r ∂ E ∂ w k \Delta{w_k}= \eta\Delta{r}\frac{\partial E}{\partial w_{k}} \\[10pt] w_{k}^{(t+1)}=w_{k}^{(t)} - \eta\Delta{r}\frac{\partial E}{\partial w_{k}} \\[10pt] Δwk=ηΔr∂wk∂Ewk(t+1)=wk(t)−ηΔr∂wk∂E

这里 Δ r \Delta{r} Δr 为 w 在梯度 l ⃗ \vec{l} l 方向增长一个微小单位,分解到各维度方向增长就是 Δ r cos ⁡ θ k \Delta{r}\cos{\theta_k} Δrcosθk, θ k \theta_k θk 为梯度 l ⃗ \vec{l} l 与 w k w_k wk 维度方向的夹角。

η = 1 ∑ k = 1 n ( ∂ E ∂ w k ) 2 cos ⁡ θ k = η ∂ E ∂ w k = ∂ E ∂ w k ∑ k = 1 n ( ∂ E ∂ w k ) 2 \eta=\frac{1}{\sqrt{\sum\limits_{k=1}^{n}{(\frac{\partial E}{\partial {w_k}})^2}}}\\[10pt] %% \cos{\theta_k}=\eta\frac{\partial E}{\partial {w_k}}=\frac{\frac{\partial E}{\partial {w_k}}}{\sqrt{\sum\limits_{k=1}^{n}{(\frac{\partial E}{\partial {w_k}})^2}}}\\[10pt] η=k=1∑n(∂wk∂E)2 1cosθk=η∂wk∂E=k=1∑n(∂wk∂E)2 ∂wk∂E

python 实战

以异或门为例:

真值表为:

i i i x i 1 x_{i1} xi1 x i 2 x_{i2} xi2 y i y_i yi
i=1 0 0 0
i=2 0 1 1
i=3 1 0 1
i=4 1 1 0

可以把真值表中的每一行都看作是一个样本, x i 1 x_{i1} xi1 与 x i 2 x_{i2} xi2 为异或门的 第 i 个样本输入, y i y_i yi 为第 i 个样本的输出。

LogisticRegression

定义好逻辑回归训练类 LogisticRegression,包括前向计算,反向传播

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap


class LogisticRegression:
    """手动实现的逻辑回归"""

    def __init__(self, learning_rate=0.1, n_iterations=10000):
        self.lr = learning_rate
        self.n_iter = n_iterations
        self.weights = None
        self.bias = None
        self.losses = []

    def sigmoid(self, z):
        """Sigmoid激活函数"""
        return 1 / (1 + np.exp(-z))

    def fit(self, X, y):
        """训练逻辑回归模型"""
        n_samples, n_features = X.shape

        # 初始化参数
        self.weights = np.random.randn(n_features)
        self.bias = 0

        # 梯度下降
        for iteration in range(self.n_iter):
            # 前向传播
            u = np.dot(X, self.weights) + self.bias
            z = self.sigmoid(u)

            # 计算损失,避免log中出现0的情况,加上一个非常小的值
            loss = -np.mean(y * np.log(z + 1e-15) +
                            (1 - y) * np.log(1 - z + 1e-15))
            self.losses.append(loss)

            # 计算梯度
            dw = (1 / n_samples) * np.dot(X.T, (z - y))
            db = (1 / n_samples) * np.sum(z - y)

            # 更新参数
            self.weights -= self.lr * dw
            self.bias -= self.lr * db

            # 打印进度
            if iteration % 1000 == 0:
                accuracy = self.score(X, y)
                print(
                    f"Iteration {iteration}, Loss: {loss:.4f}, Accuracy: {accuracy:.4f}"
                )

    def predict_proba(self, X):
        """预测概率"""
        linear_output = np.dot(X, self.weights) + self.bias
        return self.sigmoid(linear_output)

    def predict(self, X, threshold=0.5):
        """预测类别"""
        probabilities = self.predict_proba(X)
        return (probabilities >= threshold).astype(int)

    def score(self, X, y):
        """计算准确率"""
        predictions = self.predict(X)
        return np.mean(predictions == y)

训练及结果

准备样本数据进行训练并绘制损失函数,分别尝试 线性特征 与使用 多项式特征 来训练求解

python 复制代码
def create_xor_data():
    """创建异或门数据"""
    X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
    y = np.array([0, 1, 1, 0])
    return X, y


def add_polynomial_features(X):
    """添加多项式特征解决线性不可分问题"""
    # 添加平方项和交叉项
    X_poly = np.hstack([
        X,
        X[:, 0:1]**2,  # x1²
        X[:, 1:2]**2,  # x2²
        (X[:, 0:1] * X[:, 1:2]),  # x1*x2
    ])
    return X_poly

def visualize_results(X, y, model, title, feature_type='linear'):
    """可视化决策边界和结果"""
    fig, axes = plt.subplots(1, 2, figsize=(12, 5))

    # 创建网格点
    x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
    y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
                         np.arange(y_min, y_max, 0.01))

    if feature_type == 'poly':
        # 为多项式特征准备网格数据
        grid = np.c_[xx.ravel(), yy.ravel()]
        grid_poly = add_polynomial_features(grid)
        Z = model.predict(grid_poly)
    else:
        grid = np.c_[xx.ravel(), yy.ravel()]
        Z = model.predict(grid)

    Z = Z.reshape(xx.shape)

    # 绘制决策边界
    axes[0].contourf(xx, yy, Z, alpha=0.4, cmap=ListedColormap(['#FFAAAA', '#AAAAFF']))
    axes[0].scatter(X[:, 0], X[:, 1], c=y, s=100, cmap=ListedColormap(['red', 'blue']), edgecolors='k')
    axes[0].set_xlabel('x1')
    axes[0].set_ylabel('x2')
    axes[0].set_title(f'Decision Boundary - {title}')
    axes[0].grid(True, alpha=0.3)

    # 绘制损失曲线
    axes[1].plot(model.losses)
    axes[1].set_xlabel('Iteration')
    axes[1].set_ylabel('Loss')
    axes[1].set_title('Loss Curve')
    axes[1].grid(True, alpha=0.3)

    plt.tight_layout()
    plt.show()


def main():
    # 1. 准备数据
    X, y = create_xor_data()
    print("原始数据:")
    print("X:", X)
    print("y:", y)
    print()

    # 2. 尝试线性特征(无法解决异或问题)
    print("=" * 50)
    print("1. 使用线性特征(应该失败):")
    print("=" * 50)

    model_linear = LogisticRegression(learning_rate=0.1, n_iterations=10000)
    model_linear.fit(X, y)
    print(f"线性模型准确率: {model_linear.score(X, y):.4f}")
    print(f"权重: {model_linear.weights}, 偏置: {model_linear.bias:.4f}")
    print(f"预测结果: {model_linear.predict(X)}")

    visualize_results(X, y, model_linear, "Linear Features", 'linear')

    # 3. 使用多项式特征(可以解决异或问题)
    print("\n" + "=" * 50)
    print("2. 使用多项式特征(应该成功):")
    print("=" * 50)

    X_poly = add_polynomial_features(X)
    print("多项式特征形状:", X_poly.shape)
    print("特征示例:", X_poly[0])

    model_poly = LogisticRegression(learning_rate=0.1, n_iterations=20000)
    model_poly.fit(X_poly, y)
    print(f"多项式模型准确率: {model_poly.score(X_poly, y):.4f}")
    print(f"权重: {model_poly.weights}, 偏置: {model_poly.bias:.4f}")
    print(f"预测结果: {model_poly.predict(X_poly)}")

    # 显示详细预测
    print("\n详细预测:")
    for i in range(len(X)):
        prob = model_poly.predict_proba(X_poly[i:i+1])[0]
        pred = model_poly.predict(X_poly[i:i+1])[0]
        print(f"X={X[i]}, y={y[i]}, 预测概率={prob:.6f}, 预测类别={pred}")

    visualize_results(X, y, model_poly, "Polynomial Features", 'poly')

运行结果

运行 main() 得到如下结果:

  1. 使用线性特征

    log 复制代码
    原始数据:
    X: [[0 0]
    [0 1]
    [1 0]
    [1 1]]
    y: [0 1 1 0]
    
    ==================================================
    1. 使用线性特征(应该失败):
    ==================================================
    Iteration 0, Loss: 0.6989, Accuracy: 0.5000
    Iteration 1000, Loss: 0.6931, Accuracy: 0.5000
    Iteration 2000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 3000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 4000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 5000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 6000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 7000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 8000, Loss: 0.6931, Accuracy: 0.7500
    Iteration 9000, Loss: 0.6931, Accuracy: 0.5000
    线性模型准确率: 0.5000
    权重: [-2.48590055e-16 -2.48352572e-16], 偏置: 0.0000
    预测结果: [1 1 1 1]
  2. 多项式特征

    log 复制代码
     ==================================================
     1. 使用多项式特征(应该成功):
     ==================================================
     多项式特征形状: (4, 5)
     特征示例: [0 0 0 0 0]
     Iteration 0, Loss: 0.9076, Accuracy: 0.5000
     Iteration 1000, Loss: 0.2192, Accuracy: 1.0000
     Iteration 2000, Loss: 0.1162, Accuracy: 1.0000
     Iteration 3000, Loss: 0.0774, Accuracy: 1.0000
     Iteration 4000, Loss: 0.0576, Accuracy: 1.0000
     Iteration 5000, Loss: 0.0457, Accuracy: 1.0000
     Iteration 6000, Loss: 0.0378, Accuracy: 1.0000
     Iteration 7000, Loss: 0.0322, Accuracy: 1.0000
     Iteration 8000, Loss: 0.0280, Accuracy: 1.0000
     Iteration 9000, Loss: 0.0248, Accuracy: 1.0000
     Iteration 10000, Loss: 0.0223, Accuracy: 1.0000
     Iteration 11000, Loss: 0.0202, Accuracy: 1.0000
     Iteration 12000, Loss: 0.0184, Accuracy: 1.0000
     Iteration 13000, Loss: 0.0170, Accuracy: 1.0000
     Iteration 14000, Loss: 0.0157, Accuracy: 1.0000
     Iteration 15000, Loss: 0.0146, Accuracy: 1.0000
     Iteration 16000, Loss: 0.0137, Accuracy: 1.0000
     Iteration 17000, Loss: 0.0129, Accuracy: 1.0000
     Iteration 18000, Loss: 0.0121, Accuracy: 1.0000
     ...
     X=[0 0], y=0, 预测概率=0.014450, 预测类别=0
     X=[0 1], y=1, 预测概率=0.989687, 预测类别=1
     X=[1 0], y=1, 预测概率=0.989687, 预测类别=1
     X=[1 1], y=0, 预测概率=0.008247, 预测类别=0

总结

  • 逻辑回归是线性分类器,决策边界是 超平面

    w 1 x 1 + w 2 x 2 + . . . + w n x n = 0 w_1x_1+w_2x_2+...+w_nx_n=0 w1x1+w2x2+...+wnxn=0

  • 对于原始异或问题

    bash 复制代码
    (0,0) → 类别0
    (0,1) → 类别1
    (1,0) → 类别1
    (1,1) → 类别0

    在二维空间中,不存在一条直线能完美分离这 4 个点。这是线性不可分问题的经典例子。

  • 解决方案:特征映射

    通过添加多项式特征,将数据映射到高维空间:

    x 1 x 2 \] → \[ x 1 x 2 x 1 2 x 2 2 x 1 x 2 \] \\begin{bmatrix} x_1 \& x_2 \\end{bmatrix} \\rightarrow \\begin{bmatrix} x_1 \& x_2 \& {x_1}\^2 \& {x_2}\^2 \& {x_1x_2} \\end{bmatrix} \[x1x2\]→\[x1x2x12x22x1x2

那么决策边界就变成了多项式

w 1 x 1 + w 2 x 2 + w 3 x 1 2 + w 4 x 2 2 + w 5 x 1 x 2 = 0 w_1x_1+w_2x_2+w_3{x_1}^2+w_4{x_2}^2+w_5{x_1x_2}=0 w1x1+w2x2+w3x12+w4x22+w5x1x2=0

在高维空间中,数据变得线性可分,这就是神经网络中 隐藏层 的思想基础。

相关推荐
深度之眼3 小时前
入选TPAMI顶刊!多模态图像融合新突破!
深度学习·机器学习·多模态
LiYingL4 小时前
PictSure:通过视觉嵌入功能挑战 _Few-Shot _分类的新方法
人工智能·分类·数据挖掘
IT阳晨。5 小时前
【CNN与卷积神经网络(吴恩达)】卷积神经网络学习笔记
笔记·深度学习·神经网络·cnn
一招定胜负5 小时前
逻辑回归核心原理与实践指南
算法·逻辑回归·线性回归
Better Bench5 小时前
ThinkStation PGX 与 RTX 4090 深度学习性能对比测试报告
人工智能·深度学习·显卡·联想·4090·计算性能·pgx
薛不痒5 小时前
机器学习算法之线性回归&逻辑回归
算法·机器学习·逻辑回归
sponge'5 小时前
opencv学习笔记13:U-Net
人工智能·深度学习·机器学习
_codemonster6 小时前
AI大模型入门到实战系列(六)文本分类
人工智能·分类·数据挖掘
零小陈上(shouhou6668889)6 小时前
水稻病害检测(YOLO数据集,多分类,稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫)
yolo·分类·数据挖掘