快速入门pytorch,建立自己的深度学习模型

Pytorch(list,tuple,nArray以及Tensor)

预备知识:讲述了列表(list),元组(tuple),数组(Array-numpy).

list和tuple的最大区别就是是否可以修改,对于list而言是可变的数据类型可以进行增删改查,而tuple就是不可变的数据类型,tuple一旦被创建就不能增删改。

然后数组与list、tuple的最大区别就是:前者要求数组内的所有的数据类型一致,而后者内的元素数据类型可以不一致.

在List中存放的是元素的指针,因此一个元素需要存放指针+数据,增加了存储和消耗CPU.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6pebjuQl-1666968898084)(C:\Users\panhengyu\AppData\Roaming\Typora\typora-user-images\image-20221022132100569.png)]

  1. 在numpy中的每个维度长度都记录在shape属性中(元组表示),数组中的维是数组深度(嵌套数组)的一个级别,嵌套数组是将数组作为元素的数组,即数组中有数组. 比如:(2,3)表示第一个维度的长度为2,第二个维度的长度为3.比如: 通过np.admin()获得维度数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aM85vbaU-1666968898089)(C:\Users\panhengyu\AppData\Roaming\Typora\typora-user-images\image-20221022161411134.png)]

  1. numpy数组中的轴(axis):

    numpy数组的某个轴,指的是:该数组的某个维度的方向,其方向从索引号由低到高。许多numpy方法或函数在调用时,常常需要指定一个关键参数“axis=X”,它表示的是沿哪个轴的方向进行运算(例如,求均值,方差等),这里的X表示的是轴的索引号(axis=0表示轴0,axis=1表示轴1,…,依此类推)。

​ numpy的维度与轴数一致.以维度(3,4,5)的三维数组为例,它有3个维度,因此,它的轴有3个,即”轴0“,”轴1“,”轴2“长度分别为3,4,5。

比如:
a.mean(axis=1):表示沿轴1方向求每个元素的均值.
a.mean(axis=0):表示沿着轴0方向求每个元素的均值.
a.mean的结果维度肯定是剩余轴构成的维度.

比如:图像批处理
一幅RGB图像的1个通道的数据可表示为一个(H,W)的数组,现在有3个通道,因此,一幅RGB图像可以用维度为(3,H,W)的数组来表示,而N幅图像则可以用维度为(N,3,H,W)的数组来表示。

参考:https://blog.csdn.net/caijungan/article/details/119861315

Tensors

Tensors 和Numpy的n维数组是类似的.除了如此,Tensors也可以运行在GPU上或者其他硬件加速器上. 并且NumPy和Tensors之间互换的时候经常是分享内存的,因此无需有额外的拷贝开销. Tensors也是可以自动微分优化的.

Tuple/List=>np.array()=>nArray=>torch.tensor(List)/torch.from_numpy(nArray)=>Tensor:

张量操作有成千上万,这些操作都可以在GPU上运行,默认情况下,张量是在CPU上创建的.我们需要使用.to方法,蒋张量显式移动到GPU。

1.把张量移动到GPU上加速

if torch.cuda.is_available():
    tensor=tensor.to("cuda")

2. 张量拼接

torch.cat([tensor,tensor,tensor],dim=1):对三个张量在1维度进行拼接.

3. 矩阵乘法和矩阵元素相乘:

# This computes the matrix multiplication between two tensors. y1, y2, y3 will have the same value
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)

y3 = torch.rand_like(y1)
torch.matmul(tensor, tensor.T, out=y3)

# This computes the element-wise product. z1, z2, z3 will have the same value
z1 = tensor*tensor
z2 = tensor.mul(tensor.T)
z3 = torch.rand_like(z1)
tensor.mul(tensor,tensor.T,out=z3)

4. In-place operations 将结果存储到操作数中的操作称为就地操作,以_为后缀,

tensor.add_(5):在原来操作数的张量上进行修改,对每个元素加上5,然后存放在tensor张量上.

in-place操作可以节省一些内存空间,但是在计算倒数的时候,由于失去一些历史记录,会出错,因此in-place操作是不推荐的.

Build Model

the torch.nn包命名空间提供了你构建自己神经网络所需要的所有块(building blocks).比如torch.nn.modules包中含有一些模块,torch.nn.functional包含有各种损失函数等.

  1. Get Device for Training:

    device = "gpu" if torch.cuda.is_available() else "cpu"
    print(device)
    
  2. Define the class

    我们定义的类是torch.nn.Module类的子类,里面必须包含有**_ _init _ _ 方法(初始化),并且每个torch.nn.Module的子类都要在forward**方法中实现对输入数据的操作.

    class NeuralNetwork(nn.Module):
        def __init__(self):
            super(NeuralNetwork,self).__init__()
    
    
        def forward(self,x):
    

    然后:实例化NeuralNetwork,然后把他搬到GPU上运行

    model = NeuralNetwork().to(device)
    print(model)
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OqBIV70u-1666968898091)(Pytorch.assets/image-20221028211450124-16669628915731.png)]

  3. Model Parameters

    神经网络中的所有层都是参数化的,有在训练过程中被优化的相关权重和偏置.使用你模型的parameters()方法和named_parameters()方法 可以访问这些参数.

    print(f"Model structure: {model}\n\n")
    
    for name, param in model.named_parameters():
        print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
    

完整的代码如下:

from tkinter import N
from turtle import forward
import torch
import torch.nn as nn
import torch.nn.modules as m
import torch.nn.functional as f


class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork,self).__init__()
        self.flatten=nn.Flatten()
        # nn.Sequential 是有序的模块容器.数据按照定义的顺序通过所有模块
        self.linear_relu_stack=nn.Sequential(
            nn.Linear(28*28,512),
            nn.ReLU(),
            nn.Linear(512,512),
            nn.ReLU(),
            nn.Linear(512,10)
        )

    def forward(self,x):
        x=self.flatten(x)
        logits=self.linear_relu_stack(x)
        return logits

device = "cuda" if torch.cuda.is_available() else "cpu"
print(device)
model=NeuralNetwork().to(device)
print(model)
X=torch.rand(1,28,28,device=device)
logits=model(X)
# he logits are scaled to values [0, 1] representing the model’s predicted probabilities for each class.
#其中dim 参数决定了沿着这一维度的值加起来和为1
y_pred=torch.nn.Softmax(dim=1)(logits)
print(y_pred)

Autograd

建立好了模型后,需要对模型进行训练,使模型中的权重调整到最优即优化问题.

其中在训练神经网络过程中,最经常使用的优化算法就是反向传播(back propagation).

模型中的参数会根据loss function的梯度被调整.

torch.autograd: 支持任意可计算图的自动梯度计算.

在这里插入图片描述

  1. Computing Gradients:

​ 为了优化我们神经网络的权重参数,我们需要计算我们损失函数中参数的梯度,比如,我们需要固定 x 和 y x和y xy中计算 δ l o s s δ w \frac{\delta loss}{\delta w} δwδloss δ l o s s δ b \frac{\delta loss}{\delta b} δbδloss

loss.backward()
print(w.grad)
print(b.grad)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvEumbSn-1666968898094)(Pytorch.assets/image-20221028215323256-16669652050627.png)]

  1. Disabling Gradient Tracking

    默认,对于requires_grad=True的所有张量(tensor)都会被跟踪它们的计算记录和支持梯度计算.但很多时候我们不需要做这些.比如说,我们已经训练完整个模型了,只需要把这个模型应用在一些输入数据上时,i.e. we only want to do forward computations through the network. We can stop tracking computations by surrounding our computation code with torch.no_grad() block:

    with torch.no_grad():
    	#这个方法块内的计算记录不会被记录.
    	
    

    或者同样的在张量上使用*detach()*方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-feACyDWn-1666968898096)(Pytorch.assets/image-20221028222434407-16669670768179.png)]

forward和backward的过程:

Optimization

  1. Hyperparameters

    超参数是控制你模型优化速度的可变参数.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6e32shm-1666968898098)(Pytorch.assets/image-20221028223037097-166696743853513.png)]

  2. Optimization Loop

    一旦我们设置好超参,那么我们就可以训练和优化我们的模型.每一个优化循环的iteration叫做epoch

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ofuoJe4q-1666968898100)(Pytorch.assets/image-20221028223213136-166696753448515-166696756380517.png)]

  3. select the loss function and Optimizer

    optimizer优化器是在torch.optim包上

    定义一个优化器:
    optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)
    

    在Training Loop中,optimization happens in three steps

    1. optimizer.zero_grad():作用是情况model.parameters()中所有参数的梯度,梯度一般都是累加的,但是为了避免重复计算,我们需要在每个回合显式清零
    2. loss.backward():损失函数调用backward(),反向梯度计算
    3. 一旦我们有了梯度后,我们就会调用 optimizer.step() 根据反向梯度来更新参数.
def train_loop(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        # Compute prediction and loss
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {
      
      loss:>7f}  [{
      
      current:>5d}/{
      
      size:>5d}]")


def test_loop(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    with torch.no_grad():
        for X, y in dataloader:
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()

    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {
      
      (100*correct):>0.1f}%, Avg loss: {
      
      test_loss:>8f} \n")
    
    
    
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

epochs = 10
for t in range(epochs):
    print(f"Epoch {
      
      t+1}\n-------------------------------")
    train_loop(train_dataloader, model, loss_fn, optimizer)
    test_loop(test_dataloader, model, loss_fn)
print("Done!")    

Saving and Loading Model Weights

Save:Pytorch模型将已经学习后的参数存放在内部状态文件夹中,叫做 state_dict ,可以用 torch.save() 方法保存.

model = models.vgg16(pretrained=True)
torch.save(model.state_dict(), 'model_weights.pth')

Load: 需要创建相同模型的实例,然后加载参数model.load_state_dict(torch.load(path)),然后再用model.eval()

model = models.vgg16() # we do not specify pretrained=True, i.e. do not load default weights
model.load_state_dict(torch.load('model_weights.pth'))
model.eval()

如果我们想要保存和加载参数和模型,那么

torch.save(model,path)

model=

参考文献

https://pytorch.org/tutorials/beginner/basics/saveloadrun_tutorial.html

猜你喜欢

转载自blog.csdn.net/Blockchain210/article/details/127580852