返回顶部

请叫我杨先生

导航

Pytorch 第一阶段知识点查漏补缺

第一阶段知识点查漏补缺

d2l

1.d2l官方也没有过多解释这个包的信息,但是却给出了用法:

DESCRIPTION
Please import d2l by one of the following ways:

from d2l import mxnet as d2l  # Use MXNet as the backend
from d2l import torch as d2l  # Use PyTorch as the backend
from d2l import tensorflow as d2l  # Use TensorFlow as the backend

PACKAGE CONTENTS
mxnet
tensorflow
torch
点击这里可以下载查看d2l支持的包,或者直接在cmd环境中键入pip install -U d2l -i https://mirrors.aliyun.com/pypi/simple/查看已经安装过的包。
2.查看d2l调用的包的地址 ,发现这个包是来自于我们本地已经编译过的函数,在jupyter中键入(在一个空的程序执行框内,不能有任何注释): d2l.synthetic_data??

Signature: d2l.synthetic_data(w, b, num_examples)
Source:   
def synthetic_data(w, b, num_examples):
    """Generate y = Xw + b + noise.

    Defined in :numref:`sec_linear_scratch`"""
    X = d2l.normal(0, 1, (num_examples, len(w)))
    y = d2l.matmul(X, w) + b
    y += d2l.normal(0, 0.01, y.shape)
    return X, d2l.reshape(y, (-1, 1))
File:      d:\miniconda\lib\site-packages\d2l\torch.py
Type:      function

我们用代码测试下

from d2l import torch as d2l 
import torch 

# 用法一,可以读取本地的函数 
ture_w = torch.tensor([1,3.2],requires_grad=True)  
true_b = torch.zeros(1,requires_grad=True)
features,labels = d2l.synthetic_data(ture_w,true_b,1000)

-->据此初步给出结论: d2l 就是一个容器,或者说一个整合怪。将所有冗杂的东西都塞进d2l里面,如果要再次调用的话,就可以直接调用d2l里面的函数了。

-------------2021/12/21更正知识点:d2l就是我们下载的李沐老师推行的一个包😂,里面有李沐大佬编写的synthetic_data()这个方法,只是我们照着他的来写,以为要是我们自己编写的函数,用d2l.synthetic_data??查看到的是存在d:\miniconda\lib\site-packages\d2l\torch.py下----------

torch.utils.data

Pytorch 的数据处理: imoprt torch.utils.data实现数据的自由读取
torch.utils.data主要包括以下三个类:

  1. class torch.utils.data.Dataset
    表示Dataset的抽象类。
    所有其他数据集都应该进行子类化。所有子类应该override__len__和__getitem__,前者提供了数据集的大小,后者支持整数索引,范围从0到len(self)。

  2. class torch.utils.data.TensorDataset(data_tensor, target_tensor)
    包装数据和目标张量的数据集。通过沿着第一个维度索引两个张量来恢复每个样本。

data_tensor (Tensor) - 包含样本数据
target_tensor (Tensor) - 包含样本目标(标签)
  1. class torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=<function default_collate>, pin_memory=False, drop_last=False)
    数据加载器。组合数据集和采样器,并在数据集上提供单进程或多进程迭代器。
dataset:输入的 TensorDataset包装好的样本 
batch_size:小批量梯度的批量大小 
shuffle:洗牌,随机化我们的数据 
  1. class torch.utils.data.sampler.Sampler(data_source)
    所有采样器的基础类。
    每个采样器子类必须提供一个__iter__方法,提供一种迭代数据集元素的索引的方法,以及返回迭代器长度的__len__方法。

同样的,我们使用代码来验证下官方的解释:官网解释,源码

# class torch.utils.data.TensorDataset(data_tensor, target_tensor) 包装数据 
import torch  
from d2l import torch as d2l  
from torch.utils import data 

features = torch.arange(1,21).reshape(10,2)
labels = torch.randn(10,1) 
train_data = data.TensorDataset(features,labels) # <torch.utils.data.dataset.TensorDataset at 0x2b82714edf0> 
#data.TensorDataset(features,labels)返回的是一个 tuple 的地址 
train_loader = data.DataLoader(dataset=train_data,batch_size=10,shuffle=True)
next(iter(train_loader)) # train_loader <torch.utils.data.dataloader.DataLoader at 0x2b827082100> 返回的是一个地址

为了简便起见,我们截取前面三条数据进行输出:

[tensor([[ 5,  6],
         [13, 14],
         [ 1,  2]),
 tensor([[-0.5224],
         [-0.2214],
         [-0.2276]])]

TensorDataset()方法传入特征和标签包装成一个数据,其中每个样本和标签一一对应,返回该数据的地址
DataLoader()方法传入梯度的批量,是否洗牌等参数,获得批量大小的数据,方便用于SGD (Small batch gradient descent)

torch.nn

class torch.nn.Sequential(* args) torch.nn.Sequential() 是torch.nn模块中的一个方法,用更加严谨的话来说就是一个时序容器。Modules 会以他们传入的顺序被添加到容器中。当然,也可以传入一个OrderedDict

我们最开始实现的是LinearRegression,只有一个模型,我们并不需要Sequential这个时序容器,Sequential实例将数据传入到第一层,然后将第一层的输出作为第二层的输入,依此类推。在下面的例子中,我们的模型只包含一个层,因此实际上不需要Sequential。但是由于以后几乎所有的模型都是多层的,在这里使用Sequential会让你熟悉标准的流水线。

import torch.nn as nn
# Example of using Sequential
model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )
# model[0]调用第一个模型,model[1]调用第二个函数等等

Linear layers

class torch.nn.Linear(in_features, out_features, bias=True)对输入数据做线性变换:\(y=Ax+b\)

in_features - 每个输入样本的大小
out_features - 每个输出样本的大小
bias - 若设置为False,这层不会学习偏置。默认值:True

weight -形状为(out_features x in_features)的模块中可学习的权值
bias -形状为(out_features)的模块中可学习的偏置

李沐d2l里面是这样描述的:正如我们在构造nn.Linear时指定输入和输出尺寸一样。现在我们直接访问参数以设定初始值。我们通过net[0]选择网络中的第一个图层,然后使用weight.data和bias.data方法访问参数。然后使用替换方法normal_和fill_来重写参数值。

# Example of using Sequential2 
net = nn.Sequential(nn.Linear(in_features=2, out_features=1)) # 一个线性回归的模型 

net[0].weight.data.normal_(mean=0, std=0.01)  # 时序容器,我们选择第一个线性回归模型
net[0].bias.data.fill_(0) 
'''normal_(mean=0, std=1, , gengerator=None*)
将tensor用均值为mean和标准差为std的正态分布填充。'''

class torch.nn.MSELoss(size_average=True)

\(loss(x,y)=1/n∑(xi−yi)2\)

  1. x 和 y 可以是任意形状,每个包含n个元素。
  2. 对n个元素对应的差值的绝对值求和,得出来的结果除以n。
  3. 如果在创建MSELoss实例的时候在构造函数中传入size_average=False,那么求出来的平方和将不会除以n

torch.optim

torch.optim是一个实现了各种优化算法的库。大部分常用的方法得到支持,并且接口具备足够的通用性,使得未来能够集成更加复杂的方法。
为了使用torch.optim,你需要构建一个optimizer对象。这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。
为了构建一个Optimizer,你需要给它一个包含了需要优化的参数(必须都是Variable对象)的iterable。然后,你可以设置optimizer的参 数选项,比如学习率,权重衰减,等等。

提示一下,我在pytorch找到的内容如下:

  • The Variable API has been deprecated(弃用): Variables are no longer necessary to use autograd with tensors. Autograd automatically supports Tensors with requires_grad set to True. Below please find a quick guide on what has changed:
  • Variable(tensor) and Variable(tensor, requires_grad) still work as expected, but they return Tensors instead of Variables.
  • Methods such as var.backward(), var.detach(), var.register_hook() now work on tensors with the same method names. 这段话也就是说,以前的Variable 类创建出来的对象var调用var.backward()等方法才能够进行反向传播,而现在直接调用tensor.backward()就可以了(前提是tensorrequires_grad)
    所以我也有点不知所以...
optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)

像上面这种直接调用model.parameters()的就包含了所有的参数,当然我们也可以单独为每一个超参数进行设置
给算法传入的是dict类型的数据,SGD包括学习率,w和b,我么在字典里面单独设置,字典外共享设置。

from torch import optim,nn

model = nn.Sequential(
    nn.Linear(2,1),
    nn.Linear(3,1)
)

optimizer_1 = optim.SGD([
    {'params': model[0].parameters()},
    {'params': model[1].parameters(), 'lr': 1e-3}
    ], lr=1e-2, momentum=0.9)
# 这意味着model[0]的参数将会使用1e-2的学习率,model[1]的参数将会使用1e-3的学习率,并且0.9的momentum将会被用于所 有的参数。
# 等价于
optimizer_2 = optim.SGD([
    {'params': model[0].parameters(), 'lr': 1e-2},
    {'params': model[1].parameters(), 'lr': 1e-3}
    ], momentum=0.9)

所有的optimizer都实现了step()方法,这个方法会更新所有的参数。它能按两种方式来使用:就好像我们之前用的:

        ..... 
    for X, y in data_iter:
        l = loss(net(X) ,y) # 我们之前定义的在optim模块中的MSEloss()算法
        trainer.zero_grad() # 每次调用SGD之后都要清空 ,因为我们进行的是小批量梯度下降
        l.backward() # 在前面我们进行了前向传播,现在进行反向传播更新我们的参数 
        trainer.step()
    l = loss(net(features), labels) # 完成一次迭代之后查看我们的损失函数的值
        .... #(伪代码)

optimizer.step() 只要optimizer进行了反向传播之后,我们就可以用.step()来更新我我们所有参数

posted on 2021-12-21 10:04  YangShusen'  阅读(2760)  评论(2编辑  收藏  举报