• 周华志《机器学习》(西瓜书)习题3.3——python实现对率回归(包含详细推导)


    1. 题目:

    编程实现对率回归,并给出西瓜数据集3.0α上的结果。

    数据集3.0α如下图

    在这里插入图片描述

    2. 对率回归(或逻辑回归)模型简介:

    首先回顾线性回归模型
    y = w T x + b y = \boldsymbol{w^{T}}\boldsymbol{x}+b y=wTx+b
    该模型训练后,最终会找到y与x之间的线性关系。但有些数据并不符合这种线性关系,而是符合g(y)与x是线性关系,这样对数据的要求就降低了,所以衍生出了广义线性回归模型
    y = g − 1 ( w T x + b ) y = g^{-1}(\boldsymbol{w^{T}}\boldsymbol{x}+b) y=g1(wTx+b)
    而上述模型用于回归任务,如果考虑分类任务,我们则要将y看成是样本是正例的可能性,所以要保证预测值最终在0-1之间,所以我们需要将y外面套上一个对数几率函数
    g ( x ) = ln ⁡ x 1 − x g(x) = \ln \frac{x}{1-x} g(x)=ln1xx
    将对数几率函数带入到广义线性回归模型,即可得到对率回归模型
    ln ⁡ y 1 − y = w T x + b \ln \frac{y}{1-y} = \boldsymbol{w^{T}}\boldsymbol{x}+b ln1yy=wTx+b
    也可写成
    y = 1 1 + e − ( w T x + b ) y = \frac{1}{1+e^{-(\boldsymbol{w^{T}}\boldsymbol{x}+b)}} y=1+e(wTx+b)1

    3.如何训练(推导)

    首先,我们需要将y看成是正例的几率,写成p(y=1|x),
    1-y看成是反例的几率,写成p(y=0|x)。带入到对率回归模型(上面那个)当中可以得:
    ln ⁡ p ( y = 1 ∣ x ) p ( y = 0 ∣ x ) = w T x + b \ln \frac{p(y=1|x)}{p(y=0|x)} = \boldsymbol{w^{T}}\boldsymbol{x}+b lnp(y=0x)p(y=1x)=wTx+b
    现在求p(y=1|x)
    ln ⁡ p ( y = 1 ∣ x ) 1 − p ( y = 1 ∣ x ) = w T x + b \ln \frac{p(y=1|x)}{1-p(y=1|x)} = \boldsymbol{w^{T}}\boldsymbol{x}+b ln1p(y=1x)p(y=1x)=wTx+b
    p ( y = 1 ∣ x ) 1 − p ( y = 1 ∣ x ) = e w T x + b \frac{p(y=1|x)}{1-p(y=1|x)} =e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b} 1p(y=1x)p(y=1x)=ewTx+b
    1 1 − p ( y = 1 ∣ x ) − 1 = e w T x + b \frac{1}{1-p(y=1|x)} - 1 =e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b} 1p(y=1x)11=ewTx+b
    p ( y = 1 ∣ x ) = e w T x + b e w T x + b + 1 p(y=1|x) =\frac{e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b} }{e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b}+1 } p(y=1x)=ewTx+b+1ewTx+b
    p(y=0|x):
    p ( y = 0 ∣ x ) = 1 − p ( y = 1 ∣ x ) p(y=0|x) = 1 - p(y=1|x) p(y=0x)=1p(y=1x)
    p ( y = 0 ∣ x ) = 1 e w T x + b + 1 p(y=0|x) = \frac{1 }{e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b}+1 } p(y=0x)=ewTx+b+11
    至此,得到了正例反例的概率分布,现在需要做的就是将wb估计出来,这里就需要用到概率论与数理统计的参数估计知识中的极大似然法。极大似然法适用于分布已知,参数未知的情况,所以这里符合条件。极大似然法要求先找到“对数似然方程l(w,b),流程就是先将每个样本对应的概率得到,然后相乘,再取对数,就可找到对数似然方程,然后找到该函数得极大值点,对应就是w和b得估计值。回到本问题,首先得到对数似然为:
    l ( w , b ) = ∑ i = 1 m ln ⁡ p ( y i ∣ x i ; w , b ) \boldsymbol{l}(\boldsymbol{w},b) = \sum_{i=1}^{m}\ln p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) l(w,b)=i=1mlnp(yixi;w,b)
    然后,在西瓜书中,为方便,规定了符号:
    β = ( w ; b ) \boldsymbol{\beta}=(\boldsymbol{w};b) β=(w;b)
    x ^ = ( x ; 1 ) \boldsymbol{\widehat{x}}=(\boldsymbol{x};1) x =(x;1)
    p 1 ( x ^ ; β ) = p ( y = 1 ∣ x ^ ; β ) p_{1}(\boldsymbol{\widehat{x};\beta})=p(y=1|\boldsymbol{\widehat{x};\beta}) p1(x ;β)=p(y=1x ;β)
    p 0 ( x ^ ; β ) = p ( y = 0 ∣ x ^ ; β ) p_{0}(\boldsymbol{\widehat{x};\beta})=p(y=0|\boldsymbol{\widehat{x};\beta}) p0(x ;β)=p(y=0x ;β)
    则可以对似然项进行重写:
    p ( y i ∣ x i ; w , b ) = y i p 1 ( x ^ i ; β ) + ( y i − 1 ) p 0 ( x ^ i ; β ) p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) = y_{i}p_{1}(\boldsymbol{\widehat{x}_{i};\beta})+(y_{i}-1)p_{0}(\boldsymbol{\widehat{x}_{i};\beta}) p(yixi;w,b)=yip1(x i;β)+(yi1)p0(x i;β)
    可以看到,在训练过程中,y只会取0和1,在y=1时,只有前一项有效,y=0时,只有后一项有效。
    然后,对
    p ( y = 1 ∣ x ) = e w T x + b e w T x + b + 1 p(y=1|x) =\frac{e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b} }{e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b}+1 } p(y=1x)=ewTx+b+1ewTx+b

    p ( y = 0 ∣ x ) = 1 e w T x + b + 1 p(y=0|x) = \frac{1 }{e^{ \boldsymbol{w^{T}}\boldsymbol{x}+b}+1 } p(y=0x)=ewTx+b+11
    进行重写得:
    p 1 ( x ^ ; β ) = e β T x ^ e β T x ^ + 1 p_{1}(\boldsymbol{\widehat{x};\beta}) =\frac{e^{\beta^{T}\widehat{x}} }{e^{\beta^{T}\widehat{x}}+1 } p1(x ;β)=eβTx +1eβTx

    p 0 ( x ^ ; β ) = 1 e β T x ^ + 1 p_{0}(\boldsymbol{\widehat{x};\beta}) =\frac{1}{e^{\beta^{T}\widehat{x}}+1 } p0(x ;β)=eβTx +11
    然后,将这两个式子带入到似然项中:
    p ( y i ∣ x i ; w , b ) = y i e β T x ^ i e β T x ^ i + 1 + ( 1 − y i ) 1 e β T x ^ i + 1 p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) = y_{i}\frac{e^{\beta^{T}\widehat{x}_{i}} }{e^{\beta^{T}\widehat{x}_{i}}+1 }+(1-y_{i})\frac{1}{e^{\beta^{T}\widehat{x}_{i}}+1 } p(yixi;w,b)=yieβTx i+1eβTx i+(1yi)eβTx i+11
    两边取ln,得
    ln ⁡ p ( y i ∣ x i ; w , b ) = ln ⁡ [ y i e β T x ^ i e β T x ^ i + 1 + ( 1 − y i ) 1 e β T x ^ i + 1 ] \ln p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) =\ln[ y_{i}\frac{e^{\beta^{T}\widehat{x}_{i}} }{e^{\beta^{T}\widehat{x}_{i}}+1 }+(1-y_{i})\frac{1}{e^{\beta^{T}\widehat{x}_{i}}+1 }] lnp(yixi;w,b)=ln[yieβTx i+1eβTx i+(1yi)eβTx i+11]
    当yi = 1时:
    ln ⁡ p ( y i ∣ x i ; w , b ) = ln ⁡ e β T x ^ i e β T x ^ i + 1 = β T x ^ i − ln ⁡ ( e β T x ^ i + 1 ) \ln p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) =\ln \frac{e^{\beta^{T}\widehat{x}_{i}} }{e^{\beta^{T}\widehat{x}_{i}}+1 }= \beta^{T}\widehat{x}_{i}-\ln(e^{\beta^{T}\widehat{x}_{i}}+1) lnp(yixi;w,b)=lneβTx i+1eβTx i=βTx iln(eβTx i+1)
    当yi = 0时:
    ln ⁡ p ( y i ∣ x i ; w , b ) = ln ⁡ 1 e β T x ^ i + 1 = − ln ⁡ ( e β T x ^ i + 1 ) \ln p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) =\ln \frac{1}{e^{\beta^{T}\widehat{x}_{i}}+1 }= -\ln(e^{\beta^{T}\widehat{x}_{i}}+1) lnp(yixi;w,b)=lneβTx i+11=ln(eβTx i+1)
    结合两个情况,可以看到,区别在于 β T x ^ i \beta^{T}\widehat{x}_{i} βTx i项,所以可以在该项前面加上yi,得到最终为:
    ln ⁡ p ( y i ∣ x i ; w , b ) = y i β T x ^ i − ln ⁡ ( e β T x ^ i + 1 ) \ln p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) = y_{i}\beta^{T}\widehat{x}_{i}-\ln(e^{\beta^{T}\widehat{x}_{i}}+1) lnp(yixi;w,b)=yiβTx iln(eβTx i+1)
    可以看到,当yi=1时,第一项有效,当yi=0时,第一项无效。

    然后,我们将上述推导的 ln ⁡ p ( y i ∣ x i ; w , b ) \ln p(y_{i}|\boldsymbol{x_{i}};\boldsymbol{w},b) lnp(yixi;w,b)放回对数似然方程中(为看方便,截个图放这儿)对数似然方程
    可以得到:
    l ( β ) = ∑ i = 1 m [ y i β T x ^ i − ln ⁡ ( e β T x ^ i + 1 ) ] \boldsymbol{l}(\boldsymbol{\beta}) = \sum_{i=1}^{m}[y_{i}\beta^{T}\widehat{x}_{i}-\ln(e^{\beta^{T}\widehat{x}_{i}}+1)] l(β)=i=1m[yiβTx iln(eβTx i+1)]
    现在,我们完成了对数似然方程的构造,按照极大似然法的流程,接下来只需要最大化“对数似然” l ( β ) \boldsymbol{l}(\boldsymbol{\beta}) l(β),就可得到w和b的估计值。但是,出于对机器学习中一般习惯于“最小化”(例如最小化损失函数),所以这里我们将 l ( β ) \boldsymbol{l}(\boldsymbol{\beta}) l(β)取个相反数得到 l ′ ( β ) \boldsymbol{l{}'}(\boldsymbol{\beta}) l(β)
    l ′ ( β ) = ∑ i = 1 m [ − y i β T x ^ i + ln ⁡ ( e β T x ^ i + 1 ) ] \boldsymbol{l{}'}(\boldsymbol{\beta}) = \sum_{i=1}^{m}[-y_{i}\beta^{T}\widehat{x}_{i}+\ln(e^{\beta^{T}\widehat{x}_{i}}+1)] l(β)=i=1m[yiβTx i+ln(eβTx i+1)]
    那么最大化 l ( β ) \boldsymbol{l}(\boldsymbol{\beta}) l(β)其实就等同于最小化 l ′ ( β ) \boldsymbol{l{}'}(\boldsymbol{\beta}) l(β)
    至此,就可以使用梯度下降法,找到 l ′ ( β ) \boldsymbol{l{}'}(\boldsymbol{\beta}) l(β)的极小点。对其梯度下降法总结起来就是一个公式:
    β t + 1 = β t − s ∂ l ′ ( β ) ∂ β \boldsymbol{\beta} ^{t+1}=\boldsymbol{\beta} ^{t}-s\frac{\partial \boldsymbol{l{}'}(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} βt+1=βtsβl(β)
    其中 ∂ l ′ ( β ) ∂ β \frac{\partial \boldsymbol{l{}'}(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} βl(β)为:
    ∂ l ′ ( β ) ∂ β = − ∑ i = 1 m x ^ i ( y i − p 1 ( x ^ i ; β ) ) \frac{\partial \boldsymbol{l{}'}(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}}=-\sum_{i=1}^{m}\boldsymbol{\widehat{x}_{i}}(y_{i}-p_{1}(\boldsymbol{\widehat{x}_{i}};\boldsymbol{\beta})) βl(β)=i=1mx i(yip1(x i;β))
    s是步长, ∂ l ′ ( β ) ∂ β \frac{\partial \boldsymbol{l{}'}(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} βl(β)为梯度,每次下降按照梯度方向移动s单位,就可逐渐靠近极小点。找到极小点后,对应的 β \beta β就是训练结果。

    4.代码实现(python)

    import numpy as np
    import openpyxl
    import matplotlib.pyplot as plt
    from matplotlib import cm
    
    def sigmoid(x):
        return 1 / (1 + np.exp(-x))
        
    def init_xy():
        sheet1 = openpyxl.load_workbook('./xigua3.0.xlsx')['Sheet1']
        x = np.zeros((2,17))
        y = np.zeros((1,17))
        for i in range(17):
            x[0][i] = sheet1[chr(ord('A')+i)+'1'].value
        for i in range(17):
            x[1][i] = sheet1[chr(ord('A')+i)+'2'].value
        for i in range(17):
            y[0][i] = sheet1[chr(ord('A')+i)+'3'].value
        return x.T, y.T
        
    def function_p1(x_hat, b):
        a = np.math.exp(np.dot(np.transpose(b), x_hat))
        return a / (1+a)
        
    def function_p2(x, b):
        return 1 - function_p1(x, b)
    
    def train():
        x,y = init_xy()
        b = np.ones((3,1))
        dl_sub = 0
        train_n = 2000
        step_size = 0.1
        
        for step in range(train_n):
            dl = 0
            for i in range(17):
                x_t = x[i]
                x_hat = np.append(x_t, 1)
                x_hat = x_hat.reshape(3,1)
                dl_sub = np.dot(x_hat, y[i][0] - function_p1(x_hat, b))
                dl += dl_sub
            b = b + step_size * dl
        return b
    
    def test(x, y, b):
        right = 0
        for i in range(17):  
            x_hat = np.append(x[i], 1)
            y_pre = sigmoid(np.dot(b.T, x_hat))
            if (y_pre >= 0.5 and y[i] == 1) or (y_pre < 0.5 and y[i] == 0):
                right += 1
                
        print("正确率为:", right/17)
    
    b = train()
    x,y = init_xy()
    test(x, y, b)
    
    • 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

    4.运行结果

    在这里插入图片描述

  • 相关阅读:
    识不足则多虑,威不足则多怒,信不足则多言
    初识JavaScript
    【C语言】多进程服务器
    一文带你深入理解 AQS
    【华为OD机试真题 python】 冠亚军排名【2022 Q4 | 100分】
    JAVA--枚举类
    网络运维的重要性
    可视化—gojs 超多超实用经验分享(三)
    Spring之事务实现原理及其注解@Transactional底层和传播机制原理
    一个Android应用层开发如何转型深入Android Framework?
  • 原文地址:https://blog.csdn.net/qq_43038891/article/details/125549004