據(jù)集的下載與整理:從NIfTI到訓(xùn)練集)
簡介面向醫(yī)學(xué)影像與深度學(xué)習(xí)研究者提供腦腫瘤MRI分類與分割兩套配套數(shù)據(jù)。分類部分涵蓋神經(jīng)膠質(zhì)瘤、腦膜瘤、垂體瘤及無腫瘤四種標(biāo)簽便于訓(xùn)練圖像分類模型分割部分補充了腫瘤區(qū)域坐標(biāo)標(biāo)注可支持語義分割與目標(biāo)檢測任務(wù)也能為RSNA等競賽提供預(yù)訓(xùn)練基礎(chǔ)。壓縮包內(nèi)共2000個文件以jpg格式的腦部MRI圖像為主1849個另有150個txt標(biāo)注文件與1個yaml配置txt文件用于記錄標(biāo)簽或坐標(biāo)yaml描述數(shù)據(jù)集結(jié)構(gòu)且分類與分割分別給出了訓(xùn)練/測試或訓(xùn)練/驗證/測試目錄下載后無需額外整理即可直接開展實驗。資源包整體約92MB體積適中適合快速下載和離線實驗。目前已有526人瀏覽學(xué)習(xí)適合醫(yī)工交叉方向的學(xué)生、算法工程師及競賽參與者直接取用作為數(shù)據(jù)基線或模型練手素材。1. 腦腫瘤 MRI 數(shù)據(jù)集下載先想清楚你要的是原始影像還是訓(xùn)練用的標(biāo)注樣本做醫(yī)學(xué)圖像分割的開發(fā)者拿到“腦腫瘤 MRI 數(shù)據(jù)集下載”這個需求心里想的通常不是網(wǎng)盤里一堆 DICOM 原片而是可以直接送進(jìn) U-Net 的訓(xùn)練數(shù)據(jù)每例包含 T1、T1ce、T2、FLAIR 四個序列外加對應(yīng)的腫瘤區(qū)域分割 mask。公開的腦腫瘤 MRI 數(shù)據(jù)集大多數(shù)按 NIfTI.nii.gz文件組織一個病例對應(yīng) 5 個文件也有一部分社區(qū)整合版把全量數(shù)據(jù)打成 H5下載和加載都更快。下載階段最常見的誤會是把原始體數(shù)據(jù)當(dāng)成標(biāo)注數(shù)據(jù)或者沒意識到訓(xùn)練集和驗證集的劃分信息藏在某個邊角 CSV 里。常見做法是先把發(fā)布說明里的文件清單讀一遍再寫下載腳本而不是拿到鏈接就一把梭。這篇內(nèi)容按一套可以直接照著走的流程講先認(rèn)清數(shù)據(jù)形態(tài)再用命令行和 Python 腳本批量下載做格式整理與下載后自查讓 30 GB 級的數(shù)據(jù)集在一個工作日內(nèi)落盤并進(jìn)入預(yù)處理。2. 下載前先分清腦腫瘤 MRI 數(shù)據(jù)集的三種形態(tài)這決定你的轉(zhuǎn)換腳本怎么設(shè)計第一批做腦腫瘤 MRI 深度學(xué)習(xí)的人面對的是零散歸檔現(xiàn)在的情況反過來公開數(shù)據(jù)集很多選擇困難。同一個需求可能對應(yīng)三種完全不同形態(tài)的數(shù)據(jù)包文件后綴可能是 .nii.gz、.nii、.dcm也可能是 .h5同一個來源不同年份發(fā)布還可能是兩種組織方式。轉(zhuǎn)換腳本不該等文件落盤了才想著適配下載前就要把數(shù)據(jù)形態(tài)定下來。數(shù)據(jù)形態(tài)直接決定三件麻煩事要不要解壓嵌套目錄、要不要自己合并多序列、要不要重采樣到統(tǒng)一尺寸。下面按最常見的三種形態(tài)分別講最后給一張對比表方便你對照選型。2.1 多模態(tài)分割數(shù)據(jù)集四個序列加 mask是訓(xùn)練腦腫瘤分割模型最常用的原料多模態(tài)分割數(shù)據(jù)集是大多數(shù)腦腫瘤分割實驗的起點。一份典型的數(shù)據(jù)包按病例劃分目錄每個病例包含四個 MRI 序列T1、T1ce打藥后的增強 T1、T2 和 FLAIR另外還有一個分割 mask 文件。mask 的體素值通常約定 1、2、4 分別表示壞死區(qū)、水腫區(qū)、增強腫瘤區(qū)0 是背景。下載腳本要處理的是類似{case_id}_t1ce.nii.gz這種固定后綴而不是在解壓后一個個去找哪個文件是 T1。為什么把標(biāo)注 mask 的類別數(shù)看得比總病例數(shù)還重要因為網(wǎng)絡(luò)輸出層的類別數(shù)必須等于 mask 類別數(shù)加背景mask 里只有一類“腫瘤區(qū)域”和背景輸出就是 2 類三分類標(biāo)注則輸出 4 類。不少數(shù)據(jù)集在發(fā)布說明里寫的是“3 類標(biāo)注”實際 mask 取值范圍是 0、1、2、4轉(zhuǎn)換腳本里非常容易漏掉 4 這個值后面訓(xùn)練時報 out-of-range 錯誤才算踩到坑。所以拿到數(shù)據(jù)集第一步就是統(tǒng)計 mask 的取值集合而不是信任發(fā)布說明。選擇多模態(tài)分割數(shù)據(jù)集時我一般看三個指標(biāo)病例數(shù)、是否為多中心采集、是否自帶訓(xùn)練驗證切分。多中心采集意味著 MRI 掃描儀型號和掃描協(xié)議不同圖像對比度差異明顯模型泛化能力才會被真實反映出來。自帶切分的數(shù)據(jù)集能省掉維護(hù) stratify 列表的工作但注意切分文件往往掛在下載頁最下面一個不起眼的 CSV 里漏下載后面還得回頭補。形態(tài)文件組織典型單病例體積標(biāo)注最適合的任務(wù)多模態(tài) NIfTI 分割集每病例 4 個序列 .nii.gz 1 個 mask100–300 MB像素級分割 mask語義分割、多模態(tài)融合單序列影像集每病例 1 個 .nii.gz 或 .dcm 目錄20–80 MB無或病例級標(biāo)簽重建、預(yù)訓(xùn)練、異常檢測H5 打包版一個 .h5 包含 image/label 兩個數(shù)據(jù)集全量 10–60 GB已編碼為數(shù)組標(biāo)簽快速迭代、驗證推理單序列影像集下載量約為四序列數(shù)據(jù)的一半以下網(wǎng)絡(luò)條件不太好時是快速搭通管線的好選擇。H5 打包版看似一步到位但標(biāo)簽編碼有 one-hot 和類別序號兩種習(xí)慣讀出來的 shape 可能是 (N,4,H,W)也可能是 (N,H,W,4)轉(zhuǎn)換腳本比用 NIfTI 時更難猜。2.2 單序列影像集體積小、適合先跑通流程別指望它直接訓(xùn)分割模型很多腦腫瘤 MRI 數(shù)據(jù)集的公開下載其實是單序列版本例如只有 T1 加權(quán)像或者只有 T2 加權(quán)像。它們常常來自影像歸檔站元數(shù)據(jù)干凈文件名按patient_id_sequence.nii.gz組織沒有 mask。這類數(shù)據(jù)對剛接觸醫(yī)學(xué)圖像的新手有一個隱藏價值用很小體積把 nibabel 讀取、方向重采樣、像素歸一化這一整套流程先跑通等拿到多模態(tài)標(biāo)注數(shù)據(jù)時你早熟悉 NIfTI header 里哪些字段會搗亂。但拿它訓(xùn)練分割模型非常勉強。單序列數(shù)據(jù)大多沒有像素級標(biāo)注即使有也是“有腫瘤/無腫瘤”的切片級或病例級標(biāo)簽?zāi)苡?xùn)練的是圖像分類或弱監(jiān)督模型不是逐像素的 U-Net。我早期處理腦腫瘤 MRI 數(shù)據(jù)時犯過這個錯看到一個幾千例的單序列大包就急著開訓(xùn)練結(jié)果任務(wù)定義完全不對白跑了兩天預(yù)處理。下載前一定先問自己這輪實驗?zāi)繕?biāo)是分割、分類還是自監(jiān)督預(yù)訓(xùn)練目標(biāo)不同數(shù)據(jù)形態(tài)直接選不同。2.3 H5 打包版本免解壓但先確認(rèn)維度順序和標(biāo)簽編碼社區(qū)整理的 H5 版本通常是把 NIfTI 重采樣到統(tǒng)一尺寸比如 1283 或 240×240×155后寫入一個文件。好處是下載完成后不用再逐病例掃描目錄樹壞處是打包者可能已經(jīng)做過前置處理比如把原始體素值縮放到某個區(qū)間卻沒有在說明里寫清楚。你下載的不只是數(shù)據(jù)還是一套別人處理過的值域這屬于典型的黑匣子問題。打開 H5 文件先看三樣?xùn)|西根目錄下有幾個數(shù)據(jù)集或分組、image 數(shù)組的維度順序、label 數(shù)組的取值集合。用 h5py 就能完成import h5py import numpy as np with h5py.File(brain_mri_dataset.h5, r) as f: print(f.keys()) # 看看根目錄下的 key img f[image] # 圖像數(shù)組 lab f[label] # 標(biāo)簽數(shù)組 print(img.shape, img.dtype) # (240, 240, 155, 4) 表示最后一維是通道 print(lab.shape, lab.dtype) # 標(biāo)簽通常只有 1 個通道 print(np.unique(lab[:])) # 統(tǒng)計標(biāo)簽取值集合確認(rèn)是 0,1,2,4f.keys()能直接暴露打包者的命名習(xí)慣有的用image有的用data有的用volumesshape的最后一維是 4 代表四個 MRI 序列已經(jīng)按通道堆疊訓(xùn)練腳本里就不用再合并np.unique跑一遍標(biāo)簽類別數(shù)和發(fā)布說明是否一致立刻見分曉。切分方面有些打包版把 train 和 test 放在同一個 H5 文件的不同分組里有些用兩個文件這直接影響數(shù)據(jù)讀取邏輯最好在下載說明里確認(rèn)而不是等代碼運行到報錯再回頭翻。一句話選型邏輯要訓(xùn)練分割模型選多模態(tài) NIfTI 分割集要快速驗證全流程選單序列小包或 H5 打包版要跑對比實驗發(fā)表結(jié)論再用帶官方切分的多模態(tài)集。第 3 章開始我按多模態(tài) NIfTI 這個最典型場景寫下載和轉(zhuǎn)換腳本。3. 用命令行和 Python 把腦腫瘤 MRI 數(shù)據(jù)集批量下載下來最小命令與斷點續(xù)傳下載這類數(shù)據(jù)集最怕兩件事鏈接失效和下載中斷。鏈接失效因為發(fā)布者經(jīng)常更新版本舊文件被移到歸檔目錄下載中斷則是因為單文件大、網(wǎng)絡(luò)波動多幾 GB 的包下到 80% 斷掉沒有斷點續(xù)傳就得從頭再來。下面先給一個能立刻用的 wget 命令再給一個 Python 斷點續(xù)傳腳本最后說并發(fā)策略。3.1 先用 wget 拉鏡像包斷點續(xù)傳加校驗文件大小如果數(shù)據(jù)發(fā)布方直接給了 tar.gz 整包地址最快的做法是 wget 一把拉。注意兩個參數(shù)-c斷點續(xù)傳-O指定落盤文件名避免服務(wù)器端文件名太隨意。# -c 支持?jǐn)帱c續(xù)傳-O 指定保存文件名-q 關(guān)閉進(jìn)度刷屏 wget -c -q -O brain_mri_data.tar.gz \ https://example.com/brain-mri-release-2024/brain_mri_data.tar.gz # 下載完立刻做兩件事看文件大小、算校驗和 ls -lh brain_mri_data.tar.gz md5sum -c brain_mri_data.tar.gz.md5-c的原理是 wget 檢測本地已有文件大小通過 HTTP Range 請求從斷點繼續(xù)拉取剩余部分適合單文件下載。md5sum -c需要數(shù)據(jù)發(fā)布方同時提供.md5校驗文件沒有的話就用md5sum brain_mri_data.tar.gz手動算出來和發(fā)布頁上的哈希字符串比對。體積和發(fā)布說明對不上、校驗和不一致都直接重下別指望解壓時能修復(fù)。3.2 Python 斷點續(xù)傳腳本requests 流式寫入、超時和退避重試整包下載方便但有些數(shù)據(jù)源只允許按病例文件逐個下載或者你想自己控制哪些病例要、哪些不要這時候就要寫腳本。下面這段是我常用的下載函數(shù)核心是斷點續(xù)傳加失敗重試import os import time import requests CHUNK_SIZE 1024 * 1024 # 每次讀 1 MB避免內(nèi)存暴漲 TIMEOUT 30 # 連接超時 30 秒 def resume_download(url, dest, max_retries5): downloaded os.path.getsize(dest) if os.path.exists(dest) else 0 headers {Range: fbytes{downloaded}-} for attempt in range(max_retries): try: with requests.get(url, headersheaders, streamTrue, timeoutTIMEOUT) as resp: resp.raise_for_status() total int(resp.headers.get(Content-Length, 0)) downloaded mode ab if downloaded 0 else wb with open(dest, mode) as f: for chunk in resp.iter_content(CHUNK_SIZE): if chunk: f.write(chunk) downloaded len(chunk) return True except (requests.ConnectionError, requests.Timeout): # 退避重試間隔按失敗次數(shù)遞增別在斷網(wǎng)瞬間瘋狂打請求 time.sleep(5 * (attempt 1)) return FalseRange頭是斷點續(xù)傳的關(guān)鍵服務(wù)器收到后會從指定字節(jié)開始返回streamTrue讓響應(yīng)體按塊讀取配合iter_content邊讀邊寫不會把整個文件載入內(nèi)存modeab追加寫入保證重試時不會把已下載部分覆蓋。max_retries一般給到 5 次每次退避時間遞增避免網(wǎng)絡(luò)抖動時連續(xù)失敗。3.3 并發(fā)下載策略線程數(shù)不是越大越好單文件串行、多文件并發(fā)更穩(wěn)數(shù)據(jù)量大時單線程下載幾十個文件確實慢但并發(fā)開大了又容易被服務(wù)端限流。我一般用線程池下多個文件連接數(shù)控制在 4 到 8 個。這里有個容易翻車的點多線程下載一個文件時要自己處理每個線程的寫入偏移復(fù)雜度高且容易損壞文件更穩(wěn)的做法是單文件串行續(xù)傳、多文件并行下載。from concurrent.futures import ThreadPoolExecutor, as_completed from pathlib import Path def download_item(item): local Path(item[local]) if local.exists() and local.stat().st_size item[size]: return f{local.name} 已存在跳過 ok resume_download(item[url], str(local)) return f{local.name} 下載{成功 if ok else 失敗} items load_manifest() # 從 CSV/JSON 讀取每個病例的 url、本地路徑、期望大小 with ThreadPoolExecutor(max_workers6) as pool: futures [pool.submit(download_item, it) for it in items] for fut in as_completed(futures): print(fut.result())max_workers6是經(jīng)過幾次倒騰后比較舒服的值太快會被服務(wù)端拒連接太慢壓不住帶寬。load_manifest建議從數(shù)據(jù)發(fā)布方提供的清單文件讀取而不是自己在代碼里寫死文件列表清單里最好帶每文件的期望大小下載前先比對能跳過已完成的文件省時也省流量。還要注意一個坑平臺對下載鏈接常帶簽名參數(shù)和過期時間。下載大文件最怕兩個小時后 token 過期請求直接返回 403。解決辦法是下載前先判斷 URL 是否還有效無效就重新生成或重新登錄拿新鏈接再繼續(xù)斷點續(xù)傳。4. 把下載好的腦腫瘤 MRI 數(shù)據(jù)整理成能訓(xùn)練的數(shù)據(jù)集NIfTI 讀取、mask 清洗與 H5 導(dǎo)出下載完成只是第一步。原始 NIfTI 文件存在三個問題不同病例的體素間距不一致、四個序列需要按通道合并、mask 標(biāo)簽可能有異常值。這一章按讀取、清洗、導(dǎo)出的順序把數(shù)據(jù)整理成能直接喂給 3D 網(wǎng)絡(luò)的格式。4.1 用 nibabel 讀取 NIfTI 并確認(rèn) shape、像素間距和方向nibabel 是讀取 NIfTI 的標(biāo)準(zhǔn)庫它把影像頭信息和像素數(shù)組分開處理。第一次打開一個病例時我會先打印 shape、zooms 和 affine確認(rèn)數(shù)據(jù)沒有讀歪import nibabel as nib img nib.load(subj_001_t1ce.nii.gz) data img.get_fdata() # 像素數(shù)組shape 通常是 (H, W, D) affine img.affine # 4x4 空間變換矩陣 print(data.shape, data.dtype) print(affine) # 體素間距單位 mm分別是 x/y/z 三個方向 print(img.header.get_zooms())get_fdata()返回 float64 數(shù)組會做一次方向矯正比舊的get_data()更靠譜affine記錄體素坐標(biāo)到解剖坐標(biāo)的映射重采樣和坐標(biāo)對齊都靠它get_zooms()返回三元組比如(0.5, 0.5, 1.0)表示 x、y 方向體素 0.5 mmz 方向 1.0 mm。不同病例的 zooms 不一致時后續(xù)要做重采樣否則同一個網(wǎng)絡(luò)輸入的空間分辨率不統(tǒng)一。4.2 多模態(tài)拼接與 mask 標(biāo)簽清洗同一病例的四個序列是分開的 NIfTI 文件需要按通道合并成一個多維數(shù)組。合并前先確認(rèn)四個序列的空間 shape 一致不一致就要先重采樣。這里給出合并函數(shù)import numpy as np import nibabel as nib seqs [t1, t1ce, t2, flair] def load_multimodal(case_id): volume [] for seq in seqs: path fdata/{case_id}/{case_id}_{seq}.nii.gz volume.append(nib.load(path).get_fdata()) # 把四個序列堆疊到最后一個維度得到 (H, W, D, 4) volume np.stack(volume, axis-1) mask_path fdata/{case_id}/{case_id}_seg.nii.gz mask nib.load(mask_path).get_fdata().astype(np.int32) return volume, mask vol, mask load_multimodal(subj_001) print(np.unique(mask)) # 期望看到 [0, 1, 2, 4]np.stack(..., axis-1)把四個 (H,W,D) 數(shù)組合并成 (H,W,D,4)后面訓(xùn)練時再轉(zhuǎn)成通道在前的 (4,H,W,D) 或按框架要求處理astype(np.int32)是為了讓 mask 成為整數(shù)標(biāo)簽避免浮點 mask 在損失函數(shù)里出現(xiàn)奇怪行為。np.unique(mask)這一步必須做如果看到 3 而不是 4說明標(biāo)簽編碼里有你沒預(yù)料到的類別值。4.3 裁剪、歸一化并導(dǎo)出 H5 訓(xùn)練集模型訓(xùn)練前還需要兩步歸一化和裁剪。MRI 的體素值不是固定的 0 到 255不同掃描儀的強度范圍差異很大直接用原始值訓(xùn)練會讓模型對絕對強度過擬合。常見做法是使用分位數(shù)歸一化再裁剪出包含目標(biāo)區(qū)域的 3D patch。import h5py import numpy as np def normalize(x, low0.01, high0.99): 按分位數(shù)縮放避免個別高亮噪聲把圖像對比度壓沒。 lo, hi np.percentile(x, [low * 100, high * 100]) x (x - lo) / (hi - lo 1e-6) return np.clip(x, 0.0, 1.0) def save_h5(subjects, out_path, target_shape(128, 128, 128)): n len(subjects) with h5py.File(out_path, w) as f: imgs f.create_dataset( images, shape(n, 4, *target_shape), dtypenp.float32, chunks(1, 4, 128, 128, 128), compressiongzip ) lbl f.create_dataset( labels, shape(n, *target_shape), dtypenp.uint8, chunks(1, 128, 128, 128), compressiongzip ) for i, case in enumerate(subjects): vol, mask preprocess_case(case, target_shape) imgs[i] np.transpose(vol, (3, 0, 1, 2)) # 通道在前 lbl[i] mask print(f寫入完成共 {n} 個病例)np.percentile的 low 和 high 參數(shù)決定歸一化的抗噪能力0.01 和 0.99 是比較穩(wěn)的默認(rèn)值如果圖像里增強區(qū)特別亮可以改成 0.02 和 0.98chunks(1,4,128,128,128)讓 H5 按“一個病例”為單位存儲訓(xùn)練時隨機(jī)讀取單個樣本不會把整個文件讀進(jìn)內(nèi)存compressiongzip會壓縮存儲空間但寫盤會變慢磁盤充足時可以去掉。preprocess_case包括重采樣、中心裁剪到target_shape和歸一化這部分邏輯建議單獨維護(hù)一個函數(shù)方便后面替換不同的預(yù)處理策略。5. 腦腫瘤 MRI 數(shù)據(jù)集下載與整理的避坑手冊斷點、限流與標(biāo)注對齊這一章把實際踩過的坑按“現(xiàn)象、原因、解決”寫出來每條都對應(yīng)下載或整理階段一個具體故障。先看現(xiàn)象再對癥處理比翻日志高效得多。5.1 現(xiàn)象下載完解壓到一半報 CRC 錯誤解壓 tar.gz 時提示某個文件 CRC 校驗失敗或者解出來的 .nii.gz 文件大小明顯不對。原因基本是下載過程中網(wǎng)絡(luò)中斷后續(xù)傳沒有生效或者中轉(zhuǎn)存儲把文件切分后重組時出了錯。解決方法是不要信任“下載完成”的提示而是比對發(fā)布方給的文件大小和校驗和。我習(xí)慣在下載腳本里就寫死期望大小下載后立刻校驗不一致就刪除重下而不是留在解壓階段才暴露。5.2 現(xiàn)象并發(fā)下載剛開始就被服務(wù)器返回 403原因有兩個一是鏈接里的簽名參數(shù)過期二是單個 IP 并發(fā)請求數(shù)超過服務(wù)端閾值。一開始我以為 403 是賬號問題反復(fù)登錄浪費時間。后來把并發(fā)線程數(shù)從 16 降到 6同時下載前先打印 URL 里的有效期參數(shù)問題就消失了。解決方法是控制并發(fā)數(shù)并把帶簽名的鏈接當(dāng)成一次性資源拿到鏈接先確認(rèn)過期時間超過一小時的鏈接重新生成別做無效重試。5.3 現(xiàn)象nibabel 打開 .nii.gz 報 header 解析錯誤現(xiàn)象是nib.load()直接報錯或者能打開但get_fdata()返回全零。原因常常是文件本身沒有下載完整讀取了截斷的 gzip 流。我遇到過一種更隱蔽的情況數(shù)據(jù)發(fā)布方把 mask 文件單獨放在另一個壓縮包里目錄結(jié)構(gòu)里存在同名空文件占位下載腳本匹配到了空文件。解決方法是先看文件真實大小0 字節(jié)或遠(yuǎn)小于期望值的直接標(biāo)記為失敗重新從正確路徑下載。5.4 現(xiàn)象T1 和 FLAIR 方向翻轉(zhuǎn)三維疊加后解剖位置對不上現(xiàn)象是同一個病例的 T1 和 FLAIR 都各自能看但疊加到同一個坐標(biāo)系時左右相反或頭腳顛倒。原因多數(shù)是發(fā)布方在轉(zhuǎn)換 DICOM 時沒有統(tǒng)一使用同一個方向約定也可能某個序列被單獨重采樣過。解決方法是繪制前先比對四個序列的affine不一致時用nibabel把目標(biāo)序列重采樣到參考序列的網(wǎng)格上。代碼里可以用nib.progress或者scipy.ndimage.affine_transform做一次空間對齊別直接按數(shù)組下標(biāo)疊圖。5.5 現(xiàn)象mask 取值范圍是 0、1、2、4但代碼只處理了 0、1、2、3這是標(biāo)簽編碼的經(jīng)典坑。數(shù)據(jù)發(fā)布說明寫“3 類標(biāo)注”實際 mask 里的增強腫瘤區(qū)是 4 而不是 3。訓(xùn)練腳本里如果用 3 作為類別數(shù)損失函數(shù)計算時會出現(xiàn) out-of-range 錯誤或者模型學(xué)習(xí)時類別錯位。解決方法是下載后立刻用np.unique(mask)統(tǒng)計每個病例的標(biāo)簽取值發(fā)現(xiàn) 4 就做映射把 4 改成 3再確認(rèn)類別順序和網(wǎng)絡(luò)輸出層一致。這個映射應(yīng)該在預(yù)處理階段統(tǒng)一做不要讓訓(xùn)練循環(huán)去傳一個變種標(biāo)簽。6. 十分鐘驗證下載到手的腦腫瘤 MRI 數(shù)據(jù)集三個自查腳本與保留習(xí)慣數(shù)據(jù)整理完先別急著訓(xùn)練花十分鐘做三個驗證動作。第一個動作是核對文件數(shù)量和總體積寫一個循環(huán)統(tǒng)計目錄下文件數(shù)按文件命名規(guī)則估算病例數(shù)再與發(fā)布說明比對。如果你預(yù)期 500 個病例、預(yù)計 2500 個 .nii.gz實際只有 2400肯定有文件漏下載。第二個動作是隨機(jī)抽 3 個病例打印 NIfTI 的 shape、zooms 和 affine確認(rèn)讀取正常且體素間距落在合理范圍。6.1 文件數(shù)與總體積核對統(tǒng)計腳本很短核心是一行g(shù)lob加stat但能擋住大多數(shù)漏下載問題from pathlib import Path import numpy as np files list(Path(data).rglob(*.nii.gz)) sizes [f.stat().st_size for f in files] print(f文件總數(shù): {len(files)}, 總體積: {np.sum(sizes) / 1024**3:.2f} GB) print(f最小文件: {np.min(sizes) / 1024:.1f} KB, 最大文件: {np.max(sizes) / 1024:.1f} MB)st_size是字節(jié)數(shù)可能直接顯示成以 GB 為單位最小文件如果只有幾 KB基本可以斷定是空殼或占位文件需要重新下載。這里的文件總數(shù)和發(fā)布說明的病例數(shù)乘 5 對不上時優(yōu)先檢查是不是嵌套目錄漏掃了。6.2 隨機(jī)抽樣本讀 header第二個動作是用 numpy 隨機(jī)抽 3 個病例讀一遍 shape 和 zoomsimport random import nibabel as nib cases random.sample(all_cases, 3) for case in cases: img nib.load(fdata/{case}/{case}_t1.nii.gz) print(case, img.shape, img.header.get_zooms())這一步的目的不是看數(shù)值而是確認(rèn)所有病例的 shape 在同一數(shù)量級zooms沒有明顯的異常值。如果發(fā)現(xiàn)某病例 z 方向體素間距是 5 mm其他都是 1 mm那它可能在采集中被壓縮過后續(xù)預(yù)處理時要特別處理而不是直接送進(jìn)網(wǎng)絡(luò)。6.3 跑一次最小預(yù)處理管線第三個動作是拿一個病例跑通預(yù)處理全流程讀取、歸一化、裁剪到目標(biāo)尺寸轉(zhuǎn)成模型輸入張量檢查張量 shape 和標(biāo)簽類別數(shù)。這一步通過后訓(xùn)練腳本的報錯風(fēng)險就大大降低。真正的“訓(xùn)練能跑起來”不需要第一天就完成但“數(shù)據(jù)能正確讀進(jìn)來”應(yīng)該在下載當(dāng)天確認(rèn)。我現(xiàn)在的習(xí)慣是任何腦腫瘤 MRI 數(shù)據(jù)集到手先花半天做這套驗證再進(jìn)入模型開發(fā)。數(shù)據(jù)驗證不是浪費時間它把“下載”和“出結(jié)果”之間的大量不確定性提前排掉。早期我跳過驗證直接訓(xùn)練結(jié)果發(fā)現(xiàn) mask 類別映射錯了整整兩輪實驗回頭改數(shù)據(jù)時模型要重新訓(xùn)時間成本反而翻倍。希望這套下載、整理、驗證的流程能幫到你。本文還有配套的精品資源點擊獲取