• [互动交流] 如何有效地利用多GPU进行模型训练?
    大型深度学习模型,需要在包含多个GPU的计算机上进行训练。我们希望通过有效地利用多GPU来加速训练过程,同时减少通信开销和梯度聚合的开销。我们需要找到一种方法来有效地将模型拆分并在多个GPU上训练,以提高训练速度和效率。
  • [互动交流] 如何解决过拟合问题以提高模型的泛化能力?
    机器学习模型,用于预测客户的信用卡欺诈行为。如果模型在训练数据上过度拟合,它可能只会识别出训练数据中的模式,而无法泛化到新的、未见过的数据。这可能导致在测试数据上的准确率降低。因此,我们需要找到一种方法来解决过拟合问题,以提高模型的泛化能力。
  • [互动交流] 如何利用无监督学习进行知识蒸馏?
    复杂的人工智能系统,它由一个大的预训练模型和一个小的目标模型组成。由于标记数据的成本很高,我们希望使用无监督学习来进行知识蒸馏,以便将预训练模型的知识迁移到目标模型中。在这种情况下,我们需要开发一种有效的无监督知识蒸馏方法,以减少对标记数据的依赖
  • [互动交流] 如何设计有效的数据增强方法以改善模型的泛化能力?
    图像分类问题。我们有一个小规模的图像数据集,而且收集更多的数据很困难。为了解决这个问题,我们可以使用数据增强方法来增加训练数据。然而,如何设计有效的数据增强策略以最大化模型的泛化能力是一个重要的问题。例如,我们是否应该使用旋转、平移、缩放等变换?如何选择这些变换的参数?
  • [互动交流] 如何利用迁移学习来加速模型训练和提高性能?
    自然语言处理模型,需要从英文文本中提取情感信息。如果已经有了一个用于提取英文文本信息的预训练模型,我们希望利用这个预训练模型来加速我们的情感分析模型。在这种情况下,如何选择源任务和目标任务,以及如何调整预训练模型以适应新的情感分析任务,是我们需要解决的问题。
  • [互动交流] 如何设计有效的多任务学习算法?
    人工智能助手,它需要同时完成日历管理、邮件回复、语音识别等多项任务。为了提高助手的效率和准确性,我们可以设计一个多任务学习算法,使它能够同时学习和优化各项任务。通过共享底层网络参数和学习策略,我们可以提高助手的整体性能并减少每个任务的训练时间。
  • [问题求助] 如何利用强化学习来解决复杂的决策问题?
    自动驾驶系统。在行驶过程中,车辆需要实时地根据道路状况、交通信号、其他车辆的位置和速度等信息做出决策,以确保安全行驶。传统的基于规则或机器学习的方法往往难以处理如此复杂和实时性的决策问题。强化学习有可能为自动驾驶系统提供更有效的解决方案。
  • [互动交流] 如何处理不平衡数据集对分类算法的影响?
    信用卡欺诈检测系统。在训练数据中,非欺诈交易的数量远远大于欺诈交易的数量。如果系统仅仅使用数量作为分类依据,它可能会将所有交易都归类为非欺诈交易,因为它更容易被正确分类。然而,这样的模型对于银行来说并没有太大的用处。因此,我们需要找到一种方法来处理不平衡数据集对分类算法的影响
  • [互动交流] 如何提高人工智能系统的解释性和透明度?
    在许多应用场景中,我们需要人工智能系统能够提供更详细的解释和透明的决策过程,以便用户可以理解并信任系统的输出结果。然而,目前的技术往往难以实现这一点。有什么好的建议和经验可以分享吗?
  • [热门活动] 【数字人专题直播有奖提问】DTSE Tech Talk 技术直播 NO.45:看直播提问题赢华为云定制U型按摩枕、华为云定制POLO衫等好礼!
    中奖结果公示感谢各位小伙伴参与本次活动,本次活动获奖名单如下:请各位获奖的伙伴在10月23日之前点击此处填写收货地址,如逾期未填写视为弃奖。再次感谢各位小伙伴参与本次活动,欢迎关注华为云DTSE Tech Talk 技术直播更多活动~直播简介【直播主题】华为云数字人赋能千行百业,共享AIGC新机遇【直播时间】2023年10月18日 16:30-18:00【直播专家】左雯 华为云媒体DTSE技术布道师【直播简介】数字人作为元宇宙中真人沉浸式体验的重要入口和AIGC的关键要素,伴随元宇宙和AIGC双轮产业进步,关注本期直播,告诉你数字人将如何带来千行百业的产业变革?直播链接:cid:link_1活动介绍【互动方式】直播前您可以在本帖留下您疑惑的问题,专家会在直播时为您解答。直播后您可以继续在本帖留言,与专家互动交流。我们会在全部活动结束后对参与互动的用户进行评选。【活动时间】即日起—2023年10月19日【奖励说明】评奖规则:活动1:直播期间在直播间提出与直播内容相关的问题,对专家评选为优质问题的开发者进行奖励。奖品:华为云定制U型按摩枕活动2:在本帖提出与直播内容相关的问题,由专家在所有互动贴中选出最优问题贴的开发者进行奖励。奖品:华为云定制POLO衫更多直播活动直播互动有礼:官网直播间发口令“华为云 DTSE”抽华为云定制短袖T恤、填写问卷抽华为云定制保温杯等好礼分享问卷有礼 :邀请5位朋友以上完成问卷即可获得华为云定制棒球帽。老观众专属福利:连续报名并观看DTT直播3期以上抽送华为云DTT定制T恤。【注意事项】1、所有参与活动的问题,如发现为复用他人内容,则取消获奖资格。2、为保证您顺利领取活动奖品,请您在活动公示奖项后2个工作日内私信提前填写奖品收货信息,如您没有填写,视为自动放弃奖励。3、活动奖项公示时间截止2023年10月20日,如未反馈邮寄信息视为弃奖。本次活动奖品将于奖项公示后30个工作日内统一发出,请您耐心等待。4、活动期间同类子活动每个ID(同一姓名/电话/收货地址)只能获奖一次,若重复则中奖资格顺延至下一位合格开发者,仅一次顺延。5、如活动奖品出现没有库存的情况,华为云工作人员将会替换等价值的奖品,获奖者不同意此规则视为放弃奖品。6、其他事宜请参考【华为云社区常规活动规则】。
  • [技术干货] PyTorch批训练及优化器使用【转】
    一、PyTorch批训练1. 概述PyTorch提供了一种将数据包装起来进行批训练的工具——DataLoader。使用的时候,只需要将我们的数据首先转换为torch的tensor形式,再转换成torch可以识别的Dataset格式,然后将Dataset放入DataLoader中就可以啦。import torchimport torch.utils.data as Data torch.manual_seed(1) # 设定随机数种子 BATCH_SIZE = 5 x = torch.linspace(1, 10, 10)y = torch.linspace(0.5, 5, 10) # 将数据转换为torch的dataset格式torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y) # 将torch_dataset置入Dataloader中loader = Data.DataLoader( dataset=torch_dataset, batch_size=BATCH_SIZE, # 批大小 # 若dataset中的样本数不能被batch_size整除的话,最后剩余多少就使用多少 shuffle=True, # 是否随机打乱顺序 num_workers=2, # 多线程读取数据的线程数 ) for epoch in range(3): for step, (batch_x, batch_y) in enumerate(loader): print('Epoch:', epoch, '|Step:', step, '|batch_x:', batch_x.numpy(), '|batch_y', batch_y.numpy())'''''shuffle=TrueEpoch: 0 |Step: 0 |batch_x: [ 6. 7. 2. 3. 1.] |batch_y [ 3. 3.5 1. 1.5 0.5]Epoch: 0 |Step: 1 |batch_x: [ 9. 10. 4. 8. 5.] |batch_y [ 4.5 5. 2. 4. 2.5]Epoch: 1 |Step: 0 |batch_x: [ 3. 4. 2. 9. 10.] |batch_y [ 1.5 2. 1. 4.5 5. ]Epoch: 1 |Step: 1 |batch_x: [ 1. 7. 8. 5. 6.] |batch_y [ 0.5 3.5 4. 2.5 3. ]Epoch: 2 |Step: 0 |batch_x: [ 3. 9. 2. 6. 7.] |batch_y [ 1.5 4.5 1. 3. 3.5]Epoch: 2 |Step: 1 |batch_x: [ 10. 4. 8. 1. 5.] |batch_y [ 5. 2. 4. 0.5 2.5] shuffle=FalseEpoch: 0 |Step: 0 |batch_x: [ 1. 2. 3. 4. 5.] |batch_y [ 0.5 1. 1.5 2. 2.5]Epoch: 0 |Step: 1 |batch_x: [ 6. 7. 8. 9. 10.] |batch_y [ 3. 3.5 4. 4.5 5. ]Epoch: 1 |Step: 0 |batch_x: [ 1. 2. 3. 4. 5.] |batch_y [ 0.5 1. 1.5 2. 2.5]Epoch: 1 |Step: 1 |batch_x: [ 6. 7. 8. 9. 10.] |batch_y [ 3. 3.5 4. 4.5 5. ]Epoch: 2 |Step: 0 |batch_x: [ 1. 2. 3. 4. 5.] |batch_y [ 0.5 1. 1.5 2. 2.5]Epoch: 2 |Step: 1 |batch_x: [ 6. 7. 8. 9. 10.] |batch_y [ 3. 3.5 4. 4.5 5. ]'''2. TensorDatasetclasstorch.utils.data.TensorDataset(data_tensor, target_tensor)TensorDataset类用来将样本及其标签打包成torch的Dataset,data_tensor,和target_tensor都是tensor                                  3. DataLoader复制代码 代码如下:classtorch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,num_workers=0, collate_fn=<function default_collate>, pin_memory=False,drop_last=False)dataset就是Torch的Dataset格式的对象;batch_size即每批训练的样本数量,默认为;shuffle表示是否需要随机取样本;num_workers表示读取样本的线程数。二、PyTorch的Optimizer优化器本实验中,首先构造一组数据集,转换格式并置于DataLoader中,备用。定义一个固定结构的默认神经网络,然后为每个优化器构建一个神经网络,每个神经网络的区别仅仅是优化器不同。通过记录训练过程中的loss值,最后在图像上呈现得到各个优化器的优化过程。代码实现:import torchimport torch.utils.data as Dataimport torch.nn.functional as Ffrom torch.autograd import Variableimport matplotlib.pyplot as plttorch.manual_seed(1) # 设定随机数种子 # 定义超参数LR = 0.01 # 学习率BATCH_SIZE = 32 # 批大小EPOCH = 12 # 迭代次数 x = torch.unsqueeze(torch.linspace(-1, 1, 1000), dim=1)y = x.pow(2) + 0.1*torch.normal(torch.zeros(*x.size())) #plt.scatter(x.numpy(), y.numpy())#plt.show() # 将数据转换为torch的dataset格式torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y)# 将torch_dataset置入Dataloader中loader = Data.DataLoader(dataset=torch_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2) class Net(torch.nn.Module): def __init__(self): super(Net, self).__init__() self.hidden = torch.nn.Linear(1, 20) self.predict = torch.nn.Linear(20, 1) def forward(self, x): x = F.relu(self.hidden(x)) x = self.predict(x) return x # 为每个优化器创建一个Netnet_SGD = Net()net_Momentum = Net()net_RMSprop = Net()net_Adam = Net() nets = [net_SGD, net_Momentum, net_RMSprop, net_Adam] # 初始化优化器opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.8)opt_RMSprop = torch.optim.RMSprop(net_RMSprop.parameters(), lr=LR, alpha=0.9)opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99)) optimizers = [opt_SGD, opt_Momentum, opt_RMSprop, opt_Adam] # 定义损失函数loss_function = torch.nn.MSELoss()losses_history = [[], [], [], []] # 记录training时不同神经网络的loss值 for epoch in range(EPOCH): print('Epoch:', epoch + 1, 'Training...') for step, (batch_x, batch_y) in enumerate(loader): b_x = Variable(batch_x) b_y = Variable(batch_y) for net, opt, l_his in zip(nets, optimizers, losses_history): output = net(b_x) loss = loss_function(output, b_y) opt.zero_grad() loss.backward() opt.step() l_his.append(loss.data[0]) labels = ['SGD', 'Momentum', 'RMSprop', 'Adam'] for i, l_his in enumerate(losses_history): plt.plot(l_his, label=labels[i])plt.legend(loc='best')plt.xlabel('Steps')plt.ylabel('Loss')plt.ylim((0, 0.2))plt.show()实验结果:由实验结果可见,SGD的优化效果是最差的,速度很慢;作为SGD的改良版本,Momentum表现就好许多;相比RMSprop和Adam的优化速度就非常好。实验中,针对不同的优化问题,比较各个优化器的效果再来决定使用哪个。三、其他补充1. Python的zip函数zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表。x = [1, 2, 3]y = [4, 5, 6]z = [7, 8, 9]xyz = zip(x, y, z)print xyz[(1, 4, 7), (2, 5, 8), (3, 6, 9)] x = [1, 2, 3]x = zip(x)print x[(1,), (2,), (3,)] x = [1, 2, 3]y = [4, 5, 6, 7]xy = zip(x, y)print xy[(1, 4), (2, 5), (3, 6)]torch.optim.SGD(params, lr=<object object>, momentum=0, dampening=0, weight_decay=0, nesterov=False)1 实现随机梯度下降算法( momentum 可选) Args: params(iterable): 待优化的迭代参数或者是定义了参数组的 dict eg: model.parameters() lr (float): 学习率 dampening(float, optional): 动量的抑制因子 (默认值: 0) weight_decay(float, optional): 权重衰减 (L2 正则化) (默认值: 0) nesterov (bool, optional): 使用 Nesterov 动量 (默认值: False)torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)实现 RMSprop 算法. Args: alpha(float, optional): 平滑常量 (default: 0.99) eps(float, optional): 为了增加数值计算的稳定性而加到分母里的项 (默认值: 1e-8) centered (bool, optional) : 如果为 True, 计算 RMSProp 的中值, 并且用它的方差预测值对梯度进行归一化torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)实现 Adamax 算法 ( Adam 的一种基于无穷范数的变种). Args: betas (Tuple[float, float], optional): 用来计算梯度和平方梯度的系数 参考链接:cid:link_0                   cid:link_1
  • [技术干货] pytorch 分批次训练【转】
    1.介绍之前的都是使用直接训练虽然它有它自己的优点但分批次训练也是一种重要的方法直接训练(full training)是指每次更新模型参数时,使用数据集中的所有样本,称为一个周期(epoch)。直接训练的优点是可以充分利用数据信息,更容易收敛到全局最优。直接训练的缺点是需要更多的内存空间,训练速度较慢,容易过拟合。分批次训练(batch training)是指每次更新模型参数时,只使用数据集中的一部分样本,称为一个批次(batch)。分批次训练的优点是可以减少内存消耗,加快训练速度,增加随机性,有利于模型的泛化。分批次训练的缺点是可能陷入局部最优,需要调整批次大小和学习率等超参数。2.实操使用的数据集依然是8个特征的糖尿病预测二分问题数据集的获取,见我之前文章(45条消息) pytorch-- 多维特征处理_小户爱的博客-CSDN博客首先是基础版本import torchimport torch.nn as nnimport numpy as npfrom torch.utils.data import Datasetfrom torch.utils.data import DataLoaderimport matplotlib.pyplot as pltclass DiabetesDataset(Dataset): def __init__(self, filepath): xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32, skiprows=1) self.len = xy.shape[0] self.x_data = torch.from_numpy(xy[:, :-1]) self.y_data = torch.from_numpy(xy[:, [-1]]) self.mean = torch.mean(self.x_data, dim=0) # 计算数据的均值 self.std = torch.std(self.x_data, dim=0) # 计算数据的标准差 def __getitem__(self, index): x = self.x_data[index] x = (x - self.mean) / self.std # 对数据进行归一化和标准化 y = self.y_data[index] return x, y def __len__(self): return self.lendataset = DiabetesDataset('diabetes.csv')train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.linear1 = nn.Linear(8, 6) self.linear2 = nn.Linear(6, 4) self.linear3 = nn.Linear(4, 1) self.sigmoid = nn.Sigmoid() def forward(self, x): x = self.sigmoid(self.linear1(x)) x = self.sigmoid(self.linear2(x)) x = self.sigmoid(self.linear3(x)) return xmodel = Model()criterion = nn.BCELoss(reduction='mean')optimizer = torch.optim.SGD(model.parameters(), lr=0.01)epoch_list = []loss_list = []if __name__ == '__main__': for epoch in range(100): epoch_list.append(epoch) sum = 0 for i, data in enumerate(train_loader, 0): inputs, labels = data y_pred = model(inputs) loss = criterion(y_pred, labels) sum += loss.item() print(epoch, i, loss.item()) optimizer.zero_grad() loss.backward() optimizer.step() loss_list.append(sum/24) plt.plot(epoch_list, loss_list, ls='-.', c='blue', label='DiabetesDataset') plt.xlabel('epoch') plt.ylabel('loss') plt.show()几点说明:a. class DiabetesDataset(Dataset):数据集的引入 因为要分批次所以要写几个魔法函数b.def __getitem__(self, index): x = self.x_data[index] y = self.y_data[index] return x, ydef __len__(self): return self.len他们两个是为了dataset = DiabetesDataset('diabetes.csv')train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)这里面  dataset=dataset  就会自动调用def __getitem__(self, index): 来获取数据同时调用def __len__(self):来获取长度 从而正确的进行 分组batch_size=32   这个是分的批次大小 ,我这里选择每批次32,shuffle=True 是否随机打乱  num_workers=2 表示加载时使用多少个子进程这个根据自己的配置自行选择b. if __name__ == '__main__':这个是windows 系统要写上的不写会报错好奇为什么自己查吧c.for epoch in range(100): for i, data in enumerate(train_loader, 0): inputs, lables = data y_pred = model(inputs) loss = criterion(y_pred, lables) print(epoch, i, loss.item()) optimizer.zero_grad() loss.backward() optimizer.step()第一层循环每次运行到 for i, data in enumerate(train_loader, 0): 这里时由于之前选择了shuffle=True  因此会打乱索引充分批次 具体的批次分发如下:比如我们有12组数据 每批有2个 每32一个batchinputs, lables = data 这里的data 就是分批后一组的 x,y 的元组3. 最基本的优化:之前那种我们会发现运行的速度反而会较之前慢一些 因为还进行了分批次等操作 同时也没有特别好的运用 GPU并行能力,数据也不是很客观 可以尝试使用self.relu = nn.ReLU() # 使用ReLU激活函数,增加非线性self.dropout = nn.Dropout(0.2) # 使用Dropout层,防止过拟合self.batchnorm = nn.BatchNorm1d(6) # 使用BatchNorm层,加速收敛
  • [技术干货] 9个让PyTorch模型训练提速的技巧【转】
    导读一个step by step的指南,非常的实用。不要让你的神经网络变成这样让我们面对现实吧,你的模型可能还停留在石器时代。我敢打赌你仍然使用32位精度或GASP甚至只在一个GPU上训练。我明白,网上都是各种神经网络加速指南,但是一个checklist都没有(现在有了),使用这个清单,一步一步确保你能榨干你模型的所有性能。本指南从最简单的结构到最复杂的改动都有,可以使你的网络得到最大的好处。我会给你展示示例Pytorch代码以及可以在Pytorch- lightning Trainer中使用的相关flags,这样你可以不用自己编写这些代码!**这本指南是为谁准备的?**任何使用Pytorch进行深度学*模型研究的人,如研究人员、博士生、学者等,我们在这里谈论的模型可能需要你花费几天的训练,甚至是几周或几个月。我们会讲到:使用DataLoadersDataLoader中的workers数量Batch size梯度累计保留的计算图移动到单个16-bit 混合精度训练移动到多个GPUs中(模型复制)移动到多个GPU-nodes中 (8+GPUs)思考模型加速的技巧Pytorch-Lightning你可以在Pytorch的库Pytorch- lightning中找到我在这里讨论的每一个优化。Lightning是在Pytorch之上的一个封装,它可以自动训练,同时让研究人员完全控制关键的模型组件。Lightning 使用最新的最佳实践,并将你可能出错的地方最小化。我们为MNIST定义LightningModel并使用Trainer来训练模型。from pytorch_lightning import Trainermodel = LightningModule(…)trainer = Trainer()trainer.fit(model)1. DataLoaders这可能是最容易获得速度增益的地方。保存h5py或numpy文件以加速数据加载的时代已经一去不复返了,使用Pytorch dataloader加载图像数据很简单(对于NLP数据,请查看TorchText)。在lightning中,你不需要指定训练循环,只需要定义dataLoaders和Trainer就会在需要的时候调用它们。dataset = MNIST(root=self.hparams.data_root, train=train, download=True)loader = DataLoader(dataset, batch_size=32, shuffle=True)for batch in loader: x, y = batch model.training_step(x, y) ...2. DataLoaders 中的 workers 的数量另一个加速的神奇之处是允许批量并行加载。因此,您可以一次装载nb_workers个batch,而不是一次装载一个batch。# slowloader = DataLoader(dataset, batch_size=32, shuffle=True)# fast (use 10 workers)loader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=10)3. Batch size在开始下一个优化步骤之前,将batch size增大到CPU-RAM或GPU-RAM所允许的最大范围。下一节将重点介绍如何帮助减少内存占用,以便你可以继续增加batch size。记住,你可能需要再次更新你的学x率。一个好的经验法则是,如果batch size加倍,那么学x率就加倍。4. 梯度累加在你已经达到计算资源上限的情况下,你的batch size仍然太小(比如8),然后我们需要模拟一个更大的batch size来进行梯度下降,以提供一个良好的估计。假设我们想要达到128的batch size大小。我们需要以batch size为8执行16个前向传播和向后传播,然后再执行一次优化步骤。# clear last stepoptimizer.zero_grad()# 16 accumulated gradient stepsscaled_loss = 0for accumulated_step_i in range(16): out = model.forward() loss = some_loss(out,y) loss.backward() scaled_loss += loss.item() # update weights after 8 steps. effective batch = 8*16optimizer.step()# loss is now scaled up by the number of accumulated batchesactual_loss = scaled_loss / 16在lightning中,全部都给你做好了,只需要设置accumulate_grad_batches=16:trainer = Trainer(accumulate_grad_batches=16)trainer.fit(model)5. 保留的计算图一个最简单撑爆你的内存的方法是为了记录日志存储你的loss。losses = []...losses.append(loss)print(f current loss: {torch.mean(losses) })上面的问题是,loss仍然包含有整个图的副本。在这种情况下,调用.item()来释放它。![1_CER3v8cok2UOBNsmnBrzPQ](9 Tips For Training Lightning-Fast Neural Networks In Pytorch.assets/1_CER3v8cok2UOBNsmnBrzPQ.gif)# badlosses.append(loss)# goodlosses.append(loss.item())Lightning会非常小心,确保不会保留计算图的副本。6. 单个GPU训练一旦你已经完成了前面的步骤,是时候进入GPU训练了。在GPU上的训练将使多个GPU cores之间的数学计算并行化。你得到的加速取决于你所使用的GPU类型。我推荐个人用2080Ti,公司用V100。乍一看,这可能会让你不知所措,但你真的只需要做两件事:1)移动你的模型到GPU, 2)每当你运行数据通过它,把数据放到GPU上。# put model on GPUmodel.cuda(0)# put data on gpu (cuda on a variable returns a cuda copy)x = x.cuda(0)# runs on GPU nowmodel(x)如果你使用Lightning,你什么都不用做,只需要设置Trainer(gpus=1)。# ask lightning to use gpu 0 for trainingtrainer = Trainer(gpus=[0])trainer.fit(model)在GPU上进行训练时,要注意的主要事情是限制CPU和GPU之间的传输次数。# expensivex = x.cuda(0)# very expensivex = x.cpu()x = x.cuda(0)如果内存耗尽,不要将数据移回CPU以节省内存。在求助于GPU之前,尝试以其他方式优化你的代码或GPU之间的内存分布。另一件需要注意的事情是调用强制GPU同步的操作。清除内存缓存就是一个例子。# really bad idea. Stops all the GPUs until they all catch uptorch.cuda.empty_cache()但是,如果使用Lightning,惟一可能出现问题的地方是在定义Lightning Module时。Lightning会特别注意不去犯这类错误。7. 16-bit 精度16bit精度是将内存占用减半的惊人技术。大多数模型使用32bit精度数字进行训练。然而,最近的研究发现,16bit模型也可以工作得很好。混合精度意味着对某些内容使用16bit,但将权重等内容保持在32bit。要在Pytorch中使用16bit精度,请安装NVIDIA的apex库,并对你的模型进行这些更改。# enable 16-bit on the model and the optimizermodel, optimizers = amp.initialize(model, optimizers, opt_level= O2 )# when doing .backward, let amp do it so it can scale the losswith amp.scale_loss(loss, optimizer) as scaled_loss: scaled_loss.backward()amp包会处理好大部分事情。如果梯度爆炸或趋向于0,它甚至会缩放loss。在lightning中,启用16bit并不需要修改模型中的任何内容,也不需要执行我上面所写的操作。设置Trainer(precision=16)就可以了。trainer = Trainer(amp_level= O2 , use_amp=False)trainer.fit(model)8. 移动到多个GPUs中现在,事情变得非常有趣了。有3种(也许更多?)方法来进行多GPU训练。分batch训练A) 拷贝模型到每个GPU中,B) 给每个GPU一部分batch第一种方法被称为“分batch训练”。该策略将模型复制到每个GPU上,每个GPU获得batch的一部分。# copy model on each GPU and give a fourth of the batch to eachmodel = DataParallel(model, devices=[0, 1, 2 ,3])# out has 4 outputs (one for each gpu)out = model(x.cuda(0))在lightning中,你只需要增加GPUs的数量,然后告诉trainer,其他什么都不用做。# ask lightning to use 4 GPUs for trainingtrainer = Trainer(gpus=[0, 1, 2, 3])trainer.fit(model)模型分布训练将模型的不同部分放在不同的GPU上,batch按顺序移动有时你的模型可能太大不能完全放到内存中。例如,带有编码器和解码器的序列到序列模型在生成输出时可能会占用20GB RAM。在本例中,我们希望将编码器和解码器放在独立的GPU上。# each model is sooo big we can t fit both in memoryencoder_rnn.cuda(0)decoder_rnn.cuda(1)# run input through encoder on GPU 0encoder_out = encoder_rnn(x.cuda(0))# run output through decoder on the next GPUout = decoder_rnn(encoder_out.cuda(1))# normally we want to bring all outputs back to GPU 0out = out.cuda(0)对于这种类型的训练,在Lightning中不需要指定任何GPU,你应该把LightningModule中的模块放到正确的GPU上。class MyModule(LightningModule): def __init__(): self.encoder = RNN(...) self.decoder = RNN(...) def forward(x): # models won t be moved after the first forward because # they are already on the correct GPUs self.encoder.cuda(0) self.decoder.cuda(1) out = self.encoder(x) out = self.decoder(out.cuda(1)) # don t pass GPUs to trainermodel = MyModule()trainer = Trainer()trainer.fit(model)两者混合在上面的情况下,编码器和解码器仍然可以从并行化操作中获益。# change these linesself.encoder = RNN(...)self.decoder = RNN(...)# to these# now each RNN is based on a different gpu setself.encoder = DataParallel(self.encoder, devices=[0, 1, 2, 3])self.decoder = DataParallel(self.encoder, devices=[4, 5, 6, 7])# in forward...out = self.encoder(x.cuda(0))# notice inputs on first gpu in devicesout = self.decoder(out.cuda(4)) # <--- the 4 here使用多个GPU时要考虑的注意事项:如果模型已经在GPU上了,model.cuda()不会做任何事情。总是把输入放在设备列表中的第一个设备上。在设备之间传输数据是昂贵的,把它作为最后的手段。优化器和梯度会被保存在GPU 0上,因此,GPU 0上使用的内存可能会比其他GPU大得多。9. 多节点GPU训练每台机器上的每个GPU都有一个模型的副本。每台机器获得数据的一部分,并且只在那部分上训练。每台机器都能同步梯度。如果你已经做到了这一步,那么你现在可以在几分钟内训练Imagenet了!这并没有你想象的那么难,但是它可能需要你对计算集群的更多知识。这些说明假设你正在集群上使用SLURM。Pytorch允许多节点训练,通过在每个节点上复制每个GPU上的模型并同步梯度。所以,每个模型都是在每个GPU上独立初始化的,本质上独立地在数据的一个分区上训练,除了它们都从所有模型接收梯度更新。在高层次上:在每个GPU上初始化一个模型的副本(确保设置种子,让每个模型初始化到相同的权重,否则它会失败)。将数据集分割成子集(使用DistributedSampler)。每个GPU只在它自己的小子集上训练。在.backward()上,所有副本都接收到所有模型的梯度副本。这是模型之间唯一一次的通信。Pytorch有一个很好的抽象,叫做DistributedDataParallel,它可以帮你实现这个功能。要使用DDP,你需要做4的事情:def tng_dataloader(): d = MNIST() # 4: Add distributed sampler # sampler sends a portion of tng data to each machine dist_sampler = DistributedSampler(dataset) dataloader = DataLoader(d, shuffle=False, sampler=dist_sampler) def main_process_entrypoint(gpu_nb): # 2: set up connections between all gpus across all machines # all gpus connect to a single GPU "root" # the default uses env:// world = nb_gpus * nb_nodes dist.init_process_group("nccl", rank=gpu_nb, world_size=world) # 3: wrap model in DPP torch.cuda.set_device(gpu_nb) model.cuda(gpu_nb) model = DistributedDataParallel(model, device_ids=[gpu_nb]) # train your model now... if __name__ == __main__ : # 1: spawn number of processes # your cluster will call main for each machine mp.spawn(main_process_entrypoint, nprocs=8)然而,在Lightning中,只需设置节点数量,它就会为你处理其余的事情。# train on 1024 gpus across 128 nodestrainer = Trainer(nb_gpu_nodes=128, gpus=[0, 1, 2, 3, 4, 5, 6, 7])Lightning还附带了一个SlurmCluster管理器,可以方便地帮助你提交SLURM作业的正确详细信息。10. 福利!在单个节点上多GPU更快的训练事实证明,distributedDataParallel比DataParallel快得多,因为它只执行梯度同步的通信。所以,一个好的hack是使用distributedDataParallel替换DataParallel,即使是在单机上进行训练。在Lightning中,这很容易通过将distributed_backend设置为ddp和设置GPUs的数量来实现。# train on 4 gpus on the same machine MUCH faster than DataParalleltrainer = Trainer(distributed_backend= ddp , gpus=[0, 1, 2, 3])对模型加速的思考尽管本指南将为你提供了一系列提高网络速度的技巧,但我还是要给你解释一下如何通过查找瓶颈来思考问题。我将模型分成几个部分:首先,我要确保在数据加载中没有瓶颈。为此,我使用了我所描述的现有数据加载解决方案,但是如果没有一种解决方案满足你的需要,请考虑离线处理和缓存到高性能数据存储中,比如h5py。接下来看看你在训练步骤中要做什么。确保你的前向传播速度快,避免过多的计算以及最小化CPU和GPU之间的数据传输。最后,避免做一些会降低GPU速度的事情(本指南中有介绍)。接下来,我试图最大化我的batch size,这通常是受GPU内存大小的限制。现在,需要关注在使用大的batch size的时候如何在多个GPUs上分布并最小化延迟(比如,我可能会尝试着在多个gpu上使用8000 +的有效batch size)。然而,你需要小心大的batch size。针对你的具体问题,请查阅相关文献,看看人们都忽略了什么!—END—英文原文:https://towardsdatascience.com/9-tips-for-training-lightning-fast-neural-networks-in-pytorch-8e63a502f565
  • [技术干货] 使用 PyTorch 训练数据分析模型【转】
    使用 PyTorch 训练数据分析模型项目2023/07/12本文内容定义神经网络模型参数网络是如何运作的?定义损失函数在本教程的前一阶段中,我们获取了将用于使用 PyTorch 训练数据分析模型的数据集。 现在,我们将使用这些数据。要使用 PyTorch 训练数据分析模型,需要完成以下步骤:加载数据。 如果已完成本教程的上一步,则已经完成了数据加载。定义神经网络。定义损失函数。使用训练数据训练模型。使用测试数据测试网络。定义神经网络在本教程中,你将构建带有 3 个线性层的基本神经网络模型。 模型的结构如下所示:Linear -> ReLU -> Linear -> ReLU -> Linear一个线性层对传入数据应用一个线性转换。 必须指定输入特征的数量和输出特征的数量,它们应与类的数量相对应。ReLU 层是一个激活函数,用于将所有传入特征定义为 0 或更大。 因此,应用此层时,任何小于 0 的数字都会更改为零,而其他数字则保持不变。 我们将在 2 个隐藏层上应用激活层,在最后一个线性层上不应用激活层。模型参数模型参数取决于我们的目标和训练数据。 输入大小取决于我们向模型馈送的特征数量,在本例中为 4 个。 输出大小是 3,因为有 3 种可能的鸢尾花类型。有 3 个线性层 (4,24) -> (24,24) -> (24,3),网络将具有 744 个权重 (96+576+72)。学习速率 (lr) 设置你根据损失梯度调整网络权重的程度控制。 速率越低,训练速度就越慢。 你将在本教程中将 lr 设置为 0.01。网络是如何运作的?在此处,我们将构建一个前馈网络。 在训练过程中,网络将处理所有层的输入,计算损失以了解图像的预测标签与正确标签相差多远,并将梯度传播回网络以更新层的权重。 通过迭代庞大的输入数据集,网络将“学习”设置其权重以获得最佳结果。前向函数计算损失函数的值,后向函数计算可学习参数的梯度 。 使用 PyTorch 创建神经网络时,只需定义前向函数。 后向函数会自动定义。将以下代码复制到 Visual Studio 中的 DataClassifier.py 文件中,来定义模型参数和神经网络。py# Define model parameters input_size = list(input.shape)[1] # = 4. The input depends on how many features we initially feed the model. In our case, there are 4 features for every predict value learning_rate = 0.01 output_size = len(labels) # The output is prediction results for three types of Irises. # Define neural network class Network(nn.Module): def __init__(self, input_size, output_size): super(Network, self).__init__() self.layer1 = nn.Linear(input_size, 24) self.layer2 = nn.Linear(24, 24) self.layer3 = nn.Linear(24, output_size) def forward(self, x): x1 = F.relu(self.layer1(x)) x2 = F.relu(self.layer2(x1)) x3 = self.layer3(x2) return x3 # Instantiate the model model = Network(input_size, output_size) 还需要根据电脑上的可用设备来定义执行设备。 PyTorch 没有用于 GPU 的专用库,但你可手动定义执行设备。 如果计算机上存在 Nvidia GPU,则该设备为 Nvidia GPU;如果没有,则为 CPU。复制以下代码来定义执行设备:py# Define your execution device device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print("The model will be running on", device, "device\n") model.to(device) # Convert model parameters and buffers to CPU or Cuda 最后一步是定义函数来保存模型:py# Function to save the model def saveModel(): path = "./NetModel.pth" torch.save(model.state_dict(), path) 备注想要详细了解如何使用 PyTorch 创建神经网络? 请查看 PyTorch 文档。定义损失函数损失函数计算一个值,该值可估计输出与目标之间的差距。 主要目标是通过神经网络中的反向传播改变权重向量值来减少损失函数的值。丢失值不同于模型准确性。 损失函数表示模型在每次训练集优化迭代后的表现。 模型的准确性基于测试数据进行计算,并显示正确预测的百分比。在 PyTorch 中,神经网络包包含各种损失函数,这些函数构成了深层神经网络的构建基块。 若想详细了解这些细节,请先查看上述说明。 在此处,我们将使用针对这种分类优化的现有函数,并使用分类交叉熵损失函数和 Adam 优化器。 在该优化器中,学习速率 (lr) 设置你根据损失梯度调整网络权重的程度控制。 此处需要将它设置为 0.001 - 值越低,训练速度越慢。将以下代码复制到 Visual Studio 中的 DataClassifier.py 文件中,以定义损失函数和优化器。py# Define the loss function with Classification Cross-Entropy loss and an optimizer with Adam optimizerloss_fn = nn.CrossEntropyLoss()optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)使用训练数据训练模型。要训练模型,必须循环访问数据迭代器,将输入馈送到网络并进行优化。 只需在每次训练 epoch 后将预测得到的标签与验证数据集中的实际标签进行比较,即可验证结果。该程序将显示针对训练集的每个 epoch 或每个完整迭代的训练损失、验证损失和模型准确度。 它将以最高准确度保存模型,在 10 个 epoch 后,程序将显示最终的准确度。将以下代码添加到 DataClassifier.py 文件py# Training Function def train(num_epochs): best_accuracy = 0.0 print("Begin training...") for epoch in range(1, num_epochs+1): running_train_loss = 0.0 running_accuracy = 0.0 running_vall_loss = 0.0 total = 0 # Training Loop for data in train_loader: #for data in enumerate(train_loader, 0): inputs, outputs = data # get the input and real species as outputs; data is a list of [inputs, outputs] optimizer.zero_grad() # zero the parameter gradients predicted_outputs = model(inputs) # predict output from the model train_loss = loss_fn(predicted_outputs, outputs) # calculate loss for the predicted output train_loss.backward() # backpropagate the loss optimizer.step() # adjust parameters based on the calculated gradients running_train_loss +=train_loss.item() # track the loss value # Calculate training loss value train_loss_value = running_train_loss/len(train_loader) # Validation Loop with torch.no_grad(): model.eval() for data in validate_loader: inputs, outputs = data predicted_outputs = model(inputs) val_loss = loss_fn(predicted_outputs, outputs) # The label with the highest value will be our prediction _, predicted = torch.max(predicted_outputs, 1) running_vall_loss += val_loss.item() total += outputs.size(0) running_accuracy += (predicted == outputs).sum().item() # Calculate validation loss value val_loss_value = running_vall_loss/len(validate_loader) # Calculate accuracy as the number of correct predictions in the validation batch divided by the total number of predictions done. accuracy = (100 * running_accuracy / total) # Save the model if the accuracy is the best if accuracy > best_accuracy: saveModel() best_accuracy = accuracy # Print the statistics of the epoch print('Completed training batch', epoch, 'Training Loss is: %.4f' %train_loss_value, 'Validation Loss is: %.4f' %val_loss_value, 'Accuracy is %d %%' % (accuracy))使用测试数据测试模型。现在我们已经训练了模型,接下来可使用测试数据集来测试模型。我们将添加 2 个测试函数。 第一个函数测试你在上一部分保存的模型。 它将使用包含 45 个项的测试数据集来测试模型,并打印出模型的准确度。 第二个是可选函数,用于测试模型在预测三种鸢尾花品类的每一种时的可信度,用成功分类每个品种的概率表示。将以下代码添加到 DataClassifier.py 文件。py# Function to test the model def test(): # Load the model that we saved at the end of the training loop model = Network(input_size, output_size) path = "NetModel.pth" model.load_state_dict(torch.load(path)) running_accuracy = 0 total = 0 with torch.no_grad(): for data in test_loader: inputs, outputs = data outputs = outputs.to(torch.float32) predicted_outputs = model(inputs) _, predicted = torch.max(predicted_outputs, 1) total += outputs.size(0) running_accuracy += (predicted == outputs).sum().item() print('Accuracy of the model based on the test set of', test_split ,'inputs is: %d %%' % (100 * running_accuracy / total)) # Optional: Function to test which species were easier to predict def test_species(): # Load the model that we saved at the end of the training loop model = Network(input_size, output_size) path = "NetModel.pth" model.load_state_dict(torch.load(path)) labels_length = len(labels) # how many labels of Irises we have. = 3 in our database. labels_correct = list(0. for i in range(labels_length)) # list to calculate correct labels [how many correct setosa, how many correct versicolor, how many correct virginica] labels_total = list(0. for i in range(labels_length)) # list to keep the total # of labels per type [total setosa, total versicolor, total virginica] with torch.no_grad(): for data in test_loader: inputs, outputs = data predicted_outputs = model(inputs) _, predicted = torch.max(predicted_outputs, 1) label_correct_running = (predicted == outputs).squeeze() label = outputs[0] if label_correct_running.item(): labels_correct[label] += 1 labels_total[label] += 1 label_list = list(labels.keys()) for i in range(output_size): print('Accuracy to predict %5s : %2d %%' % (label_list[i], 100 * labels_correct[i] / labels_total[i])) 最后,让我们添加主代码。 这将启动模型训练、保存模型并在屏幕上显示结果。 我们将在训练集上仅运行两次迭代 [num_epochs = 25],因此训练过程不会花费太长时间。将以下代码添加到 DataClassifier.py 文件。pyif __name__ == "__main__": num_epochs = 10 train(num_epochs) print('Finished Training\n') test() test_species() 让我们运行测试! 确保顶部工具栏中的下拉菜单设置为 Debug。 如果设备是 64 位的,请将 Solution Platform 更改为 x64 以在本地计算机上运行项目;如果设备是 32 位的,请将其更改为 x86。要运行项目,请单击工具栏上的 Start Debugging 按钮,或者按 F5。这将弹出控制台窗口,你将看到训练过程。 如定义的一样,将对每个 epoch 打印丢失值。 预期是随着每次 epoch,损失值会变小。训练完成后,应会看到类似于下面的输出。 数字不会完全相同 - 训练取决于许多因素,并且不会总是返回相同的结果 - 但它们应该看起来相似。
  • [技术干货] 使用 PyTorch 训练图像分类器模型【转】
    本文内容定义卷积神经网络。神经网络如何工作?定义损失函数使用训练数据训练模型。在本教程的前一阶段中,我们获取了将用于使用 PyTorch 训练图像分类器的数据集。 现在,我们将使用这些数据。要使用 PyTorch 训练图像分类器,需要完成以下步骤:加载数据。 如果已完成本教程的上一步,则已经完成了数据加载。定义卷积神经网络。定义损失函数。使用训练数据训练模型。使用测试数据测试网络。定义卷积神经网络。若要使用 PyTorch 构建神经网络,你将使用 torch.nn 包。 该包包含模块、可扩展类和构建神经网络所需的全部组件。在本部分中,你将构建一个基本的卷积神经网络 (CNN) 来对 CIFAR10 数据集中的图像进行分类。CNN 是一类神经网络,定义为多层神经网络,旨在检测数据中的复杂特征。 它们最常用于计算机视觉应用程序。我们的网络将由以下 14 层构成:Conv -> BatchNorm -> ReLU -> Conv -> BatchNorm -> ReLU -> MaxPool -> Conv -> BatchNorm -> ReLU -> Conv -> BatchNorm -> ReLU -> Linear.卷积层卷积层是 CNN 的主要层,可帮助我们检测图像中的特征。 每个层都有多个通道来检测图像中的特定特征,还有多个内核来定义检测到的特征的大小。 因此,具有 64 个通道和 3 x 3 内核大小的卷积层将检测 64 个不同的特征,每个大小为 3 x 3。 定义卷积层时,需要提供输入通道数、输出通道数和内核大小。 该层中的输出通道数为下一层的输入通道数。例如:输入通道数为 3、输出通道数为 10、内核大小为 6 的卷积层将得到 RGB 图像(3 通道)作为输入,并对核大小为 6x6 的图像应用 10 个特征检测器。 较小的内核大小将缩短计算时间和权重共享。其他层我们的网络还涉及以下其他层:ReLU 层是一个激活函数,用于将所有传入特征定义为 0 或更大。 应用此层时,任何小于 0 的数字都会更改为零,而其他数字则保持不变。BatchNorm2d 层对输入应用规范化以获得零均值和单位方差并提高网络精度。MaxPool 层将帮助我们确保图像中对象的位置不会影响神经网络检测其特定特征的能力。Linear 层是网络中的最后一层,它计算每个类的分数。 在 CIFAR10 数据集中,有 10 类标签。 得分最高的标签将是模型预测的那一个。 在线性层中,必须指定输入特征的数量和输出特征的数量,它们应与类的数量相对应。神经网络如何工作?CNN 是一种前馈网络。 在训练过程中,网络将处理所有层的输入,计算损失以了解图像的预测标签与正确标签相差多远,并将梯度传播回网络以更新层的权重。 通过迭代庞大的输入数据集,网络将“学习”设置其权重以获得最佳结果。前向函数计算损失函数的值,后向函数计算可学习参数的梯度。 使用 PyTorch 创建神经网络时,只需定义前向函数。 后向函数会自动定义。将以下代码复制到 Visual Studio 中的 PyTorchTraining.py 文件以定义 CCN。pyimport torchimport torch.nn as nnimport torchvisionimport torch.nn.functional as F# Define a convolution neural networkclass Network(nn.Module): def __init__(self): super(Network, self).__init__() self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=5, stride=1, padding=1) self.bn1 = nn.BatchNorm2d(12) self.conv2 = nn.Conv2d(in_channels=12, out_channels=12, kernel_size=5, stride=1, padding=1) self.bn2 = nn.BatchNorm2d(12) self.pool = nn.MaxPool2d(2,2) self.conv4 = nn.Conv2d(in_channels=12, out_channels=24, kernel_size=5, stride=1, padding=1) self.bn4 = nn.BatchNorm2d(24) self.conv5 = nn.Conv2d(in_channels=24, out_channels=24, kernel_size=5, stride=1, padding=1) self.bn5 = nn.BatchNorm2d(24) self.fc1 = nn.Linear(24*10*10, 10) def forward(self, input): output = F.relu(self.bn1(self.conv1(input))) output = F.relu(self.bn2(self.conv2(output))) output = self.pool(output) output = F.relu(self.bn4(self.conv4(output))) output = F.relu(self.bn5(self.conv5(output))) output = output.view(-1, 24*10*10) output = self.fc1(output) return output# Instantiate a neural network model model = Network()备注想要详细了解如何使用 PyTorch 创建神经网络? 请查看 PyTorch 文档定义损失函数损失函数计算一个值,该值可估计输出与目标之间的差距。 主要目标是通过神经网络中的反向传播改变权重向量值来减少损失函数的值。丢失值不同于模型准确性。 通过损失函数可了解模型在每次训练集优化迭代后的表现。 模型的准确性基于测试数据进行计算,并显示正确预测的百分比。在 PyTorch 中,神经网络包包含各种损失函数,这些函数构成了深层神经网络的构建基块。 在本教程中,你将先使用分类交叉熵损失定义损失函数和 Adam 优化器,然后再使用分类损失函数。 学习速率 (lr) 设置你根据损失梯度调整网络权重的程度控制。 请将其设置为 0.001。 速率越低,训练速度就越慢。将以下代码复制到 Visual Studio 中的 PyTorchTraining.py 文件中,以定义损失函数和优化器。pyfrom torch.optim import Adam # Define the loss function with Classification Cross-Entropy loss and an optimizer with Adam optimizerloss_fn = nn.CrossEntropyLoss()optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)使用训练数据训练模型。要训练模型,必须循环访问数据迭代器,将输入馈送到网络并进行优化。 PyTorch 没有用于 GPU 的专用库,但你可以手动定义执行设备。 如果计算机上存在 Nvidia GPU,则该设备为 Nvidia GPU,如果没有,则为 CPU。将以下代码添加到 PyTorchTraining.py 文件pyfrom torch.autograd import Variable# Function to save the modeldef saveModel(): path = "./myFirstModel.pth" torch.save(model.state_dict(), path)# Function to test the model with the test dataset and print the accuracy for the test imagesdef testAccuracy(): model.eval() accuracy = 0.0 total = 0.0 with torch.no_grad(): for data in test_loader: images, labels = data # run the model on the test set to predict labels outputs = model(images) # the label with the highest energy will be our prediction _, predicted = torch.max(outputs.data, 1) total += labels.size(0) accuracy += (predicted == labels).sum().item() # compute the accuracy over all test images accuracy = (100 * accuracy / total) return(accuracy)# Training function. We simply have to loop over our data iterator and feed the inputs to the network and optimize.def train(num_epochs): best_accuracy = 0.0 # Define your execution device device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print("The model will be running on", device, "device") # Convert model parameters and buffers to CPU or Cuda model.to(device) for epoch in range(num_epochs): # loop over the dataset multiple times running_loss = 0.0 running_acc = 0.0 for i, (images, labels) in enumerate(train_loader, 0): # get the inputs images = Variable(images.to(device)) labels = Variable(labels.to(device)) # zero the parameter gradients optimizer.zero_grad() # predict classes using images from the training set outputs = model(images) # compute the loss based on model output and real labels loss = loss_fn(outputs, labels) # backpropagate the loss loss.backward() # adjust parameters based on the calculated gradients optimizer.step() # Let's print statistics for every 1,000 images running_loss += loss.item() # extract the loss value if i % 1000 == 999: # print every 1000 (twice per epoch) print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 1000)) # zero the loss running_loss = 0.0 # Compute and print the average accuracy fo this epoch when tested over all 10000 test images accuracy = testAccuracy() print('For epoch', epoch+1,'the test accuracy over the whole test set is %d %%' % (accuracy)) # we want to save the model if the accuracy is the best if accuracy > best_accuracy: saveModel() best_accuracy = accuracy使用测试数据测试模型。现在,可以使用测试集中的一批图像来测试模型。将以下代码添加到 PyTorchTraining.py 文件。pyimport matplotlib.pyplot as pltimport numpy as np# Function to show the imagesdef imageshow(img): img = img / 2 + 0.5 # unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) plt.show()# Function to test the model with a batch of images and show the labels predictionsdef testBatch(): # get batch of images from the test DataLoader images, labels = next(iter(test_loader)) # show all images as one image grid imageshow(torchvision.utils.make_grid(images)) # Show the real labels on the screen print('Real labels: ', ' '.join('%5s' % classes[labels[j]] for j in range(batch_size))) # Let's see what if the model identifiers the labels of those example outputs = model(images) # We got the probability for every 10 labels. The highest (max) probability should be correct label _, predicted = torch.max(outputs, 1) # Let's show the predicted labels on the screen to compare with the real ones print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(batch_size)))最后,让我们添加主代码。 这将启动模型训练、保存模型并在屏幕上显示结果。 我们将在训练集上仅运行两次迭代 [train(2)],因此训练过程不会花费太长时间。将以下代码添加到 PyTorchTraining.py 文件。pyif __name__ == "__main__": # Let's build our model train(5) print('Finished Training') # Test which classes performed well testModelAccuracy() # Let's load the model we just created and test the accuracy per label model = Network() path = "myFirstModel.pth" model.load_state_dict(torch.load(path)) # Test with batch of images testBatch()让我们运行测试! 确保顶部工具栏中的下拉菜单设置为“调试”。 将解决方案平台更改为 x64(如果使用 64 位设备)或 x86(如果使用 32 位设备)以在本地计算机上运行该项目。选择等于 2 ([train(2)]) 的时期数(完整通过训练数据集的次数)将导致对包含 10,000 个图像的整个测试数据集进行两次迭代。 在第 8 代 Intel CPU 上完成训练大约需要 20 分钟,该模型对 10 个标签的分类成功率应达到 65% 左右。要运行该项目,请单击工具栏上的开始调试按钮或按 F5 键。随即将弹出控制台窗口,你可以在其中看到训练过程。正如你所定义的那样,将每隔 1,000 批图像打印一次损失值,训练集的每次迭代打印五次。 你希望每个循环的损失值逐渐减少。还可以在每次迭代后查看模型的准确性。 模型准确性与损失值不同。 通过损失函数可了解模型在每次训练集优化迭代后的表现。 模型的准确性基于测试数据进行计算,并显示正确预测的百分比。 在本例中,它将指示模型在每次训练迭代后能够从 10,000 个图像测试集中正确分类的图像数量。训练完成后,应会看到类似于下面的输出。 数字不会完全相同 - 训练取决于许多因素,并且不会总是返回相同的结果 - 但它们应该看起来相似。仅运行 5 个时期后,模型成功率为 70%。 对于短期训练的基本模型来说,这是一个很好的结果!用一批图像进行测试,模型从该批次的 10 个图像中得出了 7 个正确的图像。 结果很不错,与模型成功率一致。可检查模型预测哪些类别的图像效果最佳。 只需添加并运行以下代码:可选 - 将以下 testClassess 函数添加到 PyTorchTraining.py 文件中,在主函数 __name__ == "__main__" 中添加此函数 testClassess() 的调用。py# Function to test what classes performed welldef testClassess(): class_correct = list(0. for i in range(number_of_labels)) class_total = list(0. for i in range(number_of_labels)) with torch.no_grad(): for data in test_loader: images, labels = data outputs = model(images) _, predicted = torch.max(outputs, 1) c = (predicted == labels).squeeze() for i in range(batch_size): label = labels[i] class_correct[label] += c[i].item() class_total[label] += 1 for i in range(number_of_labels): print('Accuracy of %5s : %2d %%' % ( classes[i], 100 * class_correct[i] / class_total[i]))输出如下所示:
总条数:7894 到第 页
上滑加载中