96SEO 2026-02-19 18:55 22
可以从本人以前的文章中可以看出作者以前从事的是嵌入式控制方面相关的工作是一个机器视觉小白之所以开始入门机器视觉的学习只要是一个idea想把机器视觉与控制相融合未来做一点小东西。

废话不多说开始正题。
摘要本文是介绍VGG16网络,个人对其的知识总结网络设计的知识点以及代码如何撰写基于pytorch编写代码。
作为一个刚入门的小白怎么去学习别人的代码一步一步的去理解每一行代码怎么将网络设计变成代码模仿大佬的代码去撰写。
作为小白如有不足之处请批评指正哈。
在此之前本人学习了机器视觉的基础知识以下是本人学习时的链接希望对你有所帮助。
https://fuhanghang.blog.csdn.net/article/details/135544761?fromshareblogdetailsharetypeblogdetailsharerId135544761sharereferPCsharesourceweixin_52531699sharefromfrom_link
https://www.bilibili.com/video/BV1V54y1B7K3/?share_sourcecopy_webvd_sourceb25ae79b699fbc0a2f70ccb983f6b74a
https://blog.csdn.net/weixin_46676835/article/details/129582927?fromshareblogdetailsharetypeblogdetailsharerId129582927sharereferPCsharesourceweixin_52531699sharefromfrom_link
https://blog.csdn.net/weixin_46676835/article/details/128730174?fromshareblogdetailsharetypeblogdetailsharerId128730174sharereferPCsharesourceweixin_52531699sharefromfrom_link
VGG16是一个深度卷积神经网络它在2014年由牛津大学视觉几何组Visual
Group提出并在ImageNet图像分类任务中取得了显著的成绩。
以下是VGG16的一些关键特点
VGG16包含16个主要的权重层包括13个卷积层和3个全连接层。
VGG16使用小的3x3卷积核进行卷积操作增加了网络的深度同时保持了较少的参数数量。
最终的输出是一个1000维的向量表示属于1000个类别的概率分布针对ImageNet数据集。
VGG16在多种任务中被广泛应用并且可以使用预训练权重进行迁移学习以提高其他任务的性能。
VGG16被广泛应用于图像分类、物体检测、图像分割等计算机视觉任务。
由于其良好的表现许多后续的研究和模型例如VGG19等都是在此基础上进行改进的。
从图中可以看出VGG16包含16个主要的权重层包括13个卷积层和3个全连接层。
1输入图像尺寸为224x224x3经64个通道为3的3x3的卷积核步长为1paddingsame填充卷积两次再经ReLU激活输出的尺寸大小为224x224x64
pooling最大化池化滤波器为2x2步长为2图像尺寸减半池化后的尺寸变为112x112x64
3经128个3x3的卷积核两次卷积ReLU激活尺寸变为112x112x128
5经256个3x3的卷积核三次卷积ReLU激活尺寸变为56x56x256
7经512个3x3的卷积核三次卷积ReLU激活尺寸变为28x28x512
9经512个3x3的卷积核三次卷积ReLU尺寸变为14x14x512
11再经过两层1x1x4096一层1x1x1000的全连接层共三层经ReLU激活
12最后通过softmax输出1000个预测结果这是官方的最终本人输出3种
有了以上理论基础后开始构建代码思路整体构建思路如下图所示写代码之前一定要构思好大致思路代码永远是为你思路框架服务的。
这一部分的代码的作用是首先是关键参数以及头文件的初始化再然后就是读取jpg文件以及txt文件的内容将其分为3类蚂蚁蜜蜂狗后续品种可以自己添加jpgtxt训练数据多少都可以由自己添加但是文件的命名格式必须为1.jpg1.txt2.jpg2.txt才能读取文件。
transforms用于图像处理和转换的模块常用于数据预处理。
torchvision.datasets提供了常用数据集的接口例如MNIST、CIFAR等。
Flatten导入特定的层MaxPool2d用于进行二维最大池化Flatten将多维输入展平为一维。
ConcatDataset用于自定义数据集和数据加载器方便批量处理数据。
argparse用于处理命令行参数使得脚本可以接受用户输入的参数。
用parse_opt()这个函数主要是见过许多大佬的文章都是用这个函数转义。
作为小白像较为官方的标准化参数结构学习。
对象parser.add_argument(--epochs,
添加参数parser.add_argument(--batch_size,
添加批次大小参数parser.add_argument(--learning_rate,
启用多个设备parser.add_argument(--device,
torch.device(opt.device)3定义文件处理类
这部分代码的编写主要是要实现一个功能如何把1.jpg1.txt2.jpg2.txt…文件读取处理并将txt文件的内容进行处理实现分类。
os.listdir(self.label_dir):with
open(os.path.join(self.label_dir,
方法用于去掉行首和行尾的空白字符包括换行符#从label_map
中则返回-1labels.append(label_map.get(line,
D:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\ants_image\\1.jpgimg_path
Image.open(img_path).convert(RGB)
#transform变量是在CustomDataset中最终调用的transforms.Compose实现image
-1。
本人当时在这就犯了一个错误。
可以从调试的框中看出我有一个txt文件的内容并不是dogs致使其返回的值为-1出现这个问题的原因是本人txt文件中dogs没有保存所以切记一定要保存文件如果自己训练模型自建数据集的话。
很多内容方面注释写的很清楚作者就不细讲了。
代码需要实现一个图像大小设置功能由于输入图像大小不确定需要将其设置成224×224大小图片满足输入网络图像大小的设定。
transforms.Compose([transforms.Resize((224,
Tensortorchvision.transforms.Normalize(mean[0.485,
CustomDataset(img_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\ants_image,label_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\ants_label,transformtransform
CustomDataset(img_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\bees_image,label_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\bees_label,transformtransform
CustomDataset(img_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\dogs_image,label_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\dogs_label,transformtransform
创建的一个组合转换对象。
这个对象整合了多个图像预处理步骤包括调整大小、转换为张量以及归一化。
调整大小:
根据给定的均值和标准差对张量进行归一化处理使得数据分布更适合神经网络训练。
归一化是VGG16网络的要求但是本人发现没有也行但所提供的代码为按照官方要求编写的。
是应用于图像的转换操作如缩放、裁剪、归一化等即在加载图像时对其进行预处理。
也就是调用transforms.Compose
从代码中也可以看出实现的效果是读取图像读取标签然后通过transform将其变成224x224。
这段代码的作用是将我所读取的数据ants_databees_datadogs_data总和起来然后随机打乱分割出训练集测试集分别是73。
val_sizeprint(训练集长度{}.format(train_data_size))
print(测试集长度{}.format(val_data_size))
DataLoader分成小批量batches以便于进行训练和验证
打印数据集大小在这里插入图片描述print(训练集大小{}.format(len(train_data)))
print(验证集大小{}.format(len(val_data)))从调试图中可知ants_data
这部分是根据上图的vgg16网络结构搭建的。
具体代码如下本人写法为小白写法应该通俗易懂。
构建子类可以减少foward代码撰写nn.Conv2d(in_channels3,
padding1),nn.Conv2d(in_channels64,
padding1),nn.MaxPool2d(kernel_size2,
#最大池化将224变成112nn.Conv2d(in_channels64,
padding1),nn.Conv2d(in_channels128,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels256,
padding1),nn.Conv2d(in_channels256,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
使用AdaptiveAvgPool2d来确保输出为固定大小self.avgpool
这部分得先明白工作步骤再写代码。
1.训练集训练调用VGG16网络结构损失函数构建随机梯度下降优化训练
2.测试集测试设置为评估模式调用VGG16网络结构损失函数构建损失计算。
3.输出训练损失测试损失准确率。
这部分是机器视觉基础概念知识。
torch.optim.SGD(My_VGG16.parameters(),
临时变量print(--------第{}轮训练开始--------.format(i
设置为训练模式#data有两个部分分别是(8,3,224,224),(8,)
记录训练损失train_losses.append(loss_temp
loss.item()#找到每个样本的预测类别然后与真实标签进行比较accuracy
使用.item()将Tensor转换为Python数值total_accuracy
data这段代码可以从图中看出data有两个部分分别是(8,3,224,224),(8,)
tensor83outputs单纯的就是输出品种结果8是因为我的batch_size
这部分代码的编写需要实现的是将训练的权值保存至.pth文件中并在窗口中显示训练时的时间loss准确率输出考虑到train_loss为list5所以直接使用循环的打印输出效果。
记录验证损失和准确率val_losses.append(total_test_loss
len(val_dataloader))accuracies.append(total_accuracy
val_data_size)print(整体测试集上的正确率:{}.format(total_accuracy
val_data_size))print(整体测试集上的Loss{}.format(total_test_loss))#
vgg16_{}.pth.format(2))torch.save(My_VGG16.state_dict(),
vgg16_dict_{}.txt.format(2))print(模型已保存)#
Loss)#train_losses[1.0952595781396937,
1.0816458507820412]plt.plot(epochs_range,
Epochs)plt.xlabel(Epochs)plt.ylabel(Loss)plt.legend()#
Epochs)plt.xlabel(Epochs)plt.ylabel(Accuracy)plt.legend()plt.tight_layout()plt.show()if
输出图片效果这是只训练了5次的网络可以看到训练效果是不理想的。
#识别3类蚂蚁蜜蜂狗可任意添加文件名为1.jpg,1.txt,内容ants
------------------------------1.初始化标准参数初始化-------------------------------
对象parser.add_argument(--epochs,
添加参数parser.add_argument(--batch_size,
添加批次大小参数parser.add_argument(--learning_rate,
启用多个设备parser.add_argument(--device,
os.listdir(self.label_dir):with
open(os.path.join(self.label_dir,
方法用于去掉行首和行尾的空白字符包括换行符#从label_map
中则返回-1labels.append(label_map.get(line,
D:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\ants_image\\1.jpgimg_path
Image.open(img_path).convert(RGB)
#transform变量是在CustomDataset中最终调用的transforms.Compose实现image
transforms.Compose([transforms.Resize((224,
Tensortorchvision.transforms.Normalize(mean[0.485,
CustomDataset(img_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\ants_image,label_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\ants_label,transformtransform
CustomDataset(img_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\bees_image,label_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\bees_label,transformtransform
CustomDataset(img_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\dogs_image,label_dirD:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\train\\dogs_label,transformtransform
#-----------------------2.将数据集总和并随机打乱并分成训练集测试集-------------------
val_sizeprint(训练集长度{}.format(train_data_size))
print(测试集长度{}.format(val_data_size))
DataLoader分成小批量batches以便于进行训练和验证
print(训练集大小{}.format(len(train_data)))
print(验证集大小{}.format(len(val_data)))#----------------------------3.创建网络模型--------------------------------
构建子类可以减少foward代码撰写nn.Conv2d(in_channels3,
padding1),nn.Conv2d(in_channels64,
padding1),nn.MaxPool2d(kernel_size2,
#最大池化将224变成112nn.Conv2d(in_channels64,
padding1),nn.Conv2d(in_channels128,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels256,
padding1),nn.Conv2d(in_channels256,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
使用AdaptiveAvgPool2d来确保输出为固定大小self.avgpool
x#------------------------------------4.训练加测试-----------------------import
torch.optim.SGD(My_VGG16.parameters(),
临时变量print(--------第{}轮训练开始--------.format(i
设置为训练模式#data有两个部分分别是(8,3,224,224),(8,)
记录训练损失train_losses.append(loss_temp
loss.item()#找到每个样本的预测类别然后与真实标签进行比较accuracy
使用.item()将Tensor转换为Python数值total_accuracy
#-----------------------5.保存数据至.pth文件并绘图---------------------------------------------------#
记录验证损失和准确率val_losses.append(total_test_loss
len(val_dataloader))accuracies.append(total_accuracy
val_data_size)print(整体测试集上的正确率:{}.format(total_accuracy
val_data_size))print(整体测试集上的Loss{}.format(total_test_loss))#
vgg16_{}.pth.format(2))torch.save(My_VGG16.state_dict(),
vgg16_dict_{}.txt.format(2))print(模型已保存)#
Loss)#train_losses[1.0952595781396937,
1.0816458507820412]plt.plot(epochs_range,
Epochs)plt.xlabel(Epochs)plt.ylabel(Loss)plt.legend()#
Epochs)plt.xlabel(Epochs)plt.ylabel(Accuracy)plt.legend()plt.tight_layout()plt.show()if
导入头文件参数标准化后读取图片并通过transform实现图片输入格式的设置。
Path#--------------------------1.参数数据初始化-----------------------------------
对象parser.add_argument(--Dropout_Val,
启用多个设备parser.add_argument(--device,
torch.device(opt.device)image_path
D:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\1.jpg
print(image)#确保你的图像预处理步骤如归一化与模型训练时使用的步骤相匹配。
通常VGG16
torchvision.transforms.Compose([torchvision.transforms.Resize((224,
224)),torchvision.transforms.ToTensor(),torchvision.transforms.Normalize(mean[0.485,
构建子类可以减少foward代码撰写nn.Conv2d(in_channels3,
padding1),nn.Conv2d(in_channels64,
padding1),nn.MaxPool2d(kernel_size2,
#最大池化将224变成112nn.Conv2d(in_channels64,
padding1),nn.Conv2d(in_channels128,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels256,
padding1),nn.Conv2d(in_channels256,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
使用AdaptiveAvgPool2d来确保输出为固定大小self.avgpool
输出测试结果需要将图片送入VGG16网络进行计算带入训练好的权值vgg16_1.pth得出预测结果将预测的结果输出成概率从而计算是什么品种。
#模型的权重在GPU上而输入张量在CPU上。
要解决这个问题你可以将输入张量移动到GPU
#模型的权重在CPU上而输入张量在GPU上。
要解决这个问题你可以将输入张量移动到CPU
torch.load(tudui_0.pth,map_locationtorch.device(cpu))
torch.reshape(image,(1,3,224,224))
class_names[predicted_index])测试输出效果
任意输入一张图片输出判断类型,二代与一代相比就是多了参数标准化import
Path#--------------------------1.参数数据初始化-----------------------------------
对象parser.add_argument(--Dropout_Val,
启用多个设备parser.add_argument(--device,
torch.device(opt.device)image_path
D:\\Pycharm\\Pytorch_test\\数据集\\练手数据集\\1.jpg
print(image)#确保你的图像预处理步骤如归一化与模型训练时使用的步骤相匹配。
通常VGG16
torchvision.transforms.Compose([torchvision.transforms.Resize((224,
224)),torchvision.transforms.ToTensor(),torchvision.transforms.Normalize(mean[0.485,
根据实际情况填写#-------------------------------------2.搭建VGG16网络结构---------------------------------------------
构建子类可以减少foward代码撰写nn.Conv2d(in_channels3,
padding1),nn.Conv2d(in_channels64,
padding1),nn.MaxPool2d(kernel_size2,
#最大池化将224变成112nn.Conv2d(in_channels64,
padding1),nn.Conv2d(in_channels128,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels256,
padding1),nn.Conv2d(in_channels256,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
padding1),nn.Conv2d(in_channels512,
padding1),nn.Conv2d(in_channels512,
padding1),nn.MaxPool2d(kernel_size2,
使用AdaptiveAvgPool2d来确保输出为固定大小self.avgpool
x#---------------------------3.输出测试结果-----------------------------
#模型的权重在GPU上而输入张量在CPU上。
要解决这个问题你可以将输入张量移动到GPU
#模型的权重在CPU上而输入张量在GPU上。
要解决这个问题你可以将输入张量移动到CPU
torch.load(tudui_0.pth,map_locationtorch.device(cpu))
torch.reshape(image,(1,3,224,224))
class_names[predicted_index])最开始训练的次数有点少导致预测结果不理想后来去吃饭前设置训练epochs
500次回来发现结果变好了一点。
提高准确率的方式很多还可以丰富训练集。
注意我的权值文件权值vgg16_1.pth可能使用的是权值vgg16_2.pth代码我就不改了。
主要是要理解以上代码。
https://pan.baidu.com/s/14xixodOGVEMK-KpE5rZTtw
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback