线性回归

主要内容包括:

  1. 线性回归的基本要素

  2. 线性回归模型从零开始的实现

  3. 线性回归模型使用pytorch的简洁实现

线性回归的基本要素

模型

为了简单起见,这里我们假设价格只取决于房屋状况的两个因素,即面积(平方米)和房龄(年)。接下来我们希望探索价格与这两个因素的具体关系。线性回归假设输出与各个输入之间是线性关系:

数据集

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

损失函数

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

优化函数 - 随机梯度下降

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

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

学习率: 代表在每次优化中,能够学习的步长的大小
批量大小: 是小批量计算中的批量大小batch size

总结一下,优化函数的有以下两个步骤:

  • (i)初始化模型参数,一般来说使用随机初始化;

  • (ii)我们在数据上迭代多次,通过在负梯度方向移动参数来更新每个参数。

矢量计算

在模型训练或预测时,我们常常会同时处理多个数据样本并用到矢量计算。在介绍线性回归的矢量计算表达式之前,让我们先考虑对两个向量相加的两种方法。

  1. 向量相加的一种方法是,将这两个向量按元素逐一做标量加法。

  2. 向量相加的另一种方法是,将这两个向量直接做矢量加法。

import torch
import time# init variable a, b as 1000 dimension vector
n = 1000
a = torch.ones(n)
b = torch.ones(n)
# define a timer class to record time
class Timer(object):"""Record multiple running times."""def __init__(self):self.times = []self.start()def start(self):# start the timerself.start_time = time.time()def stop(self):# stop the timer and record time into a listself.times.append(time.time() - self.start_time)return self.times[-1]def avg(self):# calculate the average and returnreturn sum(self.times)/len(self.times)def sum(self):# return the sum of recorded timereturn sum(self.times)

现在我们可以来测试了。首先将两个向量使用for循环按元素逐一做标量加法。

timer = Timer()
c = torch.zeros(n)
for i in range(n):c[i] = a[i] + b[i]
'%.5f sec' % timer.stop()输出:'0.01232 sec'

另外是使用torch来将两个向量直接做矢量加法:

timer.start()
d = a + b
'%.5f sec' % timer.stop()输出:'0.00029 sec'

结果很明显,后者比前者运算速度更快。因此,我们应该尽可能采用矢量计算,以提升计算效率。

线性回归模型从零开始的实现

# import packages and modules
%matplotlib inline
import torch
from IPython import display
from matplotlib import pyplot as plt
import numpy as np
import randomprint(torch.__version__)输出:1.3.0

生成数据集

使用线性模型来生成数据集,生成一个1000个样本的数据集,下面是用来生成数据的线性关系:

# set input feature number
num_inputs = 2
# set example number
num_examples = 1000# set true weight and bias in order to generate corresponded label
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)

使用图像来展示生成的数据

plt.scatter(features[:, 1].numpy(), labels.numpy(), 1);

features = torch.randn(num_examples, num_inputs,dtype=torch.float32)
print(features)输出:tensor([[ 0.0908, -0.8646],[-1.6370,  1.6305],[-0.1965,  0.8613],...,[-0.9776,  0.0575],[ 1.9371, -0.1497],[-0.1417, -1.0046]])

读取数据集

def data_iter(batch_size, features, labels):num_examples = len(features)indices = list(range(num_examples))random.shuffle(indices)  # random read 10 samplesfor i in range(0, num_examples, batch_size):j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)]) # the last time may be not enough for a whole batchyield  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, '\n', y)break
输出:tensor([[ 1.3591,  0.6950],[ 0.5206, -0.2726],[-0.6639,  0.9716],[ 2.7164, -0.6513],[-1.0642,  1.9331],[-2.2240, -0.3616],[-0.9094,  0.6691],[-0.2991,  0.2488],[ 1.8312,  0.2209],[ 0.2833, -1.1672]]) tensor([6.9694, 6.0005, 9.5797, 0.6944, 4.1964, 6.8519, 2.5178, 4.4217, 5.4679,9.9754])

初始化模型参数

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

训练

当数据集、模型、损失函数和优化函数定义完了之后就可来准备进行模型的训练了。

# super parameters init
lr = 0.03
num_epochs = 5net = linreg
loss = squared_loss# training
for epoch in range(num_epochs):  # training repeats num_epochs times# in each epoch, all the samples in dataset will be used once# X is the feature and y is the label of a batch samplefor X, y in data_iter(batch_size, features, labels):l = loss(net(X, w, b), y).sum()  # calculate the gradient of batch sample loss l.backward()  # using small batch random gradient descent to iter model parameterssgd([w, b], lr, batch_size)  # reset parameter gradientw.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()))输出:epoch 1, loss 7.605014
epoch 2, loss 7.521966
epoch 3, loss 7.550967
epoch 4, loss 7.542496
epoch 5, loss 7.535208

线性回归模型使用pytorch的简洁实现

import torch
from torch import nn
import numpy as np
torch.manual_seed(1)
torch.set_default_tensor_type('torch.FloatTensor')

生成数据集

在这里生成数据集跟从零开始的实现中是完全一样的。

num_examples = 1000true_w = [2, -3.4]
true_b = 4.2features = torch.tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)
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.float)

读取数据集

import torch.utils.data as Databatch_size = 10# combine featues and labels of dataset
dataset = Data.TensorDataset(features, labels)# put dataset into DataLoader
data_iter = Data.DataLoader(dataset=dataset,            # torch TensorDataset formatbatch_size=batch_size,      # mini batch sizeshuffle=True,               # whether shuffle the data or notnum_workers=2,              # read data in multithreading
)
for X, y in data_iter:print(X, '\n', y)break输出:tensor([[ 0.5584, -0.4995],[-0.1495, -1.6520],[-0.3280,  0.2594],[-0.4857, -1.2976],[ 1.8603,  0.4539],[-0.3628,  0.0064],[ 1.3235, -0.3536],[-2.3426, -0.5968],[-0.6290, -0.2948],[-0.0787,  0.2180]]) tensor([7.0088, 9.5071, 2.6718, 7.6535, 6.3802, 3.4601, 8.0475, 1.5223, 3.9682,3.2977])

定义模型

class LinearNet(nn.Module):def __init__(self, n_feature):super(LinearNet, self).__init__()      # call father function to init self.linear = nn.Linear(n_feature, 1)  # function prototype: `torch.nn.Linear(in_features, out_features, bias=True)`def forward(self, x):y = self.linear(x)return ynet = LinearNet(num_inputs)
# ways to init a multilayer network
# method one
net = nn.Sequential(nn.Linear(num_inputs, 1)# other layers can be added here)# method two
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......# method three
from collections import OrderedDict
net = nn.Sequential(OrderedDict([('linear', nn.Linear(num_inputs, 1))# ......]))

初始化模型参数

from torch.nn import initinit.normal_(net[0].weight, mean=0.0, std=0.01)
init.constant_(net[0].bias, val=0.0)  # or you can use `net[0].bias.data.fill_(0)` to modify it directly输出:Parameter containing:
tensor([0.], requires_grad=True)for param in net.parameters():print(param)
输出:Parameter containing:
tensor([[-0.0142, -0.0161]], requires_grad=True)
Parameter containing:
tensor([0.], requires_grad=True)

定义损失函数

loss = nn.MSELoss()    # nn built-in squared loss function# function prototype: `torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')`

定义优化函数

import torch.optim as optimoptimizer = optim.SGD(net.parameters(), lr=0.03)   # built-in random gradient descent function
print(optimizer)  # function prototype: `torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)`
输出:SGD (
Parameter Group 0dampening: 0lr: 0.03momentum: 0nesterov: Falseweight_decay: 0
)

训练

num_epochs = 3
for epoch in range(1, num_epochs + 1):for X, y in data_iter:output = net(X)l = loss(output, y.view(-1, 1))optimizer.zero_grad() # reset gradient, equal to net.zero_grad()l.backward()optimizer.step()print('epoch %d, loss: %f' % (epoch, l.item()))
# result comparision
dense = net[0]
print(true_w, dense.weight.data)
print(true_b, dense.bias.data)输出:epoch 1, loss: 0.000103
epoch 2, loss: 0.000097
epoch 3, loss: 0.000079

从零开始学Pytorch之线性回归相关推荐

  1. 从零开始学Pytorch(零)之安装Pytorch

    本文首发于公众号"计算机视觉cv" Pytorch优势   聊聊为什么使用Pytorch,个人觉得Pytorch比Tensorflow对新手更为友善,而且现在Pytorch在学术界 ...

  2. 从零开始学Pytorch(第5天)

    从零开始学Pytorch(第5天) 前言 一.模块类的构建 1. nn.Module 2.构建一个线性回归类 二.计算图和自动求导机制 1.计算图 2.自动求导 总结 前言 今天主要了解和学习Pyto ...

  3. 从零开始学Pytorch(五)之欠拟合和过拟合

    本文首发于微信公众号"计算机视觉cv" 模型选择.过拟合和欠拟合 训练误差和泛化误差 训练误差(training error)指模型在训练数据集上表现出的误差,泛化误差(gener ...

  4. mpandroidchart y轴从0开始_从零开始学Pytorch(十七)之目标检测基础

    目标检测和边界框 %matplotlib inline from PIL import Imageimport sys sys.path.append('/home/input/') #数据集路径 i ...

  5. 从零开始学Pytorch(十七)之目标检测基础

    目标检测和边界框 %matplotlib inline from PIL import Imageimport sys sys.path.append('/home/input/') #数据集路径 i ...

  6. 建议收藏!从零开始学PyTorch

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:机器学习算法那些事 PyTorch 是一个深度学习框架, ...

  7. 从零开始学Pytorch(十七)之样式分格

    样式迁移 我们介绍如何使用卷积神经网络自动将某图像中的样式应用在另一图像之上,即样式迁移(style transfer).这里我们需要两张输入图像,一张是内容图像,另一张是样式图像,我们将使用神经网络 ...

  8. 从零开始学Pytorch(十六)之模型微调

    微调 在前面的一些章节中,我们介绍了如何在只有6万张图像的Fashion-MNIST训练数据集上训练模型.我们还描述了学术界当下使用最广泛的大规模图像数据集ImageNet,它有超过1,000万的图像 ...

  9. 从零开始学Pytorch(十)之循环神经网络基础

    本节介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型.我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符.循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH ...

最新文章

  1. Android Studio 填坑指南
  2. 【杂谈】Oracle里scott的由来
  3. 问题解决——使用CriticalSection后 0xXXXXXXXX处最可能的异常: 0xC0000005: 写入位置 0x00000014 时发生访问冲突
  4. (转载)The shortest, fastest, and easiest way to compare two tables in SQL Server: UNION
  5. 图解VC++版PE文件解析器源码分析
  6. 跳出小程序 video组件 卡顿、黑屏、全屏等坑
  7. php5.23升级,2018年5月5号23:30分对php的学后感
  8. 最小的linux内核编译,Linux最小内核移植
  9. Struts2.1.6+Spring2.5.6+Hibernate3.3.2+mysql整合+分页模板
  10. java uuid_Java UUID
  11. 经验也有捷径,来看下这些热点、经验、技术等干货应有尽有的公众号吧!
  12. Team Foundation 和 Visual SourceSafe 之间的区别
  13. linux中vi编辑器(转载)
  14. 【二叉树】剑指offer:二叉树中序遍历的下一个节点
  15. 冒泡排序(C#)实现
  16. Linux 磁盘分区及LVM实战演练
  17. 天若OCR文字识别本地版
  18. 大数据分析应用的九大领域
  19. 因果推断what if
  20. 九度OJ—题目1066:字符串排序

热门文章

  1. zabbix邮件脚本报警
  2. 2017-4-20实体类,数据访问类.字符串攻击.防攻击
  3. Ant学习---第一节:Ant安装和简单使用
  4. 【MIT领导力课程笔记】前Nokia 总裁Ollila——打造移动未来
  5. vector数组的使用——机器翻译(洛谷 P1540)
  6. 排序——宇宙总统(洛谷 P1781)
  7. PAT乙级(1030 完美数列)
  8. Oracle坏块处理常用SQL
  9. Oracle 20c数据库开启原生的区块链表、AutoML以及持久化内存支持
  10. 云端之战:Google Cloud 的多云战略和甲骨文的数据库云