神经网络(人工智能)—— CNN模型在训练过程中图片的预处理过程对整体算法训练过程中计算效率的影响?

本文测试的项目:

https://github.com/zhongzhengli13/MobileNetV3-for-leaf




硬件:

CPU: 9700k 8核心(16线程,8个物理核心+8个虚拟核心)
GPU: 2060 SUPER




图片从磁盘读取时使用16线程:


image

用时:396秒


image

用时:391秒


image

用时:395秒










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

image

用时:612秒


image

用时:612秒


image

用时:615秒










如果将图片预处理过程中的transform函数去掉,不进行CPU端的图片处理,那么计算效率如何,具体操作如下:


首先对图片进行单独的预处理,不在训练时候进行处理,而是在训练之前就处理,为此增加代码:


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功能,具体如下:


image




用时:28秒


image


image




可以看到,当训练过程中不对图片进行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模型的图片进行单独的处理,而不是和训练放在一起。




posted on 2026-04-15 17:27  Angry_Panda  阅读(21)  评论(0)    收藏  举报

导航