【自学笔记】逻辑回归

让步比

即某一特定事件发生的概率,定义logit函数为让步比的log形式

l o g i t ( p ) = l o g p 1 − p logit(p) = log\frac{p}{1-p} logit(p)=log1pp

我们可以用logit函数表示特征值和对数概率间的线性关系

l o g i t ( p ( y = 1 ∣ x ⃗ ) ) = w 0 x 0 + w 1 x 1 + . . . + w m x m = w ⃗ T x ⃗ logit(p(y=1 | \vec{x} )) = w_{0}x_{0} + w_{1}x_{1} + ... + w_{m}x_{m} = \vec{w}^{T}\vec{x} logit(p(y=1∣x ))=w0x0+w1x1+...+wmxm=w Tx

  其中 l o g i t ( p ( y = 1 ∣ x ⃗ ) ) logit(p(y=1 | \vec{x} )) logit(p(y=1∣x ))表示给定特征 x ⃗ \vec{x} x ,某个特定样本属于类1的条件概率。
  实际上,我们关心的是预测某个样本属于某个特定类的概率,它是logit函数的逆函数(sigmoid函数,下面讲)

为什么要用让步比?

  侧重点不同。
  让步比(Odds)和概率(Probability)是统计学中用于描述事件发生可能性的两种不同方式。而概率更直接反映事件发生的可能性大小,而让步比则强调的是事件发生的几率与不发生的几率之间的对比。
  概率p的取值范围限制在0到1之间,而让步比 p 1 − p \frac{p}{1-p} 1pp的取值范围是0到正无穷,这使得让步比在数学运算和建模中有时更方便(比如在逻辑回归模型中,让步比的对数可以映射到实数范围,便于模型拟合)。

sigmoid函数

ϕ ( z ) = 1 1 + e − z \phi (z) = \frac{1}{1+e^{-z}} ϕ(z)=1+ez1

其中,z为净输入,z = w ⃗ T x ⃗ \vec{w}^{T}\vec{x} w Tx

绘制图像如下:
在这里插入图片描述
  在逻辑回归中,我们设定激活函数由原先的f(x)=x变成现在的sigmoid函数。

为什么要用sigmoid函数?

  1.Sigmoid函数的输出值范围在0到1之间,这可以被解释为某一事件发生的概率,所以我们不仅可以知道分类结果,还可以知道其概率。
  ->在逻辑回归中,Sigmoid函数将线性模型的输出转换为概率形式,使得模型可以预测事件发生的可能性。
  ->当 ϕ ( x ) ≥ 0.5 \phi(x) \ge 0.5 ϕ(x)0.5,我们认为预测值 y ^ = 1 \hat{y} =1 y^=1,反之 y ^ = 0 \hat{y} =0 y^=0
  2.在神经网络中,Sigmoid函数提供了非线性映射,使得网络能够学习和逼近复杂的函数。
  3.出于自身性质,sigmoid函数求导非常方便,有

ϕ ′ ( x ) = ϕ ( x ) ( 1 − ϕ ( x ) ) \phi^{'} (x)=\phi(x)(1−\phi(x)) ϕ(x)=ϕ(x)(1ϕ(x))

重新定义代价函数

  若继续使用 J ( w ⃗ ) = ∑ i 1 2 ( ϕ ( z ( i ) ) − y ( i ) ) 2 J(\vec{w} ) = \sum_{i}^{} \frac{1}{2} (\phi(z^{(i)}) - y^{(i)})^{2} J(w )=i21(ϕ(z(i))y(i))2,会导致出现多个极小值点,无法梯度下降到最小值。

  所以我们使用似然估计的方法,关于似然的知识可以参考以下文章:

【For非数学专业】通俗理解似然函数、概率、极大似然估计和对数似然

假设数据集中每一个样本相互独立,则:
   L ( w ⃗ ) = P ( y ⃗ ∣ x ⃗ ; w ⃗ ) = ∏ i = 1 m P ( y ( i ) ∣ x ( i ) ; w ⃗ ) = ∏ i = 1 m ( ϕ ( z ( i ) ) ) y ( i ) ( 1 − ϕ ( z ( i ) ) ) 1 − y ( i ) L(\vec{w}) = P(\vec{y}|\vec{x};\vec{w}) = \prod_{i=1}^{m}P(y^{(i)} | x^{(i)}; \vec{w}) = \prod_{i=1}^{m}(\phi(z^{(i)}))^{y(i)}(1-\phi(z^{(i)}))^{1-y(i)} L(w )=P(y x ;w )=i=1mP(y(i)x(i);w )=i=1m(ϕ(z(i)))y(i)(1ϕ(z(i)))1y(i)

显然这个函数不好求最小值,所以我们取对数似然:
   l ( w ⃗ ) = l o g L ( w ⃗ ) = ∑ i = 1 n y ( i ) l o g ( ϕ ( z ( i ) ) ) + ∑ i = 1 n ( 1 − y ( i ) ) l o g ( 1 − ϕ ( z ( i ) ) ) l(\vec{w}) = logL(\vec{w}) = \sum_{i=1}^{n}y^{(i)}log(\phi(z^{(i)})) + \sum_{i=1}^{n}(1 - y^{(i)})log(1 - \phi(z^{(i)})) l(w )=logL(w )=i=1ny(i)log(ϕ(z(i)))+i=1n(1y(i))log(1ϕ(z(i)))

然后就可以用梯度上升(类似梯度下降)的方法来求得最大似然

为什么要用这个当作代价函数?

在这里插入图片描述
  可以看到,如果J(w)与y越接近,代价越接近0;反之,代价趋于无穷大。
  在给定观测数据的情况下,似然用于描述参数值的可信度。故取得最大似然,就可以让这组 w ⃗ \vec{w} w 最可靠。
  综上,这个最大似然估计函数起到了代价函数的效果。

梯度下降使用

  为了“下降”,我们让 J ( w ⃗ ) = − ∑ i = 1 n y ( i ) l o g ( ϕ ( z ( i ) ) ) − ∑ i = 1 n ( 1 − y ( i ) ) l o g ( 1 − ϕ ( z ( i ) ) ) J(\vec{w}) = -\sum_{i=1}^{n}y^{(i)}log(\phi(z^{(i)})) - \sum_{i=1}^{n}(1 - y^{(i)})log(1 - \phi(z^{(i)})) J(w )=i=1ny(i)log(ϕ(z(i)))i=1n(1y(i))log(1ϕ(z(i)))
  与线性感知器相同,分别对b和 w j w_{j} wj求偏导,利用梯度下降:

先求 ϕ \phi ϕ对z的偏导,有:
∂ ϕ ( z ) ∂ z = ∂ ∂ z 1 1 + e − z = e − z ( 1 + e − z ) 2 = ϕ ( z ) ( 1 − ϕ ( z ) ) \frac{\partial \phi(z)}{\partial z} = \frac{\partial }{\partial z}\frac{1}{1+e^{-z}} = \frac{e^{-z}}{(1+e^{-z})^{2}} = \phi(z)(1-\phi(z)) zϕ(z)=z1+ez1=(1+ez)2ez=ϕ(z)(1ϕ(z))

对于w有
∂ J ∂ w j = ( y ∗ 1 ϕ ( z ) − ( 1 − y ) ∗ 1 1 − ϕ ( z ) ) ∗ ∂ ϕ ( z ) ∂ w j \frac{\partial J}{\partial w_{j}} = (y * \frac{1}{\phi(z)} - (1-y) * \frac{1}{1 - \phi(z)}) * \frac{\partial \phi(z)}{\partial w_{j}} wjJ=(yϕ(z)1(1y)1ϕ(z)1)wjϕ(z)
    = ( y ∗ 1 ϕ ( z ) − ( 1 − y ) ∗ 1 1 − ϕ ( z ) ) ∗ ∂ ϕ ( z ) ∂ z ∗ ∂ z ∂ w j =(y * \frac{1}{\phi(z)} - (1-y) * \frac{1}{1 - \phi(z)}) * \frac{\partial \phi(z)}{\partial z} * \frac{\partial z}{\partial w_{j}} =(yϕ(z)1(1y)1ϕ(z)1)zϕ(z)wjz
    = ( y ∗ 1 ϕ ( z ) − ( 1 − y ) ∗ 1 1 − ϕ ( z ) ) ∗ ϕ ( z ) ( 1 − ϕ ( z ) ) ∗ ∂ z ∂ w j = (y * \frac{1}{\phi(z)} - (1-y) * \frac{1}{1 - \phi(z)}) * \phi(z)(1-\phi(z)) * \frac{\partial z}{\partial w_{j}} =(yϕ(z)1(1y)1ϕ(z)1)ϕ(z)(1ϕ(z))wjz
    = ( y − ϕ ( z ) ) ∗ x j = (y - \phi(z)) * x_{j} =(yϕ(z))xj
   
△ w ⃗ = η ▽ J ( w ⃗ ) \bigtriangleup \vec{w} = \eta \bigtriangledown J(\vec{w}) w =ηJ(w )
△ w j = − η ∂ J ∂ w j = − η ∑ i = 1 n ( y ( i ) − ϕ ( z ( i ) ) ) x j ( i ) \bigtriangleup w_{j} = -\eta\frac{\partial J}{\partial w_{j}} = -\eta\sum_{i=1}^{n}(y^{(i)}-\phi(z^{(i)}))x^{(i)}_{j} wj=ηwjJ=ηi=1n(y(i)ϕ(z(i)))xj(i)
   
同理,对于b有:
∂ J ∂ b = ( y − ϕ ( z ) ) ∗ ∂ z ∂ b \frac{\partial J}{\partial b} = (y - \phi(z)) * \frac{\partial z}{\partial b} bJ=(yϕ(z))bz
    = y − ϕ ( z ) = y - \phi(z) =yϕ(z)
   
△ b = − η ∂ J ∂ b = − η ∑ i = 1 n ( y ( i ) − ϕ ( z ( i ) ) ) \bigtriangleup b = -\eta\frac{\partial J}{\partial b} = -\eta\sum_{i=1}^{n}(y^{(i)}-\phi(z^{(i)})) b=ηbJ=ηi=1n(y(i)ϕ(z(i)))

   此外,为了不同大小的训练集之间的代价函数值可以互相比较,一般会在J上除以m,求得平均损失即:

J ( w ⃗ ) = − 1 m ∑ i = 1 n y ( i ) l o g ( ϕ ( z ( i ) ) ) − 1 m ∑ i = 1 n ( 1 − y ( i ) ) l o g ( 1 − ϕ ( z ( i ) ) ) J(\vec{w}) = -\frac{1}{m}\sum_{i=1}^{n}y^{(i)}log(\phi(z^{(i)})) - \frac{1}{m}\sum_{i=1}^{n}(1 - y^{(i)})log(1 - \phi(z^{(i)})) J(w )=m1i=1ny(i)log(ϕ(z(i)))m1i=1n(1y(i))log(1ϕ(z(i)))

那么 △ w j \bigtriangleup w_{j} wj △ b \bigtriangleup b b相应除以m即可

用scikit-learn训练

   注意,该模型只能用于二分类,所以我们只考虑Iris-setosa和Iris-versicolor两种花,对应0和1

# 导入必要的库和工具
from matplotlib.colors import ListedColormap  # 用于创建颜色图
import matplotlib.pyplot as plt  # 用于绘图
import numpy as np  # 用于数值计算
from distutils.version import LooseVersion  # 用于版本号的比较
import matplotlib  # 用于绘图的库
from sklearn.model_selection import train_test_split  # 用于数据集的划分
from sklearn.preprocessing import StandardScaler  # 用于特征标准化
from sklearn.linear_model import Perceptron  # 感知机分类器
from sklearn import datasets  # 用于获取数据集

# 加载鸢尾花数据集
iris = datasets.load_iris()

X = iris.data[:, [2, 3]]  # 选取花瓣长度和花瓣宽度作为特征
y = iris.target  # 目标变量(类别标签)

# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=1, stratify=y)
# test_size=0.3表示测试集占30%,stratify=y确保训练集和测试集中的类别分布与原始数据集一致
# random_state=1是为了每次运行时都能得到相同的结果,便于复现

# 特征标准化
# 通过计算训练集的平均值和标准差来标准化数据
sc = StandardScaler()
sc.fit(X_train)  # 计算X_train的平均值和标准差

X_train_std = sc.transform(X_train)  # 使用计算出的平均值和标准差对X_train进行标准化
X_test_std = sc.transform(X_test)  # 使用相同的平均值和标准差对X_test进行标准化

# 创建并训练感知机模型
ppn = Perceptron(eta0=0.1, random_state=1)  # eta0是学习率,random_state是随机种子
ppn.fit(X_train_std, y_train)  # 使用标准化后的训练集对感知机模型进行训练


def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):

    # 设置标记和颜色

    markers = ('s', 'x', 'o', '^', 'v')  # 不同类别的标记符号
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')  # 不同类别的颜色
    cmap = ListedColormap(colors[:len(np.unique(y))])  # 创建一个颜色图,长度等于类别数

    # 生成决策边界的网格

    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1  # 第一个特征的范围

    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1  # 第二个特征的范围
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))  # 构建网格
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)  # 预测网格上每个点的类别
    Z = Z.reshape(xx1.shape)  # 重塑预测结果形状

    # 绘制决策边界
    plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)  # 填充颜色的决策边界
    plt.xlim(xx1.min(), xx1.max())  # 设置x轴的范围
    plt.ylim(xx2.min(), xx2.max())  # 设置y轴的范围

    # 绘制训练数据点
    for idx, cl in enumerate(np.unique(y)):  # 遍历每个类别

        plt.scatter(x=X[y == cl, 0],  # 类别为cl的x1数据点
                    y=X[y == cl, 1],  # 类别为cl的x2数据点
                    alpha=0.8,  # 设置透明度
                    color=colors[idx],  # 使用对应颜色
                    marker=markers[idx],  # 使用对应标记
                    label=cl,  # 设置图例标签
                    edgecolor='black')  # 设置边框颜色

    # 如果存在测试集,突出显示测试数据点

    if test_idx is not None:
        X_test, y_test = X[test_idx, :], y[test_idx]  # 分离测试集的特征和标签
        if LooseVersion(matplotlib.__version__) < LooseVersion('0.3.4'):  # 检查matplotlib版本

            plt.scatter(X_test[:, 0],
                        X_test[:, 1],
                        c='',
                        edgecolor='black',
                        alpha=1.0,
                        linewidth=1,
                        marker='o',
                        s=100,
                        label='test set')
        else:  # 对于更现代的matplotlib版本,使用'c=None'而不是'c=""'

            plt.scatter(X_test[:, 0],
                        X_test[:, 1],
                        c='none',
                        edgecolor='black',
                        alpha=1.0,
                        linewidth=1,
                        marker='o',
                        s=100,
                        label='test set')
# 将训练集和测试集的标准化特征数据堆叠在一起
X_combined_std = np.vstack((X_train_std, X_test_std))  # 使用numpy的vstack函数沿垂直轴堆叠矩阵

# 将训练集和测试集的标签数据拼接在一起
y_combined = np.hstack((y_train, y_test))  # 使用numpy的hstack函数沿水平轴拼接数组

# 调用plot_decision_regions函数绘图
# 注意:这里假设plot_decision_regions是之前定义的自定义函数,用于可视化分类器的决策边界
plot_decision_regions(X=X_combined_std, y=y_combined, 
                      classifier=ppn,  # 这里的ppn假设是训练好的分类器对象
                      test_idx=range(105, 150))  # 指定测试集的样本索引,用于突出显示在图中

# 设置x轴的标签
plt.xlabel('petal length [standardized]')  # x轴标签为“花瓣长度[标准化]”

# 设置y轴的标签
plt.ylabel('petal width [standardized]')  # y轴标签为“花瓣宽度[标准化]”

# 添加图例,并设置其位置
plt.legend(loc='upper left')  # 图例位于左上角

# 调整布局,确保图例不会被裁剪
plt.tight_layout()  # 自动调整子图参数以填充整个图像区域

# 保存图片(注释掉的代码)
# plt.savefig('images/03_01.png', dpi=300)  # 将图像保存为PNG文件,分辨率为300dpi

# 显示图像

plt.show()  # 绘制并显示图像

效果如下

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值