赞
踩
Pytorch官网:快速入门Pytorch地址:
https://pytorch.org/tutorials/beginner/basics/intro.html
步骤:
1.数据准备——2. 模型选择/开发——3. 模型训练调优——4. 模型评估测试
https://pytorch.org/tutorials/beginner/basics/data_tutorial.html
import torch from torch import nn from torch.utils.data import DataLoader # 处理数据API:torch.utils.data.DataLoader and torch.utils.data.Dataset # Dataset存储示例及其对应的标签 # DataLoader将可迭代对象包装在Dataset周围。 from torchvision import datasets #PyTorch提供特定于域的库,如TorchText、TorchVision和TorchAudio,所有这些都包括数据集。 #每个TorchVision数据集包含两个参数:Transform和Target_Transform,分别用于修改样本和标签。 from torchvision.transforms import ToTensor, Lambda, Compose import matplotlib.pyplot as plt # 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(), ) # 加载数据:https://pytorch.org/tutorials/beginner/basics/data_tutorial.html # 我们将Dataset作为参数传递给DataLoader。 # 这将在我们的数据集上封装一个可迭代的包,并支持自动批处理、采样、洗牌和多进程数据加载。 # 在这里,我们定义了一个64的批处理大小batch size,即dataloader迭代中的每个元素都将返回一个由64个特性和标签组成的批处理。 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("Shape of X [N, C, H, W]: ", X.shape) print("Shape of y: ", y.shape, y.dtype) break
# 创建模型 #构建神经网络:https://pytorch.org/tutorials/beginner/basics/buildmodel_tutorial.html # PyTorch中定义一个神经网络:需要创建了一个继承自nn.Module的类。 # 我们在__init_函数中定义网络层,并指定数据在forward函数中通过网络。 # 为了加速神经网络中的操作,如果有可用的话,我们将其移动到GPU。 # Get cpu or gpu device for training. device = "cuda" if torch.cuda.is_available() else "cpu" print("Using {} device".format(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), nn.ReLU() ) def forward(self, x): x = self.flatten(x) logits = self.linear_relu_stack(x) return logits model = NeuralNetwork().to(device) print(model)
# 优化模型参数:https://pytorch.org/tutorials/beginner/basics/optimization_tutorial.html # 要训练模型,我们需要一个损失函数和一个优化器。 loss_fn = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=1e-3) # 在单个训练循环中,模型对训练数据集进行预测(分批反馈),并反向传播预测误差以调整模型的参数。 def train(dataloader, model, loss_fn, optimizer): size = len(dataloader.dataset) 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): size = len(dataloader.dataset) 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 /= size 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) print("Done!")
# 保存模型 # 保存模型的常见方法是序列化内部状态字典(包含模型参数)。 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是一种与数组和矩阵非常相似的专门数据结构。在PyTorch中,我们使用张量对模型的输入和输出以及模型的参数进行编码。张量与NumPy的ndarray相似,只是张量可以在GPU或其他硬件加速器上运行。
import torch import numpy as np # 初始化张量Tensor #法一: 使用数据,初始化Tensor data = [[1, 2],[3, 4]] x_data = torch.tensor(data) print("数据初始化Tensor",x_data.shape) #法二: NumPy数组,初始化Tensor np_array = np.array(data) x_np = torch.from_numpy(np_array) #法三:另一个张量,初始化Tensor x_ones = torch.ones_like(x_data) # retains the properties of x_data print(f"Ones Tensor: \n {x_ones} \n") x_rand = torch.rand_like(x_data, dtype=torch.float) # overrides the datatype of x_data print(f"Random Tensor: \n {x_rand} \n") #法四:使用随机值或常量值,初始化Tensor shape = (2,3,) #shape决定了输出张量的尺寸。 rand_tensor = torch.rand(shape) ones_tensor = torch.ones(shape) zeros_tensor = torch.zeros(shape) print(f"Random Tensor: \n {rand_tensor} \n") print(f"Ones Tensor: \n {ones_tensor} \n") print(f"Zeros Tensor: \n {zeros_tensor}") # 张量属性——描述它们的形状、数据类型和存储它们的设备。 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}") # 张量操作:https://pytorch.org/docs/stable/torch.html。100多个张量运算,包括算术、线性代数、矩阵操作(转置、索引、切片)、采样等。 # 默认情况下,张量是在CPU上创建的。我们需要使用.to方法显式地将张量移动到GPU上(在检查GPU可用性后)。 if torch.cuda.is_available(): tensor = tensor.to('cuda') # 标准数字索引和切片: tensor = torch.ones(4, 4) print('First row: ',tensor[0]) print('First column: ', tensor[:, 0]) print('Last column:', tensor[..., -1]) tensor[:,1] = 0 print(tensor) # 连接多个tensor t1 = torch.cat([tensor, tensor, tensor], dim=1) print(t1) # 算数运算 #通过将张量的所有值聚合为一个值,您可以使用item()将其转换为Python数值: agg = tensor.sum() agg_item = agg.item() print(agg_item, type(agg_item)) # 代替操作——加,在之前基础上+5 print(tensor, "\n") tensor.add_(5) print(tensor) # 和Numpy共享底层数据 # 张量到Numpy数组 t = torch.ones(5) print(f"t: {t}") # t: tensor([1., 1., 1., 1., 1.]) n = t.numpy() print(f"n: {n}") # n: [1. 1. 1. 1. 1.] #张量的变化反映在NumPy数组中。 t.add_(1) print(f"t: {t}") print(f"n: {n}") # NumPy数组到张量 n = np.ones(5) t = torch.from_numpy(n) # NumPy数组的变化反映在张量中。 np.add(n, 1, out=n) print(f"t: {t}") print(f"n: {n}")
我们希望数据集代码与模型训练代码分离,以获得更好的可读性和模块化。pytorch提供了torch.utils.data.DataLoader和torch.utils.data.Dataset,允许使用预加载的数据集以及您自己的数据。Dataset存储样本及其对应的标签,DataLoader将一个可迭代对象包装在数据集周围,以便方便地访问样本。
PyTorch域库提供了许多预加载的数据集(比如fashionmist),它们是torch.utils.data的子类。数据集和实现特定数据的函数。它们可以用来制作模型的原型和基准测试。例如: Image Datasets, Text Datasets, and Audio Datasets
从 TorchVision 加载 Fashion-MNIST 数据集的示例。Fashion-MNIST是Zalando文章图像的数据集,由60,000个培训示例和10,000个测试示例组成。每个示例包括28×28灰度图像和来自10个类别之一的相关标签。
import torch from torch.utils.data import Dataset from torchvision import datasets from torchvision.transforms import ToTensor, Lambda import matplotlib.pyplot as plt # 加载数据集 # 加载带有以下参数的FashionMNIST数据集: # root是存储训练/测试数据的路径, # train指定训练或测试数据集, # download=True downloads the data from the internet if it’s not available at root. # transform和target_transform指定功能和标签转换 training_data = datasets.FashionMNIST( root="data", train=True, download=True, transform=ToTensor() ) test_data = datasets.FashionMNIST( root="data", train=False, download=True, transform=ToTensor() ) # 迭代和可视化数据集 labels_map = { 0: "T-Shirt", 1: "Trouser", 2: "Pullover", 3: "Dress", 4: "Coat", 5: "Sandal", 6: "Shirt", 7: "Sneaker", 8: "Bag", 9: "Ankle Boot", } figure = plt.figure(figsize=(8, 8)) 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) plt.title(labels_map[label]) plt.axis("off") plt.imshow(img.squeeze(), cmap="gray") plt.show() # 创建自定义数据集 # 必须包含__init__, __len__, and __getitem__三个方法。 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)# 照片名,label:tshirt1.jpg, 0 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): #从给定索引idx的数据集加载并返回示例。 img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0]) image = read_image(img_path)#基于索引,标识图像在磁盘上的位置,并使用read_image将其转换为张量 label = self.img_labels.iloc[idx, 1]#从self.img_labels中的csv数据中检索相应的标签 if self.transform: image = self.transform(image) if self.target_transform: label = self.target_transform(label) sample = {"image": image, "label": label} return sample # DataLoaders为训练准备数据,并可以根据需要迭代该数据集。 # 在训练模型时,我们通常希望以“小批量”的方式传递样本,在每个epoch重新洗刷数据以减少模型过拟合,并使用Python的多处理来加速数据检索。 # DataLoader是一个迭代器。 from torch.utils.data import DataLoader #该数据集加载到Dataloader。小批量 train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True) test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True) # 通过DataLoader迭代 #下面的每次迭代都返回一批train_features和train_labels ' '(分别包含' ' batch_size=64个特性和标签)。 # shuffle=True,在遍历所有批次之后,数据将被打乱(为了更细粒度地控制数据加载顺序)。 # Display image and label. train_features, train_labels = next(iter(train_dataloader)) print(f"Feature batch shape: {train_features.size()}") print(f"Labels batch shape: {train_labels.size()}") img = train_features[0].squeeze() label = train_labels[0] plt.imshow(img, cmap="gray") plt.show() print(f"Label: {label}")
我们使用Transformers来对数据进行一些操作,并使其适合训练。所有TorchVision数据集都有两个参数——transform以修改功能和target_transform以修改标签——它们接受包含转换逻辑的可调用参数。torchvision.transforms模块提供了几种常用的开箱即用转换。
例如:FashionMNIST功能采用PIL图像格式,标签为整数。对于训练,我们需要normalized标准化张量功能,以及one-hot编码的张量标签。为了进行这些转换,我们使用ToTensor和Lambda。
其中ToTensor(),将PIL图像或NumPy ndarray转换为FloatTensor。并将图像的像素强度值缩放到[0.,1]范围内。
其中Lambda,定义一个函数来将整数转换为一个one-hot编码张量。它首先创建一个大小为10的零张量(数据集中标签的数量),并调用scatter_,该函数在标签y给定的索引上赋值为1。
import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda
ds = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),#normalized标准化,将PIL图像或NumPy ndarray转换为FloatTensor。并将图像的像素强度值缩放到[0.,1]范围内。
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))#定义一个函数来将整数转换为一个one-hot编码
#它首先创建一个大小为10的零张量(数据集中标签的数量),并调用scatter_,该函数在标签y给定的索引上赋值为1。
)
torch.nn命名空间提供了构建自己的神经网络所需的所有构建块。torch.nn.Module是所有神经网络模块的基类。神经网络是由其他模块(层)组成的模块本身。
例子:将建立一个神经网络,对FashionMNIST数据集中的图像进行分类。
import os import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms #希望能够在GPU等硬件加速器上训练我们的模型,让我们检查 torch.cuda 是否可用,否则我们将继续使用 CPU。 device = 'cuda' if torch.cuda.is_available() else 'cpu' print('Using {} device'.format(device)) # Define the Class #我们通过神经网络子类 nn.Module 来定义神经网络。 # 在__init__中初始化神经网络层。每一个nn.Module子类实现了forward方法中对输入数据的操作。 class NeuralNetwork(nn.Module):#定义神经网络,继承自 nn.Module def __init__(self):#初始化 super(NeuralNetwork, self).__init__() self.flatten = nn.Flatten()# 将每个2D 28x28图像转换为一个由784像素值组成的连续数组 self.linear_relu_stack = nn.Sequential(#Sequential是一个有序的模块容器。数据按照定义的相同顺序通过所有模块。您可以使用顺序容器来组合一个像seq_modules这样的快速网络。 nn.Linear(28*28, 512),#使用weights 和 biases.对输入应用线性变换的模块。 nn.ReLU(),#非线性激活在模型的输入和输出之间创建了复杂的映射。它们在线性变换后应用于引入非线性, nn.Linear(512, 512), nn.ReLU(), nn.Linear(512, 10), nn.ReLU() ) def forward(self, x):#自动调用model.forward() x = self.flatten(x) logits = self.linear_relu_stack(x) return logits model = NeuralNetwork().to(device)#创建实例自定义的神经网络 print(model) #调用model,将返回一个10维张量,其中包含每个类的原始预测值。我们通过nn.Softmax得到预测概率。 X = torch.rand(1, 28, 28, device=device) logits = model(X) pred_probab = nn.Softmax(dim=1)(logits)#logits被缩放到值[0,1]代表模型对每个类的预测概率。dim参数表示数值之和必须为1的维度。 y_pred = pred_probab.argmax(1) print(f"Predicted class: {y_pred}") #在训练过程中优化了相关的权重和偏差,nn.Module模块自动跟踪模型对象中定义的所有字段 # ,并使用模型的parameters()或named_parameters()方法访问所有参数。 print("Model structure: ", model, "\n\n") for name, param in model.named_parameters(): print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
在训练神经网络时,最常用的算法是反向传播算法。在该算法中,根据损失函数相对于给定参数的梯度来调整参数(模型权值)。为了计算这些梯度,PyTorch内置了一个名为torch.autograd的差异化引擎。它支持自动计算梯度为任何计算图形。
import torch
x = torch.ones(5) # input tensor
y = torch.zeros(3) # expected output
w = torch.randn(5, 3, requires_grad=True)# 默认情况下,所有require_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)
print('Gradient function for z =',z.grad_fn)#grad_fn存储反向传播函数的引用;
print('Gradient function for loss =', loss.grad_fn)
loss.backward()#计算导数,loss.backward(),从w.grad和b.grad中检索值。
print(w.grad)
print(b.grad)
#先决条件代码 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), nn.ReLU() ) def forward(self, x): x = self.flatten(x) logits = self.linear_relu_stack(x) return logits model = NeuralNetwork() # Hyperparameters 超参数是可调参数,让您控制模型优化过程。不同的超参数值可以影响模型训练和收敛速度。 #为训练定义了以下超参数: # epoch的数量——在数据集上迭代的次数 # Batch Size-模型在每个epoch 中看到的数据样本的数量 # Learning Rate-在每个batch/epoch更新模型参数的次数。较小的值产生缓慢的学习速度,而较大的值可能导致在训练过程中不可预测的行为 learning_rate = 1e-3 batch_size = 64 epochs = 5 # 一旦我们设置了超参数,我们就可以用一个优化循环来训练和优化我们的模型。优化循环的每次迭代称为epoch。 #每个epoch包括两个主要部分: # 训练循环-迭代训练数据集,并尝试收敛到最优参数。 # 验证/测试循环——遍历测试数据集以检查模型性能是否得到改善。 # 损失函数Loss Function #当使用一些训练数据时,未经训练的网络很可能给出不正确的答案。 # 损失函数用来度量得到的结果与目标值的不相似程度,它是我们在训练过程中希望最小化的损失函数。 # 为了计算损失,我们使用给定数据样本的输入进行预测,并将其与真实数据标签值进行比较。 # 常见的损失函数:nn.MSELoss (Mean Square Error)用于回归任务;nn.NLLLoss (Negative Log Likelihood)用于分类任务。 # nn.CrossEntropyLoss 结合了 nn.LogSoftmax、nn.NLLLoss. # Initialize the loss function loss_fn = nn.CrossEntropyLoss()# 模型的输出logit传递给nn.CrossEntropyLoss,它将标准化logit并计算预测误差。 # 优化器Optimizer #优化是在每个训练步骤中调整模型参数以减少模型误差的过程。 # 优化算法定义了如何执行这个过程(在本例中,我们使用了随机梯度下降)。 # 所有优化逻辑都封装在优化器对象中。这里,我们使用SGD优化器;此外,PyTorch中还有许多不同的优化器,如ADAM和RMSProp,它们更适合于不同类型的模型和数据。 optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)# 初始化需要训练的模型参数来初始化优化器,并通过学习速率超参数。 # 在训练循环中,优化分为三个步骤: # 调用optimizer.zero_grad()重置模型参数的梯度。渐变默认为累加;为了防止重复计算,我们在每次迭代时显式地将它们置零。 # 通过调用loss.backward()来反向传播预测损失。 # 有了梯度之后,我们调用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) 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 /= size 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!")
import torch import torch.onnx as onnx import torchvision.models as models # 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(而不是model.state_dict())传递给保存函数: torch.save(model, 'model.pth') model = torch.load('model.pth')#加载模型:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。