线性回归的原理及实现

1.回归问题的定义

在实现线性回归之前,我们先搞清楚什么是回归。通常在生活中遇到的问题我们可以将其分为两类,一种是回归问题,一种是分类问题。

所谓回归是指将输入变量(X)的映射函数(f)近似为连续输出变量(y)的任务。连续输出变量是实数值,例如整数或浮点值。这些通常是数量,例如数量和大小。比如我们经常遇到的预测房屋价格、气温、销售额等连续值的问题。常用的回归模型如本篇介绍的线性回归。

所谓分类是指找一个函数判断输入数据所属的类别,可以是二类别问题(是/不是),也可以是多类别问题(在多个类别中判断输入数据具体属于哪一个类别)。与回归问题(regression)相比,分类问题的输出不再是连续值,而是离散值,用来指定其属于哪个类别。softmax回归模型可以用来解决分类问题(虽然称其为softmax回归但实际解决的是分类问题)。

2.线性回归的理论推导过程

2.1问题简述

我们以一个简单的房屋价格预测作为例子来解释线性回归的基本概念。这个应用的目标是预测一栋房子的售出价格(元)。我们知道这个价格取决于很多因素,如房屋状况、地段、市场行情等。为了简单起见,这里我们假设价格只取决于房屋状况的两个因素,即面积(平方米)和房龄(年)。接下来我们希望探索价格与这两个因素的具体关系。

2.2模型定义

设房屋的面积为x1,房龄为x2,售出价格为y。我们需要建立基于输入x1和x2来计算输出y的表达式,也就是模型(model)。顾名思义,线性回归假设输出与各个输入之间是线性关系:
在这里插入图片描述
其中w1和w2是权重(weight),b是偏差(bias),且均为标量。它们是线性回归模型的参数(parameter)。模型输出y^是线性回归对真实价格y的预测或估计。我们通常允许它们之间有一定误差。

我们最终的期望即通过大量的输入数据(x1,x2)推导出w1,w2,b,此时所得结果y^与真实结果y符合性最好。而后可根据已知系数w1,w2,b和输入数据x1,x2来预测结果y

2.3模型训练

模型训练(model training):通过数据来寻找特定的模型参数值,使模型在数据上的误差尽可能小。(即寻找预测结果y^与真实结果y符合性最好的参数

2.3.1训练数据集

我们通常收集一系列的真实数据,例如多栋房屋的真实售出价格和它们对应的面积和房龄。我们希望在这个数据上面寻找模型参数来使模型的预测价格与真实价格的误差最小。在机器学习术语里,该数据集被称为训练数据集(training data set)或训练集(training set),一栋房屋被称为一个样本(sample),其真实售出价格叫作标签(label),用来预测标签的两个因素叫作特征(feature)。特征用来表征样本的特点。

假设我们采集的样本数为n,索引为i的样本的特征为x(i)1和x(i)2,标签为y(i)。对于索引为ii的房屋,线性回归模型的房屋价格预测表达式为
在这里插入图片描述

2.3.2损失函数

在模型训练中,我们需要衡量价格预测值与真实值之间的误差。通常我们会选取一个非负数作为误差,且数值越小表示误差越小。一个常用的选择是平方函数。它在评估索引为i的样本误差的表达式为
在这里插入图片描述

其中常数1/2使对平方项求导后的常数系数为1,这样在形式上稍微简单一些。显然,误差越小表示预测价格与真实价格越相近,且当二者相等时误差为0。给定训练数据集,这个误差只与模型参数相关,因此我们将它记为以模型参数为参数的函数。在机器学习里,将衡量误差的函数称为损失函数(loss function)。这里使用的平方误差函数也称为平方损失(square loss)。通常,我们用训练数据集中所有样本误差的平均来衡量模型预测的质量,即在这里插入图片描述

在模型训练中,我们希望找出一组模型参数,记为w∗1,w∗2,b∗w1∗,w2∗,b∗

,来使训练样本平均损失最小:
在这里插入图片描述

2.3.3优化算法

当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analyticalsolution)。本节使用的线性回归和平方误差刚好属于这个范畴。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numericalsolution)。

在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic
gradientdescent)在深度学习中被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch)BB,然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积作为模型参数在本次迭代的减小量。

在训练本节讨论的线性回归模型的过程中,模型的每个参数将作如下迭代:
在这里插入图片描述
在上式中,|B|代表每个小批量中的样本个数(批量大小,batch_size),η称作学习率(learningrate)并取正数。需要强调的是,这里的批量大小和学习率的值是人为设定的,并不是通过模型训练学出的,因此叫作超参数(hyperparameter)。我们通常所说的“调参”指的正是调节超参数,例如通过反复试错来找到超参数合适的值。

2.4模型预测

模型训练完成后,我们将模型参数w1,w2,bw1,w2,b在优化算法停止时的值分别记作w1^ w2^ b^ 。注意,这里我们得到的并不一定是最小化损失函数的最优解w∗1,w∗2,b∗w1∗,w2∗,b∗,而是对最优解的一个近似。然后,我们就可以使用学出的线性回归模型 x1w1^ + x2w2^ +b^ 来估算训练数据集以外任意一栋面积(平方米)为x1、房龄(年)为x2的房屋的价格了。这里的估算也叫作模型预测、模型推断或模型测试。

2.5线性回归的神经网络图

在深度学习中,我们可以使用神经网络图直观地表现模型结构。为了更清晰地展示线性回归作为神经网络的结构,使用神经网络图表示本节中介绍的线性回归模型。神经网络图隐去了模型参数权重和偏差。

在这里插入图片描述

在图3.1所示的神经网络中,输入分别为x1和x2,因此输入层的输入个数为2。输入个数也叫特征数或特征向量维度。图3.1中网络的输出为o,输出层的输出个数为1。需要注意的是,我们直接将图3.1中神经网络的输出o作为线性回归的输出。由于输入层并不涉及计算,按照惯例,图示的神经网络的层数为1。所以,线性回归是一个单层神经网络。输出层中负责计算oo的单元又叫神经元。在线性回归中,o的计算依赖于x1和x2。也就是说,输出层中的神经元和输入层中各个输入完全连接。因此,这里的输出层又叫全连接层(fully-connectedlayer)或稠密层(dense layer)。

2.6矢量计算表达式

向量相加的一种方法是,将这两个向量按元素逐一做标量加法。向量相加的另一种方法是,将这两个向量直接做矢量加法。实验证明后者在计算时更省时。因此,我们应该尽可能采用矢量计算,以提升计算效率。

让我们再次回到本节的房价预测问题。如果我们对训练数据集里的3个房屋样本(索引分别为1、2和3)逐一预测价格,将得到
在这里插入图片描述
现在,我们将上面3个等式转化成矢量计算。设
在这里插入图片描述

对3个房屋样本预测价格的矢量计算表达式为
在这里插入图片描述
其中的加法运算使用了广播机制

在这里插入图片描述

3.线性回归的代码实现(pytorch版本)

#author Simon
#data 20200411
import torch
import numpy as np
import random

#生产数据集
num_inputs = 2             #设输入参数个数为2
num_examples = 1000        #设训练数据样本集为1000
true_w = [2,-3.4]          #设定真实参数值 以对比模型所得出的参数
true_b = 4.2features = torch.randn(num_examples,num_inputs,dtype=torch.float32)      #从标准正太分布中抽取一组随机数
labels = true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b
labels+=torch.tensor(np.random.normal(0,0.01,size=labels.size()),dtype=torch.float32)  #设置白噪声项(均值为0 标准差为0.01的正太分布) 代表了数据集中无意义的干扰

print(features[0],labels[0])

#读取数据
def data_iter(batch_size,features,labels):                   
    num_examples=len(features)    
    indices=list(range(num_examples))    
    random.shuffle(indices)    
    for i in range(0,num_examples,batch_size):     
        j=torch.LongTensor(indices[i:min(i+batch_size,num_examples)])            
        yield features.index_select(0,j),labels.index_select(0,j)

batch_size=10
for X,y in data_iter(batch_size,features,labels):    
    print(X,y)    
    break
    
#初始化模型参数
w=torch.tensor(np.random.normal(0,0.01(num_inputs,1)),dtype=torch.float32)
b=torch.zeros(1,dtype=torch.float32)
w.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True)
#定义模型
def linreg(X,w,b):                    
    return torch.mm(X,w)+b
#定义损失函数
def squared_loss(y_hat,y):    
    return(y_hat-y.view(y_hat.size()))**2/2
#定义优化算法
def sgd(params,lr,batch_size):    
    for param in params:        
    param.data-=lr*param.grad/batch_size
    
#训练模型
lr=0.03
num_epochs=5
net=linreg
loss=squared_loss
for epoch in range(num_epochs):    
    for X,y in data_iter(batch_size,features,labels):
        l=loss(net(X,w,b),y).sum()        
        l.backward()        
        sgd([w,b],lr,batch_size)       
        w.grad.data.zero_()        
        b.grad.data.zero_()    
        train_l=loss(net(features,w,b),labels)    
     print('epoch %d,loss %f'%(epoch+1,train_l.mean().item()))
     
print(true_w,'\n',w)
print(true_b,'\n',b)



程序运行结果:
在这里插入图片描述

参考链接:
http://zh.d2l.ai/chapter_deep-learning-basics/linear-regression.html
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/code/chapter03_DL-basics/3.2_linear-regression-scratch.ipynb

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值