LR(logistic regression)逻辑回归Loss和梯度的推导及与Linear Regression的区别

Logistic regression和Linear Regression的区别

  • 预测目标不同:Logistic regression预测一个概率,例如二分类,是或者否;Linear Regression预测连续值,例如房价
  • 输出前处理不同:Logistic regression要过一下sigmoid;Linear Regression模型输出就是预测值
  • loss函数不同:Logistic regression用的是CE;Linear Regression用的是MSE

上个Pytorch代码

LinearRegressionModel的代码

import torch.nn as nn
import torch

class LinearRegressionModel(nn.Module):
    def __init__(self, in_features, out_features):
        super(LinearRegressionModel, self).__init__()
        self.fc = nn.Linear(in_features, out_features)
    def forward(self, input):
        output = self.fc(input)
        return output

if __name__ == '__main__':
    
    in_features,out_features = 1,1
    bs = 100
    model = LinearRegressionModel(in_features,out_features)
    optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
    input = torch.unsqueeze(torch.linspace(-1, 1, bs), dim=1)
    target = 2*input + 1 + 0.2*torch.rand(input.size())
    epoch = 1000
    for i in range(epoch):
        optimizer.zero_grad()
        output = model(input)
        loss = nn.MSELoss()(output, target)
        loss.backward()
        print('loss = {}'.format(loss))
        optimizer.step()

Logistics Regression的代码(使用CE Loss)

再来一份Logistic Regression的code,注意由于是CrossEntropy的要求,out_features必须得是2才行:

import torch.nn as nn
import torch

class LogisticsRegressionModel(nn.Module):
    def __init__(self, in_features, out_features):
        super(LogisticsRegressionModel, self).__init__()
        self.fc = nn.Linear(in_features, out_features)
        
    def forward(self, input):
        output = nn.Sigmoid()(self.fc(input))
        return output

if __name__ == '__main__':
    
    in_features,out_features = 1,1
    bs = 100
    model = LogisticsRegressionModel(in_features,out_features)
    optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

    x0 = torch.randn((bs,1))+1
    y0 = torch.zeros(bs)
    x1 = torch.randn((bs,1))-1
    y1 = torch.ones(bs)
    input = torch.cat((x0, x1), dim=0)
    target = torch.cat((y0, y1), dim=0).long()
    epoch = 1000
    for i in range(epoch):
        optimizer.zero_grad()
        output0 = model(input)
        output1 = 1-output0
        output = torch.concat([output0, output1], dim=1)
        loss = nn.CrossEntropyLoss()(output, target)
        loss.backward()
        print('loss = {}'.format(loss))
        optimizer.step()

Logistics Regression的代码(使用BCE Loss)

注意target在这里是float:

import torch.nn as nn
import torch

class LogisticsRegressionModel(nn.Module):
    def __init__(self, in_features, out_features):
        super(LogisticsRegressionModel, self).__init__()
        self.fc = nn.Linear(in_features, out_features)
        
    def forward(self, input):
        output = nn.Sigmoid()(self.fc(input))
        return output

if __name__ == '__main__':
    
    in_features,out_features = 1,1
    bs = 100
    model = LogisticsRegressionModel(in_features,out_features)
    optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

    x0 = torch.randn((bs,1))+1
    y0 = torch.zeros(bs)
    x1 = torch.randn((bs,1))-1
    y1 = torch.ones(bs)
    input = torch.cat((x0, x1), dim=0)
    target = torch.cat((y0, y1), dim=0).float()  
    epoch = 1000
    for i in range(epoch):
        optimizer.zero_grad()
        output = model(input)
        loss = nn.BCELoss()(output, target.view(-1,1))
        
        loss.backward()
        print('loss = {}'.format(loss))
        optimizer.step()

logistic regression的推导

逻辑斯蒂回归的先验分布是伯努利分布,softmax的先验分布是多项式分布

LR太简单了,简单到经常被用,但是很多推导仍然迷糊的程度,这篇主要用来总结一下。

线性回归的表达式:
f(x)=wTx+bf(x)=w^Tx+bf(x)=wTx+b
由于带一个b,我们可以令x′=[1,x]Tx'=[1, x]^Tx=[1,x]T,同时w′=[b,w]Tw'=[b, w]^Tw=[b,w]T,这样直线方程就可以简化成
f′(x)=w′Txf'(x)=w^{'T}xf(x)=wTx
所以,当有m组训练数据,n维features时,一会儿得到的梯度是n+1维,接下来推梯度,先得推导一下loss function。由于线性回归结果是个实数,为了让他属于(0,1)之间,给它过一个sigmoid。如果是多分类,最后接Softmax。假设有一组样本(x1,y1),(x2,y2)...(xn,yn)(x_1,y_1),(x_2,y_2)...(x_n,y_n)(x1,y1),(x2,y2)...(xn,yn),针对2分类的情况,yn=0或1y_n=0或1yn=01,给定xix_ixi的情况下,yiy_iyi是1的概率是pi=11+exp(−wxi)p_i=\frac{1}{1+exp(-wx_i)}pi=1+exp(wxi)1,loss function利用了最大似然的想法:
L=ln[∏i=1npiyi(1−pi)(1−yi)]L=∑i[yilnpi+(1−yi)ln(1−pi)]obj=arg max⁡wL(w)当然可以改成obj=arg min⁡w−L(w)所以L=−∑i[yilnpi+(1−yi)ln(1−pi)]L=ln[\prod_{i=1}^np_i^{y_i}(1-p_i)^{(1-y_i)}] \\ L=\sum_i[{y_ilnp_i+(1-y_i)ln(1-p_i)]} \\ obj = \argmax_w{L(w)} \\ 当然可以改成 obj = \argmin_w{-L(w)} \\ 所以 \\ L=-\sum_i[{y_ilnp_i+(1-y_i)ln(1-p_i)]} L=ln[i=1npiyi(1pi)(1yi)]L=i[yilnpi+(1yi)ln(1pi)]obj=wargmaxL(w)当然可以改成obj=wargminL(w)所以L=i[yilnpi+(1yi)ln(1pi)]
接下来开始求梯度,注意∂pi∂wi=pi(1−pi)xi\frac{\partial p_i}{\partial w_i} = p_i(1-p_i)x_iwipi=pi(1pi)xi
∂L∂w=−∑i=1nxi(yi−pi)\frac{\partial L}{\partial w}=-\sum_{i=1}^nx_i(y_i-p_i)wL=i=1nxi(yipi)

最后用Adam求解就可以

另外一个问题是LR是不是凸函数,当然是,因为二阶Hessian矩阵>=0,下面我们求一下二阶导数:
∂2L∂2w=−∑i=1npi(1−pi)xixiT>=0\frac{\partial^2 L}{\partial^2 w}=-\sum_{i=1}^np_i(1-p_i)x_ix_i^T >= 02w2L=i=1npi(1pi)xixiT>=0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值