简介:腹部14器官切片分割(BTCV)资源包,面向医学影像分析和深度学习分割任务,提供三个切面(轴位面、冠状面、矢状面)的2D切片数据、标签文件与可视化代码,适合需要多切面分割样本进行模型训练或算法验证的开发者。数据来自BTCV公开数据集,已做对比度拉伸(windowing)并统一缩放为512×512,同时去除ROI占比低于3%的切片,减少无效样本干扰。压缩包共2000个文件,其中1998个PNG图像对应CT切片与mask标签,另有1个Python可视化脚本show.py和1个JSON类别配置classes.json,整体约854.92MB;mask标签包含0背景及1~13号,对应脾脏、左右肾、胆囊、食道、肝脏、胃、主动脉、下腔静脉、门静脉和脾静脉、胰腺、左右肾上腺,类别定义清晰。附带脚本可将切片与mask叠加显示,便于快速检查标注质量。目前已有1290人学习浏览,适合需要多切面2D分割数据开展实验或复现研究的读者。
1. 腹部14器官分割的BTCV数据:先搞清楚这包切片数据能干嘛
做过腹部CT分割实验的人,多半都经历过这种尴尬:模型在榜单上刷到不错的Dice,换到自己手里的数据一跑,指标掉得没法看。差距往往不在网络结构,而在数据本身——切片怎么裁、标签怎么对、窗宽窗位用的什么。医学图像分割里的BTCV数据集,就是用来兜这种底的:它把腹部主要器官的标签统一到了一个坐标系下,省去你从零标注的时间,而标题里提到的“3个切面切片数据 + 标签文件 + 可视化代码”,本质上是把三维体素切成了更适合二维模型输入的形态。这篇文章顺着这个数据包讲清楚:三切面数据怎么来的、标签文件怎么核对、可视化代码怎么用,以及最容易翻车的那几个细节。适合刚入行分割任务、想把公开数据搬到本地训练,并且不想在预处理上浪费两周的同学。
2. 解剖标签索引与三切面数据布局:先把nii.gz里的坐标摆正
2.1 从二维切片到三维体素:BTCV标签索引与14类器官对照表
BTCV 的原始数据是 nii.gz 格式,每个病例对应一个三维 CT 体素,体积数据 shape 大概是 (H, W, D) 这样的三通道空间坐标。灰度值是 CT 的 HU 值,范围可以到 -1024 到 3000 多,而标签文件是单通道整数图,每个像素的值代表一个器官类别。标题里说的“腹部14器官”,实际落地时通常指官方标注的 13 个解剖结构加一个背景,合计 14 个类别;也有一些衍生包会把膀胱、腹主动脉等额外结构合进来做成 14 个器官。动手之前,务必先看标签文件里到底有哪些值,别拿默认的类表硬套。
我一般用 nibabel 直接读 nii.gz,然后立刻看一眼形状和标签分布:
import nibabel as nib import numpy as np img = nib.load("data/imagesTr/img_001.nii.gz") lab = nib.load("data/labelsTr/label_001.nii.gz") vol = img.get_fdata() # float64,HU值 label = lab.get_fdata().astype(np.uint8) # 整数标签 print("volume shape:", vol.shape) print("label shape:", label.shape) print("unique label values:", np.unique(label))这段代码的逻辑很简单:get_fdata()把 nii 里的体素数据装进 numpy 数组,标签读出来立刻转成uint8,避免后续计算时被 float 干扰。np.unique(label)是第一个体检项——如果打印出来的最大值是 13,说明这就是标准的「1~13 器官 + 0背景」布局;如果最大值是 14 甚至更高,那就要去翻 readme 里器官编号和名称的对照表,不要猜。
需要记住的标签索引对应关系,在绝大多数 BTCV 家族数据集里是固定的:1 脾脏、2 右肾、3 左肾、4 胆囊、5 食管、6 肝脏、7 胃、8 主动脉、9 下腔静脉、10 胰腺、11 右肾上腺、12 左肾上腺、13 十二指肠。后面写可视化代码时,这个对照表会直接决定调色板里每个器官的颜色,错了会张冠李戴。
2.2 三个切面的切片数据是怎么切出来的:先分清 axis 0/1/2
三维体素有三个方向,对应医学影像里常说的横断面(axial)、冠状面(coronal)、矢状面(sagittal)。用 numpy 的视角看,vol[:, :, z]取出的是某一层横断面,vol[:, y, :]是冠状面,vol[x, :, :]是矢状面。但这个对应关系只在数据的方向编码是标准 RAS 时才严格成立,不能想当然。
我拿到任何 nii 文件,第一步永远是查方向:
from nibabel.orientations import aff2axcodes codes = aff2axcodes(img.affine) print(codes) # e.g. ('R', 'A', 'S')aff2axcodes返回的是一个三元组,表示每个 axis 对应的解剖方向。如果输出是('R', 'A', 'S'),那 axis 0 是左右、axis 1 是前后、axis 2 是头脚方向;如果是('L', 'P', 'S')之类的 LPS 排列,直接用vol[:, :, z]取横断面虽然还能出图,但左右会被镜像。更稳妥的做法是先用nibabel.as_closest_canonical()把体素统一到标准方向再做切片,代价是多花几十秒内存,省掉后面所有脑子里的坐标系换算。
切片数据包的组织方式,常见的是在项目目录下按三个子目录分好:
data/ imagesTr/ # 原始三维 nii.gz labelsTr/ # 原始标签 nii.gz slices/ axial/ # 横断面切片 coronal/ # 冠状面切片 sagittal/ # 矢状面切片注意,具体文件名以你手里那个包的 readme 为准,不同来源的切片文件命名习惯差异很大。有的包直接把 nii 切成 png,有的保存成 npy,还有的干脆把三个切面堆成一个.h5文件。无论哪种形式,都不影响理解:三切面数据就是从三维体素里按固定步长抽出来的二维图像序列,标签文件同步抽取,两个文件之间隔着索引一一对应。
2.3 切片数据与标签文件的对应关系:索引对齐是第一步
三切面数据的正确性,完全取决于切片和标签是否对得上。拿横断面举例,三维体素有 D 层,slice_0042.png对应的就是label_0042.png里同一层所有器官的像素分布。这句话听起来是废话,实际坑很多——有的包把 CT 切片做了旋转或翻转变换,但标签却保持原始方向;有的包为了压缩省空间,把标签图从 PNG 转成了 JPG,结果边缘糊掉一圈。初次拿到数据包时,我建议先别急着跑训练,抽一个中间层,把原图切片和标签切片叠加出来看 10 秒,确认边界咬合再往下走。
判断索引是否对齐的快速办法,是对标签统计非零像素占比。每一层的标签像素占比应该是一个连续变化的值,如果某几层突然从 20% 掉到 0 又跳回来,多半是切片顺序被重排或丢帧了。
for i in range(label.shape[2]): mask = label[:, :, i] ratio = (mask > 0).mean() if i % 50 == 0: print(f"slice {i:3d}, foreground ratio = {ratio:.4f}")这段代码按每隔 50 层打印一次前景占比,跑完一眼就能看出整体分布。占比接近 0 的层在腹部数据里是正常的——比如靠近肺部和骨盆的区域确实没有腹部器官——但占比突变则说明索引有问题。我一般会把这个统计存成 CSV,结合可视化截图一起归档,作为数据质量检查的一部分。
3. 从nii.gz生成三切面切片:预处理脚本与窗宽窗位参数
3.1 用窗宽窗位把CT从HU变成能看的图:腹部窗口的取值
CT 的原始值 HU 动态范围极大,空气是 -1024,骨骼可以到 2000 以上,如果直接plt.imshow(vol[:, :, 100]),出来的图基本是一团黑,因为软组织那几十 HU 的差异在 3000 的跨度里根本显示不出来。医学图像分割里几乎不直接使用原始 HU 做可视化,常规操作是先做一次 clip,把灰度范围压缩到腹部软组织所在的窗口。
腹部 CT 最常采用的窗宽窗位组合是窗宽 400、窗位 40,对应的取值区间大约是 -160 到 240。这套参数适合看肝脏、胰腺、脾脏这些实质性器官,血管和肾脏也基本落在里头。我自己的习惯是稍微保守一点,用更窄的 [-125, 275],把皮下脂肪也带进来一点,方便网络学背景。不同来源的数据包可能在预处理阶段已经帮你做了归一化,所以拿到手先看像素值范围再决定要不要再做一次窗宽窗位。
WINDOW_WIDTH = 400 WINDOW_LEVEL = 40 low = WINDOW_LEVEL - WINDOW_WIDTH / 2 high = WINDOW_LEVEL + WINDOW_WIDTH / 2 hu_clipped = np.clip(vol, low, high) hu_norm = (hu_clipped - low) / (high - low) print("after clip:", hu_norm.min(), hu_norm.max())逻辑说明:np.clip把超出窗口的 HU 截断,然后线性拉伸到 0~1,得到的就是一张可以直接存图或喂给网络的灰度图。这两个参数高低直接影响对比度——窗口太窄,肝脏和胰腺的纹理看不清;窗口太宽,软组织对比度被稀释。数据包里如果已经给了预处理过的 png,先检查它的像素范围,如果已经是 0~255 或 0~1 且细节清楚,就没必要再重复走一遍窗宽窗位,重复 clip 反而会把已经压好的动态范围再切掉一截。
3.2 三切面切片数据与标签同步导出:完整脚本
当你需要自己从 nii.gz 生成三切面数据时,最关键的要求是体积数据和标签数据走同一条变换流水线,任何旋转、翻转、取样操作都保持一致。下面是我常用的导出脚本主体:
import os import numpy as np import nibabel as nib AXIS_MAP = {"axial": 2, "coronal": 1, "sagittal": 0} def export_slices(vol, lab, out_dir, plane="axial"): axis = AXIS_MAP[plane] n = vol.shape[axis] # 把要切的轴放到最后一个维度,统一后续逻辑 vol_moved = np.moveaxis(vol, axis, -1) lab_moved = np.moveaxis(lab, axis, -1) for i in range(n): v = vol_moved[:, :, i] # 二维横断面/冠状面/矢状面 l = lab_moved[:, :, i] # 可视化预览时统一旋转,训练数据不要做这一步 v = np.rot90(v, k=-1) l = np.rot90(l, k=-1) # 窗宽窗位归一化 low, high = -160.0, 240.0 v = np.clip(v, low, high) v = (v - low) / (high - low) np.save(os.path.join(out_dir, f"{plane}_slice_{i:04d}.npy"), v) np.save(os.path.join(out_dir, f"{plane}_label_{i:04d}.npy"), l) for plane in ["axial", "coronal", "sagittal"]: os.makedirs(f"./output/{plane}", exist_ok=True) export_slices(vol, label, f"./output/{plane}", plane)逻辑说明:np.moveaxis把目标轴挪到最后一个维度,这样循环里每次取出[:, :, i]就得到一张二维切片;体积数据和标签数据做完全一样的 moveaxis 和 rot90,保证像素一一对应。np.rot90(k=-1)是为了让切片在视觉预览时方向正常,但训练时我强烈建议不要旋转——网络自己学习方向鲁棒性,比你手动转错方向再排查半天要省事。
参数说明:窗宽窗位我写死成-160和240,对应上面说的窗宽 400、窗位 40。如果你的任务更关注肝脏边界,可以改成窗宽 200、窗位 40;如果关注胰腺和肾上腺这种小器官,建议同时导出窗宽 400 和窗宽 200 两套,输入网络时做双通道,这是一个常见的 trick:让网络同时看到软组织的大对比和细节纹理。
3.3 最小可用命令:跑通一个病例的三切面导出
上面脚本封装好之后,命令行调用大致如下。实际项目中,我会给脚本加argparse参数,方便不同病例切换输入输出路径:
python export_slices.py \ --volume data/imagesTr/img_001.nii.gz \ --label data/labelsTr/label_001.nii.gz \ --out ./output/img_001 \ --window-level 40 \ --window-width 400 \ --planes axial coronal sagittal参数说明:--volume和--label分别是三维 CT 和标签文件路径;--window-level和--window-width控制窗位窗宽,分别对应公式里的WINDOW_LEVEL和WINDOW_WIDTH;--planes指定要导出哪几个切面,默认三个都导出。输出目录下会生成三个子目录,每个目录里是成对的xxx_slice_{index}.npy和xxx_label_{index}.npy,文件名里的 index 就是原始体素里那一层的坐标。
这里有一个很多人会踩的坑:npy文件并不保存 spacing(体素间距)和 direction 信息,一旦切完,三维坐标和原始 nii 的对应关系就只能靠文件名里的 index 去反推。所以我建议在输出目录里同时也生成一个meta.json,记录 affine、shape、窗宽窗位这些参数,作为后悔药。后续如果发现方向错了,还能根据 meta 信息把切片还原回三维体素重新处理,不至于推倒重来。
4. 标签文件与可视化代码的落地玩法:单通道整数图之外的坑
4.1 标签文件的两套供货方式:整张单通道图和独立单器官掩码
标题里把“标签文件”单独列出来,是因为这个数据包的标签可能有两种形态。第一种是标准的单通道整数图,每个像素值 0~13,一个文件装下所有器官;第二种是每个器官单独一个二值 mask,14 个文件对应 14 个类别。这两种形态各有适用场景:单通道整数图体积小、读取快、训练时直接用 CrossEntropyLoss,是首选;独立 mask 的好处是方便逐器官做后处理或指标评估,但训练时还要花一步把所有 mask 合并回整数图,纯属多此一举。
我拿到标签文件的第一件事,永远是统计每个类别的像素占比,这一步能发现绝大多数标签转换问题:
counts = np.bincount(label.ravel(), minlength=14) organ_names = ["background", "spleen", "right_kidney", "left_kidney", "gallbladder", "esophagus", "liver", "stomach", "aorta", "inferior_vena_cava", "pancreas", "right_adrenal", "left_adrenal", "duodenum"] for cid in range(14): print(f"{cid:2d} {organ_names[cid]:20s} {counts[cid]:10d}")这段代码用np.bincount统计每个标签值出现的次数,minlength=14保证即使某一类完全没出现也会得到 0。正常腹部 CT 里,肝脏和脾脏应该占大头,胆囊和肾上腺占比很少。如果发现某个病例里胆囊像素数是 0,可能是转换时把标签值弄丢了,也可能病人确实做过胆囊切除,需要对照原始 nii 再确认。永远不要只信文件名后缀,标签值的直方图是最诚实的体检报告。
4.2 可视化代码怎么落地:mask叠加与调色板
数据包附带的可视化代码,常见用法是把原始灰度切片和标签叠加在一起,生成一张彩色预览图。实现上会涉及两部分逻辑:灰度图转伪彩、标签 mask 转半透明蒙版。核心代码并不复杂:
import matplotlib.pyplot as plt import numpy as np # 13个器官 + 背景,每个器官给一个颜色,BGR顺序也可以,一致就行 COLORS = np.array([ [0.0, 0.0, 0.0], # 0 background [0.8, 0.2, 0.2], # 1 spleen [0.8, 0.5, 0.1], # 2 right kidney [0.2, 0.8, 0.2], # 3 left kidney [0.8, 0.8, 0.1], # 4 gallbladder [0.6, 0.3, 0.6], # 5 esophagus [0.9, 0.7, 0.2], # 6 liver [0.2, 0.5, 0.8], # 7 stomach [0.9, 0.3, 0.3], # 8 aorta [0.3, 0.7, 0.9], # 9 IVC [0.4, 0.8, 0.4], # 10 pancreas [0.9, 0.8, 0.5], # 11 right adrenal [0.9, 0.5, 0.8], # 12 left adrenal [0.5, 0.5, 0.9], # 13 duodenum ], dtype=float) def overlay_slice(image, label, alpha=0.45): rgb = np.stack([image] * 3, axis=-1) overlay = np.zeros_like(rgb) for cid in range(1, 14): mask = label == cid overlay[mask] = COLORS[cid] blended = (1 - alpha) * rgb + alpha * overlay return np.clip(blended, 0, 1) plt.imsave("preview_axial.png", overlay_slice(hu_norm, label_slice), dpi=120)逻辑说明:np.stack([image]*3, axis=-1)把单通道灰度图扩展成 RGB 三通道;循环里逐类别把标签 mask 对应的像素染成预设颜色;最后(1-alpha) * rgb + alpha * overlay做半透明融合。alpha 的取值需要现场调:0.3 太淡,器官边界看不清;0.6 太浓,CT 内部结构被完全盖住。我自己常用 0.45 起步,主要看叠加后血管和器官边缘是否仍然可辨。
调色板这个细节容易被忽略,但直接影响你肉眼判断实验结果。器官颜色之间要拉开距离,尤其左肾和右肾、肝和脾这种相邻器官,如果给的颜色太接近,一眼扫过去很难快速定位病灶区域。上面代码里的配色只是示例,实际使用可以根据喜好改,但建议把调色板固定成一个常量,所有实验共用,不同实验之间对比时才不会看花眼。
4.3 三切面拼图:一张图同时看三个方向的切片
单独一张横断面切片看不出器官在三维空间里的延展,三切面拼图才是真正帮你理解数据的姿势。数据包里的可视化代码一般会做这种组合画布,把同一坐标点对应的横断面、冠状面、矢状面拼在一起输出:
fig, axes = plt.subplots(1, 3, figsize=(18, 6)) coordinates = [ (hu_norm[:, :, 96], label[:, :, 96], "axial"), (hu_norm[:, 128, :], label[:, 128, :], "coronal"), (hu_norm[64, :, :], label[64, :, :], "sagittal"), ] for ax, (img_slice, lab_slice, name) in zip(axes, coordinates): ax.imshow(overlay_slice(img_slice, lab_slice), cmap="gray") ax.set_title(name) ax.axis("off") fig.savefig("three_planes.png", bbox_inches="tight", dpi=100)这段代码的关键是三个切片必须取自同一空间位置附近——比如横断面取第 96 层、冠状面取第 128 列、矢状面取第 64 行,这样三个视图交叉处的体素点大致落在同一解剖结构上,便于定位。实际使用中我一般会在三维体素里选一个器官中心坐标,比如胰腺中心,然后围绕这个坐标输出三个切面,确认器官的形态是否和解剖一致。还有一个常见问题是,很多人把切好的图放到 Django static 目录后,写img标签显示不了,十有八九是 url 路径写法不对,跟可视化代码本身无关;我习惯直接用savefig落到本地磁盘再开浏览器看图,别让路径问题耽误调参。
5. 避坑:三切面数据最容易翻车的5个细节
5.1 标签索引对不上:0到底是背景还是器官
现象:训练时损失函数一直不收敛,验证集 Dice 接近 0,打印预测结果发现模型把脾脏区域预测成了背景。
原因:数据包里的标签文件有两种索引体系——一种是 0 表示背景、1~13 表示器官,另一种是 0~12 表示器官、13 表示背景。后者常出现在有人用np.argmax对 one-hot 标签取反推时搞错了类别编号。你拿默认的 CrossEntropyLoss 去训,背景和器官的边界在整个标签空间里都是乱的。
解决:加载标签后第一件事打印np.unique(label),确认最大值和 0 的含义。如果你的损失函数是CrossEntropyLoss,记得设置ignore_index=0(前提是你确定了 0 是背景);如果模型输出 14 类,而标签只有 0~12,那就是类别数定义错了,赶紧去改数据加载器里的num_classes。
5.2 冠状和矢状切面搞反:方向编码才是根因
现象:用vol[:, y, :]导出的冠状面,看起来头像左右颠倒,矢状面上下颠倒,但横断面完全正常。
原因:nii.gz 文件的方向编码不一定是 RAS。有些数据来自不同的采集设备,affine 里记录的可能是 LPS 或其他方向。你按自己习惯的 axis 顺序去切,出来的图像坐标系和医学影像的标准显示方向不一致,左右或前后就会反转。
解决:写脚本之前先跑aff2axcodes打印方向码,再用nib.as_closest_canonical()统一到标准方向。切片生成脚本里保留一份meta.json记录 affine,后续训练出的预测结果要投影回原始三维空间时,还能根据这个 affine 做逆变换,不然预测结果和原始数据对不上,后处理全白做。注意:训练数据里不要为了预览好看做 rot90,保持原始方向喂给网络,否则模型学习的方向和你验证时的方向不一致,推理时又得转回来,多一层出错机会。
5.3 CT图一片黑或一片白:窗宽窗位没做对
现象:plt.imshow直接显示切片,图像几乎全黑,只有骨骼边缘有细微灰度;或者整张图白茫茫一片,器官完全无法分辨。
原因:CT 原始 HU 范围是 -1024 到 3000+,腹部的肝脏、胰腺、肾脏这些软组织集中在 -100 到 200 之间。直接线性映射到灰度,软组织那 300 HU 的动态范围被压缩到整个显示范围的十分之一,肉眼自然什么都看不见。
解决:腹部用窗宽 400、窗位 40 做 clip,或者更保守的 [-125, 275]。如果数据包里已经预处理过,先检查像素范围:如果是 0~1 之间且图像细节清楚,就不要二次 clip。还有一个独立的问题:有的人对标签文件也做了窗宽窗位归一化,把整数标签变成了浮点数,再转存 png 时被取整,相邻器官边界互相污染。标签文件永远只做空间变换,灰度变换只针对图像通道。
5.4 标签png被有损压缩:器官边缘多出一圈伪影
现象:训练时在器官边界区域出现持续的 Dice 损失,模型输出的边缘比标签大一圈,肉眼检查标签 png,边缘位置有一圈锯齿或光晕。
原因:有人为了节省空间,把标签 png 保存成 JPG 或者用了有损压缩选项。JPG 的压缩算法在边缘会产生振铃效应,原本锐利的器官边界变成渐变带,像素值不再是整数类别,而是一堆小数。
解决:标签文件只允许存无损格式——PNG 的 palette 模式或直接存 npy。读取时强制转uint8,并检查唯一值数量:如果np.unique(label)的数量远超 14,说明标签已经被压缩污染,这批数据不可用。正确做法是回到 nii.gz 重新导出标签切片,并且不要在导出时做任何插值或平滑操作。
5.5 三切面数据里背景切片占大头:正样本稀疏到没法训练
现象:训练集 3000 张切片,其中 2000 张完全没有前景像素,模型快速收敛到预测全背景。
原因:腹部 CT 在靠近肺部和骨盆的区域,本来就没有腹部器官;加上三维体素每层都切出来,训练数据里背景样本的比例远高于前景。尤其是胆囊和肾上腺这种体积本来就小的器官,可能在 80% 的切片里完全不存在。
解决:导出切片时做一次前景筛选,统计每张切片label > 0的像素占比,把低于阈值的切片直接丢弃或降低采样权重。常用做法是保留前景占比大于 0.5% 的切片,再按器官稀有程度做加权采样。如果这样做之后数据量不够,可以回归到随机采样但配合WeightedRandomSampler,给稀有器官所在的切片更高的权重。我的建议是:三切面数据的价值在于用二维模型吃三维上下文,但如果背景切片过多导致类别不平衡,反而比直接用三维模型更差,这一步筛选不是可选项。
6. 给这套数据做最后的体检:直方图、连通域巡检和抽查修复
数据到手、预处理跑通之后,我习惯先做一轮 10 分钟的三步体检,过了再开训练。第一步是标签直方图,上一章已经写过,主要确认每个病例的器官分布是否合理;第二步是逐器官连通性检查,因为正常解剖结构下,脾脏、肾脏、胆囊这些器官在三维体素里应该各自是一个连通域。
from scipy.ndimage import label for cid in [1, 2, 3, 4, 10]: # 脾、右肾、左肾、胆囊、胰腺 mask = label_arr == cid labeled, n_components = label(mask) print(f"organ {cid}: components = {n_components}, voxels = {mask.sum()}") if n_components > 1: sizes = np.bincount(labeled.ravel())[1:] print(" component sizes:", sizes)这段代码用scipy.ndimage.label对单个器官 mask 做连通域标记。如果某个器官拆成了十几个小碎片,多半是标签转换时发生了插值错位或形态学腐蚀残留,需要回到原始 nii.gz 重新提取。有一点例外:左肾可能因为肾门凹陷在某个切面断开,但碎片数量一般不超过 3 个,如果超过 5 个基本可以认定标签有问题。
第三步是切片巡检,三切面拼图批量生成后,我会把几十张预览图合成一张长图,用肉眼快速扫一遍。这一步看起来原始,却是发现极端问题的最后防线:比如某个病例的标签和 CT 之间整体偏移了 5 个像素、某个切面被子采样过导致分辨率不统一,这些在直方图里看不出来,但长图上一眼就能暴露。我最近一次用这个流程,发现某批数据的矢状面切片被整体左右翻转,就是因为长图里钙化点位置全反了,而不是靠数值统计抓到的。
这件事给我留下的习惯是:任何数据包,无论来源多正规,都默认它有问题,直到体检通过。可视化代码不能只当成出图工具,它是坐标核对、标签核对的辅助手段;跑训练之前花 10 分钟做一遍,比训练跑完再发现数据错了返工强得多。希望帮到你。
本文还有配套的精品资源,点击获取