Machine Learning —— pytorch入门

Machine Learning —— pytorch入门

torch简单操作

1、张量生成

from __future__ import print_function
import torch

x1 = torch.empty(5, 3)
#生成一个未初始化的5*3的张量,数值随机
print(x1)

x2 = torch.rand(5, 3)
#生成一个均匀分布的张量,元素从0-1
print(x2)
#其他随机张量生成函数:torch.randn()标准正态分布、torch.normal()离散正太分布、torch.linespace()线性间距向量

x3 = torch.zeros(5, 3, dtype = torch.long)
#初始化一个全零张量,可以指定元素的类型
print(x3)

x4 = torch.tensor([5.5, 3])
#将矩阵转化为张量
print(x4)

x5 = x.new_ones(5, 3, dtype = torch.double)
#利用已有张量创建新张量,新创建张量属性与原张量一致,若不设定值属性,则类型与原张量也一致
print(x5)

x6 = torch.randn_like(x, dtype = torch.float)
print(x6)

print(x.size())
#获取张量的形状,输出的torch.Size()是一个元组

2、张量的操作

y = torch.rand(5, 3)

#加法
print(x + y)
print(torch.add(x, y))

result = torch.empty(5, 3)
torch.add(x, y, out = result)
print(result)

y.add_(x)
#‘_’符合在所有替换自身操作符的末尾都有

#调整张量形状
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)
#参数中的-1就代表这个位置由其他位置的数字来推断
#如果是torch.view(-1),则原张量会变成一维的结构

#查看张量的大小
x = torch.randn(1)
print(x)
print(x.item())

3、张量和numpy互换

#在CPU情况下,张量和array共享物理地址
a = torch.ones(5)
print(a)

b = a.numpy()
#张量转numpy
print(b)

a.add_(1)
print(a)
print(b)

import numpy as np

a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out = a)
print(a)
print(b)
  • GPU下的转换
#使用“torch.device”使用和禁止GPU
if torch.cuda.is_available():
    device = torch.device('cuda')           #创建一个cuda device对象  
    y = torch.ones_like(x, device = device) #在GPU上创建一个张量
    x = x.to(device)                        #.to(device)=.to('cuda')
    z = x + y
    print(z)
    print(z.to('cpu', torch.double))        #.to也可以直接转换类型

out:
	tensor([1.3832], device='cuda:0')
	tensor([1.3832], dtype=torch.float64)

Autograd: 自动求导(automatic differentiation)

PyTorch 中所有神经网络的核心是autograd包

  • autograd包为张量上的所有操作提供了自动求导.它是一个运行时定义的框架,这意味着反向传播是根据你的代码如何运行来定义,并且每次迭代可以不同

变量(Variable)

  • autograd.Variable是autograd包的核心类.它包装了张量(Tensor),支持几乎所有的张量上的操作.一旦你完成你的前向计算,可以通过.backward()方法来自动计算所有的梯度
  • 可以通过.data属性来访问变量中的原始张量,关于这个变量的梯度被计算放入.grad属性中
  • 对自动求导的实现还有一个非常重要的类,即函数(Function)
  • 变量(Variable)和函数(Function)是相互联系的,并形成一个非循环图来构建一个完整的计算过程.每个变量有一个.grad_fn属性,它指向创建该变量的一个Function,用户自己创建的变量除外,它的grad_fn属性为None
  • 计算导数,可以在一个变量上调用.backward().如果一个Variable是一个标量(它只有一个元素值),你不必给该方法指定任何的参数,但是该Variable有多个值,你需要指定一个和该变量相同形状的的grad_output参数
import torch
from torch.autograd import Variable

#创建一个变量
x = Variable(torch.ones(2, 2), requires_grad = True)
print(x)

#对变量进行操作
y = x + 2
print(y)
#y是通过x操作创建的,y有grad_fn,而x是用户创建的,所以x的grad_fn为None
print(x.grad_fn)
print(y.grad_fn)


#在y上执行操作
z = y * y *3
out = z.mean()

print(z, out)

梯度(Gradient)

现在我们来执行反向传播

out.backward()
#out.backward()相当于执行out.backward(torch.Tensor([1.0]))

#输出out对x的梯度 d(out)/dx
print(x.grad)

此时得到一个值全为4.5的矩阵,该结果的推导过程:
o u t = 1 4 ∑ i z i out=\frac{1}{4}\sum_iz_i out=41izi

z i = 3 ( x i + 2 ) 2 z_i=3(x_i+2)^2 zi=3(xi+2)2

∂ o u t ∂ x i = 3 2 ( x i + 2 ) \frac{\partial out}{\partial x_i}=\frac{3}{2}(x_i+2) xiout=23(xi+2)

其他例子
x = torch.randn(3)
print(x)

x = Variable(x, requires_grad = True)

y = x * 2
while y.data.norm() < 1000:
    #data.norm():L2范数
    y = y * 2
    
print(y)

gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)

print(x.grad)

Neural network

可以使用torch.nn包来构建神经网络,torch.nn包依赖autograd包定义模型并求导,一个nn.module包含各个层和一个**faward(input)**方法,该方法返回output

神经网络的典型训练过程:
  • 定义神经网络模型(权重等)
  • 在数据集上迭代
  • 通过神经网络处理输入
  • 计算损失
  • 将梯度反向传播调整网络参数
  • 更新网络参数
    w i + 1 = w i − η ∗ g r a d i e n t w_{i+1}=w_i-\eta *gradient wi+1=wiηgradient

定义网络

#定义网络
import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    #定义Net的初始化函数,这个函数定义了神经网络的基本结构
    def __init__(self):
        super(Net, self).__init__()
        #对继承自父类的属性进行初始化
        #复制并使用Net的父类的初始化方法,即先运行nn.Module的初始化函数
        #super(Net, self).__init__():首先找到Net的父类(比如是类NNet),然后把类Net的对象self转换为类NNet的对象,然后“被转换”的类NNet对象调用自己的init函数
        
        self.conv1 = nn.Conv2d(1, 6, 5)  #定义conv1函数的图像卷积函数:输入为图像(1个频道,即灰度图),输出为6张特征图,卷积核为5*5正方形
        self.conv2 = nn.Conv2d(6, 16, 5) #定义conv2函数的图像卷积函数:输入6张特征图,输出16张特征图,卷积核为5*5正方形
        
        self.fc1 = nn.Linear(16 * 5 *5, 120) #定义fc1全连接函数为线性函数:y=wx+b,将16*5*5个节点连接到120个节点上
        self.fc2 = nn.Linear(120, 84)        #定义fc2全连接函数为线性函数:y=wx+b,将1210个节点连接到84个节点上
        self.fc3 = nn.Linear(84, 10)         #定义fc3全连接函数为线性函数:y=wx+b,将84个节点连接到10个节点上
        
    #定义该神经网络的前向传播函数,后向传播函数会随前向传播函数自动生成    
    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))#x输入经过卷积conv1,经过激活函数ReLU,使用2*2窗口进行最大池化,然后更新到x
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)     
        x = x.view(-1, self.num_flat_features(x))      #view函数将张量x变形成一维的向量,总特征数不变,为接下来的全连接做准备
        x = F.relu(self.fc1(x))   #x输入后经过全连接1,再经过ReLU激活函数,然后更新到x
        x = F.relu(self.fc2(x))   
        x = self.fc3(x)           #x输入经过全连接3,然后更新x
        
    #使用num_flat_features函数计算张量x的总特征量(每个数字都是一个特征)
    def num_flat_features(self, x):
        size = x.size()[1:]   #pytorch只接收批输入,[1:]把注意力放在后三维
        num_features = 1
        for s in size:
            num_features *= s
        return num_features
    
net = Net()
print(net)
输出:
Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

net.parameters()函数可返回模型需要学习的参数

params = list(net.parameters())
print(len(params))
for param in params:
    print(param.size())
10
torch.Size([6, 1, 5, 5])
torch.Size([6])
torch.Size([16, 6, 5, 5])
torch.Size([16])
torch.Size([120, 400])
torch.Size([120])
torch.Size([84, 120])
torch.Size([84])
torch.Size([10, 84])
torch.Size([10])

forward的输入和输出都是autograd.Variable,以上网络的输入大小是3232,如果使用MNIST数据集训练网络,需要把图片大小重新调整到3232

input = Variable(torch.randn(1, 1, 32, 32))
out = net(input)
print(out)

将所有参数的梯度缓存清零,然后进行随机梯度反向传播(未完成)

net.zero_grad()
out.backward(torch.randn(1, 10))
注意
  • torch.nn只支持小批量输入
  • nn.Conv2d接收一个4维的张量,分别是s(Samples)x n(Channels)x Height x Width(样本数x通道数x高x宽)
  • 如果有单个样本,需使用input.unsqueeze(0)来添加其它的维数
回顾类
  • torch.Tensor:多维数组
  • autograd.Variable:包装一个Tensor,记录在其上执行过的操作,除了拥有Tensor的API,还有类似backward()的API,也保持这个向量的梯度
  • nn.Module:神经网络模块,封装参数,移到GPU上运行,导出,加载等
  • nn.parameter:当把它赋值给一个Module时,被自动注册为一个参数
  • autograd.Function:实现自动求导操作的前向和反向定义,每个变量操作至少创建一个函数节点

损失函数

一个损失函数接收(output,target)作为输入
在nn包中有几种不同的损失函数

out = net(input)
target = Variable(torch.arange(1, 11))
criterion = nn.MSELoss()

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

反向跟踪loss,使用它的.grad_fn属性,你会看到向下面这样的一个计算图:

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
      -> view -> linear -> relu -> linear -> relu -> linear
      -> MSELoss
      -> loss

反向传播

更新权重

使用各种不同的更新规则,比如SGD,Nesterov-SGD,Adam, RMSPROP等.为了能做到这一点,构建一个包torch.optim实现了所有的这些规则

import torch.optim as optim

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

#in your trainning loop:
optimizer.zero_grad()  # zero the gradient buffers
output = net(input)
loss = criter(output, target)
loss.backward()
optimizer.setp() # does the update

参考

https://blog.youkuaiyun.com/weixin_41070748/article/details/89890330?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162052260016780366559053%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=162052260016780366559053&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-3-89890330.first_rank_v2_pc_rank_v29&utm_term=pytorch

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值