深度学习-----通过本地数据实现图片识别的训练
一、训练数据的准备工作
首先,我们需要在将本地的图片内容整理好让代码方便读取
示例代码:
import osdef train_test_file(root, dir):# root:数据集根路径,如 '.\\食物分类\\food_dataset';dir:子文件夹(train 或 test 等),如 'train'file_txt = open(dir + '.txt', 'w')# 以写入模式创建/打开 txt 文件,用于保存图片路径及对应标签索引,文件名为 dir + '.txt'(如 train.txt)path = os.path.join(root, dir)# 拼接得到子文件夹完整路径,如 '.\\食物分类\\food_dataset\\train'for roots, directories, files in os.walk(path):# os.walk 遍历路径下所有内容,roots 是当前遍历到的文件夹路径,directories 是当前文件夹下子文件夹列表,files 是当前文件夹下文件列表if len(directories) != 0:# 若当前文件夹下有子文件夹(即找到分类文件夹,如 '八宝粥' 等)dirs = directories# 保存子文件夹列表(后续用其找标签索引)else:# 若当前文件夹下无子文件夹,说明遍历到了具体图片文件所在层级now_dir = roots.split('\\')# 拆分当前文件夹路径,得到路径各部分列表,用于提取分类名称(如从 '.\\食物分类\\food_dataset\\train\\八宝粥' 拆出 ['., '食物分类', 'food_dataset', 'train', '八宝粥'] )for file in files:# 遍历当前文件夹下的图片文件path_1 = os.path.join(roots, file)# 拼接得到图片完整路径,如 '.\\食物分类\\food_dataset\\train\\八宝粥\\img_八宝粥罐_22.jpg'print(path_1)# 打印图片路径,方便调试查看file_txt.write(path_1 + ' ' + str(dirs.index(now_dir[-1])) + '\n')# 将图片路径和对应分类的索引写入 txt 文件,索引通过 dirs(分类文件夹列表)找 now_dir[-1](当前分类名称)的位置得到file_txt.close()# 关闭 txt 文件,确保内容写入保存root = r'.\食物分类\food_dataset2' # 图片数据集根路径,用 r 字符串避免转义问题
train_dir = 'train' # 要处理的子文件夹(train 集,可按需改 test 等)
test_dir = 'test'
train_test_file(root,train_dir)
train_test_file(root,test_dir)
这段代码的主要功能是为图像分类任务生成训练集和测试集的文件列表及对应的标签。具体来说,它会遍历指定目录下的文件,生成包含文件路径和类别标签的文本文件。
代码的主要逻辑如下:
定义了
train_test_file
函数,接收两个参数:root
(根目录)和dir
(子目录,如 "train" 或 "test")在函数内部:
- 创建一个以子目录名命名的文本文件(如 train.txt)
- 拼接完整路径,遍历该路径下的所有文件和子目录
- 对于每个文件,获取其完整路径
- 确定该文件所属的类别(通过子目录在目录列表中的索引)
- 将文件路径和对应类别标签写入文本文件
最后指定了根目录和训练 / 测试子目录,分别调用函数生成对应的文本文件
二、用生成好的路径加标签文件训练模型
实现了一个基于 PyTorch 的图像识别训练流程,使用 CNN(卷积神经网络)对图片进行分类。下面我将详细讲解如何通过本地数据实现图片识别的训练过程:
1. 数据准备阶段
首先需要准备好本地图片数据,并按照特定格式组织:
- 图片存储:将所有训练图片和测试图片存放在本地文件夹中
- 标签文件:创建两个文本文件
train.txt
和test.txt
,格式为每行一个样本,包含图片路径和对应标签,用空格分隔,例如:plaintext
images/apple/001.jpg 0 images/banana/002.jpg 1 ...
2. 数据预处理与加载
代码中使用了 PyTorch 的数据处理工具:
# 定义数据转换方式
data_transforms = {'train': transforms.Compose([transforms.Resize([256, 256]), # 调整图片大小为256x256transforms.ToTensor(), # 转换为Tensor格式]),'valid': transforms.Compose([transforms.Resize([256, 256]),transforms.ToTensor(),]),
}
自定义数据集类food_dataset
继承自Dataset
,实现了三个核心方法:
__init__
:初始化函数,读取图片路径和标签__len__
:返回数据集大小__getitem__
:根据索引返回图片和对应的标签(已转换为 Tensor)
然后通过DataLoader
创建数据加载器:
train_dataloader = DataLoader(training_data, batch_size=8, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=8, shuffle=True)
DataLoader
的作用是:
- 将数据分批处理(batch_size=8)
- 打乱数据顺序(shuffle=True)
- 支持多线程加载数据
3. 模型定义
代码定义了一个 CNN 模型,包含多个卷积层和全连接层:
class CNN(nn.Module):def __init__(self):super().__init__()# 卷积层1:3通道输入,64通道输出self.conv1 = nn.Sequential(nn.Conv2d(3, 64, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(2),)# 卷积层2:64通道输入,128通道输出self.conv2 = nn.Sequential(nn.Conv2d(64,64,5,1,2),nn.ReLU(),nn.Conv2d(64, 128, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(2),)# 更多卷积层...self.conv3 = nn.Sequential(...)self.conv4 = nn.Sequential(...)# 全连接层:输出类别数为20self.out = nn.Linear(256*64*64, 20)def forward(self, x): # 前向传播x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = self.conv4(x)x = x.view(x.size(0), -1) # 展平特征图output = self.out(x)return output
模型工作原理:
- 卷积层负责提取图片的特征(边缘、纹理等)
- 池化层(MaxPool2d)负责降低特征图维度,减少计算量
- 全连接层负责最终的分类决策
4. 训练与测试函数
训练函数:
def train(dataloader, model, loss_fn, optimizer):model.train() # 开启训练模式for X, y in dataloader:X, y = X.to(device), y.to(device) # 移动到计算设备pred = model(X) # 模型预测loss = loss_fn(pred, y) # 计算损失# 反向传播与参数更新optimizer.zero_grad() # 清空梯度loss.backward() # 反向传播计算梯度optimizer.step() # 更新参数
测试函数:
def test(dataloader, model, loss_fn):model.eval() # 开启评估模式test_loss, correct = 0, 0with torch.no_grad(): # 禁用梯度计算,节省内存for X, y in dataloader:X, y = X.to(device), y.to(device)pred = model(X)test_loss += loss_fn(pred, y).item()correct += (pred.argmax(1) == y).type(torch.float).sum().item()# 计算平均损失和准确率test_loss /= len(dataloader)correct /= len(dataloader.dataset)
5. 训练过程
最后设置训练参数并开始训练:
# 损失函数和优化器
loss_fn = nn.CrossEntropyLoss() # 交叉熵损失,适用于分类问题
optimizer = torch.optim.Adam(model.parameters(), lr=0.0005) # Adam优化器# 训练5个epochs
epochs = 5
for t in range(epochs):print(f"轮次: {t+1}")train(train_dataloader, model, loss_fn, optimizer)# 训练结束后测试
test(test_dataloader, model, loss_fn)
运行流程总结
- 准备图片数据和标签文件(train.txt 和 test.txt)
- 定义数据转换方式和数据集类
- 创建数据加载器,分批加载数据
- 定义 CNN 模型结构
- 设置损失函数和优化器
- 进行多轮训练(每个 epoch 包含训练和测试)
- 训练完成后评估模型性能
通过这个流程,模型会从本地图片数据中学习特征,逐步提高对图片的分类准确率。如果需要提高模型性能,可以考虑增加数据增强、调整网络结构或优化超参数等方法。