大多数机器学习工作流程包含处理数据,建立模型,优化模型参数,和保存训练模型。

将使用FashionMNIST 数据集来训练一个神经网络,功能是预测一张输入图片是否属于其中【T-shirt/top, Trouser, Pullover, Dress, Coat, Sandal, Shirt, Sneaker, Bag, or Ankle boot】的一类。

处理数据

PyTorch 有两种处理数据的类:torch.utils.data.DataLoader 和torch.utils.data.Dataset。

Dataset存储有样本数据以及其对应的标签。而DataLoader包装着一个围绕着数据集的可迭代对象。

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

Pytorch 提供了特定领域的库,如TorchText,TorchVision和TorchAudio,其中都包含有数据集。这里使用的是TorchVision数据集。

torchvison.datasets模块包含很多现实世界数据的数据集,如CIFAR,COCO等。这里使用的FashionMNIST数据集。

每个TorchVision数据集含有两个参数transform和target_transform分别修改样本数据和标签。

# 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(),)

将Dataset作为参数传递给DataLoader。DataLoader包装一个围绕数据集的可迭代对象,并其支持自动分批,取样,重新打乱和多进程处理数据加载。

batch_size=64

# Create data loaders
train_dataloader=DataLoader(training_data,batch_size=batch_size)
test_dataloader=DataLoader(test_data,baatch_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

创建模型

为了定义Pytorch里的神经网络,定义一个类,继承nn.Module。并在__init__函数中定义神经网络的层和在forward函数中定义数据在模型中传递。为了加速在神经网络的操作,可以将模型放到GPU或MPS上。

# Create model
device=('cuda' if torch.cuda.is_available() else 'cpu')
print(f'using {device} divice')

# define model
class NeuralNetWork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flattern=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.flattern(x)
        logits=self.linear_relu_stack(x)
        return logits

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

优化模型参数

为了训练模型,需要一个损失函数和优化器。

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
        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(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')

为了更好的训练模型,让模型整体多执行几次。

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!')

保存模型

一种通用方式去保存模型是序列化内部状态字典(含有模型参数)

torch.save(model.state_dict(),'model.pth')
print('Saved Pytorch Model State to model.pth')

加载模型

加载模型包含重新创建一个模型架构和加载状态字典数据到模型里。

model=NeuralNetWork().to(device)
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_dataset[0][0],test_dataset[0][1]
with torch.no_grad():
    x=x.to(device)
    pred=model(x)
    predicted,actual=classes[pred[0].argmax(0)],classes[y]
    print(f'Predicted:"{predicted}",Actual:"{actual}"')

整体代码:

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

# working with data
train_dataset=torchvision.datasets.FashionMNIST(root=r'data',train=True,transform=ToTensor(),download=False)
test_dataset=torchvision.datasets.FashionMNIST(root=r'data',train=False,transform=ToTensor(),download=False)
# img,label=train_dataset[0]
# print(type(img))
# print(type(label))

batch_size=64
train_dataloader=DataLoader(dataset=train_dataset,batch_size=batch_size)
test_dataloader=DataLoader(dataset=test_dataset,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

# Create model
device='cpu'
# device=('cuda' if torch.cuda.is_available() else 'cpu')
print(f'using {device} divice')

# define model
class NeuralNetWork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flattern=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.flattern(x)
        logits=self.linear_relu_stack(x)
        return logits

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

#
loss_fn=nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.06)

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
        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(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')



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!')

# save models
torch.save(model.state_dict(),'model.pth')
print('Saved Pytorch Model State to model.pth')

# loading models
model=NeuralNetWork().to(device)
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_dataset[0][0],test_dataset[0][1]
with torch.no_grad():
    x=x.to(device)
    pred=model(x)
    predicted,actual=classes[pred[0].argmax(0)],classes[y]
    print(f'Predicted:"{predicted}",Actual:"{actual}"')

 

 posted on 2024-03-23 15:11  会飞的金鱼  阅读(14)  评论(0)    收藏  举报