1. 线性回归

1.1 线性模型

当输入包含d个特征,预测结果表示为:

    

x为样本的特征向量,w为权重向量,上式可表示为:

    

对于含有n个样本的数据集,可用X来表示n个样本的特征集合,其中行代表样本,列代表特征,那么预测值可用矩阵乘法表示为:

    

给定训练数据特征X和对应的已知标签y,线性回归的⽬标是找到⼀组权重向量w和偏置b:当给定从X的同分布中取样的新样本特征时,这组权重向量和偏置能够使得新样本预测标签的误差尽可能小。

1.2 损失函数(loss function)

损失函数又称代价函数(cost function),通常用其来度量目标的实际值和预测值之间的误差。在回归问题中,常用的损失函数为平方误差函数:

    

     

我们的目标便是求得最小化损失函数下参数w和b的值:

    

    求解上式,一般有以下两种方式:

 1> 正规方程(解析解)

    

2> 梯度下降(gradient descent)

(1)初始化模型参数的值,如随机初始化;

(2)从数据集中随机抽取小批量样本且在负梯度的方向上更新参数,并不断迭代这一步骤。

    

上式中:n表示每个小批量中的样本数,也称批量大小(batch size)、α表示学习率(learning rate),n和α的值需要手动预先指定,而不是模型训练得到的,这类参数称为超参数(hyperparameter),选择超参数的过程称为调参(hyperparameter tuning)。

梯度下降和正规方程比较:

 

1.3 矢量化加速

为了加快模型训练速度,可以采用矢量化计算的方式,这通常会带来数量级的加速。下边用代码简单对比测试下矢量化计算的加速效果。

import math
import time
import numpy as np
import torch
from d2l import torch as d2l # a、b是全为1的10000维向量
n = 10000
a = torch.ones(n)
b = torch.ones(n) class Timer:
def __init__(self):
"""记录多次运行时间"""
self.tik = None
self.times = []
self.start() def start(self):
"""启动计时器"""
self.tik = time.time() def stop(self):
"""停止计时器并将时间记录在列表中"""
self.times.append(time.time() - self.tik)
return self.times[-1] def avg(self):
"""返回平均时间"""
return sum(self.times) / len(self.times) def sum(self):
"""返回总时间"""
return sum(self.times) def cumsum(self):
"""返回总时间"""
return np.array(self.times).cumsum().tolist() c = torch.zeros(n)
timer = Timer()
for i in range(n):
c[i] = a[i] + b[i]
print(f'{timer.stop():.5f} sec') timer.start()
d = a + b
print(f'{timer.stop():.5f} sec')  

代码运行结果如下,可见矢量化代码确实极大的提高了计算速度。

    注:这里矢量化计算d=a+b的时间不知道为什么统计出来是0,可能是跟电脑的计时器精度有关。

2. 从零实现线性回归

线性回归的实现过程可以简单总结为以下几个步骤:

(1)读取数据(或构造数据),转换成需要的格式和类型,并生成标签 ;

(2)定义初始化模型参数、定义模型、定义损失函数、定义优化算法;

(3)使用优化算法训练模型。

import random
import torch
import numpy as np
from matplotlib import pyplot as plt
from d2l import torch as d2l # 构造数据集
def synthetic_data(w, b, num_examples):
"""生成 y = Xw + b + 噪声。"""
# 均值为0,方差为1的随机数,行数为样本数,列数是w的长度(行代表样本,列代表特征)
X = torch.normal(0, 1, (num_examples, len(w))) # pytorch较新版本
# X = torch.tensor(np.random.normal(0, 1, (num_examples, len(w))), dtype=torch.float32) # pytorch1.1.0版本
y = torch.matmul(X, w) + b
# 均值为0,方差为1的随机数,噪声项。
y += torch.normal(0, 0.01, y.shape) # pytorch较新版本
# y += torch.tensor(np.random.normal(0, 0.01, y.shape), dtype=torch.float32) # pytorch1.1.0版本
return X, y.reshape((-1, 1)) true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features:', features[0], '\nlabel:', labels[0]) d2l.set_figsize()
d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1) # 生成一个data_iter函数,该函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为batch_size的小批量
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):
batch_indices = torch.tensor(indices[i:min(i+batch_size, num_examples)])
yield features[batch_indices], labels[batch_indices] batch_size = 10
for X, y in data_iter(batch_size, features, labels):
print(X, '\n', y)
break # 定义初始化模型参数
w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True) # pytorch较新版本
# w = torch.autograd.Variable(torch.tensor(np.random.normal(0, 0.01, size=(2, 1)),
# dtype=torch.float32), requires_grad=True) # pytorch1.1.0版本
b = torch.zeros(1, requires_grad=True) # 定义模型
def linreg(X, w, b):
"""线性回归模型。"""
return torch.matmul(X, w) + b # 定义损失函数
def squared_loss(y_hat, y):
"""均方损失。"""
return (y_hat - y.reshape(y_hat.shape))**2 / 2 # 定义优化算法
def sgd(params, lr, batch_size):
"""小批量随机梯度下降"""
with torch.no_grad():
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_() # 训练过程
lr = 0.03
num_epochs = 3
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) # X和y的小批量损失
# 因为l形状是(batch_size, 1),而不是一个标量。l中的所有元素被加到一起并以此来计算关于[w, b]的梯度
l.sum().backward()
sgd([w, b], lr, batch_size) # 使用参数的梯度更新参数
with torch.no_grad():
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}') print(f'w的估计误差:{true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差:{true_b - b}') 

3. 使用深度学习框架(PyTorch)实现线性回归

使用PyTorch封装的高级API可以快速高效的实现线性回归

import numpy as np
import torch
from torch import nn # 'nn'是神经网路的缩写
from torch.utils import data
from d2l import torch as d2l # 构造数据集
def synthetic_data(w, b, num_examples):
"""生成 y = Xw + b + 噪声。"""
# 均值为0,方差为1的随机数,行数为样本数,列数是w的长度(行代表样本,列代表特征)
X = torch.normal(0, 1, (num_examples, len(w))) # pytorch较新版本
# X = torch.tensor(np.random.normal(0, 1, (num_examples, len(w))), dtype=torch.float32) # pytorch1.1.0版本
y = torch.matmul(X, w) + b
# 均值为0,方差为1的随机数,噪声项。
y += torch.normal(0, 0.01, y.shape) # pytorch较新版本
# y += torch.tensor(np.random.normal(0, 0.01, y.shape), dtype=torch.float32) # pytorch1.1.0版本
return X, y.reshape((-1, 1)) true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000) d2l.set_figsize()
d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1) # 调用框架中现有的API来读取数据
def load_array(data_arrays, batch_size, is_train=True):
"""构造一个PyTorch数据迭代器"""
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size, shuffle=is_train) batch_size = 10
data_iter = load_array((features, labels), batch_size) print(next(iter(data_iter))) # 使用框架预定义好的层
net = nn.Sequential(nn.Linear(2, 1)) # 初始化模型参数(等价于前边手动实现w、b以及network的方式)
net[0].weight.data.normal_(0, 0.01) # 使用正态分布替换掉w的值
net[0].bias.data.fill_(0) # 计算均方误差使用MSELoss类,也称为平方L2范数
loss = nn.MSELoss() # 实例化SGD实例
trainer = torch.optim.SGD(net.parameters(), lr=0.03) # 训练
num_epochs = 3 # 迭代三个周期
for epoch in range(num_epochs):
for X, y in data_iter:
l = loss(net(X), y)
trainer.zero_grad() # 优化器,先将梯度清零
l.backward()
trainer.step() # 模型更新
l = loss(net(features), labels)
print(f'epoch {epoch + 1}, loss {l:f}') w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)

4. 报错总结

1. torch.normal()报错,这个是由于PyTorch版本问题,torch.normal()函数的参数形式和用法有所变化。

要生成均值为0且方差为1的随机数,pytorch1.1.0和pytorch1.9.0可以分别采用以下形式:

# pytorch1.9.0
X = torch.normal(0, 1, (num_examples, len(w)))
# pytorch1.1.0(也适用于高版本)
X = torch.tensor(np.random.normal(0, 1, (num_examples, len(w))), dtype=torch.float32)

2. d2l库安装报错。这个我在公司电脑上直接一行pip install d2l成功安装,回家换自己电脑,各种报错。解决之后发现大多都是找不到安装源、缺少相关库或者库版本不兼容的问题。

安装方式:conda install d2l 或 pip install d2l。网速太慢下不下来可以选择国内源镜像:

pip install d2l -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

国内常用源镜像:

# 清华:https://pypi.tuna.tsinghua.edu.cn/simple
# 阿里云:http://mirrors.aliyun.com/pypi/simple/
# 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
# 华中理工大学:http://pypi.hustunique.com/
# 山东理工大学:http://pypi.sdutlinux.org/
# 豆瓣:http://pypi.douban.com/simple/ 

    需要注意的是:有时候使用conda install d2l命令无法下载,改为pip 命令后即可下载成功。这是因为有些包只能通过pip安装。Anaconda提供超过1,500个软件包,包括最流行的数据科学、机器学习和AI框架,这与PyPI上提供的150,000多个软件包相比,只是一小部分。

    Python官方安装whl包和tar.gz包安装方法:

安装whl包:pip install wheel,pip install xxx.whl

安装tar.gz包:cd到解压后路径,python setup.py install

参考资料

[1] Python错误笔记(2)之Pytorch的torch.normal()函数

[2] 动手学深度学习 李沐

【深度学习 01】线性回归+PyTorch实现的更多相关文章

  1. 金玉良缘易配而木石前盟难得|M1 Mac os(Apple Silicon)天生一对Python3开发环境搭建(集成深度学习框架Tensorflow/Pytorch)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_189 笔者投入M1的怀抱已经有一段时间了,俗话说得好,但闻新人笑,不见旧人哭,Intel mac早已被束之高阁,而M1 mac已经 ...

  2. windows10环境下安装深度学习环境anaconda+pytorch+CUDA+cuDDN

    步骤零:安装anaconda.opencv.pytorch(这些不详细说明).复制运行代码,如果没有报错,说明已经可以了.不过大概率不行,我的会报错提示AssertionError: Torch no ...

  3. 【深度学习】线性回归(Linear Regression)——原理、均方损失、小批量随机梯度下降

    1. 线性回归 回归(regression)问题指一类为一个或多个自变量与因变量之间关系建模的方法,通常用来表示输入和输出之间的关系. 机器学习领域中多数问题都与预测相关,当我们想预测一个数值时,就会 ...

  4. 动手学深度学习8-softmax分类pytorch简洁实现

    定义和初始化模型 softamx和交叉熵损失函数 定义优化算法 训练模型 import torch from torch import nn from torch.nn import init imp ...

  5. 【深度学习】基于Pytorch的ResNet实现

    目录 1. ResNet理论 2. pytorch实现 2.1 基础卷积 2.2 模块 2.3 使用ResNet模块进行迁移学习 1. ResNet理论 论文:https://arxiv.org/pd ...

  6. 深度学习之入门Pytorch(1)------基础

    目录: Pytorch数据类型:Tensor与Storage 创建张量 tensor与numpy数组之间的转换 索引.连接.切片等 Tensor操作[add,数学运算,转置等] GPU加速 自动求导: ...

  7. 动手学深度学习11- 多层感知机pytorch简洁实现

    多层感知机的简洁实现 定义模型 读取数据并训练数据 损失函数 定义优化算法 小结 多层感知机的简洁实现 import torch from torch import nn from torch.nn ...

  8. 常用深度学习框架(keras,pytorch.cntk,theano)conda 安装--未整理

    版本查询 cpu tensorflow conda env list source activate tensorflow python import tensorflow as tf 和 tf.__ ...

  9. 对比学习:《深度学习之Pytorch》《PyTorch深度学习实战》+代码

    PyTorch是一个基于Python的深度学习平台,该平台简单易用上手快,从计算机视觉.自然语言处理再到强化学习,PyTorch的功能强大,支持PyTorch的工具包有用于自然语言处理的Allen N ...

随机推荐

  1. Solution -「ARC 125F」Tree Degree Subset Sum

    \(\mathcal{Description}\)   Link.   给定含有 \(n\) 个结点的树,求非负整数对 \((x,y)\) 的数量,满足存在 \(\exist S\subseteq V ...

  2. operator 之旅(一)

    环境准备 依赖版本 MAC M1 kubernetes: 1.18.3 go: 1.17.6 kubebuilder:3.1.0 知识必备 Kubernetes的Group.Version.Resou ...

  3. MongoDB 带访问控制的副本集部署

    当你需要用到一个MongoDB 副本集集群,用于开发测试时, 可以通过下面的步骤简单完成. 版本及环境 MongoDB4.4  Centos6.5  一. 下载安装 MongoDB Server 及 ...

  4. BI工具数据可视化效果哪家强?我选这款!

    BI工具是商业智能(Business Intelligence)软件的英文缩写.目前,商业智能通常被理解为将企业中现有的数据转化为知识,帮助企业做出明智的业务经营决策的工具. 企业经常会为如何选择BI ...

  5. 开源报表工具太复杂?不如用这款免费web报表工具

    随着信息系统的高速发展,报表平台逐渐成为了信息系统当中最为核心和重要的功能模块.报表工具有助于将原始数据可视化显示,使决策者或者相关人员能够一览整体的数据趋势,完整的报表解决方案会提供多样的表格数据展 ...

  6. 【C# 程序集】.net core 3.0中动态卸载|卸载程序集

    原文:https://docs.microsoft.com/zh-cn/dotnet/core/dependency-loading/understanding-assemblyloadcontext ...

  7. Qt:lambda表达式

    说明 c11之后加入了lambda表达式,所以Qt也支持 加载项 CONFIG += c++11 用法 [ capture ] ( parameters ) mutable -> return_ ...

  8. Python:批量创建py文件

    import os filePrefix='Test' fileSuffix='.py' fileNum=7 #文件个数 for i in range(0,fileNum): filename=fil ...

  9. js 数组/对象/日期的浅克隆

    //封装 function clone (obj) { // Handle the 3 simple types, and null or undefined if (null == obj || & ...

  10. C# 爬取图片

    网络收集整理  爬取图片 引用AngleSharp  NuGet 包 using AngleSharp; using System; using System.Collections.Generic; ...