pytorch使用

import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" #原始环境为了避免混乱的包冲突

1. 张量(tensor)

import torch
import numpy as np

1.1 初始化

data = [[1, 2],[3, 4]]
x_data = torch.tensor(data) #从列表初始化
np_array = np.array(data)
x_data = torch.from_numpy(np_array) #从numpy初始化
x_ones = torch.ones_like(x_data)    #保持相同规模,全部置1
x_rand = torch.rand_like(x_data, dtype=torch.float) #保持相同规模,生成随机数

根据维度进行初始化

shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

1.2 张量运算

像numpy一样进行索引和切片

tensor[0] #第一行
tensor[:,0] #第一列
tensor[...,-1] #最后一列
t1 = torch.cat([tensor, tensor, tensor], dim=1) #进行拼接

算数运算

#内积
tensor*tensor   tensor.mul(tensor)
#矩阵乘法
X@X  X.matmul(X)
tensor.sum() #所有元素求和
#增加_ , 进行原地操作
tensor.add_(5) #所有元素增加5

内存共享(可以轻松使用numpy的所有运算)

#从tensor生成numpy , 与从numpy生成tensor,二者内存共享
np_ = tensor.numpy() 
tensor = torch.from_numpy(np_)

2. 数据集和数据读取

2.1 可视化(随机展示9张图片)

import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt

 #training_data每个索引包含一个元组,第一个数据为图像tensor,第二个数据为预测类别int
figure = plt.figure(figsize=(8, 8))  #创建一个图像对象,尺寸为8X8
cols, rows = 3, 3
for i in range(1, cols * rows + 1): 
    sample_idx = torch.randint(len(training_data), size=(1,)).item() #生成随机索引
    img, label = training_data[sample_idx] #根据索引读取图片和预测标签
    figure.add_subplot(rows, cols, i) #在3X3的子图网格中添加子图
    plt.title(label)  #可以让预测标签映射到实际名字作为显示
    plt.axis("off")
    plt.imshow(img.squeeze(), cmap="gray") #显示压缩的灰度图
plt.show()

2.2 自定义数据集类进行读取

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

class CustomImageDataset(Dataset): #继承自Dataset的类

自定义数据集类必须包含三部分:__init__, __len__, and __getitem__

def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
        self.img_labels = pd.read_csv(annotations_file)  #图片名字和对应标签
        self.img_dir = img_dir   #图片路径
        self.transform = transform   
        self.target_transform = target_transform

def __len__(self):
     return len(self.img_labels)   #数据的个数
def __getitem__(self, idx):
        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0]) #拼接图像路径,和图像名称
        image = read_image(img_path)  #读取图片成张量格式
        label = self.img_labels.iloc[idx, 1] #对应图片的标签
        if self.transform:
            image = self.transform(image) 
        if self.target_transform:
            label = self.target_transform(label)
        return image, label #返回图像和对应标签

2.3 数据洗牌和迭代

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)
train_features, train_labels = next(iter(train_dataloader)) #每次可以得到64个随机数据

2.4 Transforms

简单处理

transform=ToTensor(),  #对数据进行处理,这里是变成张量格式,同时归一化处理
#对标签数据进行处理,这里是根据类别进行one-hot编码
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))

Script the transformation

transforms = torch.nn.Sequential(
    transforms.CenterCrop(10),
    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
)
scripted_transforms = torch.jit.script(transforms)

3. 建立一个神经网络

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
device = (  #检验cuda能否使用
    "cuda"
    if torch.cuda.is_available()
    else "mps"
    if torch.backends.mps.is_available()
    else "cpu"
)
print(f"Using {device} device")
class NeuralNetwork(nn.Module):  #注意这里的模型是有参数的(权重和偏差)
    def __init__(self):
        super().__init__() #父类初始化
        self.flatten = nn.Flatten() #将二维图像展平成一维向量
        self.linear_relu_stack = nn.Sequential( #按序组合多个层
            nn.Linear(28*28, 512), #全连接层,将28×28图像展平后,连接到512神经元的隐藏层
            nn.ReLU(),    #ReLU激活函数
            nn.Linear(512, 512),     #全连接层,将512隐藏层输出连接到另一个512隐藏层
            nn.ReLU(),    #ReLU激活函数
            nn.Linear(512, 10),    #全连接层,将512隐藏层输出连接到10维的输出层
        )

    def forward(self, x):  #前向传播
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits
model = NeuralNetwork().to(device)  #j将这个类放到gpu上

4. 完整的前向传播和反向传播

一次训练迭代过程过程

def train_loop(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset) #总训练数据集大小
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        # Compute prediction and loss
        pred = model(X)
        loss = loss_fn(pred, y)

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

        if batch % 100 == 0: #每一百轮输出一次
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")


def test_loop(dataloader, model, loss_fn):
    # Set the model to evaluation mode - important for batch normalization and dropout layers
    # Unnecessary in this situation but added for best practices
    model.eval()
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    # Evaluating the model with torch.no_grad() ensures that no gradients are computed during test mode
    # also serves to reduce unnecessary gradient computations and memory usage for tensors with requires_grad=True
    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")

进行多次迭代更新参数

model = NeuralNetwork()
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!")

存储模型

torch.save(model, 'model.pth')
model = torch.load('model.pth')
posted @ 2023-09-19 00:11  失控D大白兔  阅读(7)  评论(0编辑  收藏  举报