• 逻辑回归(Logistic Regression)


     


    线性模型

    逻辑回归,本质是一种线性模型 y = w x + b y=wx+b y=wx+b

    不过逻辑回归和线性模型不同的是,为了实现二分类任务,加了 s i g m o d sigmod sigmod 函数。

    • 这个不仅要满足映射到 [0,1],还要满足:当 x = 0 时;y 正好为 0.5;且 x = 负无穷 和 x = 正无穷的时候,y 分别趋近于 0 和 1。
    • s i g m o i d sigmoid sigmoid 是连续可导函数,为我们计算带来了方便。
    • s i g m o i d sigmoid sigmoid 是最简单的满足这样条件的函数,更“自然”,数学上的解释 —— 满足最大似然估计的结果

    s i g m o i d sigmoid sigmoid 函数,使得预测的结果从样本成绩变成了样本成绩的概率。

    • 样本成绩: y = w x + b y=wx+b y=wx+b
    • 样本成绩的概率: p = σ ( y ) = 1 1 + e w x + b p=\sigma(y) =\frac{1}{1+e^{wx+b}} p=σ(y)=1+ewx+b1

    如果这个概率 p > 0.5 p > 0.5 p>0.5,把这个数据分类为 y = 1 y=1 y=1(正样本)。

    如果这个概率 p < 0.5 p < 0.5 p<0.5,就把这个数据分类为 y = 0 y=0 y=0(负样本)。

     


    损失函数

    这个损失函数的意义是模型预测出来的值 p p p 要和样本的标签值 y y y 尽量一致,即正样本的预测值要尽量为正,负样本要为负,否则会产生一个损失值。

    按照 y 、 p y、p yp 之间的关系,我们反过来设计:

    • 如果样本的标签值 y = 1 y=1 y=1,模型预测出来的值 p 越小 p 越小 p越小,损失值越大
    • 如果样本的标签值 y = 0 y=0 y=0,模型预测出来的值 p 越大 p 越大 p越大,损失值越小

    用数学语言表达:

    • − l o g ( p )      i f      y = 1 -log(p)~~~~if~~~~y=1 log(p)    if    y=1
    • − l o g ( 1 − p )      i f      y = 0 -log(1-p)~~~~if~~~~y=0 log(1p)    if    y=0

    函数图像:

    p p p 接近 1 时,损失函数接近正无穷,会分为正样本,但实际值却是负样本。

    所以,我们会给一个正无穷的惩罚,直到 p p p 的减小,惩罚值会越来越低,直到当 p = 0 p=0 p=0 时,会分为负样本,实际值也是负样本,就没有惩罚。

    不过目前这个损失函数是分类函数形式,我们需要合并为一个函数:

    • L ( p , y ) = − y   l o g ( p ) − ( 1 − y )   l o g ( 1 − p ) ) L(p, y)=-y~log(p) - (1-y)~ log(1-p)) L(p,y)=y log(p)(1y) log(1p))

    这是对单个训练样本(一张图)的损失函数,但我们输入都神经网络的通常是一个训练集(大量的图片)。

    我们需要累加单个训练样本的结果,再求平均值:

    • 1 m ∑ i = 1 m L ( p i , y i ) \frac{1}{m}\sum_{i=1}^{m}L(p_{i}, y_{i}) m1i=1mL(pi,yi)

    为什么使用这个损失函数呢?

    这个损失函数(逻辑回归)的函数图像是一个向下凸的图形。


    因为学习,就是找到一组 w 和 b,使这个损失函数最小。

    也就是在这个函数图像的底部找到一组 w 和 b。

    这个损失函数没有局部最优解,只存在唯一的全局最优解。

    我们要做的,是求出成本函数的梯度,而后运用梯度下降法求出损失最小的一组 w 和 b。

     


    损失函数的梯度

    损失函数 L o s s ( p , y ) Loss(p, y) Loss(p,y),是指对单个样本的做的损失。

    成本函数 J ( θ ) J(\theta) J(θ),是数据集上总的成本和损失。

    • J ( θ ) = − 1 m ∑ m i = 1 y i l o g ( σ ( X b i θ ) ) + ( 1 − y i ) l o g ( 1 − σ ( X b i θ ) ) J(\theta)=-\frac{1}{m}\sum_{m}^{i=1}y_{i}log(\sigma(X^{i}_{b}\theta))+(1-y_{i})log(1-\sigma(X^i_{b}\theta)) J(θ)=m1mi=1yilog(σ(Xbiθ))+(1yi)log(1σ(Xbiθ))

    求损失函数的梯度: Δ J = { ∂ J ( θ ) ∂ θ 0 ∂ J ( θ ) ∂ θ 1 ⋅ ⋅ ⋅ ∂ J ( θ ) ∂ θ n } \Delta J=

    {J(θ)θ0J(θ)θ1···J(θ)θn}" role="presentation" style="position: relative;">{J(θ)θ0J(θ)θ1···J(θ)θn}
    ΔJ= θ0J(θ)θ1J(θ)⋅⋅⋅θnJ(θ)

    比较难处理的就是 σ ( t ) \sigma(t) σ(t)

    • σ ( t ) = 1 1 + e − t = ( 1 + e − t ) − 1 \sigma(t)=\frac{1}{1+e^{-t}}=(1+e^{-t})^{-1} σ(t)=1+et1=(1+et)1

    σ ( t ) \sigma(t) σ(t) 求导:

    • σ ( t ) ′ = − ( 1 + e − t ) − 2 ⋅ e − t ⋅ ( − 1 ) = ( 1 + e − t ) − 2 ⋅ e − t \sigma(t)'=-(1+e^{-t})^{-2}·e^{-t}·(-1)=(1+e^{-t})^{-2}·e^{-t} σ(t)=(1+et)2et(1)=(1+et)2et

    l o g   σ ( t ) log~\sigma(t) log σ(t) 求导:

    • l o g   σ ( t ) = 1 σ ( t ) ⋅ σ ( t ) ′ = 1 σ ( t ) ⋅ ( 1 + e − t ) − 2 ⋅ e − t log~\sigma(t)=\frac{1}{\sigma(t)}·\sigma(t)'=\frac{1}{\sigma(t)}·(1+e^{-t})^{-2}·e^{-t} log σ(t)=σ(t)1σ(t)=σ(t)1(1+et)2et
    • l o g   σ ( t ) = 1 ( 1 + e − t ) − 1 ⋅ ( 1 + e − t ) − 2 ⋅ e − t log~\sigma(t)=\frac{1}{(1+e^{-t})^{-1}}·(1+e^{-t})^{-2}·e^{-t} log σ(t)=(1+et)11(1+et)2et
    • l o g   σ ( t ) = ( 1 + e − t ) − 1 ⋅ e − t log~\sigma(t)=(1+e^{-t})^{-1}·e^{-t} log σ(t)=(1+et)1et
    • l o g   σ ( t ) = e − t 1 + e − t = 1 + e − t − 1 1 + e − t = 1 − 1 1 + e − t = 1 − σ ( t ) log~\sigma(t)=\frac{e^{-t}}{1+e^{-t}}=\frac{1+e^{-t}-1}{1+e^{-t}}=1-\frac{1}{1+e^{-t}}=1-\sigma(t) log σ(t)=1+etet=1+et1+et1=11+et1=1σ(t)

    成本函数 J J J 分成了俩段,先对前段求导:

    • 前半段求导结果 d ( y i   l o g   σ ( X b i θ ) ) d θ j = y i ( 1 − σ ( X b i θ ) ) ⋅ X j i \frac{d(y_{i}~log~\sigma(X^{i}_{b}\theta))}{d\theta_{j}}=y_{i}(1-\sigma(X^{i}_{b}\theta))·X^{i}_{j} dθjd(yi log σ(Xbiθ))=yi(1σ(Xbiθ))Xji

    对后段求导:

    • l o g ( 1 − σ ( t ) ) ′ = 1 1 − σ ( t ) ⋅ ( − 1 ) ⋅ σ ( t ) ′ = − 1 1 − σ ( t ) ⋅ ( 1 + e − t ) − 2 ⋅ e − t log(1-\sigma(t))'=\frac{1}{1-\sigma(t)}·(-1)·\sigma(t)'=-\frac{1}{1-\sigma(t)}·(1+e^{-t})^{-2}·e^{-t} log(1σ(t))=1σ(t)1(1)σ(t)=1σ(t)1(1+et)2et

    其中: − 1 1 − σ ( t ) = 1 1 + e − t 1 + e − t − 1 1 + e − t = 1 + e − t e − t -\frac{1}{1-\sigma(t)}=\frac{1}{\frac{1+e^{-t}}{1+e^{-t}}-\frac{1}{1+e^{-t}}}=\frac{1+e^{-t}}{e^{-t}} 1σ(t)1=1+et1+et1+et11=et1+et

    代入: l o g ( 1 − σ ( t ) ) ′ = 1 + e − t e − t ⋅ ( 1 + e − t ) − 2 ⋅ e − t = − ( 1 + e − t ) − 1 = − σ ( t ) log(1-\sigma(t))'=\frac{1+e^{-t}}{e^{-t}}·(1+e^{-t})^{-2}·e^{-t}=-(1+e^{-t})^{-1}=-\sigma(t) log(1σ(t))=et1+et(1+et)2et=(1+et)1=σ(t)

    • 后半段的求导结果 d ( 1 − y i )   l o g ( 1 − σ ( X b i θ ) ) d θ j = ( 1 − y i ) ⋅ ( − σ ( X b i θ ) ) ⋅ X j i \frac{d(1-y_{i})~log(1-\sigma(X^{i}_{b}\theta))}{d\theta_{j}}=(1-y_{i})·(-\sigma(X^{i}_{b}\theta))·X^{i}_{j} dθjd(1yi) log(1σ(Xbiθ))=(1yi)(σ(Xbiθ))Xji

    对成本函数 J ( θ ) J(\theta) J(θ) 求导,得先把俩段导数相加:

    • 前半段: y i X j i − y i σ ( X b i θ ) ⋅ X j i y_{i}X^{i}_{j}-y_{i}\sigma(X^{i}_{b}\theta)·X^{i}_{j} yiXjiyiσ(Xbiθ)Xji
    • 后半段: − σ ( X b i θ ) ⋅ X j i + y i σ ( X b i θ ) ⋅ X j i -\sigma(X^{i}_{b}\theta)·X^{i}_{j}+y_{i}\sigma(X^{i}_{b}\theta)·X^{i}_{j} σ(Xbiθ)Xji+yiσ(Xbiθ)Xji

    相加结果:

    • y i X j i − σ ( X b i θ ) ⋅ X j i = ( y i − σ ( X b i θ ) ) ⋅ X j i y_{i}X^{i}_{j}-\sigma(X^{i}_{b}\theta)·X^{i}_{j}=(y_{i}-\sigma(X^{i}_{b}\theta))·X^{i}_{j} yiXjiσ(Xbiθ)Xji=(yiσ(Xbiθ))Xji

    对某个 θ j \theta_{j} θj 求导,消去负号,结合相加结果,得出:

    • J ( θ ) θ j = 1 m ∑ i = 1 m ( σ ( X b i θ ) − y i ) X j i \frac{J(\theta)}{\theta_{j}}=\frac{1}{m}\sum_{i=1}^{m}(\sigma(X^{i}_{b}\theta)-y_{i})X^{i}_{j} θjJ(θ)=m1i=1m(σ(Xbiθ)yi)Xji

    其中的 σ ( X b i θ ) \sigma(X^{i}_{b}\theta) σ(Xbiθ) 就是预测值 p   o r   y ^ p~or~\hat{y} p or y^

    • J ( θ ) θ j = 1 m ∑ i = 1 m ( y i ^ − y i ) X j i \frac{J(\theta)}{\theta_{j}}=\frac{1}{m}\sum_{i=1}^{m}(\hat{y_{i}}-y_{i})X^{i}_{j} θjJ(θ)=m1i=1m(yi^yi)Xji

    要求 Δ J \Delta J ΔJ 的梯度:

    • Δ J ( θ ) = { ∂ J ∂ θ 0 ∂ J ∂ θ 1 ⋅ ⋅ ⋅ ∂ J ∂ θ n } = 1 m ⋅ { ∑ i = 1 m σ ( X b i θ ) − y i ∑ i = 1 m ( σ ( X b i θ ) − y i ) ⋅ X 1 i ⋅ ⋅ ⋅ ∑ i = 1 m ( σ ( X b i θ ) − y i ) ⋅ X n i } = 1 m ⋅ X b T ⋅ ( σ ( X b θ ) − y ) \Delta J(\theta)=
      {Jθ0Jθ1···Jθn}" role="presentation" style="position: relative;">{Jθ0Jθ1···Jθn}
      = \frac{1}{m}·
      {i=1mσ(Xbiθ)yii=1m(σ(Xbiθ)yi)·X1i···i=1m(σ(Xbiθ)yi)·Xni}" role="presentation" style="position: relative;">{i=1mσ(Xbiθ)yii=1m(σ(Xbiθ)yi)·X1i···i=1m(σ(Xbiθ)yi)·Xni}
      =\frac{1}{m}·X^{T}_{b}·(\sigma(X_{b}\theta)-y)
      ΔJ(θ)= θ0Jθ1J⋅⋅⋅θnJ =m1 i=1mσ(Xbiθ)yii=1m(σ(Xbiθ)yi)X1i⋅⋅⋅i=1m(σ(Xbiθ)yi)Xni =m1XbT(σ(Xbθ)y)

     


    解决二分类问题:鸢尾花分类

    编程实现:

    import numpy as np
    from .metrics import accuracy_score
    
    class LogisticRegression:
    
        def __init__(self):
            """初始化Logistic Regression模型"""
            self.coef_ = None
            self.intercept_ = None
            self._theta = None
    
        def _sigmoid(self, t):
            return 1. / (1. + np.exp(-t))
    
        def fit(self, X_train, y_train, eta=0.01, n_iters=1e4):
            """根据训练数据集X_train, y_train, 使用批量-梯度下降法训练Logistic Regression模型"""
            assert X_train.shape[0] == y_train.shape[0], \
                "the size of X_train must be equal to the size of y_train"
    
            def J(theta, X_b, y):
                y_hat = self._sigmoid(X_b.dot(theta))
                try:
                    return - np.sum(y*np.log(y_hat) + (1-y)*np.log(1-y_hat)) / len(y)
                except:
                    return float('inf')
    
            def dJ(theta, X_b, y):
                return X_b.T.dot(self._sigmoid(X_b.dot(theta)) - y) / len(y)
    
            def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
    
                theta = initial_theta
                cur_iter = 0
    
                while cur_iter < n_iters:
                    gradient = dJ(theta, X_b, y)
                    last_theta = theta
                    theta = theta - eta * gradient
                    if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
                        break
    
                    cur_iter += 1
    
                return theta
    
            X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
            initial_theta = np.zeros(X_b.shape[1])
            self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)
    
            self.intercept_ = self._theta[0]
            self.coef_ = self._theta[1:]
    
            return self
    
        def predict_proba(self, X_predict):
            """给定待预测数据集X_predict,返回表示X_predict的结果概率向量"""
            assert self.intercept_ is not None and self.coef_ is not None, \
                "must fit before predict!"
            assert X_predict.shape[1] == len(self.coef_), \
                "the feature number of X_predict must be equal to X_train"
    
            X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
            return self._sigmoid(X_b.dot(self._theta))
    
        def predict(self, X_predict):
            """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
            assert self.intercept_ is not None and self.coef_ is not None, \
                "must fit before predict!"
            assert X_predict.shape[1] == len(self.coef_), \
                "the feature number of X_predict must be equal to X_train"
    
            proba = self.predict_proba(X_predict)
            return np.array(proba >= 0.5, dtype='int')
    
        def score(self, X_test, y_test):
            """根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""
    
            y_predict = self.predict(X_test)
            return accuracy_score(y_test, y_predict)
    
        def __repr__(self):
            return "LogisticRegression()"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

     


    sklearn 调包:

    import numpy as np
    import matplotlib.pyplot as plt
     
    from sklearn.datasets import load_iris                 # 导入鸢尾花数据集
    from sklearn.model_selection import train_test_split   # 导入数据划分函数
    from sklearn.linear_model import LogisticRegression    # 导入逻辑回归
     
    # 导入评价指标
    from sklearn.metrics import accuracy_score   
    
    iris = load_iris()
     
    iris_X = iris.data[:100, ]     # x有4个属性,共有100个样本,鸢尾花的label原本是3类,这里为了展示二分类,我只取了鸢尾花的前100个数据,也就是label只有0和1
    
    iris_y = iris.target[:100, ]   # y的取值有2个,分别是0,1
    
    model = LogisticRegression()   # 选逻辑回归作为分类器
    model.fit(X_train, y_train)    # 训练模型
    
    y_test_pred = model.predict(X=X_test)   # 预测测试集的label
     
    print(y_test_pred)             # 模型预测的测试集label
    print(y_test)                  # 测试集实际label 
    
    accuracy_score(y_test, y_test_pred) # 查看模型预测的准确率
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

     


    解决多分类问题:OvR、OvO

    逻辑回归只能解决二分类的问题,现在我们可以通过 OvR、OvO 实现多分类。

    • OvR:一对剩余所有

    如下图解决四分类问题:

    n n n 个类别就进行 n n n 次分类,选择分类得分最高的。

    from sklearn.multiclass import OneVsRestClassifier
    
    ovr = OneVsRestClassifier(log_reg)
    ovr.fit(X_train, y_train)
    ovr.score(X_test, y_test)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • OvO:一对一

    如下图解决四分类问题:

    n n n 个类别就进行 C ( n ,   2 ) C(n,~2) C(n, 2) 次分类,选择赢数最高的分类。

    from sklearn.multiclass import OneVsOneClassifier
    
    ovo = OneVsOneClassifier(log_reg)
    ovo.fit(X_train, y_train)
    ovo.score(X_test, y_test)
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    vue3:10、组合式API-模板引用和defineExpose宏函数
    STM32F4X RTC
    普冉PY32系列(十一) 基于PY32F002A的6+1通道遥控小车II - 控制篇
    王杰qtday4
    这几个免费、商用图片素材网,你一定要知道。
    Git 学习(二)---- 分支及协作开发
    TensorFlow的GPU使用相关设置整理
    扩展欧几里得算法 | exgcd 证明 + 板子 + 习题
    Leetcode 数据库中等题(day 1)
    替代MySQL半同步复制,Meta技术团队推出MySQL Raft共识引擎
  • 原文地址:https://blog.csdn.net/qq_41739364/article/details/126648708