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. Dubbo扩展点应用之三异步调用

    Dubbo不只提供了堵塞式的同步调用,同时提供了异步调用的方式.这种方式主要应用于提供者接口响应耗时明显,消费者端可以利用调用接口的时间去做一些其他的接口调用,利用Future模式来异步等待和获取结果 ...

  2. 用 JuiceFS 备份 Nginx 日志可以这么简单

    在我们线上的生产环境中要备份的东西很多,各种服务日志.数据库数据.用户上传数据.代码等等.用 JuiceFS 来备份可以节省你大量时间,我们会围绕这个主题写一系列的教程,整理出一套最佳实践,方便大家. ...

  3. Sqlmap数据库注入攻击

    实验目的 利用sqlmap命令破解出access数据中的admin的密码bfpns 实验原理 SQLMap是一个先进的自动化SQL注入工具,其主要功能是扫描.发现并利用给定的URL的SQL注入漏洞.目 ...

  4. 【windows 操作系统】【CPU】用户模式和内核模式(用户层和内核层)

    所有的现代操作系统中,CPU是在两种不同的模式下运行的: 注意以下内容来自微软: windows用户模式和内核模式 运行 Windows 的计算机中的处理器有两个不同模式:用户模式 和内核模式 . 用 ...

  5. ElasticSearch学习笔记(详细)

    目录 ElasticSearch概述 ElasticSearch入门 安装 基本操作 查看es相关信息 索引操作 文档操作 bulk批量API 进阶检索 Search API Query DSL 分词 ...

  6. c# 窗口不显示标题栏及周围有/无边框的设置

    一 : 不显示标题栏也无边框: 方法1:属性里直接设置 方法2:手写代码(两种效果一样) this.FormBorderStyle = FormBorderStyle.None; 二 : 不显示标题栏 ...

  7. anaconda及jupyter notebook的使用之numpy模块的用法(2)

    今日内容概要 numpy模块结束 ndarray创建 numpy内置方法 索引与切片(花式索引.布尔索引) 常用函数 统计方法 随机数 numpy的内置方法 import numpy as np 1. ...

  8. SpringBoot连接Redis (Sentinel模式&Cluster模式)

    一.引入pom <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  9. PHP日常错误总结

    session问题 问题描述 初到公司开发的项目在本地测试没有问题,部署到线上之后出来验证码一直错误,或者是CSRF token mismatch. 这些问题都是和session有关系,打开两个页面, ...

  10. PHP message:filesize(): stat failed for 错误

    PHP message:filesize(): stat failed for 错误 message:filesize(): stat failed for F:s2017\SinaImgUpload ...