宫颈细胞图像分类数据集复现:特征与图像双路方案实战

发布时间:2026/10/15 5:05:21
宫颈细胞图像分类数据集复现:特征与图像双路方案实战
1. 从一篇论文复现说起为什么这个细胞分类数据集值得花时间啃做医学图像分类的朋友大概都有过这种体验论文里的指标漂亮得不像话自己一上手复现要么数据拿不到要么预处理对不上要么训练半天准确率卡在某个数字死活上不去。我这次复现的这篇工作核心是围绕一个宫颈细胞图像数据集展开的特征与图像双路分类方案。标题里提到的这个数据集是一个专门针对宫颈细胞涂片、按细胞形态学类别做了精细标注的图像集合包含多个类别覆盖了从正常细胞到不同病变程度的细胞形态。它最大的价值在于标注不是简单的“正常/异常”二分类而是按照细胞学分类体系做了多类别划分这对做细粒度分类的人来说等于直接省掉了一大半标注成本。我为什么盯上这个方向因为宫颈细胞学筛查本身是一个高度依赖医生经验的领域阅片工作量大、疲劳度高、不同医生之间的一致性也存在波动。用图像分类模型做辅助初筛把明显正常的片子快速过滤掉把可疑的片子优先推给医生复核这个逻辑在工程上是成立的。而这个数据集恰好提供了足够细的类别标签让你可以训练一个多分类模型而不是只能做一个粗糙的二分类。适合谁来参考这篇内容如果你正在做医学图像分类、细粒度视觉分类、或者想找一个有真实标注、类别不均衡、图像质量参差不齐的数据集来练手那这个复现过程里的坑和技巧对你都有直接参考价值。哪怕你不做医学方向里面关于数据清洗、类别不均衡处理、特征与图像双路融合的思路放到其他细粒度分类任务里同样适用。我这次复现不是一次就成功的。第一轮跑下来准确率比论文低了将近十个百分点排查了两天才发现是数据划分方式出了问题。第二轮调整了预处理和增强策略指标才慢慢逼近论文水平。下面我把整个复现过程拆开讲包括数据集结构怎么理解、双路方案为什么这么设计、每一步的参数怎么定、遇到问题怎么排查。你照着这个思路走至少能少踩我踩过的那些坑。2. 数据集结构与类别体系拆解先搞清楚你手里到底是什么2.1 图像来源与采集方式对后续处理的影响这个数据集的图像来自宫颈细胞涂片经过染色后拍摄的显微图像。染色方式决定了细胞核和细胞质的颜色对比度也直接影响了后续做颜色归一化时该保留什么、该削弱什么。我拿到数据后的第一件事不是急着写DataLoader而是先随机抽了几十张图肉眼过了一遍。这一步非常关键因为你会直观感受到几个问题不同图像之间的亮度差异很大有些偏蓝、有些偏粉细胞在视野中的位置和大小不固定部分图像存在模糊、气泡、杂质干扰。这些现象不是数据集的质量问题而是真实涂片显微成像的固有特点。理解这一点之后你就不会想着用一套固定的阈值去做分割而是会转向更鲁棒的预处理策略。从采集方式来看这些图像大概率是在不同时间、不同设备条件下累积的所以存在明显的域偏移。什么叫域偏移简单说就是训练集里某一种色调的图特别多模型学会了“看到偏蓝的就认为是某一类”而不是真正学到了细胞形态。这是医学图像分类里非常隐蔽的一个坑指标看着高换一批数据就崩。我在复现时专门做了一个小实验把图像按整体色调聚类发现确实存在几个明显的色调簇而且和类别分布有一定相关性。这个发现直接促使我在预处理阶段加入了颜色归一化而不是直接用原始RGB喂给网络。2.2 类别划分逻辑与不均衡程度的量化这个数据集的类别是按照细胞学形态等级来划分的从正常细胞到不同级别的异常细胞类别数量大概在个位数到十出头这个量级。具体类别名称我这里不展开但你要理解它的划分逻辑不是按“有病/没病”分而是按细胞核增大程度、核质比、染色质分布等形态学特征分级。这意味着相邻类别之间的视觉差异可能非常细微模型需要捕捉的是很局部的纹理和形状变化而不是全局的显著差异。我统计了一下每个类别的样本数量不均衡程度相当明显。最多的类别样本数是最少类别的十几倍。这种长尾分布如果直接训练模型会倾向于把样本少的类别全部预测成样本多的类别因为这样总体损失最小。我第一轮就吃了这个亏少数类的召回率低得可怜。量化不均衡程度有个简单办法算一下最大类样本数除以最小类样本数再算一下每个类别的样本占比。如果最大类占比超过百分之三四十而最小类不到百分之二那你就必须做重采样或者损失加权否则模型基本学不到少数类。2.3 标注质量核查别默认标签一定是对的我在正式训练前做了一轮标注质量抽查随机抽了每个类别各若干张图人工核对标签是否合理。结果发现少量图像的标签存在歧义有些是边界模糊导致标注员判断不一致有些可能是标注时的疏漏。这不是说数据集不好而是任何真实标注数据都会有这个问题。我的处理方式是把明显存疑的样本单独拿出来要么修正标签要么直接从训练集中剔除。剔除的比例控制在百分之几以内不会影响整体分布。如果你不做这一步模型会学到噪声标签表现为训练集准确率很高但验证集波动大。注意标注核查不要全量做成本太高。按类别分层抽样每个类别抽几十张重点看类别边界附近的样本。发现系统性错误才需要扩大核查范围。3. 双路方案的设计动机特征路和图像路到底各自解决什么问题3.1 为什么单靠图像端到端分类不够稳图像端到端分类说白了就是把原始图像丢进CNN让网络自己学特征。这条路在数据量充足、类别差异明显的时候很好用。但在这个任务里有两个问题第一样本量对于深层网络来说不算充裕尤其是少数类第二类别之间的差异集中在细胞核区域而整张图里细胞核只占一小部分网络很容易被背景纹理带偏。我试过直接用ResNet系列做端到端训练不加任何额外处理验证集准确率比论文低不少而且混淆矩阵显示相邻类别之间互相误判严重。这就引出了特征路的价值。特征路不是让网络从零学而是先提取一些有明确形态学含义的量化特征比如细胞核面积、核质比、圆形度、纹理熵等把这些特征作为额外输入或者独立的分类分支。这些特征的好处是可解释、计算量小、对样本量要求低。哪怕某个类别只有几十张图只要你提取的特征在数值上有区分度分类器就能学到东西。图像路负责捕捉人眼难以量化的复杂纹理特征路负责提供稳定的形态学先验两者互补。3.2 特征提取的具体选择与计算过程我选的特征分三组。第一组是几何特征细胞核面积、周长、圆形度、长短轴比。圆形度的计算方式是四倍圆周率乘以面积除以周长平方越接近1说明越圆。第二组是纹理特征用灰度共生矩阵提取对比度、相关性、能量、同质性四个量分别在0度、45度、90度、135度四个方向上算然后取均值和方差。第三组是强度特征细胞核区域的平均灰度、灰度标准差、以及核区域与周围细胞质区域的灰度比值。这些特征的计算前提是先做细胞核分割。我用的是一种基于颜色空间的阈值分割加形态学后处理的方法先把图像转到Lab颜色空间在a通道上做Otsu阈值分割因为染色后的细胞核在a通道上对比度最高然后做开运算去掉小噪点闭运算填补核内空洞最后保留面积在合理范围内的连通区域作为候选核。这个过程不需要深度学习OpenCV几十行代码就能搞定速度快而且参数含义明确方便调试。实操心得分割参数不要一套用到底。我按图像的整体亮度分了两档亮图用一套阈值暗图用另一套分割成功率明显提升。这个分档阈值是通过统计所有图像的平均亮度分布取中位数来划分的。3.3 两路信息怎么融合拼接、加权还是决策级融合融合方式我试了三种。第一种是特征拼接把提取的形态学特征向量和CNN倒数第二层的特征向量拼在一起再过一个全连接层分类。第二种是加权求和两路各自输出类别概率按权重相加。第三种是决策级融合两路各自独立分类最后用投票或者取最大置信度。实测下来特征拼接在小样本类别上表现最好因为形态学特征直接参与了梯度回传网络会学着去利用这些数值。加权求和的方式对权重很敏感我调了几轮才找到合适的比例。决策级融合最稳定但上限最低适合作为baseline。我最终采用的是特征拼接方案但做了一个改进不是简单拼接而是先把形态学特征过一个小的嵌入网络映射到和CNN特征相同的维度再做逐元素相加。这样做的理由是直接拼接会让全连接层需要处理维度差异很大的两组输入训练初期不稳定。映射到同一维度后相加相当于让两路信息在同一个表示空间里融合收敛更平滑。4. 完整复现实操流程从数据读取到模型评估4.1 环境准备与依赖版本锁定我用的深度学习框架是PyTorch版本锁定在一个相对稳定的发行版。为什么要强调锁定版本因为医学图像预处理里用到的一些图像库不同版本之间的插值行为、颜色空间转换系数可能有细微差异这些差异累积起来会影响最终指标。我的依赖清单包括PyTorch及其视觉库、OpenCV用于传统图像处理、scikit-image用于纹理特征提取、NumPy和Pandas用于数据处理、scikit-learn用于分类器和评估指标。所有版本号我都记录在requirements文件里确保下次复现时环境一致。数据读取这块我没有用框架自带的数据集类而是自己写了一个Dataset子类。原因是我需要在读取时同时返回原始图像、分割后的细胞核掩码、以及提取好的形态学特征向量。自定义Dataset的__getitem__方法里我做了几件事读图、颜色归一化、细胞核分割、特征提取、图像增强、转Tensor。这里有个性能问题如果每次取数据都重新做分割和特征提取训练会非常慢。我的做法是提前把所有图像的分割掩码和特征向量算好存成文件训练时直接读取。这样虽然占用一些磁盘空间但训练速度提升了好几倍。4.2 颜色归一化与图像增强的参数选择颜色归一化我用的是基于统计的方法对每张图分别在Lab空间的L、a、b三个通道上做标准化减去该通道的均值再除以标准差。但这里有个细节均值和标准差是在整张图上算还是只在细胞区域算我试过两种发现只在细胞区域算效果更好因为背景区域会稀释统计量。具体做法是用分割掩码把背景置零后再算统计量然后对整张图做归一化。图像增强方面我用了随机旋转、随机水平垂直翻转、随机缩放、以及轻微的颜色抖动。旋转角度范围控制在正负30度以内因为细胞形态学特征对方向敏感旋转太大会破坏核的长短轴比例。缩放比例在0.9到1.1之间模拟不同放大倍率。颜色抖动只在亮度和对比度上做小幅调整饱和度不动因为染色强度变化主要体现在亮度上。这里有个坑增强不能用在特征提取之前否则形态学特征会跟着变。我的流程是先对原始图做特征提取再对图像做增强用于CNN训练两路数据分开处理。4.3 模型结构搭建与关键层参数CNN主干我选了一个中等深度的网络不是特别深的那种。原因是数据量有限太深的网络容易过拟合而且训练时间长。主干后面接一个全局平均池化层把特征图压成向量。形态学特征那边输入维度是二十多维经过两层全连接映射到和CNN特征相同的维度每层后面加批归一化和ReLU激活。融合层做逐元素相加然后接一个Dropout层丢弃率设在0.5左右再接最终的分类全连接层。损失函数我用的是带类别权重的交叉熵。权重怎么定我用的是每个类别样本数的倒数然后归一化让权重之和等于类别数。这样少数类的损失会被放大梯度更新时模型会更关注少数类。优化器用Adam学习率初始设在千分之一配合余弦退火调度每轮结束后学习率按余弦曲线下降。批大小设在32因为再大显存吃紧再小训练不稳定。训练轮数我设了50轮但实际在30轮左右验证集指标就基本饱和了后面主要是微调。4.4 训练过程监控与早停策略训练时我监控四个指标训练损失、验证损失、验证集总体准确率、以及验证集上每个类别的召回率。为什么要单独看每个类别的召回率因为总体准确率会被多数类主导少数类召回率才是真正反映模型有没有学到东西的指标。我设的早停条件是如果验证集总体准确率连续8轮没有提升就停止训练取验证集指标最好的那一轮模型参数作为最终模型。这里有个经验验证集划分不能随机分。因为同一个涂片可能贡献了多张图像如果随机分同一涂片的图可能同时出现在训练集和验证集导致验证指标虚高。我采用的是按涂片分组划分确保同一涂片的图像只出现在训练集或验证集其中之一。这个细节论文里不一定写但你不做的话复现指标和论文对不上是必然的。5. 常见问题与排查技巧实录5.1 指标不达预期的排查顺序复现时指标低不要一上来就调模型结构。我总结的排查顺序是先查数据划分有没有泄漏再查预处理是否和论文一致然后查类别不均衡处理是否到位最后才看模型和超参数。我第一轮指标低就是数据划分泄漏导致的按涂片分组后验证指标反而更真实虽然数字降了一点但后续提升空间清晰了。5.2 典型问题速查表问题现象可能原因排查方法解决措施训练准确率高但验证准确率低过拟合或数据泄漏检查划分方式看训练验证损失曲线按涂片分组划分增加正则化少数类召回率极低类别不均衡未处理看混淆矩阵统计各类召回率加类别权重对少数类过采样训练损失不下降学习率过大或数据未归一化检查输入数据范围打印梯度范数降低学习率加批归一化验证指标波动大批大小太小或验证集太小看每轮指标方差增大批大小用分层抽样扩大验证集分割效果差导致特征不准阈值不适应图像差异可视化分割掩码按亮度分档设阈值加形态学后处理5.3 独家避坑技巧第一个技巧在训练前先跑一个极简baseline比如只用形态学特征加一个逻辑回归分类器。这个baseline准确率不会太高但它能告诉你特征本身有没有区分度。如果逻辑回归都能到七八十说明特征可用后面CNN融合有希望。如果逻辑回归只有三四十那要么特征选错了要么分割有问题先解决这个再谈深度模型。第二个技巧混淆矩阵要按行归一化看。不归一化的混淆矩阵会被多数类主导看不出少数类的误判方向。按行归一化后你能清楚看到每个真实类别被预测成了什么相邻类别之间的混淆最严重这提示你可能需要针对这两类做专门的特征增强或者后处理规则。第三个技巧模型集成时不要只集成最后几轮的模型。我试过取验证指标最好的三轮模型做投票提升有限。后来改成取不同训练阶段的模型比如第20轮、第30轮、第40轮各取一个集成后提升更明显因为不同阶段的模型学到的表示有差异互补性更强。6. 复现后的思考与可扩展方向这次复现跑通之后我对这个数据集和这类任务有了几个新的认识。第一医学图像分类里数据预处理和划分的重要性不亚于模型设计。我花在数据上的时间大概占整个复现周期的六成但正是这些时间让最终指标稳住了。第二特征路和图像路的融合不是简单的加法融合位置、融合方式、两路权重的平衡都需要实验。我试了五六种融合方案才找到相对满意的。第三类别不均衡是这类任务的常态不要指望一个损失函数解决所有问题重采样、损失加权、后处理阈值调整可以组合使用。后续如果想继续深入有几个方向可以尝试。一是把分割也换成可学习的模块让整个流程端到端可训练但要注意数据量是否支撑。二是引入注意力机制让CNN更关注细胞核区域减少背景干扰。三是做跨数据集的泛化实验看在别的涂片数据上表现如何这能检验模型学到的是形态学本质还是数据集特有的偏差。我个人在实际操作中的体会是复现一篇论文最大的收获往往不是最终指标而是排查问题的过程中对数据和任务的深入理解这些东西换一个数据集照样用得上。