PyTorch简明教程 | 1-基础操作和CNN简介

from __future__ import print_function
import torch


##1 基本操作
#构建tensor
x = torch.empty(5, 3)
x = torch.rand(5, 3)
x = torch.zero(5, 3, dtype=torch.long)

#Operation
y = torch.rand(5, 3)
torch.add(x, y)
result = torch.empty(5, 3)
torch.add(x, y, out=result) #x+y结果放到result里
y.add_(x)
x.copy_(y)

#Tensor变换
print(x[:, 1]) #打印第一列
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) #-1意思是让torch自己推断第一维大小

##torch几个维度查看和变换的函数
torch.size()
b = a.view(-1, 3, 2)  #前后尺寸要一致

torch.squeeze() / torch.unsqueeze() 
#torch.squeeze(n)函数表示压缩tensor中第n维为1的维数
>>> b.squeeze(2).size()
torch.Size([1, 3, 2])
>>> b.squeeze(0).size()
torch.Size([3, 2])
#torch.unsqueeze(n)则是在第n维增加一个维数=1

torch.permute() #按照自己期望的位置重新排序
permute(2, 0, 1)  #注意数字是维度的index而不是数值

#numpy互转
#np和torch共享地址,修改一个会改变另一个
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
# [2. 2. 2. 2. 2.]
print(b)
# tensor([ 2.,  2.,  2.,  2.,  2.], dtype=torch.float64)

#CUDA tensor
if torch.cuda.is_available():
    device = torch.device("cuda")            # 一个CUDA device对象。
    y = torch.ones_like(x, device=device)    # 直接在GPU上创建tensor
    x = x.to(device)                         # 也可以使用``.to("cuda")``把一个tensor从CPU移到GPU上
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))         # ``.to``也可以在移动的过程中修改dtype

##2 自动求导
# requires_grad是True,那么PyTorch就会追踪所有与之相关的operation。反向传播backward()
# 在测试时,with torch.no_grad() 不计算梯度
# Function类,与tensor相互连接从而形成一个有向无环图,记录历史。每个tensor有一个grad_fn属性来引用创建这个tensor的Function

x = torch.ones(2, 2, requires_grad=True)

#梯度
out.backward()
print(x.grad)  #d(out)/dx

print((x ** 2).requires_grad)

with torch.no_grad():  #用来停止梯度计算
    print((x ** 2).requires_grad)


##3 神经网络
#torch.nn来创建

#1)定义网络
import torch
import torch.nn as nn
# import torch.nn.function as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 输入是1个通道的灰度图,输出6个通道(feature map),使用5x5的卷积核
        self.conv1 = nn.Conv2d(1, 6, 5)
        # 第二个卷积层也是5x5,有16个通道
        self.conv2 = nn.Conv2d(6, 16, 5)
        #全连接
        self.fc1 = nn.Linear(16*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), (2,2))
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = view(-1, self.num_flat_features(x))
        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:]  # 除了batch维度之外的其它维度。
            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的weight


#2)测试网络
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)

#清空梯度
net.zero_grad()
out.backward(torch.randn(1, 10))
#注意:torch.nn只支持mini-batches的输入。整个torch.nn包的输入都必须第一维是batch,即使只有一个样本也要弄成batch是1的输入。
#nn.Conv2d的输入是一个4D的Tensor,shape是nSamples x nChannels x Height x Width。
#如果你只有一个样本(nChannels x Height x Width),那么可以使用input.unsqueeze(0)来增加一个batch维。

#3)损失函数
output = net(input)
criterion = nn.MSELoss()
loss = criterion(output, target)

#4)计算梯度
net.zero_grad()     # 清掉tensor里缓存的梯度值。
loss.backward()

#5)更新参数
import torch.optim as optim
# 创建optimizer,需要传入参数和learning rate
optimizer = optim.SGD(net.parameters(), lr=0.01)

#清除梯度,optimizer.zero_grad()一次清除所有。
optimizer.zero_grad()
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()

 

posted @ 2020-08-22 18:37  eo_will  阅读(338)  评论(0编辑  收藏  举报