Pytorch的基本使用

2018-11-30  本文已影响0人  Zimix

本篇内容参考官方文档自己总结而来仅供自学自查,详细需求请查阅官方文档。

数据类型

什么是张量?简单来说就可以看成是向量。一阶张量,就是一维向量,如此如此。

1. torch自己的方法构造的数据都是默认为Tensor的张量,比如:
import torch
torch.Tensor(list/ndarray)#---->将列表转为,数组转为tensor
torch.eye(3)#---->生成3行3列的值为1的对角矩阵
torch.linspace(start, end, steps=100, out=None)#---->等差数列矩阵
torch.logspace(start, end, steps=100, out=None)#---->对数等差数列矩阵

torch.zeros()、ones()、等等方法和numpy类似,不一一举例。

import torch
torch.rand(2,2)# ----->生成2X2的矩阵,数值再0-1之间
torch.randn(2,2)# ---->生服从标准正态分布的2X2
torch.arange(1,20,2)# ---->序列数组
2. numpy的array或者list数组转换而来。

这里介绍一下numpy的array和torch的tensor的区别,numpy的array是不支持GPU的,只支持CPU。而torch的tensor是两个都支持的。

>>> a = numpy.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t
torch.LongTensor([1, 2, 3])
>>> t[0] = -1
>>> a
array([-1,  2,  3])

这个方法有一个缺点也是优点,生成的tensor和array指向同一个内存地址,一个变了都会变。

import torch
a = torch.rand(2,2)
# to numpy.ndarray
a.numpy()
# 转换成支持CPU
a.cpu()
# 转换成支持GPU
a.cuda()
3. tensor的属性
>>> tt1
tensor([[0.1372, 0.6473, 0.6765],
        [0.3346, 0.1886, 0.4174]])
>>> tt1.shape
torch.Size([2, 3])
>>> tt1.size()
torch.Size([2, 3])
>>> tt1.numel()
6
>>> torch.numel(tt1)
6

基本上张量的简介就差不多了,更多内容参考pytorch中文文档

Variable类型数据是张量的升级版,给tensor加了装备:前向传播反向传播自动求导等功能,在计算图的构建中起的很重要的作用。有一个图能很形象的说明:


其中最重要的两个属性是:data和grad。.data表示该变量保存的实际数据,通过该属性可以访问到它所保存的原始张量类型,而关于该 variable(变量)的梯度会被累计到.grad 上去。与tensor不同,Variable在另一个模块内----torch.autograd。不过,pytorch 0.4之后的版本,好像把Tensor和Variabel合并了。requires_grad变成了Tensor本来的一个属性了。这里给一片博客可以参考
import torch
from torch.autograd import Variable 
# 定义三个Variable变量
# requires_grad 是设置是否需要计算梯度
x = Variable(torch.Tensor([1, 2, 3]), requires_grad=True)
w = Variable(torch.Tensor([2, 3, 4]), requires_grad=True)
b = Variable(torch.Tensor([3, 4, 5]), requires_grad=True)
# 构建计算图,公式为:y = w * x^2 + b
y = w * x * x + b 
# 自动求导,计算梯度
# 这里传入的torch.Tensor([1,1,1])是用来表示每个梯度的权重的
y.backward(torch.Tensor([1, 1, 1])) 
print(x.grad)# 2*w*x
print(w.grad)# x*x
print(b.grad)# 常量的导数为1

数据操作

- 索引 ---- 和numpy的索引相同
>>> tt1
tensor([[0.1372, 0.6473, 0.6765],
        [0.3346, 0.1886, 0.4174]])
>>> tt1[1,1]
tensor(0.1886)
>>> tt1[:,2]
tensor([0.6765, 0.4174])
- 切片---- 和numpy的切片相同
>>> tt1
tensor([[-0.3623, -0.6115,  0.7283],
        [ 0.4699,  2.3261,  0.1599]])
>>> tt1[:,1:2]
tensor([[-0.6115],
        [ 2.3261]])
>>> tt1[:,:]
tensor([[-0.3623, -0.6115,  0.7283],
        [ 0.4699,  2.3261,  0.1599]])
- 连接 ---- torch.cat()
>>> tt1 = torch.rand(2,3)
>>> tt2 = torch.rand(2,3)
>>> torch.cat((tt1,tt2),0)
tensor([[0.1372, 0.6473, 0.6765],
        [0.3346, 0.1886, 0.4174],
        [0.8388, 0.7322, 0.7819],
        [0.4745, 0.2260, 0.7371]])
>>> torch.cat((tt1,tt2),1)
tensor([[0.1372, 0.6473, 0.6765, 0.8388, 0.7322, 0.7819],
        [0.3346, 0.1886, 0.4174, 0.4745, 0.2260, 0.7371]])
- reshape ---- torch.view()、torch.reshape()
# view()
>>> tt1
tensor([[-0.3623, -0.6115,  0.7283],
        [ 0.4699,  2.3261,  0.1599]])
>>> tt1.view(-1)
tensor([-0.3623, -0.6115,  0.7283,  0.4699,  2.3261,  0.1599])
>>> tt1.view(3,2)
tensor([[-0.3623, -0.6115],
        [ 0.7283,  0.4699],
        [ 2.3261,  0.1599]])
# reshape()
>>> tt1
tensor([[-0.7242,  0.6419, -1.2202],
        [-0.7509, -0.9206,  0.9566]])
>>> tt1.reshape(3,2)
tensor([[-0.7242,  0.6419],
        [-1.2202, -0.7509],
        [-0.9206,  0.9566]])
>>> tt1
tensor([[-0.7242,  0.6419, -1.2202],
        [-0.7509, -0.9206,  0.9566]])
>>> tt = tt1.view(2,1,3)
>>> tt
tensor([[[-0.7242,  0.6419, -1.2202]],

        [[-0.7509, -0.9206,  0.9566]]])
>>> tt.shape
torch.Size([2, 1, 3])
>>> ttt = tt.squeeze()
>>> ttt
tensor([[-0.7242,  0.6419, -1.2202],
        [-0.7509, -0.9206,  0.9566]])
>>> ttt.shape
torch.Size([2, 3])

二者用法类似,返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。

数学运算

>>> tt1 = torch.randn(2,3)
>>> tt2 = torch.randn(2,3)
>>> tt1
tensor([[-0.7242,  0.6419, -1.2202],
        [-0.7509, -0.9206,  0.9566]])
>>> tt2
tensor([[-0.7343, -2.0070,  1.1552],
        [ 0.1351, -0.5211,  0.7543]])
>>> tt1+tt2
tensor([[-1.4585, -1.3651, -0.0649],
        [-0.6158, -1.4417,  1.7109]])
>>> tt1-tt2
tensor([[ 0.0100,  2.6489, -2.3754],
        [-0.8859, -0.3995,  0.2023]])
>>> tt1*tt2
tensor([[ 0.5318, -1.2883, -1.4096],
        [-0.1014,  0.4797,  0.7215]])
>>> tt1/tt2
tensor([[ 0.9863, -0.3198, -1.0562],
        [-5.5598,  1.7666,  1.2683]])

torch的:
加法torch.add(input, value, out=None)
乘法-----torch.mul(input, value, out=None)
除法-----torch.div(input, value, out=None)

# input是"被操作数",必须是tensor,value是"操作数"。
# 两个张量相加,对应位置相加
>>> torch.add(tt1,tt2)
tensor([[-1.4585, -1.3651, -0.0649],
        [-0.6158, -1.4417,  1.7109]])
# tensor+标量,为每个位置加上这个标量
>>> torch.add(tt1,1)
tensor([[ 0.2758,  1.6419, -0.2202],
        [ 0.2491,  0.0794,  1.9566]])

这三个方法类似,不一一举例。

# 以tt1为底,0为指数
>>> torch.pow(tt1,0)
tensor([[1., 1., 1.],
        [1., 1., 1.]])
# 以2.7为底,tt1为指数
>>> torch.pow(2.7,tt1)
tensor([[0.4871, 1.8919, 0.2976],
        [0.4743, 0.4008, 2.5861]])
# e为底
>>> torch.exp(tt1)
tensor([[0.4847, 1.9001, 0.2952],
        [0.4720, 0.3983, 2.6029]])

基本上够用了,方法不熟悉就边查遍用。
最后补充一点矩阵方面的东西:

流程结构

这里主要介绍模型的搭建流程。

1. 构建网络
import torch
import torch.nn.functional as F


class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)
        self.predict = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        x = F.relu(self.hidden(x))
        x = self.predict(x)
        return x
# 实例化
net = Net(10,3,2)
# 直接在Sequential类中初始化
net = torch.nn.Sequential(
    torch.nn.Linear(1, 10),
    torch.nn.ReLU(),
    torch.nn.Linear(10, 1)
)

这里有一篇文档做了更详细的举例

2. 定义优化器、损失函数

反向传播的流程是借助损失函数,优化器来实现的(更多函数请参考loss functionoptim)。

# 定义损失函数
loss_func = torch.nn.CrossEntropyLoss()

# 定义优化器
optimizer = torch.optim.SGD(net.parameters(), lr=0.02)
3. 前向传播

上面两个方法的前向传播都是如此

predict = net(input)
4. 更新参数

使用优化器通过优化损失函数,得到梯度,反向更新模型参数。

# 1. 计算loss
loss = loss_func(predict,y_true)
# 2. 计算梯度
optimizer.zero_grad()   # 梯度清空
loss.backward()         # 反向传播-->给优化器
optimizer.step()        # 单步更新-->给参数

如此一个网络搭建和一次训练就完成了!

- 最后补充一点如何决定使用CPU还是GPU

在训练网络之前,我们可以决定是通过CPU还是GPU来进行训练。

net = Net(10,3,2).cuda()
loss_func = torch.nn.CrossEntropyLoss().cuda()
#================================================
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

对应的我们在实例化网络和损失函数的时候都需要.to(device)。即:

net = Net(10,3,2).to(device)

loss_func = torch.nn.CrossEntropyLoss().to(device)

最后补充一篇解决模型超GPU显存的博客

上一篇下一篇

猜你喜欢

热点阅读