网站备案个人和企业的区别,侯斯特 wordpress,长沙人才网最新招聘信息,傻瓜式php网站开发工具一、准备数据集
一般来说#xff0c;当你不得不与图像、文本或者视频资料打交道时#xff0c;会选择使用python的标准库将原始数据加载转化成numpy数组#xff0c;甚至可以继续转换成torch.*Tensor。
对图片而言#xff0c;可以使用Pillow库和OpenCV库对视频而言#xf…一、准备数据集
一般来说当你不得不与图像、文本或者视频资料打交道时会选择使用python的标准库将原始数据加载转化成numpy数组甚至可以继续转换成torch.*Tensor。
对图片而言可以使用Pillow库和OpenCV库对视频而言可以使用scipy库和librosa库对文本而言可以使用基于原生Python或Cython加载或NLTK和SpaCy等。
Pytorch特别针对视觉方面创建torchvision库其中包含能够加载ImageNet、CIFAR10和MNIST等数据集的数据加载功能对图像的数据增强功能即torchvision.datasets和torch.utils.data.DataLoader。
这为大家搭建数据集提供了极大的便利避免了需要自己写样板代码的情况。
本次我们使用CIFAR10数据集。这是一个含有“飞机”、“汽车”、“鸟”、“猫”、“鹿”、“狗”、“青蛙”、“马”、“轮船”和“卡车”等10个分类的数据集。数据集中每张图像均为[C×H×W][3×32×32]即3通道的高32像素宽32像素的彩色图像。 CIFAR-10数据集示例
二、训练图像分类器
下面的步骤大概可以分成5个有序部分
用 torchvision 载入(loading)并归一化(normalize)CIFAR10训练数据集和测试数据集定义卷积神经网络(CNN)定义损失函数和优化器训练网络测试网络
P.S. 以下给出的代码均为在CPU上运行的代码。但本人在pycharm中运行的为自己修改过的在GPU上训练的代码示例结果和截图也都是GPU运行的结果。 2.1 载入并归一化CIFAR10数据集
用torchvision载入CIFAR10 import torch
import torchvision
import torchvision.transforms as transforms torchvision加载的数据集是PILImage数据范围[0,1]。我们需要使用transform函数将其归一化(normalize)为[-1,1]。
细心的伙伴发现了我将英文的normalize翻译成了“归一化”而不是标准化这是因为接下来的代码你会看到预处理阶段transformer变量存储的处理操作仅仅是运用了normalize的计算规则将数据范围进行了缩放并没有改变数据的分布因此翻译成“归一化”更合理。
NOTE.(抄的原文以防有小伙伴真的遇到这个意外问题) If running on Windows and you get a BrokenPipeError, try setting the num_worker of torch.utils.data.DataLoader() to 0。 --snip--transform transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])batch_size 4trainset torchvision.datasets.CIFAR10(root./data, trainTrue, downloadTrue, transformtransform)
trainloader torch.utils.data.DataLoader(trainset, batch_sizebatch_size, shuffleTrue, num_workers2)testset torchvision.datasets.CIFAR10(root./data, trainFalse, downloadTrue, transformtransform)
testloader torch.utils.data.DataLoader(testset, batch_sizebatch_size, shuffleFalse, num_workers2)classes (plane, car, bird, cat, deer, dog, frog, horse, ship, truck) transform中的ToTensor和Normalize函数究竟在做什么以及为什么要归一化等问题感兴趣的小伙伴可以阅读附录中的序号1~3文章其中
博主“小研一枚”[1]通过源码为我们讲解函数的计算行为定义等知识点答主Transformer[2]通过知乎专栏为我们做了几组代码实例。而我们则要看清文章、留言区争论的核心与我们真正求索的问题之间的区别和联系避免被争论本身误导答主“JMD”[3]则为我们科普归一化的相关知识
书归正题上述代码第一次运行的结果可能是这样子的 数据集加载运行日志
此时我们可以使用numpy库和matplotlib库查看数据集中的图片和标签。 import matplotlib.pyplot as plt
import numpy as np# functions to show an image
def imshow(img):img img / 2 0.5 # unnormalizenpimg img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()# get some random training images
dataiter iter(trainloader)
images, labels dataiter.next()# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print( .join(f{classes[labels[j]]:5s} for j in range(batch_size))) 但是如果你就这样将代码copypaste在pycharm中直接接续在载入数据的代码下面点击“运行”有可能得到的是一个RuntimeError,并建议你按照惯例设置if __name__ __main__:
所以我建议将目前为止的代码优化成下面的样子
import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader # 如果torch.utils.data.DataLoader()有报错提示“在 __init__.py 中找不到引用 data则增加此语句或者其他语句 ”
import matplotlib.pyplot as plt
import numpy as np
# ①←后续如果继续导入packages请直接在这里插入代码transform transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])batch_size 4trainset torchvision.datasets.CIFAR10(root./data, trainTrue, downloadTrue, transformtransform)
trainloader torch.utils.data.DataLoader(trainset, batch_sizebatch_size, shuffleTrue, num_workers2)testset torchvision.datasets.CIFAR10(root./data, trainFalse, downloadTrue, transformtransform)
testloader torch.utils.data.DataLoader(testset, batch_sizebatch_size, shuffleFalse, num_workers2)classes (plane, car, bird, cat, deer, dog, frog, horse, ship, truck)def imshow(img):显示图像的函数img img / 2 0.5 # 去归一化npimg img.numpy()# 上面transform.ToTensor()操作后数据编程CHW[通道靠前模式]需要转换成HWC[通道靠后模式]才能plt.imshow()plt.imshow(np.transpose(npimg, (1, 2, 0))) # 转置前将排在第0位的Channel(C)放在最后所以是(1,2,0)plt.show()# ②←后续再有定义class、function等在此插入代码编写if __name__ __main__:# 随机输出一个mini-batch的图像dataiter_tr iter(trainloader) # 取一个batch的训练集数据# images_tr, labels_tr dataiter_tr.next() 根据你的python选择迭代器调用语句images_tr, labels_tr next(dataiter_tr) # 切分数据和标签imshow(torchvision.utils.make_grid(images_tr)) # 生成网格图print( .join(f{classes[labels_tr[j]]:5s} for j in range(batch_size))) # 打印标签值# print( .join(%5s % classes[labels_tr[j]] for j in range(batch_size))) 如果你使用python3.6之前的版本那么有可能无法使用f字符串语句只能使用.format()方法# ③←后续的程序执行语句在此插入
输出图像示例 随机输出一个mini-batch的训练集图像
标签输出bird cat deer ship 2.2 定义一个卷积神经网络
可以将之前写过的识别手写数字MNIST的神经网络迁移到这里来。 # 在①后插入import代码
import torch.nn as nn
import torch.nn.functional as F# 在②后插入神经网络定义代码
class Net(nn.Module):定义一个卷积神经网络及前馈函数def __init__(self):初始化网络定义卷积层、池化层和全链接层super().__init__() # 继承父类属性。P.S. 如果看到super(Net, self).__init__()写法亦可self.conv1 nn.Conv2d(3, 6, 5) # 使用2套卷积核。输入(B×3×32×32),输出(B×6×28×28)self.pool nn.MaxPool2d(2, 2) # 最大池化操作输出时高、宽减半(B×6×14×14) (B×16×5×5)self.conv2 nn.Conv2d(6, 16, 5) # 使用4套卷积核卷积核大小为5×5。(B×16×10×10)self.fc1 nn.Linear(16 * 5 * 5, 120) # 全链接层。将数据扁平化成一维共400个输入120个输出self.fc2 nn.Linear(120, 84) # 全链接层。120个输入84个输出self.fc3 nn.Linear(84, 10) # 全链接层。84个输入10个输出用于分类def forward(self, x):前馈函数规定数据正向传播的规则x self.pool(F.relu(self.conv1(x))) # 输入 conv1卷积 ReLu激活 maxpool最大池化x self.pool(F.relu(self.conv2(x))) # conv2卷积 ReLu激活 maxpool最大池化# x torch.flatten(x, 1) # 如果你不喜欢下一种写法实现扁平化可以使用这条语句代替x x.view(-1, 16 * 5 * 5) # 相当于numpy的reshape。此处是将输入数据变换成不固定行数因此第一个参数是-1完成扁平化x F.relu(self.fc1(x)) # 扁平化数据 fc1全链接层 ReLu激活x F.relu(self.fc2(x)) # fc2全链接层 ReLu激活x self.fc3(x) # fc3全链接层 输出return x# 在③后插入神经网络实例化代码
net Net() # 实例化神经网络 2.3 定义损失函数和优化器
我们使用多分类交叉熵损失函数(Classification Cross-Entropy loss)[4]和随机梯度下降法(SGD)的动量改进版(momentum)[5][6] # 在①后插入import代码
import torch.optim as optim# 在③后插入代码
criterion nn.CrossEntropyLoss() # 交叉熵损失函数
optimizer optim.SGD(net.parameters(), lr0.001, momentum0.9) 这里必须做一个扩展。
在2.2中我们可以看到神经网络中每个层的输出都经过了激活函数的激活作用。但是在输出层后却缺少了激活函数而貌似“直接作用了损失函数”。
简单地说原因就在于torch.nn.CrossEntropyLoss()将nn.LogSoftmax()激活函数和nn.NLLLoss()负对数似然损失函数集成在一起。
logsoftmax是argmax softargmax softmax logsoftmax逐步优化的求极大值的index的期望的方法。负对数似然损失函数(Negtive Log Likehood)就是计算最小化真实分布 P(y|x) 与模型输出分布 P(y^|x) 的距离等价于最小化两者的交叉熵。实际使用函数时是one-hot编码后的标签与logsoftmax结果相乘再求均值再取反这个过程博主“不愿透漏姓名的王建森”在他的博客中做过实验[7]讲解。
上述结论的详尽说明请参考知乎上Cassie的创作《吃透torch.nn.CrossEntropyLoss()》[8]、知乎上Gordon Lee的创作《交叉熵和极大似然估计的再理解》[9]。
P.S. 对于torch.nn.CrossEntropyLoss()的官网Doc中提到的This is particularly useful when you have an unbalanced training set.关于如何处理不均衡样品的几个解决办法可以参考Quora上的问答《In classification, how do you handle an unbalanced training set?》[10]以及热心网友对此问答的翻译[11]。
2.4 训练神经网络
事情变得有趣起来了我们只需要遍历我们的迭代器将其输入进神经网络和优化器即可。
如果想在GPU上训练请参考文章开头给出的【学习源】链接中的末尾部分有教授如何修改代码的部分。 --snip--# 在③后插入代码for epoch in range(5): # 数据被遍历的次数running_loss 0.0 # 每次遍历前重新初始化loss值for i, data in enumerate(trainloader, 0):inputs, labels data # 切分数据集optimizer.zero_grad() # 梯度清零避免上一个batch迭代的影响# 前向传递 反向传递 权重优化outputs net(inputs)loss criterion(outputs, labels)loss.backward()optimizer.step()# 输出日志running_loss loss.item() # Tensor.item()方法是将tensor的值转化成python numberif i % 2000 1999: # 每2000个mini batches输出一次# print([%d, %5d] loss: %.3f % (epoch 1, i 1, running_loss / 2000)) 如果python3.6之前版本可以使用这个代码print(f[{epoch 1}, {i 1:5d}] loss: {running_loss / 2000:.3f})running_loss 0.0print(Finished Training) Out: model will be trained on device: cuda:0 某一次输出结果日志整理一下如下表 Finished Training 将loss数据整理并画图(选做) --snip--x np.linspace(2000, 12000, 6, dtypenp.int32)
# 数据每次训练输出都不一样给出画图代码至于数据大家寄几填吧~
epoch_01 np.array([...])
epoch_02 np.array([...])
epoch_03 np.array([...])
epoch_04 np.array([...])
epoch_05 np.array([...])plt.plot(x, epoch_01, ro-., x, epoch_02, bo-., x, epoch_03, yo-., x, epoch_04, ko-., x, epoch_05, go-.)
plt.legend([Epoch_1, Epoch_2, Epoch_3, Epoch_4, Epoch_5])
plt.xlabel(number of mini-batches)
plt.ylabel(loss)
plt.title(Loss during CIFAR-10 training procedure in Convolution Neural Networks)
plt.show() 通过数据我们可以看出loss的下降趋势
第一个epoch的最明显第二个epoch继续降低但趋势更平缓后三个epoch在开始较前一个epoch有较明显下降但下降幅度递减*后三个epoch在该epoch内下降趋势平缓或出现小幅震荡并保持低于前一个epoch
现在我们可以快速保存训练完成的模型到指定的路径。 --snip--PATH ./cifar_net.pth
torch.save(net.state_dict(), PATH) 保存的文件 2.5 测试神经网络
我们已经用训练集数据将神经网络训练了5次(epoches5)。但我们还需要核实神经网络是否真的学到了什么。 我们将以神经网络预测的类别标签和真实标签进行对比核实。如果预测正确则将样本添加到正确预测列表中。 首先我们像查看训练集的一个mini batch图像一样看一下一部分测试集图像。 --snip--dataiter_te iter(testloader)images_te, labels_te next(dataiter_te) # 另一种备用写法参考训练集部分imshow(torchvision.utils.make_grid(images_te))print(GroundTruth: , .join(%5s % classes[labels_te[j]] for j in range(batch_size))) # 另一种备用写法参考训练集部分 随机输出一个mini-batch的测试集图像
Out: GroundTruth: cat ship ship plane 下面我们载入之前保存的模型(注保存和再载入模型不是必要步骤这里这么做是为了演示这些操作) --snip--net Net()
net.load_state_dict(torch.load(PATH)) OK现在让我们看看神经网络如何看待这些图像的分类的 --snip--outputs net(images) # 看一下神经网络对上述展示图片的预测结果 输出的是10个分类的“能量(energy)”。某个分类的能量越高意味着神经网络认为该图像越符合该分类。因此我们可以获得那个能量的索引。 --snip--_, predicted torch.max(outputs, 1) # torch.max(input, dim)返回按照dim方向的最大值和其索引print(Predicted: , .join(f{classes[predicted[j]]:5s} for j in range(batch_size))) Out: Predicted: cat ship ship ship 看起来不错。下面就试一试在全部测试集上的表现 correct 0total 0# 由于这不是在训练模型因此对输出不需要计算梯度等反向传播过程with torch.no_grad():for data in testloader:images_pre, labels_pre dataoutputs net(images_pre) # 数据传入神经网络计算输出_, predicted torch.max(outputs.data, 1) # 获取最大能量的索引total labels_pre.size(0) # 计算预测次数correct (predicted labels_pre).sum().item() # 计算正确预测次数print(fAccuracy of the network on the 10000 test images: {100 * correct // total} %) Out: Accuracy of the network on the 10000 test images: 61 % 感觉预测的准确率比随机从10个类中蒙一个类(概率10%)要高看来神经网络确实学到了一些东西。
当然我们还可以看一下对于不同的类的学习效果 --snip--# 生成两个dict,分别用来存放预测正确数量和总数量的个数
correct_pred {classname: 0 for classname in classes}
total_pred {classname: 0 for classname in classes}# 启动预测过程无需计算梯度等
with torch.no_grad():for data in testloader:images_cl, labels_cl dataoutputs net(images_cl)_, predictions torch.max(outputs, 1)# 开始计数for label, prediction in zip(labels_cl, predictions):if label prediction:correct_pred[classes[label]] 1total_pred[classes[label]] 1# 分类别打印预测准确率
for classname, correct_count in correct_pred.items():accuracy 100 * float(correct_count) / total_pred[classname]print(fAccuracy for class: {classname:5s} is {accuracy:.1f} %) Out: Accuracy for class: plane is 66.2 % Accuracy for class: car is 80.7 % Accuracy for class: bird is 39.1 % Accuracy for class: cat is 53.4 % Accuracy for class: deer is 64.6 % Accuracy for class: dog is 35.8 % Accuracy for class: frog is 67.9 % Accuracy for class: horse is 69.5 % Accuracy for class: ship is 75.0 % Accuracy for class: truck is 65.5 % 至此我们完成了练习 在结束前让我们反思一下准确率为何会呈现上述样子我推测
数据集本身缺陷如图片太小(32×32)不足以让卷积神经网络提取到足够特征类别划分不合理(汽车卡车以及飞机鸟等较其他类别而言是否太过相似)各类别图像数量和图像本身质量等数据的预处理不足预处理阶段对数据的增强不够是否可以加入旋转/镜像/透视、裁剪、亮度调节、噪声/平滑等处理神经网络本身的结构、参数设置等是否合理如卷积/全链接层数的规定、卷积核相关的定义、损失函数的选择、batch size/epoch的平衡等(希望可以通过学习后续的Alexnet、VGG、Resnet、FastRCNN、YOLO等受到启发)避免偶然。不能以单次的结果去评价评价应当建立在若干次重复试验的基础上
本文翻译至Training a Classifier — PyTorch Tutorials 2.6.0cu124 documentation
参考
pytorch的transform中ToTensor接着Normalize http://t.csdn.cn/bCDSUpytorch中归一化transforms.Normalize的真正计算过程 - Transformer的文章 - 知乎 https://zhuanlan.zhihu.com/p/414242338标准化/归一化的目的和作用 - JMD的文章 - 知乎 https://zhuanlan.zhihu.com/p/465264729Doc--torch.nn.CrossEntropyLoss CrossEntropyLoss — PyTorch 2.6 documentationDoc-torch.optim.SGD SGD — PyTorch 2.6 documentation深度学习中常用优化器的总结 - Alex Chung的文章 - 知乎 https://zhuanlan.zhihu.com/p/166362509^交叉熵的数学原理及应用——pytorch中的CrossEntropyLoss()函数 交叉熵的数学原理及应用——pytorch中的CrossEntropyLoss()函数 - 不愿透漏姓名的王建森 - 博客园^吃透torch.nn.CrossEntropyLoss() - Cassie的文章 - 知乎 https://zhuanlan.zhihu.com/p/159477597交叉熵和极大似然估计的再理解 - Gordon Lee的文章 - 知乎 https://zhuanlan.zhihu.com/p/165139520In classification, how do you handle an unbalanced training set? https://www.quora.com/In-classification-how-do-you-handle-an-unbalanced-training-set如何处理训练样本不均衡的问题 http://t.csdn.cn/FDVYJ 文章转载自: http://www.morning.qrpdk.cn.gov.cn.qrpdk.cn http://www.morning.hkswt.cn.gov.cn.hkswt.cn http://www.morning.nrrzw.cn.gov.cn.nrrzw.cn http://www.morning.sjjq.cn.gov.cn.sjjq.cn http://www.morning.qzglh.cn.gov.cn.qzglh.cn http://www.morning.mkpqr.cn.gov.cn.mkpqr.cn http://www.morning.dmcqy.cn.gov.cn.dmcqy.cn http://www.morning.gllhx.cn.gov.cn.gllhx.cn http://www.morning.dspqc.cn.gov.cn.dspqc.cn http://www.morning.nnjq.cn.gov.cn.nnjq.cn http://www.morning.pbsqr.cn.gov.cn.pbsqr.cn http://www.morning.jxzfg.cn.gov.cn.jxzfg.cn http://www.morning.wbqt.cn.gov.cn.wbqt.cn http://www.morning.gtcym.cn.gov.cn.gtcym.cn http://www.morning.lmhcy.cn.gov.cn.lmhcy.cn http://www.morning.qncqd.cn.gov.cn.qncqd.cn http://www.morning.zzgtdz.cn.gov.cn.zzgtdz.cn http://www.morning.pwdrc.cn.gov.cn.pwdrc.cn http://www.morning.ljbpk.cn.gov.cn.ljbpk.cn http://www.morning.yfqhc.cn.gov.cn.yfqhc.cn http://www.morning.kjdxh.cn.gov.cn.kjdxh.cn http://www.morning.rdmn.cn.gov.cn.rdmn.cn http://www.morning.lslin.com.gov.cn.lslin.com http://www.morning.pluimers.cn.gov.cn.pluimers.cn http://www.morning.jyyw.cn.gov.cn.jyyw.cn http://www.morning.qllcm.cn.gov.cn.qllcm.cn http://www.morning.qcygd.cn.gov.cn.qcygd.cn http://www.morning.kspfq.cn.gov.cn.kspfq.cn http://www.morning.qgxnw.cn.gov.cn.qgxnw.cn http://www.morning.ldqzz.cn.gov.cn.ldqzz.cn http://www.morning.ltdrz.cn.gov.cn.ltdrz.cn http://www.morning.ftmzy.cn.gov.cn.ftmzy.cn http://www.morning.nfks.cn.gov.cn.nfks.cn http://www.morning.rkwwy.cn.gov.cn.rkwwy.cn http://www.morning.jphxt.cn.gov.cn.jphxt.cn http://www.morning.ppllj.cn.gov.cn.ppllj.cn http://www.morning.jstggt.cn.gov.cn.jstggt.cn http://www.morning.hctgn.cn.gov.cn.hctgn.cn http://www.morning.pfjbn.cn.gov.cn.pfjbn.cn http://www.morning.dbqg.cn.gov.cn.dbqg.cn http://www.morning.dydqh.cn.gov.cn.dydqh.cn http://www.morning.mmqhq.cn.gov.cn.mmqhq.cn http://www.morning.clbgy.cn.gov.cn.clbgy.cn http://www.morning.wphzr.cn.gov.cn.wphzr.cn http://www.morning.qxnlc.cn.gov.cn.qxnlc.cn http://www.morning.bqfpm.cn.gov.cn.bqfpm.cn http://www.morning.tgyqq.cn.gov.cn.tgyqq.cn http://www.morning.wklmj.cn.gov.cn.wklmj.cn http://www.morning.zcnfm.cn.gov.cn.zcnfm.cn http://www.morning.qwbls.cn.gov.cn.qwbls.cn http://www.morning.wchcx.cn.gov.cn.wchcx.cn http://www.morning.dlrsjc.com.gov.cn.dlrsjc.com http://www.morning.pccqr.cn.gov.cn.pccqr.cn http://www.morning.ydyjf.cn.gov.cn.ydyjf.cn http://www.morning.hrpbq.cn.gov.cn.hrpbq.cn http://www.morning.ptmch.com.gov.cn.ptmch.com http://www.morning.xnpml.cn.gov.cn.xnpml.cn http://www.morning.xlclj.cn.gov.cn.xlclj.cn http://www.morning.drytb.cn.gov.cn.drytb.cn http://www.morning.mbrbg.cn.gov.cn.mbrbg.cn http://www.morning.pumali.com.gov.cn.pumali.com http://www.morning.qsmch.cn.gov.cn.qsmch.cn http://www.morning.xhfky.cn.gov.cn.xhfky.cn http://www.morning.lmdfj.cn.gov.cn.lmdfj.cn http://www.morning.zcsyz.cn.gov.cn.zcsyz.cn http://www.morning.bxhch.cn.gov.cn.bxhch.cn http://www.morning.gjtdp.cn.gov.cn.gjtdp.cn http://www.morning.sjsfw.cn.gov.cn.sjsfw.cn http://www.morning.qfplp.cn.gov.cn.qfplp.cn http://www.morning.kpbq.cn.gov.cn.kpbq.cn http://www.morning.qrpx.cn.gov.cn.qrpx.cn http://www.morning.hxljc.cn.gov.cn.hxljc.cn http://www.morning.npfrj.cn.gov.cn.npfrj.cn http://www.morning.bpmfr.cn.gov.cn.bpmfr.cn http://www.morning.xhsxj.cn.gov.cn.xhsxj.cn http://www.morning.pcshb.cn.gov.cn.pcshb.cn http://www.morning.kpmxn.cn.gov.cn.kpmxn.cn http://www.morning.yqsq.cn.gov.cn.yqsq.cn http://www.morning.glcgy.cn.gov.cn.glcgy.cn http://www.morning.hmqwn.cn.gov.cn.hmqwn.cn