pytorch学习一(神经网络入门)
2020-03-25 本文已影响0人
幺姨母
import torch
import numpy
tensor的基本用法
类似于numpy的数组,但可以使用GPU加速计算
- 创建未初始化矩阵 torch.Tensor(height, width)
- 创建随机初始化的矩阵 torch.rand(height, width)
- 得到矩阵大小 torch.size()
- 运算
- 非原地操作y.add(x)
- 原地操作y.add_(x)
- 可以像numpy一样索引 x[:, 1]
- tensor和numpy可以相互转换,可共享内存空间
- a.numpy(), torch.from_numpy(b)
- a.add(), numpy.add(b, 1)不共享内存空间
- 用.cuda可将tensor移到GPU上 x = x.cuda()
# 1
x = torch.Tensor(5, 3)
#print(x)
# 2
x = torch.rand(5, 3)
y = torch.rand(5, 3)
#print(x)
#print(y)
# 3
#print(x.size())
# 4
z = y.add(x)
#print(z)
# 5
#print(z[:, 1])
# 6
a = torch.ones(5, 5)
b = a.numpy()
#print(b)
a.add_(1)
a = torch.from_numpy(b)
numpy.add(b, 1, out = b)
#print(a)
#print(b)
# 7
if torch.cuda.is_available():
#print("succ")
x = x.cuda()
y = y.cuda()
#print(x + y)
autograd自动求梯度
提供了所有tensor自动求微分的功能
- 创建Variable实例
- Variable类的data属性可以获取tensor
- Variable类的grad属性可以获取gradient
- 想计算某个变量的梯度调用.backward()函数
- 标量可直接调用 x.grad = dout/dx
- tensor需要指定一个跟该tensor同样大小的grad_output对该tensor加权求和
from torch.autograd import Variable
# 创建variable
x = Variable(torch.ones(2, 2), requires_grad = True)
y = x + 2
z = 3 * y ** 2
grad_output = torch.tensor([1, 1, 0.5, 1]).reshape(2, 2)
z.backward(grad_output)
#print(grad_output)
#print(x.grad)
##################
#out = z.mean()
#out.backward()
#print(x.data)
#print(x.grad)
#print(y.grad)
神经网络
可以使用torch.nn构建神经网络
一个nn.Module包含各个层和一个forward(input)方法,该方法返回output
概念
- 最大池化
- 卷积
- 过拟合
- ReLU
- 线性层
- epoch: 使用训练集的全部数据对模型进行一次完整训练,称为“一代训练”
- batch: 使用训练集的一小部分样本对模型权重进行一次反向传播的参数更新,这一小部分样本被称为“一批数据”
- iteration: 使用一个batch数据对模型进行一次参数更新的过程,称为“一次训练”
神经网络的典型训练过程
- 定义神经网络模型,有一些可学习的参数或权重
- 在数据集上迭代
- 通过神经网络处理输入
- 计算损失(输出结果和正确值的差距大小)
- 将梯度反向传播回网络的参数
- 更新网络的参数,主要使用如下简单的更新原则 weight = weight - learning_rate * gradient
import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
# 网络定义一般由两部分组成
# 1. def __init__(self): 用来定义网络节点参数
# 2. def forward(self, x): 将节点连接成图
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=3)
self.linear = nn.Linear(5766, 10)
self.relu = nn.ReLU(inplace=True)
self.maxpooling = nn.MaxPool2d((2,2))
def forward(self, x):
x = self.conv(x)
#print(x.shape)
x = self.maxpooling(x)
#print(x.shape)
x = self.relu(x)
#print(x.shape)
x = x.view(1, -1) # -1表自适应调整剩余维度
#print(x.shape)
x = self.linear(x)
return x
# 添加训练数据
if __name__ =='__main__':
# 转移到GPU上训练
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
# optimizer是优化器,即所谓的反向传播算法
# criterion是损失函数
optimizer = torch.optim.Adam(net.parameters())
criterion = nn.MSELoss()
net.train()
epoch = 100
# 卷积计算规则
# 输入形状为(batch,channel,height,width)
# 如果在GPU上训练,需要将数据导入GPU中
# 网络目标是给定随机噪声向量,输出逼近1的单位向量
input = torch.randn(1,1,64,64).cuda()
output = torch.ones(1,10).cuda()
# 训练
# 为了得到反向传播误差,需要调用loss.backward()函数
# 梯度会累加,因此每次训练时要消除已存在的梯度
for step in range(epoch):
prediction = net(input)
loss = criterion(prediction, output)
# 消除优化器梯度后自动求导
optimizer.zero_grad()
loss.backward()
# 根据自动求导反向传播进行参数优化更新
optimizer.step()
if step % 10 == 0:
print("EPOCHS:{},LOSS:{:4f}".format(step,loss))
# 输出结果时必须将tensor从GPU转移到CPU上
# 对计算图中的tensor如prediction,必须加.detach()从计算图中导出再化为numpy
print(prediction.cpu().detach().numpy())
print(output.cpu().numpy())
EPOCHS:0,LOSS:1.340370
EPOCHS:10,LOSS:0.579189
EPOCHS:20,LOSS:0.174512
EPOCHS:30,LOSS:0.048418
EPOCHS:40,LOSS:0.014742
EPOCHS:50,LOSS:0.009842
EPOCHS:60,LOSS:0.003036
EPOCHS:70,LOSS:0.001941
EPOCHS:80,LOSS:0.000184
EPOCHS:90,LOSS:0.000160
[[0.9888366 1.0040277 0.99330235 1.0093783 0.98669255 1.0013827
1.0095942 1.0066952 1.0083659 1.0059038 ]]
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]