当前位置: 首页 > news >正文

成品网站w灬源码在线看网站建设中数据字典

成品网站w灬源码在线看,网站建设中数据字典,也是网络品牌建设和推广的基础,zuiruo笑话类博客wordpress主题Transformers 库建立在 Pytorch 框架之上#xff08;Tensorflow 的版本功能并不完善#xff09;#xff0c;虽然官方宣称使用 Transformers 库并不需要掌握 Pytorch 知识#xff0c;但是实际上我们还是需要通过 Pytorch 的 DataLoader 类来加载数据、使用 Pytorch 的优化器…Transformers 库建立在 Pytorch 框架之上Tensorflow 的版本功能并不完善虽然官方宣称使用 Transformers 库并不需要掌握 Pytorch 知识但是实际上我们还是需要通过 Pytorch 的 DataLoader 类来加载数据、使用 Pytorch 的优化器对模型参数进行调整等等。这里将介绍 Pytorch 的一些基础概念以及后续可能会使用到的类 1 Pytorch 基础 Pytorch 由 Facebook 人工智能研究院于 2017 年推出具有强大的 GPU 加速张量计算功能并且能够自动进行微分计算从而可以使用基于梯度的方法对模型参数进行优化。截至 2022 年 8 月PyTorch 已经和 Linux 内核、Kubernetes 等并列成为世界上增长最快的 5 个开源社区之一。现在在 NeurIPS、ICML 等等机器学习顶会中有超过 80% 研究人员用的都是 PyTorch。 为了确保商业化和技术治理之间的相互独立2022 年 9 月 12 日 PyTorch 官方宣布正式加入 Linux 基金会PyTorch 基金会董事会包括 Meta、AMD、亚马逊、谷歌、微软、Nvidia 等公司。 1.1 张量 张量 (Tensor) 是深度学习的基础例如常见的 0 维张量称为标量 (scalar)、1 维张量称为向量 (vector)、2 维张量称为矩阵 (matrix)。Pytorch 本质上就是一个基于张量的数学计算工具包它提供了多种方式来创建张量 import torchtorch.empty(2, 3) # empty tensor (uninitialized), shape (2,3) tensor([[2.7508e23, 4.3546e27, 7.5571e31],[2.0283e-19, 3.0981e32, 1.8496e20]])torch.rand(2, 3) # random tensor, each value taken from [0,1) tensor([[0.8892, 0.2503, 0.2827],[0.9474, 0.5373, 0.4672]])torch.randn(2, 3) # random tensor, each value taken from standard normal distribution tensor([[-0.4541, -1.1986, 0.1952],[ 0.9518, 1.3268, -0.4778]])torch.zeros(2, 3, dtypetorch.long) # long integer zero tensor tensor([[0, 0, 0],[0, 0, 0]])torch.zeros(2, 3, dtypetorch.double) # double float zero tensor tensor([[0., 0., 0.],[0., 0., 0.]], dtypetorch.float64)torch.arange(10) tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])也可以通过 torch.tensor() 或者 torch.from_numpy() 基于已有的数组或 Numpy 数组创建张量 array [[1.0, 3.8, 2.1], [8.6, 4.0, 2.4]]torch.tensor(array) tensor([[1.0000, 3.8000, 2.1000],[8.6000, 4.0000, 2.4000]])import numpy as nparray np.array([[1.0, 3.8, 2.1], [8.6, 4.0, 2.4]])torch.from_numpy(array) tensor([[1.0000, 3.8000, 2.1000],[8.6000, 4.0000, 2.4000]], dtypetorch.float64)注意上面这些方式创建的张量会存储在内存中并使用 CPU 进行计算如果想要调用 GPU 计算需要直接在 GPU 中创建张量或者将张量送入到 GPU 中 torch.rand(2, 3).cuda() tensor([[0.0405, 0.1489, 0.8197],[0.9589, 0.0379, 0.5734]], devicecuda:0)torch.rand(2, 3, devicecuda) tensor([[0.0405, 0.1489, 0.8197],[0.9589, 0.0379, 0.5734]], devicecuda:0)torch.rand(2, 3).to(cuda) tensor([[0.9474, 0.7882, 0.3053],[0.6759, 0.1196, 0.7484]], devicecuda:0)1.2 张量计算 张量的加减乘除是按元素进行计算的例如 x torch.tensor([1, 2, 3], dtypetorch.double)y torch.tensor([4, 5, 6], dtypetorch.double)print(x y) tensor([5., 7., 9.], dtypetorch.float64)print(x - y) tensor([-3., -3., -3.], dtypetorch.float64)print(x * y) tensor([ 4., 10., 18.], dtypetorch.float64)print(x / y) tensor([0.2500, 0.4000, 0.5000], dtypetorch.float64)Pytorch 还提供了许多常用的计算函数如 torch.dot() 计算向量点积、torch.mm() 计算矩阵相乘、三角函数和各种数学函数等 x.dot(y) tensor(32., dtypetorch.float64)x.sin() tensor([0.8415, 0.9093, 0.1411], dtypetorch.float64)x.exp() tensor([ 2.7183, 7.3891, 20.0855], dtypetorch.float64)除了数学运算Pytorch 还提供了多种张量操作函数如聚合 (aggregation)、拼接 (concatenation)、比较、随机采样、序列化等详细使用方法可以参见 Pytorch 官方文档。 对张量进行聚合如求平均、求和、最大值和最小值等或拼接操作时可以指定进行操作的维度 (dim)。例如计算张量的平均值在默认情况下会计算所有元素的平均值。 x torch.tensor([[1, 2, 3], [4, 5, 6]], dtypetorch.double)x.mean() tensor(3.5000, dtypetorch.float64)更常见的情况是需要计算某一行或某一列的平均值此时就需要设定计算的维度例如分别对第 0 维和第 1 维计算平均值 x.mean(dim0) tensor([2.5000, 3.5000, 4.5000], dtypetorch.float64)x.mean(dim1) tensor([2., 5.], dtypetorch.float64)注意上面的计算自动去除了多余的维度因此结果从矩阵变成了向量如果要保持维度不变可以设置 keepdimTrue x.mean(dim0, keepdimTrue) tensor([[2.5000, 3.5000, 4.5000]], dtypetorch.float64)x.mean(dim1, keepdimTrue) tensor([[2.],[5.]], dtypetorch.float64) 拼接 torch.cat 操作类似通过指定拼接维度可以获得不同的拼接结果 x torch.tensor([[1, 2, 3], [ 4, 5, 6]], dtypetorch.double)y torch.tensor([[7, 8, 9], [10, 11, 12]], dtypetorch.double)torch.cat((x, y), dim0) tensor([[ 1., 2., 3.],[ 4., 5., 6.],[ 7., 8., 9.],[10., 11., 12.]], dtypetorch.float64)torch.cat((x, y), dim1) tensor([[ 1., 2., 3., 7., 8., 9.],[ 4., 5., 6., 10., 11., 12.]], dtypetorch.float64)组合使用这些操作就可以写出复杂的数学计算表达式。例如对于 z ( x y ) × ( y − 2 ) z(xy)\times(y-2) z(xy)×(y−2) 当 x 2 , y 3 x2, y3 x2,y3 时很容易计算出 z 5 z5 z5 。使用 Pytorch 来实现这一计算过程与 Python 非常类似唯一的不同是数据使用张量进行保存 x torch.tensor([2.])y torch.tensor([3.])z (x y) * (y - 2)print(z) tensor([5.])使用 Pytorch 进行计算的好处是更高效的执行速度尤其当张量存储的数据很多时而且还可以借助 GPU 进一步提高计算速度。下面以计算三个矩阵相乘的结果为例我们分别通过 CPU 和 NVIDIA GPU 来进行 import torch import timeitM torch.rand(1000, 1000) print(timeit.timeit(lambda: M.mm(M).mm(M), number5000))N torch.rand(1000, 1000).cuda() print(timeit.timeit(lambda: N.mm(N).mm(N), number5000))# 77.78975469999999 # 1.6584811117500067可以看到使用 GPU 能够明显地提高计算效率。 1.3 自动微分 Pytorch 提供自动计算梯度的功能可以自动计算一个函数关于一个变量在某一取值下的导数从而基于梯度对参数进行优化这就是机器学习中的训练过程。使用 Pytorch 计算梯度非常容易只需要执行 tensor.backward()就会自动通过反向传播 (Back Propogation) 算法完成。 注意为了计算一个函数关于某一变量的导数Pytorch 要求显式地设置该变量是可求导的即在张量生成时设置 requires_gradTrue。我们对上面计算 z ( x y ) × ( y − 2 ) z(xy)\times(y-2) z(xy)×(y−2)的代码进行简单修改就可以计算当 x 2 , y 3 x2, y3 x2,y3 时 d z d x \frac{dz}{dx} dxdz​ 和 d z d y \frac{dz}{dy} dydz​ 的值。 x torch.tensor([2.], requires_gradTrue)y torch.tensor([3.], requires_gradTrue)z (x y) * (y - 2)print(z) tensor([5.], grad_fnMulBackward0)z.backward()print(x.grad, y.grad) tensor([1.]) tensor([6.])很容易手工求解 d z d x y − 2 , d z d y x 2 y \frac{dz}{dx}y-2, \frac{dz}{dy}x2y dxdz​y−2,dydz​x2y当 x 2 , y 3 x2, y3 x2,y3 时 d z d x 1 \frac{dz}{dx}1 dxdz​1 和 d z d y 6 \frac{dz}{dy}6 dydz​6, 与 Pytorch 代码计算结果一致。 1.4 调整张量形状 有时我们需要对张量的形状进行调整Pytorch 共提供了 4 种调整张量形状的函数分别为 形状转换 view 将张量转换为新的形状需要保证总的元素个数不变例如 x torch.tensor([1, 2, 3, 4, 5, 6])print(x, x.shape) tensor([1, 2, 3, 4, 5, 6]) torch.Size([6])x.view(2, 3) # shape adjusted to (2, 3) tensor([[1, 2, 3],[4, 5, 6]])x.view(3, 2) # shape adjusted to (3, 2) tensor([[1, 2],[3, 4],[5, 6]])x.view(-1, 3) # -1 means automatic inference tensor([[1, 2, 3],[4, 5, 6]])进行 view 操作的张量必须是连续的 (contiguous)可以调用 is_conuous 来判断张量是否连续如果非连续需要先通过 contiguous 函数将其变为连续的。也可以直接调用 Pytorch 新提供的 reshape 函数它与 view 功能几乎一致并且能够自动处理非连续张量。 转置 transpose 交换张量中的两个维度参数为相应的维度 x torch.tensor([[1, 2, 3], [4, 5, 6]])x tensor([[1, 2, 3],[4, 5, 6]])x.transpose(0, 1) tensor([[1, 4],[2, 5],[3, 6]])交换维度 permute 与 transpose 函数每次只能交换两个维度不同permute 可以直接设置新的维度排列方式 x torch.tensor([[[1, 2, 3], [4, 5, 6]]])print(x, x.shape) tensor([[[1, 2, 3],[4, 5, 6]]]) torch.Size([1, 2, 3])x x.permute(2, 0, 1)print(x, x.shape) tensor([[[1, 4]],[[2, 5]],[[3, 6]]]) torch.Size([3, 1, 2])1.5 广播机制 前面我们都是假设参与运算的两个张量形状相同。在有些情况下即使两个张量形状不同也可以通过广播机制 (broadcasting mechanism) 对其中一个或者同时对两个张量的元素进行复制使得它们形状相同然后再执行按元素计算。 例如我们生成两个形状不同的张量 x torch.arange(1, 4).view(3, 1)y torch.arange(4, 6).view(1, 2)print(x) tensor([[1],[2],[3]])print(y) tensor([[4, 5]])它们形状分别为 (3, 1) 和 (1, 2)如果要进行按元素运算必须将它们都扩展为形状 (3, 2) 的张量。具体地就是将 x 的第 1 列复制到第 2 列将 y 的第 1 行复制到第 2、3 行。实际上我们可以直接进行运算Pytorch 会自动执行广播 print(x y) tensor([[5, 6],[6, 7],[7, 8]])1.6 索引与切片 与 Python 列表类似Pytorch 也可以对张量进行索引和切片。索引值同样是从 0 开始切片 [m : n]的范围是从 m 到 n 前一个元素结束并且可以对张量的任意一个维度进行索引或切片。例如 x torch.arange(12).view(3, 4)x tensor([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])x[1, 3] # element at row 1, column 3 tensor(7)x[1] # all elements in row 1 tensor([4, 5, 6, 7])x[1:3] # elements in row 1 2 tensor([[ 4, 5, 6, 7],[ 8, 9, 10, 11]])x[:, 2] # all elements in column 2 tensor([ 2, 6, 10])x[:, 2:4] # elements in column 2 3 tensor([[ 2, 3],[ 6, 7],[10, 11]])x[:, 2:4] 100 # set elements in column 2 3 to 100x tensor([[ 0, 1, 100, 100],[ 4, 5, 100, 100],[ 8, 9, 100, 100]])1.7 降维与升维 有时为了计算需要对一个张量进行降维或升维。例如神经网络通常只接受一个批次 (batch) 的样例作为输入如果只有 1 个输入样例就需要手工添加一个 batch 维度。具体地 升维torch.unsqueeze(input, dim, outNone) 在输入张量的 dim 位置插入一维与索引一样dim 值也可以为负数降维 torch.squeeze(input, dimNone, outNone) 在不指定 dim 时张量中所有形状为 1 的维度都会被删除例如 (A, 1, B, 1, C) 会变成 (A, B, C)当给定 dim 时只会删除给定的维度形状必须为 1例如对于 (A, 1, B)squeeze(input, dim0) 会保持张量不变只有 squeeze(input, dim1) 形状才会变成 (A, B)。 a torch.tensor([1, 2, 3, 4])a.shape torch.Size([4])b torch.unsqueeze(a, dim0)print(b, b.shape) tensor([[1, 2, 3, 4]]) torch.Size([1, 4])b a.unsqueeze(dim0) # another way to unsqueeze tensorprint(b, b.shape) tensor([[1, 2, 3, 4]]) torch.Size([1, 4])c b.squeeze()print(c, c.shape) tensor([1, 2, 3, 4]) torch.Size([4])2 加载数据 Pytorch 提供了 DataLoader 和 Dataset 类或 IterableDataset专门用于处理数据它们既可以加载 Pytorch 预置的数据集也可以加载自定义数据。其中数据集类 Dataset或 IterableDataset负责存储样本以及它们对应的标签数据加载类 DataLoader 负责迭代地访问数据集中的样本。 2.1 Dataset 数据集负责存储数据样本所有的数据集类都必须继承自 Dataset 或 IterableDataset。具体地Pytorch 支持两种形式的数据集 映射型 (Map-style) 数据集 继承自 Dataset 类表示一个从索引到样本的映射索引可以不是整数这样我们就可以方便地通过 dataset[idx] 来访问指定索引的样本。这也是目前最常见的数据集类型。映射型数据集必须实现 __getitem__() 函数其负责根据指定的 key 返回对应的样本。一般还会实现 __len__() 用于返回数据集的大小。 DataLoader 在默认情况下会创建一个生成整数索引的索引采样器 (sampler) 用于遍历数据集。因此如果我们加载的是一个非整数索引的映射型数据集还需要手工定义采样器。 迭代型 (Iterable-style) 数据集 继承自 IterableDataset表示可迭代的数据集它可以通过 iter(dataset) 以数据流 (steam) 的形式访问适用于访问超大数据集或者远程服务器产生的数据。 迭代型数据集必须实现__iter__() 函数用于返回一个样本迭代器 (iterator)。 注意如果在 DataLoader 中开启多进程num_workers 0那么在加载迭代型数据集时必须进行专门的设置否则会重复访问样本。例如 from torch.utils.data import IterableDataset, DataLoaderclass MyIterableDataset(IterableDataset):def __init__(self, start, end):super(MyIterableDataset).__init__()assert end startself.start startself.end enddef __iter__(self):return iter(range(self.start, self.end))ds MyIterableDataset(start3, end7) # [3, 4, 5, 6] # Single-process loading print(list(DataLoader(ds, num_workers0))) # Directly doing multi-process loading print(list(DataLoader(ds, num_workers2)))[tensor([3]), tensor([4]), tensor([5]), tensor([6])][tensor([3]), tensor([3]), tensor([4]), tensor([4]), tensor([5]), tensor([5]), tensor([6]), tensor([6])]可以看到当 DataLoader 采用 2 个进程时由于每个进程都获取到了单独的数据集拷贝因此会重复访问每一个样本。要避免这种情况就需要在 DataLoader 中设置 worker_init_fn 来自定义每一个进程的数据集拷贝 from torch.utils.data import get_worker_infodef worker_init_fn(worker_id):worker_info get_worker_info()dataset worker_info.dataset # the dataset copy in this worker processoverall_start dataset.startoverall_end dataset.end# configure the dataset to only process the split workloadper_worker int(math.ceil((overall_end - overall_start) / float(worker_info.num_workers)))worker_id worker_info.iddataset.start overall_start worker_id * per_workerdataset.end min(dataset.start per_worker, overall_end)# Worker 0 fetched [3, 4]. Worker 1 fetched [5, 6]. print(list(DataLoader(ds, num_workers2, worker_init_fnworker_init_fn))) # With even more workers print(list(DataLoader(ds, num_workers20, worker_init_fnworker_init_fn)))# [tensor([3]), tensor([5]), tensor([4]), tensor([6])]# [tensor([3]), tensor([4]), tensor([5]), tensor([6])]下面我们以加载一个图像分类数据集为例看看如何创建一个自定义的映射型数据集 import os import pandas as pd from torchvision.io import read_image from torch.utils.data import Datasetclass CustomImageDataset(Dataset):def __init__(self, annotations_file, img_dir, transformNone, target_transformNone):self.img_labels pd.read_csv(annotations_file)self.img_dir img_dirself.transform transformself.target_transform target_transformdef __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可以看到我们实现了 __init__()、__len__() 和 __getitem__() 三个函数其中 __init__() 初始化数据集参数这里设置了图像的存储目录、标签通过读取标签 csv 文件以及样本和标签的数据转换函数__len__() 返回数据集中样本的个数__getitem__() 映射型数据集的核心根据给定的索引 idx 返回样本。这里会根据索引从目录下通过 read_image 读取图片和从 csv 文件中读取图片标签并且返回处理后的图像和标签。 2.2 DataLoaders 前面的数据集 Dataset 类提供了一种按照索引访问样本的方式。不过在实际训练模型时我们都需要先将数据集切分为很多的 mini-batches然后按批 (batch) 将样本送入模型并且循环这一过程每一个完整遍历所有样本的循环称为一个 epoch。 训练模型时我们通常会在每次 epoch 循环开始前随机打乱样本顺序以缓解过拟合。 Pytorch 提供了 DataLoader 类专门负责处理这些操作除了基本的 dataset数据集和 batch_size batch 大小参数以外还有以下常用参数 shuffle是否打乱数据集sampler采样器也就是一个索引上的迭代器collate_fn批处理函数用于对采样出的一个 batch 中的样本进行处理例如前面提过的 Padding 操作。 例如我们按照 batch 64 遍历 Pytorch 自带的图像分类 FashionMNIST 数据集每个样本是一张 28x28 的灰度图以及分类标签并且打乱数据集 from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensortraining_data datasets.FashionMNIST(rootdata,trainTrue,downloadTrue,transformToTensor() )test_data datasets.FashionMNIST(rootdata,trainFalse,downloadTrue,transformToTensor() )train_dataloader DataLoader(training_data, batch_size64, shuffleTrue) test_dataloader DataLoader(test_data, batch_size64, shuffleTrue)train_features, train_labels next(iter(train_dataloader)) print(fFeature batch shape: {train_features.size()}) print(fLabels batch shape: {train_labels.size()})img train_features[0].squeeze() label train_labels[0] print(img.shape) print(fLabel: {label})# Feature batch shape: torch.Size([64, 1, 28, 28]) # Labels batch shape: torch.Size([64]) # torch.Size([28, 28]) # Label: 82.2.1 数据加载顺序和 Sampler 类 对于迭代型数据集来说数据的加载顺序直接由用户控制用户可以精确地控制每一个 batch 中返回的样本因此不需要使用 Sampler 类。 对于映射型数据集来说由于索引可以不是整数因此我们可以通过 Sampler 对象来设置加载时的索引序列即设置一个索引上的迭代器。如果设置了 shuffle 参数DataLoader 就会自动创建一个顺序或乱序的 sampler我们也可以通过 sampler 参数传入一个自定义的 Sampler 对象。 常见的 Sampler 对象包括序列采样器 SequentialSampler 和随机采样器 RandomSampler它们都通过传入待采样的数据集来创建 from torch.utils.data import DataLoader from torch.utils.data import SequentialSampler, RandomSampler from torchvision import datasets from torchvision.transforms import ToTensortraining_data datasets.FashionMNIST(rootdata,trainTrue,downloadTrue,transformToTensor() )test_data datasets.FashionMNIST(rootdata,trainFalse,downloadTrue,transformToTensor() )train_sampler RandomSampler(training_data) test_sampler SequentialSampler(test_data)train_dataloader DataLoader(training_data, batch_size64, samplertrain_sampler) test_dataloader DataLoader(test_data, batch_size64, samplertest_sampler)train_features, train_labels next(iter(train_dataloader)) print(fFeature batch shape: {train_features.size()}) print(fLabels batch shape: {train_labels.size()}) test_features, test_labels next(iter(test_dataloader)) print(fFeature batch shape: {test_features.size()}) print(fLabels batch shape: {test_labels.size()})# Feature batch shape: torch.Size([64, 1, 28, 28]) # Labels batch shape: torch.Size([64]) # Feature batch shape: torch.Size([64, 1, 28, 28]) # Labels batch shape: torch.Size([64])2.2.2 批处理函数 collate_fn 批处理函数 collate_fn 负责对每一个采样出的 batch 中的样本进行处理。默认的 collate_fn 会进行如下操作 添加一个新维度作为 batch 维自动地将 NumPy 数组和 Python 数值转换为 PyTorch 张量保留原始的数据结构例如输入是字典的话它会输出一个包含同样键 (key) 的字典但是将值 (value) 替换为 batched 张量如何可以转换的话。 例如如果样本是包含 3 通道的图像和一个整数型类别标签即 (image, class_index)那么默认的 collate_fn 会将这样的一个元组列表转换为一个包含 batched 图像张量和 batched 类别标签张量的元组。 我们也可以传入手工编写的 collate_fn 函数以对数据进行自定义处理例如前面我们介绍过的 padding 操作。 3 训练模型 Pytorch 所有的模块层都是 nn.Module 的子类神经网络模型本身就是一个模块它还包含了很多其他的模块。 3.1 构建模型 我们还是以前面加载的 FashionMNIST 数据库为例构建一个神经网络模型来完成图像分类。模型同样继承自 nn.Module 类通过 __init__() 初始化模型中的层和参数在 forward() 中定义模型的操作例如 import torch from torch import nndevice cuda if torch.cuda.is_available() else cpu print(fUsing {device} device)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, 256),nn.ReLU(),nn.Linear(256, 10),nn.Dropout(p0.2))def forward(self, x):x self.flatten(x)logits self.linear_relu_stack(x)return logitsmodel NeuralNetwork().to(device) print(model)# Using cpu device # NeuralNetwork( # (flatten): Flatten(start_dim1, end_dim-1) # (linear_relu_stack): Sequential( # (0): Linear(in_features784, out_features512, biasTrue) # (1): ReLU() # (2): Linear(in_features512, out_features256, biasTrue) # (3): ReLU() # (4): Linear(in_features256, out_features10, biasTrue) # (5): Dropout(p0.2, inplaceFalse) # ) # )可以看到我们构建的模型首先将二维图像通过 Flatten 层压成一维向量然后经过两个带有 ReLU 激活函数的全连接隐藏层最后送入到一个包含 10 个神经元的分类器以完成 10 分类任务。我们还通过在最终输出前添加 Dropout 层来缓解过拟合。 最终我们构建的模型会输出一个 10 维向量每一维对应一个类别的预测值与先前介绍过的 pipeline 模型一样这里输出的是 logits 值我们需要再接一个 Softmax 层来计算最终的概率值。下面我们构建一个包含四个伪二维图像的 mini-batch 来进行预测 import torch from torch import nndevice cuda if torch.cuda.is_available() else cpu print(fUsing {device} device)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, 256),nn.ReLU(),nn.Linear(256, 10),nn.Dropout(p0.2))def forward(self, x):x self.flatten(x)logits self.linear_relu_stack(x)return logitsmodel NeuralNetwork().to(device)X torch.rand(4, 28, 28, devicedevice) logits model(X) pred_probab nn.Softmax(dim1)(logits) print(pred_probab.size()) y_pred pred_probab.argmax(-1) print(fPredicted class: {y_pred})# Using cpu device # torch.Size([4, 10]) # Predicted class: tensor([3, 8, 3, 3])可以看到模型成功输出了维度为 (4, 10) 的预测结果每个样本输出一个 10 维的概率向量。最后我们通过 a r g m a x argmax argmax 操作将输出的概率向量转换为对应的标签。 3.2 优化模型参数 在准备好数据、搭建好模型之后我们就可以开始训练和测试验证模型了。正如前面所说模型训练是一个迭代的过程每一轮 epoch 迭代中模型都会对输入样本进行预测然后对预测结果计算损失 (loss)并求 loss 对每一个模型参数的偏导最后使用优化器更新所有的模型参数。 损失函数 (Loss function) 用于度量预测值与答案之间的差异模型的训练过程就是最小化损失函数。Pytorch 实现了很多常见的损失函数例如用于回归任务的均方误差 (Mean Square Error) nn.MSELoss、用于分类任务的负对数似然 (Negative Log Likelihood) nn.NLLLoss、同时结合了 nn.LogSoftmax 和 nn.NLLLoss 的交叉熵损失 (Cross Entropy) nn.CrossEntropyLoss 等。 优化器 (Optimization) 使用特定的优化算法例如随机梯度下降通过在每一个训练阶段 (step) 减少基于一个 batch 样本计算的模型损失来调整模型参数。Pytorch 实现了很多优化器例如 SGD、ADAM、RMSProp 等。 每一轮迭代 (Epoch) 实际上包含了两个步骤 训练循环 (The Train Loop) 在训练集上进行迭代尝试收敛到最佳的参数验证/测试循环 (The Validation/Test Loop) 在测试/验证集上进行迭代以检查模型性能有没有提升。 具体地在训练循环中优化器通过以下三个步骤进行优化 调用 optimizer.zero_grad() 重设模型参数的梯度。默认情况下梯度会进行累加为了防止重复计算在每个训练阶段开始前都需要清零梯度通过 loss.backwards() 反向传播预测结果的损失即计算损失对每一个参数的偏导调用 optimizer.step() 根据梯度调整模型的参数。 选择交叉熵作为损失函数、选择 AdamW 作为优化器完整的训练循环和测试循环实现如下 import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensordevice cuda if torch.cuda.is_available() else cpu print(fUsing {device} device)training_data datasets.FashionMNIST(rootdata,trainTrue,downloadTrue,transformToTensor() )test_data datasets.FashionMNIST(rootdata,trainFalse,downloadTrue,transformToTensor() )learning_rate 1e-3 batch_size 64 epochs 3train_dataloader DataLoader(training_data, batch_sizebatch_size) test_dataloader DataLoader(test_data, batch_sizebatch_size)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, 256),nn.ReLU(),nn.Linear(256, 10),nn.Dropout(p0.2))def forward(self, x):x self.flatten(x)logits self.linear_relu_stack(x)return logitsmodel NeuralNetwork().to(device)def train_loop(dataloader, model, loss_fn, optimizer):size len(dataloader.dataset)model.train()for batch, (X, y) in enumerate(dataloader, start1):X, y X.to(device), y.to(device)# Compute prediction and losspred model(X)loss loss_fn(pred, y)# Backpropagationoptimizer.zero_grad()loss.backward()optimizer.step()if batch % 100 0:loss, current loss.item(), batch * len(X)print(floss: {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, 0model.eval()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(dim-1) y).type(torch.float).sum().item()test_loss / num_batchescorrect / sizeprint(fTest Error: \n Accuracy: {(100*correct):0.1f}%, Avg loss: {test_loss:8f} \n)loss_fn nn.CrossEntropyLoss() optimizer torch.optim.AdamW(model.parameters(), lrlearning_rate)for t in range(epochs):print(fEpoch {t1}\n-------------------------------)train_loop(train_dataloader, model, loss_fn, optimizer)test_loop(test_dataloader, model, loss_fn) print(Done!)# Using cpu device # Epoch 1 # ------------------------------- # loss: 0.935758 [ 6400/60000] # loss: 0.991128 [12800/60000] # loss: 0.655021 [19200/60000] # loss: 0.938772 [25600/60000] # loss: 0.480326 [32000/60000] # loss: 0.526776 [38400/60000] # loss: 1.046211 [44800/60000] # loss: 0.749002 [51200/60000] # loss: 0.550378 [57600/60000] # Test Error: # Accuracy: 83.7%, Avg loss: 0.441249 # Epoch 2 # ------------------------------- # loss: 0.596351 [ 6400/60000] # loss: 0.614368 [12800/60000] # loss: 0.588207 [19200/60000] # loss: 0.698899 [25600/60000] # loss: 0.433412 [32000/60000] # loss: 0.533789 [38400/60000] # loss: 0.772370 [44800/60000] # loss: 0.486120 [51200/60000] # loss: 0.534202 [57600/60000] # Test Error: # Accuracy: 85.4%, Avg loss: 0.396990 # Epoch 3 # ------------------------------- # loss: 0.547906 [ 6400/60000] # loss: 0.591556 [12800/60000] # loss: 0.537591 [19200/60000] # loss: 0.722009 [25600/60000] # loss: 0.319590 [32000/60000] # loss: 0.504153 [38400/60000] # loss: 0.797246 [44800/60000] # loss: 0.553834 [51200/60000] # loss: 0.400079 [57600/60000] # Test Error: # Accuracy: 87.2%, Avg loss: 0.355058 # Done!可以看到通过 3 轮迭代 (Epoch)模型在训练集上的损失逐步下降、在测试集上的准确率逐步上升证明优化器成功地对模型参数进行了调整而且没有出现过拟合。 注意一定要在预测之前调用 model.eval() 方法将 dropout 层和 batch normalization 层设置为评估模式否则会产生不一致的预测结果。 4 保存及加载模型 4.1 保存和加载模型权重 Pytorch 模型会将所有参数存储在一个状态字典 (state dictionary) 中可以通过 Model.state_dict() 加载。Pytorch 通过 torch.save() 保存模型权重 import torch import torchvision.models as modelsmodel models.vgg16(pretrainedTrue) torch.save(model.state_dict(), model_weights.pth)为了加载保存的权重我们首先需要创建一个结构完全相同的模型实例然后通过 Model.load_state_dict() 函数进行加载 model models.vgg16() # we do not specify pretrainedTrue, i.e. do not load default weights model.load_state_dict(torch.load(model_weights.pth)) model.eval()4.2 保存和加载完整模型 上面存储模型权重的方式虽然可以节省空间但是加载前需要构建一个结构完全相同的模型实例来承接权重。如果我们希望在存储权重的同时也一起保存模型结构就需要将整个模型传给 torch.save() import torch import torchvision.models as modelsmodel models.vgg16(pretrainedTrue) torch.save(model, model.pth)这样就可以直接从保存的文件中加载整个模型包括权重和结构 model torch.load(model.pth)
http://www.pierceye.com/news/62377/

相关文章:

  • wordpress wending西宁网站seo外包
  • 做网站网站判刑网站首页设计要求
  • 建设银行网站怎么修改手机号码合成版本传奇手游
  • 校园网站建设结论12306网站 谁做的
  • 静安网站建设哪家好工程招标信息网下载
  • 亚马逊网站开发使用的什么方式品牌设计案例分析
  • 静态学校网站做毕业设计asp网站幻灯片不显示
  • 网站建设怎么添加视频wordpress 搜索栏js
  • 音乐网站建设方案书模板wordpress注册激活码
  • 对企业网站的印象wordpress 301错误
  • 专业建设网站的公司电子技术培训机构
  • 做网站框架浏览时怎么变长斗图在线制作生成器
  • 优秀的响应式网站陕西住房城乡建设门户网站
  • 拓展培训东莞网站建设环球资源网站什么时候做的
  • 网站链接提交收录九江县网站建设
  • 公众号里链接的网站怎么做的建设工程施工合同通用条款
  • 微网站建设完 不知道怎么推广咋办seo培训讲师招聘
  • 广告制作网站源码网站开发资料
  • asp做素材网站成都网站开发 优帮云
  • 怎么建设一个人自己网站河南省水利建设管理处网站
  • c 做网站用什么框架优书网怎么了
  • 网站建设营销推广河北廊坊公布新增阳性人员轨迹
  • ps网站怎么做超链接泰州企业建站程序
  • 电子商城网站开发公司网站开发与网页制作
  • 内部网站建设拓扑成都公司注册流程及需要的材料
  • 临淄网站建设价格往网站上传照片怎么做
  • 龙华网站建设方案书例文张家港网站制作建议
  • 婚庆网站开发背景南宁关键词自然排名
  • 哪里有放网站的免费空间你在四川省建设安全与质量监督网站
  • 招人在哪个网站比较好找ppt做的最好的网站