当前位置:网站首页>pytorch官方文档学习记录

pytorch官方文档学习记录

2022-06-25 16:34:00 岁月漫长_

官网教程:https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html

2022.6.21

一、快速入门

1. 处理数据

  • torch.utils.data.DataLoadertorch.utils.data.Dataset
    Dataset储存sampleslabel, DataLoader顾名思义,加载dataset中的数据。
    每个dataset都有两个参数,transform和target_transform,用于修改样本和标签
    TorchTextTorchVisionTorchAudio的库
# Download training data from open datasets.
training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),
)

# Download test data from open datasets.
test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor(),
)


batch_size = 64
# Create data loaders.
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)

for X, y in test_dataloader:
    print(f"Shape of X [N, C, H, W]: {
      X.shape}")
    print(f"Shape of y: {
      y.shape} {
      y.dtype}")
    break


2. 创建模型

# Get cpu or gpu device for training.
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {
      device} device")

# Define model
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        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

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

3. 优化模型参数

# 先定义损失函数和optimizer
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
## 训练部分
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device)

        # Compute prediction error
        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(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            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")

## 看每个epoch准确率和损失
epochs = 5
for t in range(epochs):
    print(f"Epoch {
      t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)
print("Done!")

4. 保存模型 加载模型

## 保存模型
torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")

## 加载模型
model = NeuralNetwork()
model.load_state_dict(torch.load("model.pth"))
## 用于预测
classes = [
    "T-shirt/top",
    "Trouser",
    "Pullover",
    "Dress",
    "Coat",
    "Sandal",
    "Shirt",
    "Sneaker",
    "Bag",
    "Ankle boot",
]

model.eval()
x, y = test_data[0][0], test_data[0][1]
with torch.no_grad():
    pred = model(x)
    predicted, actual = classes[pred[0].argmax(0)], classes[y]
    print(f'Predicted: "{
      predicted}", Actual: "{
      actual}"')

二、张量 tensors

1. 初始化张量的4个方法

张量类似于NumPy 的ndarray

## 
import torch
import numpy as np
### 1 自定义
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)
## 2 从nparray转化
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
## 3 复制另一个张量
x_ones = torch.ones_like(x_data) # 保留原始属性


x_rand = torch.rand_like(x_data, dtype=torch.float) # 覆盖原始数据类型

### 4 使用随机数或者恒定值
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

2. 张量的属性

tensor = torch.rand(3,4)
### 形状、数据类型和存储它们的设备
print(f"Shape of tensor: {
      tensor.shape}")
print(f"Datatype of tensor: {
      tensor.dtype}")
print(f"Device tensor is stored on: {
      tensor.device}")

3. 张量运算

默认情况下,张量是在 CPU 上创建的。需要使用 .to方法明确地将张量移动到 GPU

# 
if torch.cuda.is_available():
    tensor = tensor.to("cuda")
## 类似 numpy 的索引和切片,从0开始
tensor[:,1] = 0
## 连接张量 cat
t1 = torch.cat([tensor, tensor, tensor], dim=1)

4. 和numpy桥接

CPU 和 NumPy 数组上的张量可以共享它们的底层内存位置,改变一个会改变另一个。

三、 dataset和dataloader

可以用index索引 , 比如 training_data[index]

1. 自定义dataset

import os
import pandas as pd
from torchvision.io import read_image

class CustomImageDataset(Dataset):
    def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
        self.img_labels = pd.read_csv(annotations_file) ## csv保存标签
        self.img_dir = img_dir ## 路径
        self.transform = transform
        self.target_transform = target_transform
-----------------
labels.csv file looks like:
	tshirt1.jpg, 0
	tshirt2.jpg, 0
	......
	ankleboot999.jpg, 9
------------------
    def __len__(self):
        return len(self.img_labels) # 样本数量

    def __getitem__(self, idx):# idx意思是index
        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
        image = read_image(img_path) ## 转成tensor
        label = self.img_labels.iloc[idx, 1] ## 拿到label
        if self.transform:
            image = self.transform(image)
        if self.target_transform:
            label = self.target_transform(label)
        return image, label # returns the tensor image and label in a tuple.

2. 用dataloader加载数据

dataset是全部的数据,训练时我们希望用minibatches减少过拟合,加快速度

from torch.utils.data import DataLoader

train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True) ## 把数据加载到了dataloader中,可以 用dataloader进行迭代遍历数据集

# Display image and label.
train_features, train_labels = next(iter(train_dataloader))## 每次迭代都会返回一批train_features和train_labels
print(f"Feature batch shape: {
      train_features.size()}")
print(f"Labels batch shape: {
      train_labels.size()}")
img = train_features[0].squeeze() ## 这里应该是把图像转成 h*w 
label = train_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"Label: {
      label}")


四、变换 transform

对于训练,我们需要将特征转换为tensor格式并归一化到[0,1],并将标签用one-hot 编码(都是tensor)。使用ToTensorLambda

import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

ds = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),## 转换成张量,将 PIL 图像或 NumPy ndarray转换为Float Tensor. 并在 [0., 1.] 范围内缩放图像的像素强度值
    target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))## 用户定义的 lambda 函数,这里是首先创建一个大小为 10 的零张量(数据集中的标签数量)并调用 scatter_,在标签的 index 处设为1
)

五、构建模型

PyTorch中的每个模块都是 nn.Module 的子类。

1. 构建神经网络

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

### 1. 检查GPU可用性
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {
      device} device")
-------------------
### 2.定义类
# 每个子类都要继承nn.Module,并写__init__方法,实现forward

class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        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

model = NeuralNetwork().to(device)# 移动到GPU上
print(model)

---------
# 使用模型时就传入数据,然后执行forward操作,但是不能直接model.forward()
X = torch.rand(1, 28, 28, device=device)
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits) ## 使用softmax进行分类
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {
      y_pred}")

2. 模型层 layer

## nn.Flatten:把2维数据展平成1维
flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())

## nn.Linear 利用weights和biases实现线性变换 y = ax + b 
layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())

## nn.ReLU 非线性激活,负数全设为0
print(f"Before ReLU: {
      hidden1}\n\n")
hidden1 = nn.ReLU()(hidden1)
print(f"After ReLU: {
      hidden1}")

在这里插入图片描述

## nn.Sequential 按顺序堆层
seq_modules = nn.Sequential(
    flatten,
    layer1,
    nn.ReLU(),
    nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)

## nn.Softmax 输出[0, 1]之间的值,表示模型对每个类别的预测概率

softmax = nn.Softmax(dim=1) # dim 值必须总和为 1 的维度
pred_probab = softmax(logits)


###模型参数
# 使用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")

六、自动微分 TORCH.AUTOGRAD

训练神经网络时,最常用的算法是 反向传播。

import torch

x = torch.ones(5)  # input tensor
y = torch.zeros(3)  # expected output
w = torch.randn(5, 3, requires_grad=True)## requires_grad=True 表示这是需要优化的参数
b = torch.randn(3, requires_grad=True)
z = torch.matmul(x, w)+b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)

在这里插入图片描述
为了优化神经网络中参数的权重,我们需要计算我们的损失函数对参数的导数,为了计算这些导数,我们调用 loss.backward(),然后从w.gradb.grad 取得值。

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


## 禁用梯度跟踪, 比如在应用模型时

z = torch.matmul(x, w)+b
print(z.requires_grad)  # true

with torch.no_grad():
    z = torch.matmul(x, w)+b
print(z.requires_grad) # false

七、优化模型参数

### 1. 先加载代码
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)

test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        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

model = NeuralNetwork()

### 2.超参数,比如epoch,batch size,lr (学习率learning_rate)

### 3.损失函数
# 常见的损失函数包括用于回归任务的nn.MSELoss(均方误差)和 用于分类的nn.NLLLoss(负对数似然)。 nn.CrossEntropyLoss结合了nn.LogSoftmax和nn.NLLLoss。
# Initialize the loss function
loss_fn = nn.CrossEntropyLoss()  # 将模型的输出 logits 传递给 nn.CrossEntropyLoss

### 4.优化器


optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

在训练循环中,优化分三个步骤进行:

  1. 调用optimizer.zero_grad()以重置模型参数的梯度。默认情况下加起来;为了防止重复计算,我们在每次迭代时明确地将它们归零。
  2. 调用loss.backward()来反向传播预测损失。PyTorch 存储每个参数的损失梯度。
  3. 一旦我们有了反向传播中收集的梯度,调用optimizer.step()调整参数。

完整训练循环

# 1 训练loop
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}]")

# 2 测试loop
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")
# 3 初始化损失函数和优化器,并将其传递给train_loop和test_loop。增加 epoch 的数量来跟踪模型的改进性能。
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!")



八、保存和加载模型

保存和加载模型权重
PyTorch 模型将学习到的参数存储在内部状态字典中,称为state_dict. 这些可以通过以下torch.save 方法持久化:

### 保存模型
model = models.vgg16(pretrained=True)
torch.save(model.state_dict(), 'model_weights.pth')
### 要加载模型权重,首先需要创建一个相同模型的实例,然后使用load_state_dict()方法加载参数。
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()
### 在应用之前,请确保调用Model.eval()方法将dropout 和批处理标准化层设置为评估模式
原网站

版权声明
本文为[岁月漫长_]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_40859587/article/details/125397541