
Cleanlab 兼容的 PyTorch MNIST CNN 分类器mnist_pytorch 模块实战指南【免费下载链接】cleanlabCleanlabs open-source library is the standard>项目地址: https://gitcode.com/GitHub_Trending/cl/cleanlab导读cleanlab.experimental.mnist_pytorch是 cleanlab 仓库中一个极具参考价值的示例模块它提供了一个与 scikit-learn 接口完全兼容的 PyTorch 卷积神经网络CNN分类器可以直接用于在 MNIST 等图像数据中发现标签错误label issues。它同时也是 cleanlab 官方推荐的如何让自研深度学习模型与 cleanlab 无缝协作的标准模板。读完本文你将掌握该模块的类结构与参数语义、fit/predict/predict_proba的调用约定、如何在 cleanlab 的置信学习Confident Learning流程中使用它以及如何仿照它改造自己的 PyTorch 模型。模块定位为脏标签图像数据而生的 sklearn 模板在 cleanlab 的数据中心 AI 工作流中发现标签噪声的前提是拿到每个样本的跨验证out-of-sample预测概率pred_probs。cleanlab 的多数接口如cleanlab.filter.find_label_issues、cleanlab.count.estimate_confident_joint_and_cv_pred_proba都期望模型遵循 scikit-learn 的 estimator API即实现fit(X, y)、predict(X)、predict_proba(X)。PyTorch 模型天然不具备这套接口。cleanlab/experimental/mnist_pytorch.py的模块 docstring 明确说明了它的设计初衷A cleanlab-compatible PyTorch ConvNet classifier that can be used to find label issues in image data. This is a good example to reference for making your own bespoke model compatible with cleanlab.即这是一个可直接用于查找图像标签问题的 cleanlab 兼容分类器也是把自研模型改造成 cleanlab 兼容形态的最佳参考范例。该模块属于 cleanlab/experimental 目录docs/source/cleanlab/experimental/index.rst 中有明确警告Methods in this experimental module are bleeding edge and may have sharp edges. They are not guaranteed to be stable between different cleanlab versions.同时该目录下的模型依赖 torch、torchvision 等非 cleanlab 官方依赖的深度学习包使用时需自行安装详见 cleanlab/experimental/README.md。模块组成三个层次清晰的结构整个mnist_pytorch.py模块由三部分组成分工明确组成名称作用数据集加载get_mnist_dataset(loader)/get_sklearn_digits_dataset(loader)返回 PyTorchDataset对象网络定义SimpleNet(nn.Module)基础 CNN 网络结构sklearn 封装CNN(BaseEstimator)将网络包装为 sklearn 兼容分类器模块顶部还定义了四个数据规模常量供内部索引逻辑使用MNIST_TRAIN_SIZE 60000 MNIST_TEST_SIZE 10000 SKLEARN_DIGITS_TRAIN_SIZE 1247 SKLEARN_DIGITS_TEST_SIZE 550数据集加载MNIST 与 sklearn digits 双支持get_mnist_dataset标准 MNISTdef get_mnist_dataset(loader): # pragma: no cover dataset datasets.MNIST( root../data, train(loader train), downloadTrue, transformtransforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))] ), ) return datasetloader取值train或test决定加载训练集还是测试集数据下载到../data目录相对当前工作目录预处理为ToTensor()加 MNIST 官方均值0.1307、标准差0.3081的标准化。get_sklearn_digits_dataset轻量替代该函数将sklearn.datasets.load_digits的 8×8 手写数字数组封装为 PyTorchDataset固定取最后 550 个样本作为测试集源码注释明确标注 hard-coded -- do not changey_train y_all[:-SKLEARN_DIGITS_TEST_SIZE] y_test y_all[-SKLEARN_DIGITS_TEST_SIZE:]在封装过程中样本先经ToPILImage()转为图像、Resize(28)放大到 28×28再走与 MNIST 相同的标准化流程——这样sklearn digits 数据可以直接复用为 MNIST 训练的轻量冒烟测试集避免 6 万样本带来的训练开销。这也是 tests/test_model_pytorch_cnn.py 中大量使用datasetsklearn-digits跑测试的原因。内部还定义了一个TorchDataset辅助类把 numpy 数组抽象为标准 PyTorchDataset实现__getitem__与__len__这是任何自研数据封装都可以复用的模式。SimpleNet基础卷积网络结构SimpleNet是一个针对 MNIST 这类单通道小图像设计的轻量 CNN全部代码见 cleanlab/experimental/mnist_pytorch.pyclass SimpleNet(nn.Module): def __init__(self): super(SimpleNet, self).__init__() self.conv1 nn.Conv2d(1, 10, kernel_size5) self.conv2 nn.Conv2d(10, 20, kernel_size5) self.conv2_drop nn.Dropout2d() self.fc1 nn.Linear(320, 50) self.fc2 nn.Linear(50, 10) def forward(self, x, T1.0): x F.relu(F.max_pool2d(self.conv1(x), 2)) x F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2)) x x.view(-1, 320) x F.relu(self.fc1(x)) x F.dropout(x, trainingself.training) x self.fc2(x) x F.log_softmax(x, dim1) return x结构要点两层Conv2d ReLU MaxPool2d卷积特征提取第二层后接Dropout2d正则化展平到 320 维后接两个全连接层320→50→1010 对应 10 个数字类别最终输出为log_softmax即对数概率log-probabilities后续predict_proba通过np.exp(out)还原为概率矩阵forward(x, T1.0)预留了温度参数T当前实现未使用可用于未来扩展温度缩放。CNN 类把 PyTorch 网络装进 sklearn 模板CNN继承自sklearn.base.BaseEstimator是整个模块的核心。模块 docstring 明确说明cleanlab 要求所有模型遵循这套基本的 sklearn 模板因此该类使 PyTorch CNN 可以像 sklearn 模型一样被传入cross_val_predict等函数用于带噪声标签的学习learning with noisy labels等场景。构造参数Constructor Parameters__init__的完整签名与默认值如下参数默认值说明batch_size64训练批大小epochs6训练轮数log_interval50每隔多少 batch 打印一次训练日志设为None则不打印lr0.01SGD 学习率momentum0.5SGD 动量no_cudaFalse为True时禁用 GPUseed1随机种子用于torch.manual_seed与 CUDA 种子保证可复现test_batch_sizeNone预测时的批大小None时取测试集大小datasetmnistmnist或sklearn-digits决定数据集与网络输入loaderNonetrain或test一旦设置会覆盖后续所有函数调用中的 loader__init__内部还做了几件关键初始化工作self.cuda not self.no_cuda and torch.cuda.is_available() torch.manual_seed(self.seed) ... self.model SimpleNet() if self.cuda: self.model.cuda() self.loader_kwargs {num_workers: 1, pin_memory: True} if self.cuda else {} self.loader loader self._set_dataset(dataset)其中_set_dataset(dataset)根据dataset参数绑定对应的get_dataset函数以及train_size/test_size非法的dataset值会抛出ValueError。CUDA 可用时num_workers1且开启pin_memory加速数据搬运。⚠️ 关于 loader 参数的重要警告文档字符串中特别强调了loader参数的霸道行为Be careful setting theloaderparam, it will override every other loader. If you set this to test, but call .predict(loader train), then .predict() will still predict on test!即loader一旦在构造时或属性赋值时被设置就会在fit与predict_proba内部无条件覆盖你传入的任何 loader 值。设计者通过self.loader记住该设定并在 fit 与 predict_proba 开头用if self.loader is not None: loader self.loader强制替换。这在交叉验证等需要反复切换数据集的场景中尤其容易踩坑务必小心。核心方法语义fit / predict / predict_probafit(train_idx, train_labelsNone, sample_weightNone, loadertrain)这是与 sklearnfit(X, y)兼容的关键方法但参数语义做了巧妙的索引化改造。模块 docstring 说明train_idx is not X, but instead a list of indices for X (and y if train_labels is None).也就是说第一个参数不是特征矩阵 X而是样本索引数组。模型内部通过self.get_dataset(loader)拿到完整数据集再用SubsetRandomSampler(train_idx)只抽取索引对应的样本进行训练。这样设计的好处是不需要把整个大数据集如 ImageNet 级别一次性读入内存。方法内部逻辑标签注入若传入train_labels则先校验len(train_idx) len(train_labels)不一致会抛ValueError测试 test_throw_exception 验证了这一行为然后构造一个以-1填充的稀疏标签数组只把train_idx位置替换为对应标签再赋给train_dataset.targets。这一做法避免了train_data[idx]式的大数组索引复制在数据集很大时更省内存。样本权重若传入sample_weight会先校验其长度与train_labels一致再通过sample_weight[np.unique(train_labels, return_indexTrue)[1]]提取每个类别的权重作为F.nll_loss的class_weight传入损失函数实现类别加权训练。训练循环使用 SGD 优化器lr、momentum逐 epoch 调用self.model.train()开启 dropout前向计算后以F.nll_loss(output, target, class_weight)计算负对数似然损失反向传播并更新参数。log_interval非空时每 N 个 batch 打印TrainEpoch: ... Loss: ...进度日志。predict(idxNone, loaderNone)def predict(self, idxNone, loaderNone): probs self.predict_proba(idx, loader) return probs.argmax(axis1)内部直接调用predict_proba并对概率矩阵取argmax得到预测类别返回 numpy 数组。predict_proba(idxNone, loaderNone)预测阶段的核心逻辑self.loader存在时优先覆盖 loader 参数若loaderNone则通过启发式判断当传入的idx恰好等于np.arange(test_size)即请求全部测试样本时自动切到test否则用train若idx非空且长度不等于对应数据集的train_size/test_size则对dataset.data与dataset.targets做切片过滤推理时batch_size使用test_batch_size测试集完整时默认等于test_size即一次全量前向调用self.model.eval()关闭 dropout / batch-norm在torch.no_grad()下前向由于网络输出是log_softmax对数概率最终通过np.exp(out)还原为N×K 形状的概率矩阵返回K 为类别数。get_params / set_params由于该 estimator 会在fit内部自行加载数据集属于非标准 sklearn 形态因此重写了get_params/set_params来支持 sklearn 网格搜索与 clone 机制源码中有 XXX 注释说明了这一点。注意get_params返回的字典不含loader而set_params对dataset做了特殊处理其他参数直接setattr只有dataset会触发_set_dataset重新绑定数据集加载函数。在 cleanlab 中的完整使用流程附测试佐证将CNN接入 cleanlab 的标准流程在仓库测试 tests/test_model_pytorch_cnn.py 中有完整的端到端演示核心链路为from cleanlab.experimental.mnist_pytorch import CNN from cleanlab.count import estimate_confident_joint_and_cv_pred_proba, estimate_latent import cleanlab cnn CNN(epochs3, log_intervalNone, seedseed, datasetsklearn-digits) X X_train_idx # 样本索引 y y_train # 可能含噪的标签 # 1. 交叉验证得到 out-of-sample 预测概率与置信联合矩阵 cj, pred_probs estimate_confident_joint_and_cv_pred_proba(X, y, cnn, cv_n_folds2) # 2. 估计潜在先验 py、噪声矩阵 nm、逆噪声矩阵 inv est_py, est_nm, est_inv estimate_latent(cj, y) # 3. 算法化识别标签问题 err_idx cleanlab.filter.find_label_issues( y, pred_probs, confident_jointcj, filter_byprune_by_noise_rate )流程拆解交叉验证预测estimate_confident_joint_and_cv_pred_proba定义于 cleanlab/count.py对X做 K 折测试中cv_n_folds2交叉验证每个折内用CNN.fit训练、predict_proba预测汇总出所有样本的 out-of-samplepred_probs同时基于逐折合并概率再计算的策略源码注释说明该方法在小数据量下更准确估计置信联合cj。潜在结构估计estimate_latent从cj推导出无噪声先验py、噪声翻转矩阵nm与逆噪声矩阵inv这些是置信学习的核心潜变量。标签问题筛选cleanlab.filter.find_label_issues依据confident_joint与filter_byprune_by_noise_rate策略返回被判定为标签错误的样本索引。测试中还验证了模型的收敛行为在同一数据集上反复训练overfit每轮用accuracy_score评估断言分数应逐轮提升assert score prev_score这既验证了数据加载正确也验证了 cleanlab 各接口与CNN协作正常。其他测试覆盖的行为test_n_train_examples以loadertrain训练 4 个 epoch 后切到test预测断言测试集准确率 0.1说明模型学到了基本判别能力传入非法 loader 值INVALID会抛出ValueErrorpredict_proba(idxNone, loadertest)返回所有测试样本的概率。fit传入长度不匹配的train_idx/train_labels会抛出含 same length 的ValueError。依赖与使用前置条件必须自行安装 PyTorch 与 torchvision。模块 docstring 与 cleanlab/experimental/README.md 均明确指出这些深度学习依赖不是 cleanlab 官方依赖安装方式参考 PyTorch 官方站点按本地环境CPU/GPU、CUDA 版本选择。experimental 模块不受版本稳定承诺保护跨 cleanlab 版本可能发生变化生产使用需谨慎并锁定版本。首次运行get_mnist_dataset会自动下载 MNIST 数据到../data需保证网络可达与磁盘空间若想快速验证流程优先选择datasetsklearn-digits仅 1247 训练样本秒级训练。总结把任意 PyTorch 模型变成 cleanlab 兼容模型的四步模板从CNN的实现中可以提炼出改造自研模型的通用套路定义nn.Module网络前向输出log_softmax对数概率如SimpleNet继承sklearn.base.BaseEstimator实现fit/predict/predict_proba其中predict_proba返回形状为 N×K 的 numpy 概率矩阵fit返回self重写get_params/set_params保证 sklearn 工具链网格搜索、交叉验证、clone可正常工作保持 API 的索引化输入约定如fit(train_idx, train_labels)便于在超大数据集上避免内存复制。完成这四步后你的模型就可以直接用于estimate_confident_joint_and_cv_pred_proba、find_label_issues、CleanLearning等 cleanlab 核心流程在任意图像等数据类型上自动发现标签噪声——这正是mnist_pytorch模块作为 cleanlab 官方示例的价值所在。延伸阅读模块完整源码cleanlab/experimental/mnist_pytorch.py端到端测试用例tests/test_model_pytorch_cnn.pyexperimental 模块总览cleanlab/experimental/README.md置信联合估计与潜变量推断 APIcleanlab/count.py同目录下的其他深度学习适配示例cleanlab/experimental/coteaching.py、cleanlab/experimental/label_issues_batched.py【免费下载链接】cleanlabCleanlabs open-source library is the standard>项目地址: https://gitcode.com/GitHub_Trending/cl/cleanlab创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考