前言:
大部分人开始使用nnU-Net时,总会出现各种报错以及很多问题,本人在使用nnU-Net时,经历了下面几种报错,以及其对应的解决办法。建议大家建一个新的环境专门用来使用nnUnet,避免各种稀奇古怪的报错。标题中的报错可直接查看第四章节。
目录
一、设备说明及环境安装配置
设备说明:GPU采用的RTX3060,显存12G。
操作系统:Windows
CUDA:12.2
内存:32G
tip:cuda版本未必一定要一样,12.0也可以。但内存和显存最好大点。
二、anaconda环境配置及安装。
1、创建对应的环境。
教程使用anaconda对环境进行配yuanquanyi首先打开Anaconda Powershell,然后输入以下指令创建对应的环境。(下面所有的指令的中,红色标注指令或文件夹名称为本人的文件夹名称或路径等,需要根据你创建的情况进行修改,指令中黑色部分建议保持一致)。
conda activate -n segNNUnet python=3.9:表示创建了一个名字为segNNUnet的环境,python版本为3.9。(建议python版本别太低,曾经尝试过3.8版本,会报错)。
conda create -n segNNUnet python=3.9
2、下载pytorch包
①首先激活刚刚创建的环境。
指令为:
conda activate segNNUnet
进入到下面的界面表示已经进入到刚刚创建的环境中了。
②下载pytorch等包。
在pytorch官网上找出下面的界面,根据你的cuda版本和想要的pytorch版本,然后复制粘贴到刚刚的环境窗口。
(我下载的时pytorch版本时2.0.0,cuda用的是11.8,cuda版本可以向下兼容,我电脑cuda是12.2,我可以用12.1,12.0。。。等,但是无法使用12.3版本,我用的pip)。
指令如下:
pip install torch==2.0.0 torchvision==0.15.1 torchaudio==2.0.1 --index-url https://download.pytorch.org/whl/cu118
三、nnUnet资源下载
1、创建代码文件夹
①创建项目文件夹
直接创建一个文件夹,然后用pycharm打开。我创建的是nnUnet_Seg文件夹。
②选择解释器
选择解释器为刚刚创建的环境(我创建的是segNNUnet)。(本人使用的是pycharm2024版,不同版本之间,操作可能略有不同)
2、测试基本环境
在该文件夹下面新建一个test.py文件(该文件只是为了测试,该步骤不做强求,可跳过)。如图所示,表示基本环境安装完成。
import torch
if __name__ == '__main__':
# 查看cuda是否可用
print(torch.cuda.is_available())
# 返回当前设备索引
print(torch.cuda.current_device())
# 返回GPU的数量
print(torch.cuda.device_count())
# 返回gpu的名字,设备索引默认从0开始
print(torch.cuda.get_device_name(0))
3、进入到pycharm终端界面。
在pycharm软件中点击终端,查看是否进入了刚刚创建的环境,如果没有进入,就输入conda activate segNNUnet,进入该环境。
4、复制下面三条指令。
复制下面三条指令,然后粘贴到pycharm终端中运行。下面三条命令作用分别是将github上面的代码拉去到本地文件夹中、进入到nnUNet文件夹、安装所有的包。
git clone https://github.com/MIC-DKFZ/nnUNet.git
cd nnUNet
pip install -e .
最后一条指令执行过后可能会有报错,建议nnunetv2用2.3.1,这是正常的,如果不是对最新版本有要求,我推荐使用2.3.1,是没有问题的。安装2.3.1版本采用下面指令:
pip install nnunetv2==2.3.1
四、数据集创建及处理
1、创建dataset的文件夹。
文件夹目录树为:
D:\101_Python\nnUet_Seg
│── nnUNet
│
│── test.py
│
在刚刚的nnUNet文件夹下面创建三个文件夹,名称分别是:nnUNet_preprocessed、nnUNet_raw、nnUNet_results。名称必须是这三个。
新建之后的目录树为:
D:\101_Python\nnUet_Seg
│── test.py
│── nnUNet
├── nnunetv2
├── .git/
├── .github/
├── documentation/
├── nnUNet_preprocessed/
├── nnUNet_raw/
├── nnUNet_results/
├── nnunetv2/
├── .gitignore
├── LICENSE
├── pyproject.toml
├── readme.md
└── setup.py
2、创建自己的数据集
(本步是使用自己的数据集进行的操作。若用的是nnUnet的官方数据集,按照官方指定的格式进行操作后,直接跳转到第三步即可)
①创建数据文件夹
在nnUNet_raw文件夹里新建一个文件夹Task520_trueLumen。(格式要求:Task***_name,格式必须是Task开头,有3位数字,后面的名称可以任意,建议数字在500以上,若1,2等这种,容易与已有的冲突,导致报错)。在Task520_trueLumen文件夹中新建3个文件夹和一个json文件。
imagesTr:存放的是训练的图像数据
imagesTs:存放的是测试的图像数据
labelsTr:存放的是训练的标签数据
文件的目录树如下:
D:\101_Python\nnUet_Seg\nnUNet\nnUNet_raw\Task520_trueLumen
├── imagesTr/
├── imagesTs/
├── labelsTr/
└── dataset.json
②创建json文件
json数据格式如下:
{
"name": "Task520_trueLumen",
"description": "Use nnUent to mark true and false lumen",
"tensorImageSize": "3D",
"reference": "area",
"licence": "",
"modality": {
"0": "CT"
},
"file_ending": ".nii.gz",
"overwrite_image_reader_writer": "SimpleITKIO",
"labels": {
"0": "background",
"1": "true_lumen",
"2": "false_lumen"
},
"numTraining": 1,
"numTest": 0,
"training": [
{
"image": "./imagesTr/947938.nii.gz",
"label": "./labelsTr/947938.nii.gz"
}
],
"test": [
]
}
重点关注:
tensorImageSize:数据的维度,是3D的还是2D的
modality:模态,是CT的还是MRI的
labels:具体的label是几个类别,类别值是多少,需与你的标签进行对应,我是做三个类别:分别是背景,真腔,假腔,分别对应是0,1,2。如果你做的是分割某一个器官,应为两个类别:背景、器官。
numTraining:训练数据的数量,测试数据数量同理
training:训练数据的文件路径,(若都是按照我之前的操作过程,只需修改文件名称即可),但要与训练的数据的数量严格对应。测试数据路径同理。
3、添加电脑的环境变量:
在电脑设置-.>输入环境变量,点击编辑系统环境变量->环境变量->新建。
然后将刚刚创建的三个文件夹名称(nnUNet_preprocessed、nnUNet_raw、nnUNet_results)和路径输入进去如图。然后点击确定。最后最好重启一下电脑,保证环境变量生效。
4、转换数据集
方法一:指令输入(官方给出的操作)
路径要修改成你自己的。输入以下指令:
nnUNetv2_convert_MSD_dataset -i D:\101_Python\nnUet_Seg\nnUNet\nnUNet_raw\Task520_trueLumen
问题:因为我使用这条指令时,会出现以下错误,所以采用的是方法二,如果有大佬知道如何解决这个问题,欢迎在评论区给出解答。
'nnUNetv2_convert_MSD_dataset' 不是内部或外部命令,也不是可运行的程序或批处理文件。
个人推测是因为没有下面这个文件的原因,导致对应指令无法识别。
方法二:运行py脚本命令
在pycharm终端运行代码:其实就是运行py文件,但是可以加上对应的参数。下面这行命令的意思是:在D:\101_Python\nnUet_Seg/nnUNet/nnunetv2/dataset_conversion路径下运行convert_MSD_dataset.py这个python文件,同时将后面的参数传入进去。
python D:\101_Python\nnUet_Seg/nnUNet/nnunetv2/dataset_conversion/convert_MSD_dataset.py -i D:\101_Python\nnUet_Seg/nnUNet/nnUNet_raw/Task520_trueLumen
这个方法跟方法一基本差不多,但是在我的电脑上就是无法使用方法一,但是用方法二和方法三都是可以的。
方法三:运行py代码
①找到convert_MSD_dataset.py文件
找到nnunetv2文件->dataset_conversion文件夹->convert_MSD_dataset.py文件。
如图所示。
②修改代码
找到最后一行代码,然后修改括号中的内容,将第一个参数修改成之前存放数据集文件夹的路径,第二个参数修改成对应的id。(是nnUNet_raw文件夹下面的Task***_name文件夹路径,我的就是Task520_trueLumen这个文件夹路径,id就是520)。然后点击运行即可。
if __name__ == '__main__': convert_msd_dataset('/home/fabian/Downloads/Task05_Prostate', overwrite_target_id=201)
如果运行报错:这是因为你输入的id与已有的冲突了,更换id就好了。
File "D:\101_Python\nnUet_Seg\nnUNet\nnunetv2\dataset_conversion\convert_MSD_dataset.py", line 62, in convert_msd_dataset
assert len(existing_datasets) == 0, f"Target dataset id {target_id} is already taken, please consider changing " \
AssertionError: Target dataset id 520 is already taken, please consider changing it using overwrite_target_id. Conflicting dataset: ['Dataset520_trueLumen'] (check nnUNet_results, nnUNet_preprocessed and nnUNet_raw!)
结果:
运行成功后,会出现一个Data520_tureLumen文件夹,这个文件夹名字一定是Data开头,数字就是你输入的id。
在Dataset520_trueLumen文件夹下面是如下的内容。
imagesTr文件夹里面会有_0000命名的文件。
5、数据集预处理
方法一:指令输入(官方给出的操作)
输入以下指令,这里的520需要修改成你自己设置的id,与前面的保持一致。
nnUNetv2_plan_and_preprocess -d 520 --verify_dataset_integrity
我一直使用的都是代码运行的版本,还是因为类似的报错:
'nnUNetv2_plan_and_preprocess' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
方法二:运行py脚本命令
与之前的相同,找到对应需要运行的文件,将参数传入进入,这部分可能会报一些错误,可查看方法三后的解释。这里还有一个点需要注意,要将plan_and_preprocess_entrypoints.py这个文件中的plan_and_preprocess_entry()参数值修改一下。如图所示,值修改成你的电脑显存大小。若不修改会报错:
self.get_plans_for_configuration(fullres_spacing_transposed, File "/opt/conda/lib/python3.9/site-packages/nnunetv2/experiment_planning/experiment_planners/default_experiment_planner.py", line 316, in get_plans_for_configuration (self.UNet_vram_target_GB / self.UNet_reference_val_corresp_GB) TypeError: unsupported operand type(s) for /: 'NoneType' an
python D:\101_Python\nnUet_Seg/nnUNet/nnunetv2/experiment_planning/plan_and_preprocess_entrypoints.py -d 520 --verify_dataset_integrity
方法三:运行py文件
①找到plan_and_preprocess_entrypoints.py文件
nnunetv2文件夹->experiment_planning文件夹->plan_and_preprocess_entrypoints.py文件
②修改代码
在上面的py文件中找到这个函数:plan_and_preprocess_entry()
将下面两个参数行默认值添加一下(本来没有默认值的)。第一个参数值修改成你设置的id,第二个参数设置成你电脑的gpu显存即可,单位默认是G。
def plan_and_preprocess_entry():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', nargs='+', type=int,default=[520],
help="[REQUIRED] List of dataset IDs. Example: 2 4 5. This will run fingerprint extraction, experiment "
"planning and preprocessing for these datasets. Can of course also be just one dataset")
parser.add_argument('-gpu_memory_target', default=8, type=float, required=False,
help='[OPTIONAL] DANGER ZONE! Sets a custom GPU memory target (in GB). Default: None (=Planner '
'class default is used). Changing this will '
'affect patch and batch size and will '
'definitely affect your models performance! Only use this if you really know what you '
'are doing and NEVER use this without running the default nnU-Net first as a baseline.')
问题:若在运行时,一开始的报错是下面之中情况,可以安装一下blosc2这个库,后面若还有报错等,可继续安装。(这个解决办法本人不是很确定,我在安装完成后再修改就可以成功运行代码)
File "E:\Anaconda_enviro\segNNUnet\lib\site-packages\acvl_utils\cropping_and_padding\bounding_boxes.py", line 5, in <module> import blosc2
在安装blosc2后可能还会出现下面两个报错:
File "/opt/conda/lib/python3.9/site-packages/nnunetv2/preprocessing/preprocessors/default_preprocessor.py", line 23, in <module> from nnunetv2.preprocessing.cropping.cropping import crop_to_nonzero File "/opt/conda/lib/python3.9/site-packages/nnunetv2/preprocessing/cropping/cropping.py", line 5, in <module> from acvl_utils.cropping_and_padding.bounding_boxes import get_bbox_from_mask, crop_to_bbox, bounding_box_to_slice ImportError: cannot import name 'crop_to_bbox' from 'acvl_utils.cropping_and_padding.bounding_boxes' (/opt/conda/lib/python3.9/site-packages/acvl_utils/cropping_and_padding/bounding_boxes.py)
ERROR: Could not find a version that satisfies the requirement blosc2>=3.0.0b4 (from acvl-utils) (from versions: 0.1.1, 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8, 0.1.9, 0.1.10, 0.2.0, 0.3.0, 0.3.1, 0.3.2, 0.4.0, 0.4.1, 0.5.1, 0.5.2, 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.6.5, 0.6.6, 2.0.0, 2.1.0, 2.1.1, 2.2.0, 2.2.1, 2.2.2, 2.2.3, 2.2.4, 2.2.5, 2.2.6, 2.2.7, 2.2.8, 2.2.9, 2.3.0, 2.3.1, 2.3.2, 2.4.0, 2.5.0, 2.5.1)
ERROR: No matching distribution found for blosc2>=3.0.0b4
解决办法:安装acvl-utils的版本为0.2,即可保证代码运行成功,指令如下:
pip install -U acvl-utils==0.2
若没有修改第一个会出现下面的报错:
File "E:\Anaconda_enviro\segNNUnet\lib\site-packages\acvl_utils\cropping_and_padding\bounding_boxes.py", line 5, in <module> import blosc2
若没有修改第一个会出现下面的报错:
File "C:\Users\123\AppData\Roaming\Python\Python39\site-packages\nnunetv2\experiment_planning\experiment_planners\default_experiment_planner.py", line 316, in get_plans_for_configuration
(self.UNet_vram_target_GB / self.UNet_reference_val_corresp_GB)
TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'
在处理完所有的报错信息之后,进入代码的数据处理阶段,这个数据处理需要较长的时间,(建议喝杯卡布奇诺,顺便休息一小会 --_-- )。
结果:
运行成功之后,你的运行效果下面这样的情况。
在文件夹下面会出现对应的Data开头的文件夹。
文件的内容如下:
五、训练网络
1、修改训练的epoch数:
在文件中nnUNet文件夹->nnunetv2文件夹->training文件夹->nnUNetTrainer文件夹->nnUNetTrainer.py文件中,修改self.num_epochs的值。
可能未必会生效,建议在另一个文件中也修改一下。找到你创建的环境目录。我这个环境名称是nnU-Net。
也可能找不到Lib文件夹中的site-packages文件夹,可能在C盘中的这个路径下。我的就是这个路径下面。
2、开始训练
方法一:指令输入(官方给出的操作)
路径要修改成你自己的。输入以下指令:
nnUNetv2_train 4 2d 0 :
4代表你的数据id号,
2d表示进行2d的训练,可选用的参数有2d、3d_fullres(3D全分辨率)、3d_lowres(3D低分辨率)
0代表进行1层交叉验证,值在0-4之间。
3d_cascade_fullres:代表级联。不是所有的数据集都支持级联。
nnUNetv2_train 4 2d 0
nnUNetv2_train 4 2d 4nnUNetv2_train 4 3d_fullres 0
nnUNetv2_train 4 3d_fullres 4
nnUNetv2_train 1 3d_lowres 0
nnUNetv2_train 1 3d_lowres 4
nnUNetv2_train 1 3d_cascade_fullres 0nnUNetv2_train 1 3d_cascade_fullres 4
方法二:通过运行对应的py脚本
在命令行终端输入以下指令:参数传递与方法一相同。
python D:/101_Python/nnUet_Seg/nnUNet/nnunetv2/run/run_training.py 520 3d_fullres 4
可能会报以下的错误:
Traceback (most recent call last):
File "/home/nnUnet/nnUNet/nnunetv2/run/run_training.py", line 277, in <module>
os.environ['TORCHINDUCTOR_COMPILE_THREADS'] = 1
File "/opt/conda/lib/python3.9/os.py", line 684, in __setitem__
value = self.encodevalue(value)
File "/opt/conda/lib/python3.9/os.py", line 756, in encode
raise TypeError("str expected, not %s" % type(value).__name__)
TypeError: str expected, not int
找到run_training.py文件,然后将文件中的内容修改成下面这样即可。
结果:
出现下面的显示表示正在训练:
六、预测
方法一:指令输入(官方给出的操作)
-d:后面是数据id号
-i:后面是需要分割的原始数据的文件夹路径
-o:模型预测的结构输出的文件夹路径
-f:采用第几折交叉的结果,有0,1,2,3,4这五种选择,前提是你这个五个都训练过
-c:可供选择的有2d、3d_fullres、3d_lowers
nnUNetv2_predict -d 520 -i nnUNet_raw/Dataset520_trueLumen/imagesTs -o nnUNet_results/3d -f 4 -tr nnUNetTrainer -c 3d_fullres -p nnUNetPlans
方法二:通过运行对应的py脚本
1、找到predict_from_raw_data.py文件
找到nnUNet文件夹->nnunetv2文件夹->inference文件夹->predict_from_raw_data.py文件
2、修改代码
①:训练时的结果,里面有对应的权重
②:采用的是第几折验证
③:采用的哪个权重,有最后一轮的权重和效果最好的权重
('checkpoint_best.pth', 'checkpoint_best.pth')
④:存放原始数据的文件夹路径(文件以nii.gz格式保存,后面以_0000名称结尾)
⑤:存放模型输出结果的文件夹
3、运行代码:
python D:/101_Python/nnUet_Seg/nnUNet/nnunetv2/inference/predict_from_raw_data.py