《动手学习深度学习》第二天
正式开始啦!!!
线性回归
1、回归与分类的差别
最开始接触机器学习的时候,回归与分类就困扰了好久,就像书中说的那样回归的输出是连续的,就像天气的变化,在一定时间内都是连续变化的,不会说一下子温度就会从20度到30度,并且只要单位够小,从20度到21度之间可以划分为无数个不同度数。同样拿天气来说,分类预测明天是否会下雨,我们会提前给定几个状态,下雨还是不下雨,又或者说阴天,就算加上什么雷阵雨的,也是可数的几个状态。
2、线性回归原理
书中的介绍已经够清楚了,就是通过线性模型来找到输入与输出之前的关系。这里还是以房价为例,并且假设房价与面积,房龄之间是线性关系。
想要建立一个模型有以下几个步骤:
(1)收集数据
(2)构建模型,也就是通过线性表达式表示出输入与输出之间的关系:
(3)损失函数,也就是评价预测与真实值之间的指标的函数。
(4)优化算法,这里使用小批量随机梯度下降法
(5)模型预测,将求得的参数代入公式就可以啦
书中大概介绍了为什么我们一般拿到的数据集都是矩阵或者数组形式的,简单直接地用运算时间给出了结果,因为这样运算速度快。
3、线性回归实现
书中给出了用Mxnet框架的详细代码,这里只是用pytorch照着写一遍,但就是照着写一遍我还是花了整整一天,因为在计算梯度这一块一直报错,头大。
(1)首先导包
```python
import matplotlib.pyplot as plt
%matplotlib inline
import torch
from torch.autograd import Variable
import numpy as np
import random
from IPython import display```
(2)初始化数据
这里设训练数据集样本数为1000,输⼊个数(特征数)为2。给定随机⽣成的批量样本1000×2,我们使⽤线性回归模型真实权重w = [2, −3.4]⊤和偏差b = 4.2,以及⼀个随机噪声项ϵ来⽣成标签,和书中一模一样。
num_inputs = 2
num_examples = 1000
true_w = [2,-3.4]
true_b = 4.2
features = torch.tensor(np.random.normal(scale = 1,size = (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(scale = 0.01,size = labels.shape),dtype=torch.float32)# 随机生成w和b
w = torch.tensor(np.random.normal(scale=0.01,size=(num_inputs,1)),dtype=torch.float32,requires_grad = True)
b = torch.zeros(1,requires_grad = True,dtype=torch.float32)
(3)画图
这里就是大概看一下某一维度特征和标签之间的关系,对于不清楚分布的情况的数据来说,可以大概推测一个合适的模型进行建模。
def use_svg_display():
# 用矢量图显示display.set_matplotlib_formats('svg')
def set_figsize(figsize = (3.5,2.5)):use_svg_display()
# 设置图的尺寸plt.rcParams['figure.figsize'] = figsize
set_figsize()
plt.scatter(features[:,1].data,labels.data,1)
(4)定义模型
这里把批量读取数据的函数和目标函数,损失函数,优化器函数的定义都放在这里了,对应着上面的公式就可以看明白。
# 批量读取数据
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[j,:],labels[j]
# 定义线性模型
def Linreg(X,w,b):return torch.mm(X,w) + b
# 定义损失函数
def squared_loss(y_hat,y):return (y_hat - y.reshape(y_hat.shape))**2/2
# 定义sgd优化模型
def sgd(params,lr,batch_size):for param in params:
# param[:] = param - lr * param.grad/ batch_sizeparam.data -= lr * param.grad/batch_size
(5)准备训练
# 初始化训练参数
lr = 0.01
num_epochs = 10
batch_size = 10
net = Linreg
loss = squared_loss# 开始训练
for epoch in range(num_epochs):for X,y in data_iter(batch_size,features,labels):if (w.grad is not None) and (b.grad is not None):w.grad.data.zero_()b.grad.data.zero_() l = loss(net(X,w,b),y).sum()l.backward()sgd([w,b],lr,batch_size)train_l = loss(net(features,w,b),labels)print('epoch %d,loss %f,'%(epoch+1,train_l.mean()))
(6)训练结果
模型比较简单,很快就能把损失降下来,接下来就是记录下我疯狂报错的一下午。
(7)错误示范
1、报错
报了好几个错误,都是关于无法进行反向传播的,之前也用过pytorch的代码,也没有觉得在需不需要进行反向传播这一块这么繁琐,主要是自己水平也不够,就开始了各种调试,既然是没法传播的问题,想了下我就把涉及计算的X,y,w,和b都修改为了需要计算梯度的,很明显,并没有什么用,原因在成功解决问题后,推测可能是因为X,y根本没有计算反向传播的必要啊,假设y = wx + b,一个函数中不可能4个未知数吧,X,y已知,反向传播往哪里传。随后,又去看了以前使用的pytorch代码,对比了好久没有发现什么差异啊,数据都是Tensor形式的,差别就在于现在pytorch中都是封装好了优化函数的,而在这本书中,为了使我们更加了解深度学习的原理,自己的定义的优化函数SGD随机梯度下降。然后,果然,怀疑别人出错前应该先检查自己,问题就在自己写的随机梯度下降这个1行代码中,简直要吐血。
其中注释掉的那一行代码就是我原本写的,错的代码,首先要说一下在y = wx + b中,w,b是未知数,所以要进行反向传播的就是这两个参数,所以在写代码时,就会把w和b的requires_grad设置为True,然后运行到SGD时,错的那行代码会在进行梯度优化时进行梯度计算,目前为什么优化时不需要进行梯度计算,我还不知道,但是明确了就是这一行代码的错误,修改成下面的,不需要对优化过程进行梯度计算就可以了。好难,还在晕。
2、心得体会
我一直不太明白构建计算图,与梯度计算之间的关系,在代码报错后去看了好久还是看的晕乎乎,大概就是再说使用pytorch进行反向传播的时候,一定要注意哪些参数在整个代码中是需要进行反向传播的,只有需要的才要将requires_grad设置为True。学习到这里,整个人都超负荷了,这个周都不想在学习了。。。。。。。。
3、疑惑
今天又看了下书中用Mxnet框架的写法和讨论区大家的疑惑,然而我的问题还是没有解决反而更加疑惑了,为什么在Mxnet框架中在使用优化算法对w和b进行更新时,不需要开辟新的空间,而pytorch需要呢,是因为框架结构不一样吗,还是我理解错了,先把问题放在这里,等过后了解更多了再回过头来解决。
4、线性回归简洁实现
都是线性回归的相关操作,所以就放在一起了。简洁实现顾名思义就是用pytorch封装好的函数实现某些功能。那就直接上代码啦。
(1)数据初始化
还是和上面一摸一样的数据
import matplotlib.pyplot as plt
%matplotlib inline
import torch
from torch.autograd import Variable
import numpy as np
import random
from IPython import displaynum_inputs = 2
num_examples = 1000
true_w = [2,-3.4]
true_b = 4.2
features = torch.tensor(np.random.normal(scale = 1,size = (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(scale = 0.01,size = labels.shape),dtype=torch.float32,)
(2)数据读取
之前我们是自己定义的批量读取数据的函数,但是在pytorch中已经定义好了相关的类,可以直接生成对象后使用。
batch_size = 10
from torch.utils.data import Dataset,DataLoader,TensorDataset
dataset = TensorDataset(features,labels)
data_iter = DataLoader(dataset,batch_size,shuffle=True)
for X,y in data_iter:print(X,y)break
(3)模型定义
pytorch定义模型的方式有几种,这是比较通用,且方便后续修改的一种方式。
1、方法一
from torch import nn
class Lineraregssion(nn.Module):def __init__(self):super(Lineraregssion,self).__init__()self.linear = nn.Linear(2,1)def forward(self,X):out = self.linear(X)return out
lin = Lineraregssion()
print(lin)
之前也遇到过许多这样写的代码,但是在自己写的时候,还是会出现一些莫名其妙的错误,例如我在上面实例化了Linear这个类,然后再前向传播中传入x就可以了,但是在自己写的时候,竟然传入的时X,和y,哎,学习太难了。。。。。
2、方法二
net = nn.Sequential()
net.add_module('linear',nn.Linear(2,1))
print(net)
不知道是不是我级别太低了,我觉得这种构建方式比较简单好用,适合我这种初学者。
3、方式三
net = nn.Sequential(nn.Linear(2,1)
)
print(net)
还可以直接在Sequential里面添加,与上面那种方式的差别就是多了名字。
for param in net.parameters():print(param)
通过这样的循环可以查看中间到底存在哪些参数。
(4)模型参数初始化
from torch.nn import init
init.normal_(net[0].weight,mean=0,std=0.01)
init.constant_(net[0].bias,val=0)
在pytorch模型中,要是忘记初始化参数了,应该会自动初始化的,因为我就一直都没有对参数进行初始化,不影响训练。
(5)定义损失函数和优化算法
cetrion = torch.nn.MSELoss()
opt = torch.optim.SGD(lin.parameters(),0.01)
(6)训练模型
num_epoch = 10
for epoch in range(1,num_epoch + 1):for X,y in data_iter:out = lin(X)
# print(out.shape)l = cetrion(out,y.view(out.shape))opt.zero_grad()l.backward()opt.step()print('epoch: %d, loss:%f'%(epoch,l.item()))
然后可以通过取出模型中的参数查看w和b的数值
dense = lin.linear
dense.weight
dense.bias
(7)心得体会
在这里主要比之前多了解了一个非常重要的东西那就是参数的初始化,因为之前训练resnet这类模型的时候都是加载别人训练好的权重进行训练的,就在想难道非要用别人训练的权重吗,虽然别人预训练的效果是比较不错,但是如果自己要修改代码怎么办呢?现在就知道了可以通过直接调用nn里面的init对权重进行初始化,以满足自己的需求。如果要对代码的不同部分使用不同的学习率就可以这样设置
这里模型中就只用了一个线性层,就不进行试验啦。
《动手学习深度学习》第二天相关推荐
- 《动手学深度学习》中文第二版预览版发布
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨李沐@知乎 来源丨https://zhuanlan.zhihu ...
- 李沐d2l《动手学深度学习》第二版——风格迁移源码详解
本文是对李沐Dive to DL<动手学深度学习>第二版13.12节风格迁移的源码详解,整体由Jupyter+VSCode完成,几乎所有重要代码均给出了注释,一看就懂.需要的同学可以在文末 ...
- 李沐《动手学深度学习》第二版比赛2-Classify Leaves
李沐<动手学深度学习>第二版比赛2-Classify Leaves 我的偶像,李沐大神主讲的<动手学深度学习>(使用Pytorch框架,第一版使用的是MXNet框架)目前已经进 ...
- 《动手学深度学习(Dive into Deeplearning)》(第二版)——第二章 _2.3 线性代数
<动手学深度学习(Dive into Deeplearning)>(第二版)--第二章 _2.3 线性代数 第二章 预备知识 § 前情回顾 § 2.3 线性代数 2.3.1 标量 2.3. ...
- 李沐《动手学深度学习》第二版 pytorch笔记1 环境搭建
李沐<动手学深度学习>第二版pytorch笔记1 搭建环境 文章目录 李沐<动手学深度学习>第二版pytorch笔记1 搭建环境 此时尚有耐心 虚拟环境搭建 创建虚拟环境 查看 ...
- 《动手学深度学习》参考答案(第二版)-第二章
最近在学习<动手学深度学习>,结合百度和课后的大家的讨论(侵删),整理出这一份可能并不完全正确的参考答案(菜鸡的做题记录),因为个人水平有限,有错误的地方欢迎在 公众号 联系我,后面我 ...
- 《动手学深度学习》第二天
今天学习深度学习基础. 第一节讲述的是线性回归.之前看论文的时候就见过损失函数这个名词,这一次真正了解了它的定义,在优化算法中,注意到解析解和数值解两种,其中数值解的优化算法,常用的是小批量随机梯度下 ...
- 动手学深度学习打卡之二。
第二次打卡内容(2月15日-18日) Task03:过拟合.欠拟合及其解决方案:梯度消失.梯度爆炸:循环神经网络进阶(1天) Task04:机器翻译及相关技术:注意力机制与Seq2seq模型:Tran ...
- 推荐:李沐开源新作,一起来《动手学深度学习》
来源 /Datawhale 图文 / 静修 排版 / 家豪 [导读]<动手学深度学习>这本书由亚马逊首席科学家李沐,亚马逊应用科学家阿斯顿·张等大师合作打造,沉淀三年完成.本书采用交互 ...
- 364 页 PyTorch 版《动手学深度学习》分享(全中文,支持 Jupyter 运行)
1 前言 最近有朋友留言要求分享一下李沐老师的<动手学深度学习>,小汤本着一直坚持的"好资源大家一起分享,共同学习,共同进步"的初衷,于是便去找了资料,而且还是中文版的 ...
最新文章
- 英国前首相:为什么欧洲没有诞生互联网巨头?
- eclipse中创建类和包的快捷方式
- 网站优化中受欢迎的文章是怎样的?
- win7 ghost 安装串口驱动inf文件出现问题
- jQuery动态改变图片显示大小(修改)
- laravel-admin 开发 bootstrap-treeview 扩展包
- python函数示例_使用Python中的示例的input()函数
- 美国慈善机构Kars4Kids意外泄露了上万名捐赠者的个人信息
- cocos2d-x学习资源整理(持续更新)
- 计算机硬盘接口及操作系统
- PCF8563实时时钟芯片51单片机简单例程
- linux的pending状态怎么退出,状态pending是什么意思
- 如何按照滑环的原理来自制简易导电滑环
- TexturePacker纹理打包打方法及技巧
- hihocoder 1538
- excel删除无尽空白行_全了!Excel批量插入空行、批量删除空行、隔行插入空行技巧...
- python统计英文单词个数_统计英文单词的个数的python代码 及 字符串分割
- Codeforces Round #797 (Div. 3) F. Shifting String题解
- IO系统性能之二:缓存和RAID如何提高磁盘IO性能
- 25篇经典机器学习论文的分类
热门文章
- 树莓派安装Jupyter Notebook实现网页编程
- activity工作流引擎
- 10.24程序员日,开源社给大家送上大礼!【抢票贴】#疯狂倒计时24小时,10月24-25日I WANT YOU!#...
- JavaSwing设置字体样式
- Ant-Table查看详情
- 使用Pyecharts进行全国水质TDS地图可视化全过程9:构建字典,批量生成所有省份地图
- python读取tiff图像,浅谈python下tiff图像的读取和保存方法
- 用C语言程序求两个正整数的最大公约数
- 索尼a6000拍月亮_如何给月亮拍好照片
- 用循环制作乘法口诀表