Pytorch基础

大部分来源 中文pytorch手册英文pytorch手册PracticalAI 项目。

Pytorch是一个基于python的科学计算包,其目的是:
  a、代替Numpy发挥GPU性能;
  b、提供一个高度灵活和极具效率的深度学习研究平台;

1、基本概念

1.1、Tensor(张量)

pytorch的tensor本质上就是多维矩阵,pytorch的tensor可以和numpy的ndarray相互转换,唯一的不同是pytorch可以在GPU上运行。
Tensor的数据类型:
  torch.FloatTensor #32位浮点型
  torch.DoubleTensor #64位浮点型
  torch.ShortTensor #16位整型
  torch.IntTensor #32位整型
  torch.LongTensor #64位整型

测试:

import torch
import numpy as np

x = torch.Tensor(5, 3)
print (x)

b = torch.LongTensor([[2,3], [4,8], [7,9]])  #64位整型tensor
print('b is : {}'.format(b))

c = torch.zeros((3,2))    #全0的3x2tensor
print('zero tensor  : {}'.format(c))

d = torch.rand((3,2))  #随机的3x2 tensor,符合正态分布
print('normal random is:{}'.format(d))

numpy_b = b.numpy()  #tensor转numpy
print('conver to numpy is \ {}'.format(numpy_b))

e = np.array([[2,3], [4,5]])
torch_e = torch.from_numpy(e) #numpy转tensor
print('from numpy to torch.Tensor is{}'.format(torch_e))

f_torch_e = torch_e.float()  #数据类型转换,整型转float
print('change data type to float tensor:{}'.format(f_torch_e))

#使用GPU
if torch.cuda.is_available():
    d_cuda = d.cuda()
    print(d_cuda)

输出:
在这里插入图片描述

1.1.1、CUDA Tensor
支持GPU的torch版本才能使用,查询CUDA是否可用

# Is CUDA available?
print (torch.cuda.is_available())

在这里插入图片描述
创建CUDA Tensor

# Creating a zero tensor
x = torch.Tensor(3, 4).to("cuda")
print("Type: {}".format(x.type()))

输出:
在这里插入图片描述

1.2、变量(Variable)

  Variable提供了自动求导的功能。Tensor和Variable本质上没有区别,不过Variable会被放入一个计算图中,然后进行前向传播,反向传播,自动求导。
Variable的属性如下图所示:
在这里插入图片描述

Variable的三个重要属性:
data: 通过data可以取出Variable的tensor的数值;
grad_fn: 表示得到这个Variable的操作,比如通过加减还是乘除来得到;
grad: 这个Variable的反向传播梯度;

标量求导例子:

import torch
from torch.autograd import Variable

#创建Variable
x = Variable(torch.Tensor([1]), requires_grad=True)
w = Variable(torch.Tensor([2]), requires_grad=True)
b = Variable(torch.Tensor([3]), requires_grad=True)

y = w * x + b

#计算梯度
y.backward()
print(x.grad)
print(w.grad)
print(b.grad)

输出:
在这里插入图片描述

构建Variable,传入参数“requires_grad=True”表示对这个变量求梯度,默认的False。
上面代码中: y.backward()
等价于y.backward(torch.FloatTensor([1])),只不过对标量求导里面的参数可以不写。
自动求导不需要我们明确的写明那个函数对哪个函数求导,直接通过这行代码就能对所有的需要梯度的变量进行求导,得到它们的梯度,然后再获取。
矩阵求导例子:

X = torch.randn(3)
X = Variable(X, requires_grad=True)
Y = X * 2
print(Y)
Y.backward(torch.FloatTensor([1, 0.1,0.01]))
print(X.grad)

输出:
在这里插入图片描述
对于向量的求导,不能直接写Y.backword(),否则报错。需要传入参数。
Y.backword(torch.FloatTensor([1,1,1])): 表示得到结果就是它们每个分量的梯度
Y.backward(torch.FloatTensor([1, 0.1,0.01])):表示得到的梯度是它们原本梯度分别乘上1,0.1,0.01

2、Tensor的索引、分割及拼接

2.1、索引

x = torch.randn(3, 4)
print("x: \n{}".format(x))
print ("x[:2]: \n{}".format(x[:2]))
print ("x[:1, 1:3]: \n{}".format(x[:1, 1:3]))

输出:
在这里插入图片描述

由例子明显知道:
X[:N]–取前N行,不包括第N行;
X[:1,1:3] – 取第0行的第1,2,列,不包括第3列

2.2、通过维度索引筛选元素

# Select with dimensional indicies
x = torch.randn(2, 3)
print("Values: \n{}".format(x))
col_indices = torch.LongTensor([0, 2])
chosen = torch.index_select(x, dim=1, index=col_indices) #dim=1 -- 按列取,取第0列及第2列
print("Values: \n{}".format(chosen))
row_indices = torch.LongTensor([0, 1])
chosen = x[row_indices, col_indices] # 按索引取。values from (0, 0) & (1, 2)
print("Values: \n{}".format(chosen))

输出:
在这里插入图片描述

3、pytorch搭建神经网络

  pytorch使用torch.nn包来搭建各种神经网络。
  nn.Model 包含神经网络层级结构及forward(input)方法,该方法返回output。(前向传播)

例:

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120) #输入样本[* x 400], 输出[* x 120] (*表示任意数字)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square you can only specify a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, self.num_flat_features(x))    #-1--表示自动推测其它维数
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features


net = Net()
print(net)

params = list(net.parameters())   #返回模型需要学习的参数
print(len(params))
#print(params[0].size()) #conv1的权重W ,size: [6,1,5,5]  6个kernel,每个一个channel,大小5x5
for param in params:
    print(param.size())

输出:
在这里插入图片描述

《1》、nn.Conv2d函数原型:
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

作用: 在一个由多个输入plane组成的信号上执行2D卷积运算
参数说明:
  in_channels: 输入信号的channel数量。如RGB图像,3 channel。
  out_channels: 输出信号的channel数量,既是卷积核的个数。32个卷积核时会有32 个 output(feature map)。
  stride(整数或tuple类型):卷积的执行时的步长。可选参数,默认是1。
  padding(整数或tuple类型):控制对输入的边界进行0填充的数量。可选参数,默认是0。
  bias(bool类型):如果设置为true,则在计算输出时加入偏差。可选参数, 默认True。

《2》、nn.Linear函数原型:
torch.nn.Linear(in_features, out_features, bias=True)

作用:用于进行仿射变换(线性变换)
Parameters:
in_features – size of each input sample(输入样本尺寸的列数)
out_features – size of each output sample(输入样本尺寸的列数)
bias – If set to False, the layer will not learn an additive bias. Default: True

看内部实现才能很好的理解其参数的含义,其内部实现如下:
在这里插入图片描述
理解例子:

import torch
import torch.nn as nn
m = nn.Linear(20, 30)
input = torch.randn(128, 20)
print(input.size())
output = m(input)
print(output.size())

输出:
在这里插入图片描述

《3》、nn.functional.max_pool2d函数原型:
torch.nn.functional.max_pool2d(input, kernel_size, stride=None, padding=0, dilation=1, ceil_mode=False, return_indices=False)
《4》、view(*args)函数

  返回一个有相同数据单大小不同的tensor。返回的tensor必须与输入tensor有相同的数据和相同的数目。

《5》、net.parameters()

  返回模型所有需要学习的参数。

注意:

torch.nn只支持小批量输入。整个torch.nn包都只支持小批量样本而不支持单个样本。
   如nn.Conv2d将接受一个4维张量,每一维分别是:samples * channel * height * width (样本数 * 通道数 * 高 * 宽)

《6》、计算损失函数

  损失函数接受一对(net_output,target)作为输入,计算一个值来估计网络输出与目标值之间的差距(差距衡量有多种方法,如均方误差等)

input = torch.randn(1, 1, 32, 32)
output = net(input)
print(output)
target = torch.randn(10)  # a dummy target, for example
target = target.view(1, -1)  # make it the same shape as output
criterion = nn.MSELoss()  #均方误差  

loss = criterion(output, target)
print(loss)

输出:
在这里插入图片描述

《7》、反向传播

直接调用.backward()即可获取反向传播梯度。 需要注意的是,在获取梯度之前,必须清除已经存在的梯度,否则梯度将被累加到已存在的梯度。

net.zero_grad()     # zeroes the gradient buffers of all parameters

print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)

loss.backward()

print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)

输出:
在这里插入图片描述

《8》、权重更新方式

  a、自己写代码实现;
  b、import torch.optim as optim实现;

import torch.optim as optim

# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)

# in your training loop:
optimizer.zero_grad()   # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()

print('conv1.bias befor update: ')
print(net.conv1.bias)
print('conv1.bias updated: ')
optimizer.step()    # 更新 update
print(net.conv1.bias)

输出:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值