





















本文测试的项目:
https://github.com/zhongzhengli13/MobileNetV3-for-leaf
硬件:
CPU: 9700k 8核心(16线程,8个物理核心+8个虚拟核心)
GPU: 2060 SUPER
图片从磁盘读取时使用16线程:

用时:396秒

用时:391秒

用时:395秒
图片从磁盘读取时使用4线程:

用时:612秒

用时:612秒

用时:615秒
首先对图片进行单独的预处理,不在训练时候进行处理,而是在训练之前就处理,为此增加代码:
x.py 文件:
import os
from PIL import Image
from torchvision import transforms
def get_data_transforms():
"""获取图像预处理transforms(和你训练一致)"""
data_transforms = {
"train": transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.4717, 0.5892, 0.3972],
[0.1704, 0.1531, 0.1755])
]),
"val": transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.4717, 0.5892, 0.3972],
[0.1704, 0.1531, 0.1755])
]),
}
return data_transforms
def tensor_to_image(tensor):
"""
将归一化后的 tensor 转回 PIL 图片
逆归一化 + 通道转换
"""
mean = [0.4717, 0.5892, 0.3972]
std = [0.1704, 0.1531, 0.1755]
# 逆归一化
# for t, m, s in zip(tensor, mean, std):
# t.mul_(s).add_(m)
# 转成图片
tensor = tensor.clamp(0, 1) # 防止越界
image = transforms.ToPILImage()(tensor)
return image
def process_and_replace_images(folder_path, mode='val'):
"""
批量读取图片 → 预处理 → 覆盖保存
:param folder_path: 图片文件夹路径
:param mode: train / val (train会随机翻转)
"""
transforms_dict = get_data_transforms()
transform = transforms_dict[mode]
# 支持的图片格式
img_exts = ('.jpg', '.jpeg', '.png', '.bmp')
# 遍历文件夹
for x in ["Healthy", "Powdery", "Rust"]:
for filename in os.listdir(folder_path+"/"+mode+"/"+x):
file_path = os.path.join(folder_path+"/"+mode+"/"+x, filename)
print(file_path)
# 只处理图片
if filename.lower().endswith(img_exts):
print(f"正在处理: {filename}")
# 1. 读取图片
img = Image.open(file_path).convert('RGB')
# 2. 预处理
img_tensor = transform(img)
# 3. tensor 转回图片
processed_img = tensor_to_image(img_tensor)
# 4. 覆盖保存原图片
processed_img.save(file_path)
print("\n✅ 所有图片处理完成,已覆盖原文件!")
# ------------------- 运行入口(直接改路径即可) -------------------
if __name__ == "__main__":
# 在这里修改你的图片文件夹路径
IMAGE_FOLDER = r"./plant-dataset" # Linux
# IMAGE_FOLDER = r"C:\Users\xxx\Pictures" # Windows
# 处理并覆盖
process_and_replace_images(IMAGE_FOLDER, mode='train')
process_and_replace_images(IMAGE_FOLDER, mode='val')
然后修改训练文件 train.py 中的transform 函数,只保留to_tensor功能,具体如下:



可以看到,当训练过程中不对图片进行CPU端的resize、裁剪工作后,总的性能提高了20倍(都是4个线程读取图片),当保留训练过程中对图片实时进行resize、裁剪工作的情况下如果图片读取和resize、裁剪工作的线程设置为16时计算效率也会提高三分之一,即从600秒缩减到390秒。
从这个例子可以知道,CNN模型在训练过程中图片的预处理过程对整体算法训练过程中计算效率有极大的影响;我们应该尽可能的将CPU的图片处理操作简化掉,如果不能的话也就可能在这一部分进行更多线程的并行以缩短时间消耗。
上面的x.py文件中没有使用 transforms.RandomHorizontalFlip() 操作,导致 val 准确率从 95% 掉到了 90% 或 85%,也就是说本文中所进行的图片预处理的单独处理的方法在某种程度上减少了图片的多样性或者可以看做是减少了图片的数量,从而导致训练模型的性能有了一定的下降,不过这个并不是本文要探索的重点,本文的重点在于CPU端的图片预处理操作会极大的影响CNN模型的训练速度,甚至出现了20倍性能的差距,即使我们本文中的处理方法导致了val过程的性能下降,但是也可以通过增加图片数据集大小的方法来弥补,像本文中的这个transforms.RandomHorizontalFlip()操作,即使增加一倍的图片数据那也会提高整体训练速度的10倍,从而可以看到提高神经网络模型训练速度可以对CNN模型的图片进行单独的处理,而不是和训练放在一起。
本博客是博主个人学习时的一些记录,不保证是为原创,个别文章加入了转载的源地址,还有个别文章是汇总网上多份资料所成,在这之中也必有疏漏未加标注处,如有侵权请与博主联系。 如果未特殊标注则为原创,遵循 CC 4.0 BY-SA 版权协议。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。