新闻详情

新闻详情

首页 / 资讯中心 / 详情

泰迪杯直肠癌肿瘤分割:从zip解压到U-Net模型提交全流程

发布时间:2026/10/1 18:00:09来源:尧图网络
泰迪杯直肠癌肿瘤分割:从zip解压到U-Net模型提交全流程
简介面向医学院校与数据挖掘竞赛选手这份压缩包整理了第七届泰迪杯B题“直肠癌肿瘤分割”的完整参赛方案涵盖Python源码、设计文档与使用说明可助学习者快速上手医学影像分割工程。包内共24个文件以8个py脚本为主轴贯穿数据提取、ROI裁剪、HDF5数据集生成、U-Net双GPU训练、SVM纹理分类及预测等流程另有1个h5模型、1份csv临床数据、11张png结果图及README等文档整体约62MB。已有171人学习适合具备Python基础、希望实战图像分割与特征工程的人群。通过方案可学习Unet_2gpu.py的分布式训练写法、SVM_Texture.py的纹理特征融合以及HDF5DatasetWriter/Generator的数据流水线设计配合结果图直观检验模型效果是赛题复现与提升的实用参考也可为后续医学影像研究提供基线方法。1. 第七届泰迪杯数据挖掘挑战赛-B题直肠癌肿瘤分割.zip 是什么“第七届泰迪杯数据挖掘挑战赛-B题-直肠癌肿瘤分割.zip”这个文件名看似只是一个压缩包其实是很多参赛队遇到的第一道分水岭。把 zip 解压之后面对的是一堆灰度切片和一摞标注图任务直白但不好做让模型在每张切片上把直肠癌肿瘤区域逐像素标出来最后提交一份与训练标注格式一致的结果。这里说的“数据挖掘”不是拉宽表跑回归而是典型的医学图像语义分割流程解压、读取、预处理、训练、评估。这篇文章适合正在备赛的队伍也适合想快速验证 U-Net 系分割模型能不能扛住小样本肿瘤数据的开发者。我按这条链路实际最常走的路径讲顺手把容易踩的坑标出来。2. 从 zip 解压到可训练数据乱码、读取与标注统计2.1 用 zipfile 做压缩包体检伪加密、乱码和损坏文件拿到这个 zip 的第一步不是急着全选解压而是先看包内到底有什么。用 zipfile 列一下所有条目几秒钟就能判断目录结构是否合理也避免解压到一半发现文件损坏。import zipfile from pathlib import Path zip_path Path(第七届泰迪杯数据挖掘挑战赛-B题-直肠癌肿瘤分割.zip) with zipfile.ZipFile(zip_path) as zf: for info in zf.infolist(): print(info.filename, info.file_size, info.compress_type)这段代码把压缩包内的文件名、原始大小、压缩方式逐一打印出来。info.file_size为 0 的通常是目录条目compress_type为 8 表示 deflate0 表示未压缩。如果一个影像文件打印出来的原始大小只有几 KB而它又是一张 512×512 的灰度图就要警惕是不是压过头或者文件不完整。接着做完整性检查比赛文件在网盘或浏览器里下到一半的情况太常见了bad zf.testzip() print(损坏文件:, bad)testzip()会逐个校验 CRC返回第一个坏文件的文件名全部正常则返回 None。遇到损坏正确做法是回官方渠道重新下载并核对文件大小不要把时间耗在拿第三方工具硬修复上。中文文件名乱码也是高频问题。Windows 压缩工具常用 GBK 保存文件名Python 的 zipfile 会按 UTF-8 解码失败后再用 cp437 兜底于是打印出来一串乱码。遇到这种情况可以手动做一次编码还原。try: name info.filename.encode(cp437).decode(gbk) except UnicodeDecodeError: name info.filename print(name)这里默认了源编码是 GBK保险起见先捕获异常。跑完之后如果文件名正常了说明包里确实是中文字符集问题如果还不对就老老实实用 7-Zip 解压再在 Python 里用pathlib.Path读取本地目录。网上二次转载的压缩包还有可能带“伪加密”标记Windows 资源管理器打开它时要求输密码其实只是 zip 通用位标志被置位内容并没有真加密。这种包用 7-Zip 往往能直接进。但赛题官方包不会做这种处理遇到先回官方渠道重新下载别跟伪加密较劲。2.2 影像读取统一约定png 用 OpenCVnii 用 SimpleITK比赛数据如果已经转成 2D 切片最常见的格式是 png 或 jpg。读取时最容易犯的错是不传读取标志让灰色图被 OpenCV 按三通道 BGR 读进来内存直接翻三倍后面模型输入维度也跟着乱。import cv2 import numpy as np img cv2.imread(train/image_001.png, cv2.IMREAD_GRAYSCALE) mask cv2.imread(label/mask_001.png, cv2.IMREAD_GRAYSCALE) print(img.shape, img.dtype, np.unique(mask))np.unique(mask)的输出非常关键。如果是[0 255]说明标注是二值但像素值是 0 和 255需要转成(mask 127).astype(np.uint8)再给模型用。如果是[0 1 2]这样的多类标注就不能当二分类直接跑要按赛题说明判断肿瘤对应的类别再决定是合并成一类还是做多分类分割。如果遇到 nii.gz 或 nii 格式读取方式完全不同。NIfTI 是医学影像的标准封装之一SimpleITK 是最稳妥的读取库。import SimpleITK as sitk arr sitk.GetArrayFromImage(sitk.ReadImage(volume.nii.gz)) print(arr.shape, arr.dtype)这里读出来的arr.shape通常是(slice_count, H, W)第一个维度是切片数。这和 png 的(H, W)直接差一个维度后续构建(B, C, H, W)张量时需要在切片维上遍历并把单通道灰度显式加一个通道维度。读出来的 dtype 可能是 int16直接除以 255 是没有意义的需要先看数据范围再定归一化方式。我一般会把影像读取封装成一个函数统一转成 float32 的(H, W)标注统一转成 uint8 的(H, W)这样后面无论是加载 nii 还是 png训练代码都不用改。2.3 用几行代码统计肿瘤标注占比决定模型走向整理好读取逻辑后先别急着训练统计一遍标注分布。这个统计能直接决定损失函数要不要用 Dice、要不要做 ROI 裁剪也能提前发现标签错位。from pathlib import Path import numpy as np import cv2 mask_dir Path(label) ratios [] for mask_path in sorted(mask_dir.glob(*.png)): m cv2.imread(str(mask_path), cv2.IMREAD_GRAYSCALE) if m is None: continue ratios.append((m 0).sum() / m.size) print(f切片数: {len(ratios)}) print(f肿瘤像素占比 mean{np.mean(ratios):.4f} fmin{np.min(ratios):.4f} max{np.max(ratios):.4f})统计结果有两层意义。第一肿瘤区域通常只占整张切片的几个百分点说明前景背景极不均衡单用像素级交叉熵会让模型很快学会“全输出背景”。第二min 接近 0 说明存在纯背景切片如果训练时随机采样到大量纯背景样本会把一整轮 loss 拖得虚低max 如果超过 0.5则要回看具体 mask可能是有标注坐标系弄反了。这一步也许是你今晚做得最有价值的十分钟把肿瘤占比和图像尺寸范围记录下来后面对比训练日志时能少走很多弯路。3. 预处理与数据增强把直肠癌肿瘤分割变成干净的训练样本3.1 先看灰度分布再做归一化0-1 和 z-score 怎么选医学图像和自然照片的灰度分布差异很大大部分像素集中在较窄的区间里肿瘤和软组织的对比度可能就藏在几十个灰度级别中。直接img / 255.0会把背景噪声一起放大对比度反而被压没了。先画直方图比什么都直观import cv2 import matplotlib.pyplot as plt img cv2.imread(train/image_001.png, cv2.IMREAD_GRAYSCALE) plt.hist(img.ravel(), bins256, range(0, 255)) plt.show()如果直方图低端有一个极高的尖峰说明黑色背景占了大半如果整段平坦且没有明显峰谷说明原本的对比度就不好可以先用 CLAHE 做对比度受限的自适应直方图均衡化。对灰度医学切片我通常把 CLAHE 放在预处理序列的最后一步而不是归一化之后因为 CLAHE 输出的范围和原始图像一致。clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) img clahe.apply(img)参数里clipLimit2.0控制对比度增强强度值太大容易把噪声也拉出来tileGridSize8x8是常规值。完整切片如果背景占比很高应该先做 3.2 的 ROI 裁剪再做 CLAHE否则直方图统计会偏向背景。归一化方式上0-1 和 z-score 都可以用但要看数据背景占比。z-score 把均值拉到 0方差压到 1对梯度更友好训练初期更稳mean img.astype(np.float32).mean() std img.astype(np.float32).std() 1e-8 norm_img (img.astype(np.float32) - mean) / stdstd 1e-8是为了防止全灰图像除零。注意这里的 mean 和 std 是在整张图上算的如果黑色背景占了一大半均值会被背景 0 拖低肿瘤区域反而被抬高。所以更稳的做法是先用 mask 里的非零区域或者图像本身大于 0 的像素算 mean/std再对整图归一化。3.2 按坐标裁剪与 resizemask 必须用最近邻插值肿瘤在切片里通常只占一小块把整张图直接送进网络背景会占用大量激活值训练效率也差。常见做法是先按标注区域裁剪出 ROI再统一 resize 到模型输入尺寸。import cv2 import numpy as np def crop_and_resize(img, mask, target(256, 256), pad30): ys, xs np.where(mask 0) if ys.size 0: y0, y1 0, img.shape[0] x0, x1 0, img.shape[1] else: y0, y1 int(ys.min()), int(ys.max()) 1 x0, x1 int(xs.min()), int(xs.max()) 1 y0 max(0, y0 - pad) x0 max(0, x0 - pad) y1 min(img.shape[0], y1 pad) x1 min(img.shape[1], x1 pad) img_crop img[y0:y1, x0:x1] mask_crop mask[y0:y1, x0:x1] img_resized cv2.resize(img_crop, target, interpolationcv2.INTER_LINEAR) mask_resized cv2.resize(mask_crop, target, interpolationcv2.INTER_NEAREST) return img_resized, mask_resized这里有个非常隐蔽的坐标问题np.where返回的前一个是 y后一个是 x不能想当然地当成 x 和 y。顺序一颠倒裁剪区域直接就偏到另一边训练出来的模型预测结果会整体错位。另一个关键点是 mask 的 resize 必须用cv2.INTER_NEAREST。mask 是分类标签0 就是背景1 就是肿瘤用双线性插值会把边界变成 0.4、0.7 这种伪概率值后续 BCEDice 损失计算全部失真。验证方法也简单np.unique(mask_resized)出来应该还是[0, 1]出现小数就是插值用错了。pad30表示裁剪边缘额外留 30 像素目的是避免肿瘤边缘被切断让模型能看到一点周围组织。如果肿瘤本身就很大pad 作用不明显可以调回 10如果肿瘤紧贴图像边缘pad 会自动被max/min收住。3.3 数据增强与病例级划分一个切片都不能漏数据增强对医学分割的作用是提高灰度鲁棒性和空间平移鲁棒性但要守住一个底线不能破坏解剖结构关系。左右翻转和上下翻转在直肠癌切片上是安全的因为肿瘤在不同方位都有可能出现标注也跟着镜像不会产生假样本。import random import cv2 import numpy as np class SegAugment: def __call__(self, img, mask): if random.random() 0.5: img cv2.flip(img, 1) mask cv2.flip(mask, 1) if random.random() 0.5: img cv2.flip(img, 0) mask cv2.flip(mask, 0) if random.random() 0.5: alpha random.uniform(0.9, 1.1) beta random.randint(-5, 5) img np.clip(img.astype(np.float32) * alpha beta, 0, 255).astype(np.uint8) return img, mask这里亮度抖动的alpha取 0.9~1.1beta取 ±5是相对保守的设定。医学图像灰度值本身有量化意义对比度抖动太大会让模型学到错误的强度映射。弹性形变这类增强在自然图像分割里很好用但在直肠癌切片上要非常克制因为直肠周围组织的空间约束很强形变过了会生成解剖上不可能的样本。数据划分比增强更容易埋雷。同样的患者可能有多张切片如果按随机切片划分训练集和验证集同一个患者的切片会同时出现在两边模型相当于提前看到了答案验证 Dice 虚高测试集一测就掉。from sklearn.model_selection import GroupKFold groups df[patient_id] gkf GroupKFold(n_splits5) for train_idx, val_idx in gkf.split(df, groupsgroups): train_df df.iloc[train_idx] val_df df.iloc[val_idx]这里用GroupKFold而不是普通KFoldgroups传的是患者编号列。这样同一个患者的所有切片只会出现在同一折里验证结果才接近真实泛化水平。很多队伍在排行榜上看到自己邮件验证 0.9一跑盲测数据变成 0.5多半就是这个 split 用错了。4. 模型选型与训练参数U-Net 基线、Dice 损失与学习率调整4.1 先跑 U-Net别一上来就换 Transformer直肠癌肿瘤分割这类医学影像任务样本量通常只有几百到上千张切片模型参数过多会迅速过拟合。U-Net 的编码器-解码器结构天然适合像素级分割跳跃连接能把编码器里的边缘信息直接送到解码器对小目标分割尤其友好。我用一个简化但能直接跑的 U-Net 片子作为基线。输入是单通道灰度图输出是单通道概率图中间四层编码、三层解码import torch import torch.nn as nn import torch.nn.functional as F class ConvBlock(nn.Module): def __init__(self, in_ch, out_ch): super().__init__() self.net nn.Sequential( nn.Conv2d(in_ch, out_ch, 3, padding1), nn.BatchNorm2d(out_ch), nn.ReLU(inplaceTrue), nn.Conv2d(out_ch, out_ch, 3, padding1), nn.BatchNorm2d(out_ch), nn.ReLU(inplaceTrue), ) def forward(self, x): return self.net(x) class MiniUNet(nn.Module): def __init__(self, in_ch1, enc_chs(32, 64, 128, 256)): super().__init__() e0, e1, e2, e3 enc_chs self.enc1 ConvBlock(in_ch, e0) self.enc2 ConvBlock(e0, e1) self.enc3 ConvBlock(e1, e2) self.enc4 ConvBlock(e2, e3) self.pool nn.MaxPool2d(2) self.dec3 ConvBlock(e3 e2, e2) self.dec2 ConvBlock(e2 e1, e1) self.dec1 ConvBlock(e1 e0, e0) self.out nn.Conv2d(e0, 1, 1) def forward(self, x): e1 self.enc1(x) e2 self.enc2(self.pool(e1)) e3 self.enc3(self.pool(e2)) e4 self.enc4(self.pool(e3)) d3 self.dec3(torch.cat([ F.interpolate(e4, sizee3.shape[2:], modebilinear, align_cornersFalse), e3], dim1)) d2 self.dec2(torch.cat([ F.interpolate(d3, sizee2.shape[2:], modebilinear, align_cornersFalse), e2], dim1)) d1 self.dec1(torch.cat([ F.interpolate(d2, sizee1.shape[2:], modebilinear, align_cornersFalse), e1], dim1)) return torch.sigmoid(self.out(d1))输入是(B, 1, 256, 256)输出是(B, 1, 256, 256)解码器拼接时dim1指通道维。这里用F.interpolate代替转置卷积做上采样参数更少也不容易出棋盘伪影。如果显存紧张可以降enc_chs(16, 32, 64, 128)基线验证 Dice 最多掉两三个点但训练速度快很多。选型时如果发现标注是 3D 体数据可以先把 2D 基线跑通再看验证集 Dice 能不能到 0.8 以上。2D 都稳不住不要急着换 3D U-Net因为 3D 模型吃显存明显batch 会变小数据增强也更难做。4.2 混合损失BCE Dice不要只盯着 Dice肿瘤像素占比可能只有几个百分点纯二分类交叉熵会让模型很快收敛到“全预测为背景”因为这样做 loss 已经很低了。Dice loss 直接优化预测区域和标注区域的重叠但单独使用在训练初期梯度不稳定。常见做法是把两个损失按权重叠加。class BCEWithDiceLoss(nn.Module): def __init__(self, dice_weight0.5, smooth1.0): super().__init__() self.dice_weight dice_weight self.bce nn.BCEWithLogitsLoss() self.smooth smooth def forward(self, logits, mask): bce self.bce(logits, mask.float()) prob torch.sigmoid(logits) inter (prob * mask).sum(dim(2, 3)) union prob.sum(dim(2, 3)) mask.sum(dim(2, 3)) dice 1.0 - ((2.0 * inter self.smooth) / (union self.smooth)).mean() return bce * (1 - self.dice_weight) dice * self.dice_weight注意self.bce接收的是 logits不是 sigmoid 之后的值BCEWithLogitsLoss内部做了数值稳定处理。mask必须是 0.0/1.0 的 float32 张量。dice_weight0.5是一个稳妥起点如果统计出来肿瘤占比很低可以调到 0.7 或 0.8让 Dice 多主导一点。这里有个小坑smooth1.0加到分子分母后纯背景切片也会得到一个接近 1 的 Dice 权重导致验证集虚高。如果训练集里纯背景切片很多最好只在mask.sum() 0的样本上计算 dice 部分或者在 DataLoader 里过滤掉全背景样本。4.3 训练配置建议学习率、batch 和 epoch 怎么配合训练配置我一般按下面这张表起步效果不够再单独调参数而不是一开始就上大模型和大 epoch。参数建议值说明输入尺寸256×256肿瘤小目标尺寸太低会丢边界batch_size8~16显存允许时尽量大稳定 BN优化器AdamWlr1e-3weight_decay1e-4损失函数BCE Dicedice_weight 0.5~0.7学习率调度ReduceLROnPlateaumodemaxfactor0.5patience5训练轮数30~60配合早停别硬跑满训练循环骨架也非常简单关键是验证指标出现后要马上喂给调度器。import torch model MiniUNet(in_ch1).cuda() criterion BCEWithDiceLoss(dice_weight0.7) optimizer torch.optim.AdamW(model.parameters(), lr1e-3, weight_decay1e-4) scheduler torch.optim.lr_scheduler.ReduceLROnPlateau( optimizer, modemax, factor0.5, patience5) for epoch in range(60): model.train() for imgs, masks in train_loader: imgs imgs.cuda() masks masks.cuda().float() optimizer.zero_grad() loss criterion(model(imgs), masks) loss.backward() optimizer.step() val_dice evaluate(model, val_loader) print(epoch, f{loss.item():.4f}, f{val_dice:.4f}) scheduler.step(val_dice)ReduceLROnPlateau的 mode 是 max因为这里监控的是验证 Dice不是 loss。连续 5 个 epoch 没有新高学习率就乘以 0.5。如果验证 Dice 一直卡在 0.5 附近先别调模型回头检查 3.2 的 mask resize 是不是用了线性插值或者 2.2 的np.unique(mask)是不是有 255。batch 和学习率存在一个粗糙的线性关系batch 从 8 加到 16学习率也可以翻倍到 2e-3反过来 batch 减半学习率也要跟着减半。BatchNorm 在 batch2 时统计会有明显抖动这时与其调学习率不如先把 batch 拉大。5. 提交前评估与避坑Dice 阈值和五个高频翻车点5.1 用 Python 计算 Dice 和 IoU平滑项与空掩膜边界评估指标要和官方口径保持一致但算法上最常用的就是 Dice 和 IoU。实现不复杂但要写对平滑项和空掩膜的处理。import numpy as np def dice_score(pred, mask, smooth1e-7): pred (pred 0.5).astype(np.uint8) mask (mask 0.5).astype(np.uint8) inter (pred mask).sum() union (pred | mask).sum() dice (2.0 * inter smooth) / (pred.sum() mask.sum() smooth) iou (inter smooth) / (union smooth) return dice, iou这里smooth1e-7只用来防止除零不参与指标数值的实质抬高。如果一整个 batch 全是背景Dice 就会变成 1这会让日志看起来很好但实际没有意义。所以评估时最好按“有肿瘤的切片单独算 Dice纯背景切片不计入平均”的口径和官方口径保持一致后再提交。还要确认官方是按切片平均还是按病例平均。如果按病例平均你需要先对同一个患者的多个切片各自算 Dice再在患者维度上平均不能把所有切片拼成一个全张量再统一算。两种口径差几个点很正常。5.2 阈值回溯0.5 不是万能扫描最优阈值更稳模型输出的是 sigmoid 概率肿瘤边界处概率往往不是干脆的 0 和 1而是 0.3~0.7 的过渡带。固定用 0.5 切分会把一些边缘丢掉Dice 掉 2~3 个点也是常事。在验证集上扫一遍阈值比拍脑袋定 0.5 更稳best_th, best_dice 0.5, 0.0 for th in np.arange(0.3, 0.71, 0.05): pred_bin (pred_prob th).astype(np.uint8) d, _ dice_score(pred_bin, mask) if d best_dice: best_th, best_dice th, d print(best_th, best_dice)注意这个扫描只能在验证集上做不能在测试集上反复试否则阈值会过拟合到测试集噪声上。不同图像的灰度分布差异可能导致最优阈值不同但如果多数折的最优阈值都稳定在 0.45 附近就可以用 0.45 作为正式提交阈值。后处理上可以试试cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)消除小空洞再用cv2.connectedComponentsWithStats去掉面积过小的孤立点。但后处理要谨慎肿瘤本身很小的时候一个 3×3 的闭运算都可能把它吞掉。5.3 五个高频翻车点现象、原因、解决顺序翻车一验证集 Dice 0.85测试集突然掉到 0.1。 现象本地评估很高排行榜或盲测结果惨不忍睹。 原因推理时没走训练时的预处理比如训练用了 CLAHE 和 z-score推理只做了img / 255灰度分布完全对不上。 解决把预处理封装成同一个函数训练、验证、推理共用不要为推理脚本单独再写一遍。翻车二loss 在下降Dice 却卡在 0.3 不动。 现象训练日志里 loss 数值一路走低验证 Dice 就是不长。 原因mask 没有从 0/255 转成 0/1模型学的是把输出压到 255但 sigmoid 输出范围只有 0~1目标不可达。 解决在 Dataset 里加mask (mask 127).astype(np.float32)并打印np.unique(mask)确认只有 0.0 和 1.0。翻车三某一天开始预测结果全是背景只剩零星白点。 现象之前正常加了数据增强后输出大面积消失。 原因mask 的 resize 或旋转用了线性插值0/1 变成 0.7/0.2损失出现诡异梯度。 解决所有对 mask 的空间变换都改用INTER_NEAREST增强后检查np.unique(mask)。翻车四某个样本的 loss 比其他样本高 10 倍。 现象训练 loss 曲线每隔几轮就冒一次尖峰。 原因图像和标注错位或者数据里混入了坏 mask比如全白 mask 对应全黑图像。 解决训练前写一个可视化脚本把“原图、mask、原图上叠加 mask”拼成一张图快速翻看 10 秒就能发现错位。翻车五Windows 下训练卡在某一步报找不到文件。 现象代码在 Linux 正常Windows 上跑一会儿就中断。 原因压缩包解压后的路径过长Windows 的 MAX_PATH 限制造成os.listdir丢文件。 解决解压到短目录比如D:\tdcup\raw不要放在带中文且超长的多级路径里。这五个问题我在不同队伍里反复看到前三个和预处理有关后两个和数据本身有关。遇到异常先查数据再查代码不要一头扎进换模型。6. 让提交更稳3 折交叉验证、概率平均与提交前检查6.1 用 3 折交叉验证统计 Dice 方差单次划分训练集和验证集结果很容易被某个异常切片带偏。用 GroupKFold 做 3 折交叉验证能同时看到 Dice 的均值和方差方差过大说明数据划分或预处理还有问题。gkf GroupKFold(n_splits3) dice_folds [] for train_idx, val_idx in gkf.split(df, groupsdf[patient_id]): train_df df.iloc[train_idx] val_df df.iloc[val_idx] model MiniUNet(in_ch1).cuda() train_one_fold(model, train_df, val_df) dice_folds.append(evaluate(model, val_df)) print(fold dice:, [round(d, 4) for d in dice_folds]) print(mean dice:, round(np.mean(dice_folds), 4))3 折比 5 折快方差统计也够用。如果三折之间 Dice 差超过 0.1说明模型不稳定原因多半在数据拆分或增强强度上如果三折都很接近再考虑做概率平均。6.2 概率平均多折模型的最后融合把 3 个折训练出来的模型对同一张测试切片做预测对概率图求平均再重新跑最优阈值。这种方法能消掉单模型在边界上的随机噪声是医学分割里最便宜有效的集成手段。prob [model(imgs) for model in fold_models] prob torch.stack(prob, dim0).mean(dim0) pred (prob best_th).float()这里的fold_models是 3 个已训练模型列表torch.stack在模型维度上堆叠mean后得到平均概率图。权重不需要刻意分配各折模型性能接近时等权平均就够用。提交前再用下面的清单过一遍能省掉绝大多数低级失误检查项检查方式预测文件名与测试集切片名一一对应不含额外后缀图像通道预测 mask 是单通道 uint8不是三通道像素值只用 0 和 1不出现 255预处理一致推理脚本修复处理与训练完全相同压缩包格式最终提交按官方要求打包不要多一层目录我自己的习惯是每改一次预处理或损失函数就把验证 Dice 和对应的预测样本截图写进一个checkpoint_note.txt提交前回看三分钟就能确认版本有没有串。最后一两天只做预测和格式检查不再调网络这个习惯让我避过了很多次手忙脚乱。希望这次从 zip 到提交的流程对你有用希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

重庆广受信赖的GEO优化服务商行业口碑汇总与实力参考 2026/10/1 22:58:25

重庆广受信赖的GEO优化服务商行业口碑汇总与实力参考

做企业线上长线布局,选对服务商是关键,选对能落地能出效果的GEO优化服务商更是难上加难。很多企业做线上推广踩过不少坑,要么服务商技术不成熟,做了大半年看不到曝光效果,要么服务跟不上,出了问题找不到对接…

阅读更多 →
Selenium Web自动化测试实战:环境搭建、原理与框架设计 2026/10/1 22:58:25

Selenium Web自动化测试实战:环境搭建、原理与框架设计

我做了三年多的Web自动化测试,从最开始只会写“打开浏览器、点几下、截图”的脚本,到后来在公司搭起了一套能跑几百条用例的回归体系,中间踩过的坑远比想象中多。如果你正准备用Python学习Selenium做Web自动化测试,或者已经写上了…

阅读更多 →
多线程并发编程全解:底层机制、语言实操与调优排查 2026/10/1 22:58:24

多线程并发编程全解:底层机制、语言实操与调优排查

多线程这个词,凡是写过几年代码的人都不会陌生,但真正把它吃透的人其实没那么多。我见过太多项目,功能逻辑写得没问题,一上并发就各种诡异现象:数据偶尔对不上、线程卡死不动、CPU跑满了吞吐反而下降。这些问题单看代码…

阅读更多 →
下水管道缺陷检测数据集详解:YOLO+VOC格式与训练避坑指南 2026/10/1 22:58:24

下水管道缺陷检测数据集详解:YOLO+VOC格式与训练避坑指南

简介:面向下水管道缺陷检测任务,提供了一套包含1717张清晰现场图片的目标检测数据集,覆盖穿入、错口、堆积、垃圾、裂缝、泥土、树根7类常见缺陷,累计标注3401个矩形框。数据采用VOC(xml)与YOLO&#xff08…

阅读更多 →
Win10 System进程100%硬盘占用与iaStorA警告根因解析 2026/10/1 22:58:23

Win10 System进程100%硬盘占用与iaStorA警告根因解析

1. 这不是系统中毒,是硬盘在向你求救:WIN10卡顿System进程100%硬盘占用iaStorA警告的真相你刚打开Win10,鼠标指针转圈三秒起步;打开任务管理器一看,System进程的硬盘占用率死死钉在100%,点开详细信息&#…

阅读更多 →
ROS多机通信配置原理与四层排查实战 2026/10/1 22:58:17

ROS多机通信配置原理与四层排查实战

1. 为什么ROS多机通信不是“配个IP就能通”——主从架构的本质矛盾很多人第一次尝试ROS多机通信,是在Ubuntu 20.04上装完Noetic,照着Wiki把ROS_MASTER_URI和ROS_IP一设,发现两台机器ping得通、ssh连得上,但rostopic list在从机上就…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉