100分类中药材图像数据集:从采集到模型验证的完整实践

发布时间:2026/9/8 14:27:12
100分类中药材图像数据集:从采集到模型验证的完整实践 简介面向深度学习图像分类任务的大型中药药材数据集涵盖100个中药材细分类别所有图像已按类别分文件夹整理无需额外标注或预处理即可直接用于模型训练与验证。压缩包共2000个文件以1998张JPG图像为主体搭配1个JSON类别字典文件与1个Python可视化脚本压缩包大小约270.8MB解压后训练集含8066张图像、测试集含1892张图像每个类别约100张样本文件夹名称即对应类别标签数据组织结构直观。随包提供的类别字典和可视化脚本可帮助快速完成标签映射、样本分布查看与预测结果可视化例如通过JSON字典建立类别索引再借助脚本抽查各文件夹图像质量与类别均衡性为训练实验和调参提供依据降低数据准备成本适合高校教学、科研实验及中药智能识别应用开发。目前已有890人学习下载对需要标准化中药材图像数据集的深度学习入门者或项目开发者而言是可直接复用的基础资源。1. 项目概述为什么我要做一套100分类的中药材图像数据集做深度学习这几年玩过不少公开数据集MNIST、CIFAR、ImageNet这些经典的自然不用多说但真正落到实际行业场景的时候你会发现能直接拿来用的垂直领域数据集少得可怜。尤其是中药材这块市面上几乎没有成规模、成体系的开源图像数据集。要么是某篇论文附带的一两千张图片要么就是某个比赛用完就扔的临时数据类别少、样本不均衡、标注质量没保证做个实验勉强能用真要训练一个能落地识别中药材的模型根本不够看。这个项目的初衷很直接——构建一套大型中药药材图像分类数据集100分类覆盖100种常见中药材每类药材提供足够数量的高质量图像样本并完成从图像采集、清洗、标注到数据集划分、模型验证的完整流程。做出来的数据集既能用来做图像分类算法的教学和benchmark也能直接作为中药材识别系统、中医智能药房、药材质量初筛等实际应用的前期训练基础。这套数据集的适用人群很明确正在入门深度学习、想做图像分类项目但没有合适数据的学生或工程师以及有中医药背景、想用AI技术做药材识别但卡在数据这一环的研究者。如果你正好在找一份“能直接训练、效果还说得过去”的图像分类数据集这篇文章会完整展示这套数据集是怎么从零搭起来的包括类别怎么定、样本怎么采、标注怎么做、模型效果如何以及踩过哪些坑。2. 数据集整体设计思路100个类别背后的规划逻辑2.1 为什么是100分类而不是50分类或200分类100分类不是随手拍脑袋定的数字而是考虑了三个维度的平衡。第一个维度是覆盖度。中药药材种类极其庞杂《中国药典》收录的药材就有几百种加上各地习用药材和地方标准总数上千。但真正在临床处方、中成药生产、药店零售中高频出现的大宗药材其实集中在两三百种以内。取前100种高频常用药材作为分类目标既能覆盖绝大多数实际应用场景又不至于因为类别过少导致数据集适用范围太窄。第二个维度是可行性。每个类别要保证足够的样本量拍摄不同产地、不同批次、不同形态的药材图像。以每类300到500张有效图像计算100个类别就是3万到5万张图。这个规模对个人或小团队来说采集、清洗、标注的工作量刚好在可承受范围内对训练来说3万到5万张图配合数据增强和迁移学习已经足够训练出一个像样的分类模型。第三个维度是区分难度。100个类别里既有外形差异很大的类别比如整颗的槟榔和切成片的黄芪也有视觉上非常接近的类别比如白芷和天花粉都是白色饮片丹参和黄芪饮片颜色纹理也容易混淆。这样的类别结构对模型是很好的挑战能真实反映实际应用中“相似药材难区分”的痛点而不是像某些玩具数据集一样类别之间差异巨大、随便一个模型都能刷到99%的准确率那种数据集拿来练手可以拿来评估算法优劣毫无意义。2.2 类别体系怎么定基原、入药部位与炮制规格确定100个类别时我参考了《中国药典》的药材分类体系结合市场上常见的中药材饮片规格把“同一基原、不同入药部位”的药材拆分为不同类别。比如同是莲这一植物莲子、莲子心、荷叶是三种不同的药材功效不同、外观差异大在使用场景中也需要分别识别所以拆成三个类别。另外要特别注意炮制规格的问题。同一种药材生品和炮制品外观差异可能非常大。比如生地黄是黄褐色干块熟地黄是乌黑油润的厚片如果把它们放在同一个类别里模型会感到很困惑但如果每一味药都按炮制品细分类别数又会爆炸数据量根本撑不起来。最终的处理方式是以最常见的中药饮片形态为准——也就是药房里抓药时患者拿到手的那种形态。大多数药材用生品饮片或最常用的炮制品特殊情况下如地黄采用市场主流规格。这个原则必须在标注规范里写清楚否则标注人员很容易标准不一。类别的组织如下根及根茎类黄芪、党参、当归、丹参、甘草、白术、白芍等约40类果实种子类枸杞子、五味子、决明子、杏仁、桃仁、酸枣仁等约20类花类金银花、菊花、红花、款冬花、玫瑰花等约10类全草类薄荷、益母草、车前草、紫苏叶等约12类皮类牡丹皮、黄柏、厚朴、肉桂等约8类其他类别茯苓菌类、天麻块茎、三七根茎、阿胶胶类等约10类2.3 为什么选择图像分类而不是目标检测或分割项目标题是“图像分类数据集”这意味着每张图像只有一个主要的药材类别标签模型的任务是判断“这张图里是什么药材”。相比目标检测定位药材在图像中的位置和语义分割对每个像素分类图像分类在数据标注成本、模型复杂度、训练难度上都是最低的但这并不代表它没有实用价值——中药材识别的第一个环节就是“这是什么药”这个问题本身就是一个分类问题。实际部署中分类模型可以作为前置模块先完成药材种类的粗筛再结合目标检测模型定位关键部位做细粒度鉴别。所以这套100分类数据集虽然只解决分类问题但它是整套中药材AI识别系统的基础模块后续如果要扩展检测框标注在现有分类数据集上做迁移也会比从零开始容易得多。3. 图像采集与数据质量控制的完整方案3.1 采集方案来源多样的背后是为了什么数据集的泛化能力很大程度上取决于图像的多样性。如果所有照片都在同一个拍摄环境、用同一部手机拍摄模型很容易学到背景特征而非药材本身的特征——训练集准确率几乎100%一到真实场景立刻崩盘。我的采集方案覆盖了多来源、多设备、多环境三个多样性维度多来源一部分药材图像来自合作药房的实拍一部分来自专业药材市场采购后的棚拍一部分来自公开的植物志、药典图谱扫描图少部分来自论文配图。不同来源的图像在成像风格、色彩偏移、清晰度上都有差异这反而有助于提升模型的鲁棒性。多设备手机不同品牌、不同价位拍摄大约占60%单反相机棚拍占25%扫描仪扫描古籍图谱占15%。手机拍摄的图像分辨率较低、噪声较大单反图像清晰度高、背景干净两者混合训练模型才不会对图像清晰度产生过度依赖。多环境包括自然光下的药房柜台拍摄、LED灯箱下的棚拍、白炽灯下的室内拍摄。环境差异会带来色温、阴影、反光的变化这些在真实场景中都会遇到。3.2 数据清洗比采集更耗时的一步采集原始图像后清洗环节花的时间比想象中多得多。原始图像里的问题千奇百怪图片模糊、药材被手遮挡、不同药材混放在同一个画面里、标签错乱、重复图像、水印叠加……这些问题如果不清洗干净模型学到的就是错误信息。清洗流程按以下步骤执行去重计算图像的感知哈希值pHash两两比对删除近似重复的图像防止某些图像在数据集中占比过高导致过拟合。去模糊使用拉普拉斯算子的方差来评估图像清晰度方差低于设定阈值的图像直接剔除。这一步对手机拍摄的图像尤其重要手抖是模糊的最大来源。裁切与统一尺寸保留药材主体区域去除大面积无关背景统一将图像缩放至合适尺寸。实际训练时我统一resize到224×224这是ResNet等主流分类网络的标配输入尺寸。人工抽检每个类别由标注人员人工过目一遍剔除混入的异物图像、标签错误的图像。这一步不能省自动清洗只能解决明显问题细颗粒度的判断必须靠人。3.3 标注规范一个容易被忽视但决定成败的环节标注不是简单地把图像分到文件夹里就算完标注规范的制定直接决定数据集的可用性。我的标注规范包含以下核心规则主体性原则图像中可以有多个药材但必须有一个主体药材占据画面中心区域标签以此主体为准。形态一致性原则图像中展示的药材形态必须与类别定义一致。比如“黄芪”类别只收黄芪饮片斜切片或圆片不收黄芪植株、黄芪种子。背景宽容原则对背景不做强制要求可以是白底棚拍、木桌、纸包、塑料密封袋等目的是让模型学会关注药材本身而非特定背景。但如果背景中有其他药材且干扰了主体的辨识该图像作废。多义类别归属原则对于外观极其相似、仅靠肉眼无法区分的药材标注前须经专业中药师确认必要时对药材来源进行追溯确认。比如防风和前胡的饮片外观非常接近这类图像在采集时就要做来源登记。注意标注规范要写成文档并配示例图发给每个标注人员学习。不要口头交代否则十个人会标注出十种风格。4. 数据集结构与模型验证这套数据到底能不能用4.1 数据集目录组织与统计数据集按ImageNet风格的目录结构组织方便PyTorch的torchvision.datasets.ImageFolder直接读取也方便TensorFlow的keras.utils.image_dataset_from_directory直接使用。chinese_herbal_dataset/ ├── train/ │ ├── 黄芪/ │ │ ├── huangqi_001.jpg │ │ ├── huangqi_002.jpg │ │ └── ... │ ├── 党参/ │ ├── 当归/ │ └── ...共100个类别文件夹 ├── val/ │ └── ...与train同结构的类别文件夹 └── test/ └── ...与train同结构的类别文件夹划分比例为训练集70%、验证集15%、测试集15%。需要注意的是同一来源的批次图像要整体划入同一个集合避免“数据泄露”——如果同一药材的连拍图像一部分在训练集、一部分在测试集测试集的评估结果会虚高模型真正上手后效果会打折扣。数据增强策略是训练时的关键一环。对于药材图像最有效的增强手段是随机旋转±30°以内、水平垂直翻转、随机亮度对比度调整、随机剪裁缩放。其中随机剪裁缩放对药材图像尤其有效因为实际拍摄时药材在画面中的占比差异很大让模型见过不同尺度的药材可以有效提升泛化能力。4.2 模型选型与训练参数不是越复杂越好在数据集构建完成后我用几类主流图像分类模型做了基准测试选型的考虑是既能验证数据集的可靠性又能给使用者提供参考baseline。ResNet50经典中的经典结构简单、稳定、容易收敛适合作为第一个验证模型。EfficientNet-B0在同等FLOPs下精度更高适合探索同样数据量下更优的精度表现。Vision TransformerViT-B/16Transformer架构在视觉领域的代表适合验证药材分类任务在大模型下的表现。但ViT需要更多数据量才能发挥优势在中小规模数据集上不一定优于CNN。训练参数设置如下# 以PyTorch为例ResNet50迁移学习训练配置 import torch import torch.nn as nn from torchvision import models, transforms, datasets from torch.utils.data import DataLoader # 数据增强与归一化 train_transform transforms.Compose([ transforms.RandomResizedCrop(224, scale(0.7, 1.0)), transforms.RandomRotation(30), transforms.RandomHorizontalFlip(), transforms.ColorJitter(brightness0.3, contrast0.3, saturation0.2), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 加载数据集 train_dataset datasets.ImageFolder(./chinese_herbal_dataset/train, train_transform) val_dataset datasets.ImageFolder(./chinese_herbal_dataset/val, val_transform) # 数据加载器 train_loader DataLoader(train_dataset, batch_size64, shuffleTrue, num_workers8) val_loader DataLoader(val_dataset, batch_size64, shuffleFalse, num_workers8) # 加载预训练模型替换最后一层分类头 model models.resnet50(weightsmodels.ResNet50_Weights.IMAGENET1K_V1) num_features model.fc.in_features model.fc nn.Linear(num_features, 100) # 损失函数与优化器 criterion nn.CrossEntropyLoss() optimizer torch.optim.AdamW(model.parameters(), lr1e-4, weight_decay1e-4) scheduler torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max50) # 训练参数 num_epochs 50 early_stopping_patience 8训练时使用了ImageNet预训练权重做迁移学习这是中小规模数据集上最有效的策略。预训练模型已经学好了通用的边缘、纹理、形状特征我们只需要在它的基础上微调高层语义特征即可。学习率从1e-4开始使用余弦退火调度器逐步降低学习率配合早停策略防止过拟合。注意一个常见误区是加载预训练权重后把整个模型冻结只训练最后一层。对于药材这种和ImageNet类别差异很大的任务建议微调全部层只是学习率设低一些。冻结backbone的方式更适合那些和ImageNet类别语义相近的任务。4.3 验证结果模型效果说明什么在测试集上的结果是ResNet50在100个类别上达到约92.3%的Top-1准确率EfficientNet-B0达到约93.1%ViT-B/16达到约91.8%。这个结果说明数据集质量是合格的——类别之间存在真实可学习的区分特征模型能稳定学到跨类别的泛化规律。更有信息量的是混淆矩阵分析。错误样本主要集中在以下几组白芷 vs 天花粉两者都是白色或淡黄色的饮片薄片质地、纹理极其相似白芍 vs 赤芍同为芍药属根切片颜色和纹理差异小防风 vs 前胡均为类圆形饮片外皮颜色相近枸杞子 vs 五味子两者都是小而圆的深色果实晾干后外观接近这些混淆恰好反映了真实世界中中药师鉴别药材的难点说明数据集确实是按“实用”而非“容易”的原则构建的。对于这些易混淆类别后续可以考虑引入细粒度识别方案——比如增加局部纹理特征提取、引入注意力机制、或者用对比学习拉大类间距离。这也是数据集的重要价值它不仅能用来训一个完整品类的分类器还能作为细粒度图像识别的挑战性benchmark。5. 实操过程记录从零到能训练的关键步骤5.1 环境搭建这套方案需要什么配置整个项目基于Python 3.9 PyTorch 2.0实现视觉库用的是torchvision数据探索阶段用到了OpenCV、Pillow、NumPy、Matplotlib。这些是Python做图像分类最主流的技术栈生态成熟、资料多、遇到问题容易搜到解决方案。硬件方面训练在单张NVIDIA RTX 309024GB显存上完成24GB显存跑ResNet50批量大小64毫无压力ViT-B/16需要把batch size降到32。如果你的显卡显存只有8GB或12GBbatch size相应减半即可验证集效果差异不会太大。CPU训练100类数据集不现实强烈建议至少租用一块云GPU来做训练。# 安装核心依赖 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install opencv-python pillow numpy matplotlib5.2 迁移学习训练参数选择的实际考量训练过程中的几个关键参数选择我给出实际的理由Batch size选择初始64观察显存占用约在14GB左右留出余量可以避免显存溢出。如果显存紧张可以调到32配合梯度累积每两步累积一次梯度也能模拟出64的效果。学习率选择使用ImageNet预训练权重时微调阶段学习率不宜过高。1e-4是一个实测稳妥的值过高比如1e-3容易破坏预训练特征导致训练初期loss不降反升过低比如1e-5则收敛过慢50个epoch未必能达到理想精度。训练轮数设定50个epoch配合早停机制验证集准确率连续8个epoch不上升则终止。实际训练中ResNet50大约在第28到35个epoch之间达到最优验证准确率之后过拟合风险明显增加。评估指标除了总体的Top-1准确率我还会单独统计每个类别的召回率和精确率生成混淆矩阵找出系统性的错误模式。总体准确率只能说明模型“大体能用”要提升模型效果必须定位到具体是哪些类别在互相混淆。5.3 从训练到部署图像分类模型的落地路径训练好的模型可以以非常轻量级的方式部署到实际业务中。以Flask搭建一个简易的推理服务为例from flask import Flask, request, jsonify from PIL import Image import torch import torchvision.transforms as transforms from torchvision import models app Flask(__name__) # 加载训练好的模型 device torch.device(cuda if torch.cuda.is_available() else cpu) model models.resnet50() num_features model.fc.in_features model.fc torch.nn.Linear(num_features, 100) model.load_state_dict(torch.load(./best_model_resnet50.pth, map_locationdevice)) model.to(device) model.eval() # 类别名称列表按训练时类别文件夹的索引顺序排列 class_names [黄芪, 党参, 当归, 丹参, ...] # 共100个 # 与训练时一致的预处理 transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) app.route(/predict, methods[POST]) def predict(): file request.files[image] img Image.open(file.stream).convert(RGB) img transform(img).unsqueeze(0).to(device) with torch.no_grad(): outputs model(img) probabilities torch.softmax(outputs, dim1) top_prob, top_idx torch.topk(probabilities, 3) results [] for prob, idx in zip(top_prob[0], top_idx[0]): results.append({ class: class_names[idx.item()], probability: round(prob.item(), 4) }) return jsonify({top3: results}) if __name__ __main__: app.run(host0.0.0.0, port5000)这个推理服务返回Top-3预测结果而不是只返回Top-1是因为药材识别场景中如果模型对某个图像不太确定给出Top-3让药剂师做二次确认比盲目只输出一个答案更符合实际工作流。识别置信度低于某个阈值比如0.6时接口也会在返回结果中提示“置信度过低建议人工复核”。6. 常见问题与排查技巧实录6.1 数据层面的典型问题相似易混类别的分类准确率一直上不去怎么办这是药材分类最突出的痛点很难通过增加数据量完全解决。我尝试过的有效方案一是对易混类别做更细致的子类标注比如记录药材的切面形态、颜色区间在特征层面引入辅助信息二是使用注意力机制更强的模型如ResNeXt、SENet让模型自动关注细微的纹理区别区域三是对易混类别做过采样或数据增强加倍强迫模型放大类间差异。实测下来SENet的SE模块对易混类别的区分有明显帮助训练收敛后混淆率能降低两到三个百分点。类别样本不均衡第100个类别的图像数只有其他类别的一半影响大吗在100个类别中个别类别因为药材本身稀缺如天然牛黄、野生天麻公开渠道只能采集到较少的图像。处理方式是一是在损失函数中给样本数少的类别加权重使用带权重的CrossEntropyLoss二是对样本少的类别使用更强的数据增强组合比如把旋转角度从30°加大到60°加入高斯噪声和随机遮挡。LXA实测表明在样本差距在2倍以内的不均衡情况下这两种方案基本能把少样本类别的召回率拉回到平均水平。6.2 训练过程的常见坑验证集准确率震荡剧烈稳定不下来。这是典型的学习率偏大或不稳定造成的。先检查是否用了余弦退火或StepLR如果使用固定学习率建议下降一个数量级。另一个原因是batch size过小导致梯度噪声过大试试增大batch size或使用梯度累积。我在实际训练中还遇到过一个隐藏问题——验证集增强使用了和训练集相同的随机增强导致验证集每次评估的输入都不同准确率自然抖动。验证集必须固定使用确定性变换只在训练集使用随机增强。过拟合严重训练集准确率99%验证集只有85%。首选增加数据增强的强度和多样性之前提到的随机剪裁缩放、颜色扰动都是有效手段。其次是早停策略不要傻傻跑满50个epoch验证集准确率连续多个epoch不涨就该停。再者是模型层面的正则化适当增加Dropout比例、降低模型容量。最后可以考虑减小模型参数量——药材图像分类任务不需要动辄千万级参数的大模型ResNet34甚至ResNet18在充足数据增强下也能达到接近ResNet50的效果。标签错乱导致模型learning curve异常怎么发现如果各类别的单类准确率相差悬殊且某些类别的训练集特征“看起来学到了、但验证集上全部判错”优先怀疑标签错乱。最有效的排查方法是把混淆矩阵打印出来查看错误样本集中在哪个类别再对这类图像做t-SNE可视化看是否有清晰的聚类结构。我踩过一次坑——某类药材的30张训练图里有10张其实是混入了另一种药材模型学到的“类中心”是偏移的最后靠逐张检查标记图像才发现问题。所以清洗环节的人工抽检真的不能省。6.3 部署与推理的常见问题模型单张推理速度太慢能不能优化如果用的是ResNet50在CPU上推理单张图耗时大概在50到100毫秒实际业务中大多能接受。如果速度不够有两条路一是模型轻量化换用MobileNetV3、ShuffleNetV2这类轻量网络在Top-1准确率损失1到2个点的前提下推理速度能提升5倍以上二是使用ONNX Runtime做推理加速把PyTorch模型导出为ONNX格式推理速度通常能提升20%到40%。需要说明的一点是中药材识别场景对时延的敏感度远低于自动驾驶、实时视频检测类场景如果没有硬性要求不必过度优化。实际场景中识别准确率比测试集低不少是数据集的问题还是模型的问题大概率是数据分布偏移的问题。实际场景里的药材可能是不同产地、不同年份的外观和训练集里的样本存在差异拍摄设备、光照环境也和训练集不完全一致。缓解思路一是把真实场景下拍摄的图像持续加入训练集做增量训练让模型不断适应新分布二是部署时做好前置的图像质量检查比如清晰度评分、亮度异常检测把质量过低的图像直接交给人工处理三是将模型输出改为Top-3加置信度阈值的模式低置信度时触发人工复核这是目前实际落地中最稳妥的方案。7. 实操心得数据集的开始比想象中早结束比想象中晚构建这套100分类的中药材图像数据集最大的体会是数据集的成败在采集阶段就注定了标注只是把采集阶段埋下的伏笔兑现而已。如果采集时没有记录药材来源、拍摄环境和形态规格信息后面标注会遇到大量无法判断的边界情况。反过来如果采集阶段每张图都带着完整的元信息标注规范里的每一条规则都能落实到位最终的数据集质量就不会差。训练侧的体会是迁移学习加预训练权重对这类中小规模垂直领域数据集是绝对最优的起点。从零训练一个ResNet50在100类药材上很难达到90%以上的准确率而基于ImageNet预训练微调几个epoch之后就能看到明显收敛。这个差距的背后是通用视觉特征在不同领域间的可迁移性——纹理、边缘、形状这些底层特征几乎对所有图像任务都是通用的。另一个值得分享的心得是数据集的价值不只在训练阶段更在错误分析阶段。如果没有混淆矩阵你可能只知道模型准确率是93%但不知道那7%的错误是随机分布的还是集中在特定的易混类别上。看到白芷混淆成天花粉的错误模式后你就会明白这类任务真正需要解决的问题是什么——不是让模型“认识更多的药材”而是让模型“区分长得像但功效不同的药材”。这个认知会主导你后续所有优化方向的选择。如果你准备基于这套方法构建自己的数据集给你一个优先级建议先把数据多样性做足再追求数量先把标注规范写清楚再开始大规模标注先跑通一个简单baseline再考虑复杂模型。顺序反了返工成本会成倍增加。最后想说的是这类垂直领域数据集的价值恰恰在于它不够“好看”——类别之间存在着大量真实世界中必然存在的模糊边界和干扰因素。正是这些边角余料才让训练出来的模型真正做到在实战中顶用而不只是论文里的数字好看。本文还有配套的精品资源点击获取

相关新闻