nnUNet V2代码——生成dataset_fingerprint.json

前文请见nnUNetv2_plan_and_preprocess命令

阅读nnUNet\nnunetv2\experiment_planning\dataset_fingerprint\fingerprint_extractor.py

文件内只有一个DatasetFingerprintExtractor类,阅读它

在DatasetFingerprintExtractor类内涉及的其他函数都在文章后半部分说明

一. __init__函数

1. 参数

  • dataset_name_or_id:数据集名称或ID
  • num_processes:进程数
  • verbose:是否打印详细信息

2. 过程

定义一些变量,部分如下:

  • dataset_name:数据集名称,例如Dataset001_QQQQ
  • dataset_json:数据集相关信息,是用户创建的,例如:Dataset001_QQQQ/dataset_json
  • dataset:字典类型,{“样例1” : { “images” : {原始图像文件路径列表}, “label” : {分割掩码文件路径列表} }}
  • num_foreground_voxels_for_intensitystats:数据集一共会采样的前景像素数量,用于统计,后续有介绍

二.run函数

1. 参数

2. 过程

获取nnUNet_preprocessed文件夹路径,再创建nnUNet_preprocessed文件夹,最后获取dataset_fingerprint.json文件路径。代码较为清晰,不做粘贴

由上述dataset_fingerprint.json文件路径判断其是否已经存在选择覆写,则载入现有文件并返回。代码较为清晰,不做粘贴

如果fingerprint文件不存在 或 选择覆写,则:

首先获取本次训练使用数据集的读取和写入器(由determine_reader_writer_from_dataset_json函数函数获取,实质是查表,见本文最后)

接下来计算每个样例的前景体素****采样次数,再利用多进程运行analyze_case函数,快速处理数据集多个样例。多进程代码不做粘贴。

从此处继续,results列表存储了每一例数据调用analyze_case函数返回的结果:

results = [i.get()[0] for i in r]

从results列表内提取相关变量,依据这些变量,计算数据集的均值、最值等信息,存入fingerprint变量并写入dataset_fingerprint.json文件

三.analyze_case函数

1. 参数

  • image_files:image
  • segmentation_file:seg
  • reader_writer_class:样例文件读取和写入器
  • num_samples:前景体素采样次数

2. 过程

本函数统计图像大小、体素间距等信息

读取image和seg文件,按照image非零区域对image和seg裁剪,获得以下三个变量:

data_cropped, seg_cropped, bbox = crop_to_nonzero(images, segmentation)

接下来使用collect_foreground_intensities函数收集裁剪后image的统计信息

这些信息包括:

meanmedianminmaxpercentile_99_5percentile_00_5
均值中位数最小值最大值第99.5百分位数第0.5百分位数
foreground_intensities_per_channel, foreground_intensity_stats_per_channel = \
            DatasetFingerprintExtractor.collect_foreground_intensities(seg_cropped, data_cropped,
                                                                       num_samples=num_samples)

获取image体素间距(spacing)、裁剪前后的image大小(shape_before_crop和shape_after_crop)以及裁剪比例(relative_size_after_cropping):

spacing = properties_images['spacing']

shape_before_crop = images.shape[1:]
shape_after_crop = data_cropped.shape[1:]
relative_size_after_cropping = np.prod(shape_after_crop) / np.prod(shape_before_crop)

最后返回上述相关信息:

四.collect_foreground_intensities函数

1. 参数

  • segmentation:seg
  • images:image
  • seed:随机采样种子
  • num_samples:采样数

2. 过程

此函数统计image中seg前景区域内均值、最值等信息

首先进行断言和创建随机数生成器,随机数生成器用于随机采样,代码较为清晰,不做粘贴。

初始化intensities_per_channel和intensity_statistics_per_channel列表,二者分别用于记录随机采取的image前景像素值和image所有采样像素值的均值、最值等信息;去除seg中的空维度,并获取seg中非背景区域,存入foreground_mask变量;定义用于统计百分位数的数组,部分代码没有粘贴:

foreground_mask = segmentation[0] > 0

和去除掩码图的空维度类似,对图像的第一个维度遍历(我使用的数据集是ACDC数据集,此处的image第一个维度和seg第一个维度一样,都是空维度)。for循环开始:

images[i]的shape是channel * height * width;获取images[i]中在seg前景区域内的像素;再利用rs随机采样器对这些像素随机、有放回的采样;

intensities_per_channel.append(
        rs.choice(foreground_pixels, num_samples, replace=True) if num_fg > 0 else [])

由于有些样例的seg并没有前景区域(全是背景,没有前景),所以作者默认均值最值等信息是nan,如果含有前景区域则统计信息并存入intensity_statistics_per_channel变量;

mean, median, mini, maxi, percentile_99_5, percentile_00_5 = np.nan, np.nan, np.nan, np.nan, np.nan, np.nan

其余代码较为清晰,不做粘贴

for循环结束

最后返回上述计算的数据

五.涉及的函数

1. get_filenames_of_train_images_and_targets函数

a. 参数

  • raw_dataset_folder:nnUNet_raw下的数据集文件夹,例如nnunet_raw/Dataset001_QQQQ
  • dataset_json:用户创建的dataset_json

b. 过程

首先是确保成功读取dataset.json文件

如果dataset.json文件中存在dataset键值,则规范化用户定义的文件路径

否则根据raw_dataset_folder文件夹获取正确的数据集内各个样例的文件路径。

最后将数据集各样例标识符(区分样例和样例的)、image文件路径、seg文件路径打包成字典并返回

if 'dataset' in dataset_json.keys():
    dataset = dataset_json['dataset']
    for k in dataset.keys():
        dataset[k]['label'] = os.path.abspath(join(raw_dataset_folder, dataset[k]['label'])) if not os.path.isabs(dataset[k]['label']) else dataset[k]['label']
        dataset[k]['images'] = [os.path.abspath(join(raw_dataset_folder, i)) if not os.path.isabs(i) else i for i in dataset[k]['images']]
else:
    identifiers = get_identifiers_from_splitted_dataset_folder(join(raw_dataset_folder, 'imagesTr'), dataset_json['file_ending'])
    images = create_lists_from_splitted_dataset_folder(join(raw_dataset_folder, 'imagesTr'), dataset_json['file_ending'], identifiers)
    segs = [join(raw_dataset_folder, 'labelsTr', i + dataset_json['file_ending']) for i in identifiers]
    dataset = {i: {'images': im, 'label': se} for i, im, se in zip(identifiers, images, segs)}

2. get_identifiers_from_splitted_dataset_folder函数

a. 参数

  • folder:待读取的文件夹
  • file_ending:样例文件的拓展名

b. 过程

读取文件夹下的所有文件

去除文件名的拓展位和**_XXXX**,例如:QQQQQ001_0000.nii.gz --> QQQQQ001,这样就获取了每个样例的唯一标识名

去重后返回标识名列表

def get_identifiers_from_splitted_dataset_folder(folder: str, file_ending: str):
    files = subfiles(folder, suffix=file_ending, join=False)
    # all files have a 4 digit channel index (_XXXX)
    crop = len(file_ending) + 5
    files = [i[:-crop] for i in files]
    # only unique image ids
    files = np.unique(files)
    return files

3. create_lists_from_splitted_dataset_folder函数

a. 参数

b. 过程

确保identifiers是folder下所有文件的标识名列表

获取folder下所有文件名称,存入files变量

遍历所有标识名,如果符合“标识名 _XXXX.拓展名”的格式,就将其文件路径加入list_of_lists列表

遍历结束返回list_of_lists列表

def create_lists_from_splitted_dataset_folder(folder: str, file_ending: str, identifiers: List[str] = None) -> List[
    List[str]]:
    """
    does not rely on dataset.json
    """
    if identifiers is None:
        identifiers = get_identifiers_from_splitted_dataset_folder(folder, file_ending)
    files = subfiles(folder, suffix=file_ending, join=False, sort=True)
    list_of_lists = []
    for f in identifiers:
        p = re.compile(re.escape(f) + r"_\d\d\d\d" + re.escape(file_ending))
        list_of_lists.append([join(folder, i) for i in files if p.fullmatch(i)])
    return list_of_lists

4. determine_reader_writer_from_dataset_json函数

a. 参数

  • dataset_json_content:内容是dataset.json
  • example_file:数据集的一个数据
  • allow_nonmatching_filename:是否允许不匹配的文件名
  • verbose:是否输出详细信息

b. 过程

判断“overwrite_image_reader_writer”是否在dataset.json文件内设置,就是用户是否指定了文件读写器

如果设置且不为None,则按名称寻找

否则调用determine_reader_writer_from_file_ending函数,按照文件拓展名自动寻找读取器和写入器(实际是查表)

def determine_reader_writer_from_dataset_json(dataset_json_content: dict, example_file: str = None,
                                              allow_nonmatching_filename: bool = False, verbose: bool = True
                                              ) -> Type[BaseReaderWriter]:
    if 'overwrite_image_reader_writer' in dataset_json_content.keys() and \
            dataset_json_content['overwrite_image_reader_writer'] != 'None':
        ioclass_name = dataset_json_content['overwrite_image_reader_writer']
        # trying to find that class in the nnunetv2.imageio module
        try:
            ret = recursive_find_reader_writer_by_name(ioclass_name)
            if verbose: print(f'Using {ret} reader/writer')
            return ret
        except RuntimeError:
            # 略
    return determine_reader_writer_from_file_ending(dataset_json_content['file_ending'], example_file,
                                                    allow_nonmatching_filename, verbose)

5. determine_reader_writer_from_file_ending函数

a. 参数

  • 同determine_reader_writer_from_dataset_json函数

b. 过程

实际是查表,代码不做粘贴

解决一下(nnUNet) root@autodl-container-f45444a064-199bb8a9:/autodl-fs/data/nnU-Net/nnUNet/DATASET/nnUNet_raw# nnUNetv2_plan_and_preprocess -d 501 --verify_dataset_integ rity Fingerprint extraction... Dataset501_LiTS Traceback (most recent call last): File "/root/miniconda3/envs/nnUNet/bin/nnUNetv2_plan_and_preprocess", line 8, in <module> sys.exit(plan_and_preprocess_entry()) File "/root/miniconda3/envs/nnUNet/lib/python3.9/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_entrypoints.py", line 180, in plan_and_preprocess_entry extract_fingerprints(args.d, args.fpe, args.npfp, args.verify_dataset_integrity, args.clean, args.verbose) File "/root/miniconda3/envs/nnUNet/lib/python3.9/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 47, in extract_fingerprints extract_fingerprint_dataset(d, fingerprint_extractor_class, num_processes, check_dataset_integrity, clean, File "/root/miniconda3/envs/nnUNet/lib/python3.9/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 30, in extract_fingerprint_dataset verify_dataset_integrity(join(nnUNet_raw, dataset_name), num_processes) File "/root/miniconda3/envs/nnUNet/lib/python3.9/site-packages/nnunetv2/experiment_planning/verify_dataset_integrity.py", line 191, in verify_dataset_integrity label_manager = LabelManager(dataset_json['labels'], regions_class_order=dataset_json.get('regions_class_order')) File "/root/miniconda3/envs/nnUNet/lib/python3.9/site-packages/nnunetv2/utilities/label_handling/label_handling.py", line 24, in __init__ self._sanity_check(label_dict) File "/root/miniconda3/envs/nnUNet/lib/python3.9/site-packages/nnunetv2/utilities/label_handling/label_handling.py", line 53, in _sanity_check raise RuntimeError('Background label not declared (remember that this should be label 0!)') RuntimeError: Background label not declared (remember that this should be label 0!)
06-30
jzuser@vpc87-3:~/Work_dir/Gn/pystudy/NnuNet/nnUNet_raw/Dataset003_Liver$ nnUNetv2_plan_and_preprocess -d 3 --verify_dataset_integrity Fingerprint extraction... Dataset003_Liver Traceback (most recent call last): File "/home/jzuser/.local/bin/nnUNetv2_plan_and_preprocess", line 8, in <module> sys.exit(plan_and_preprocess_entry()) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_entrypoints.py", line 173, in plan_and_preprocess_entry extract_fingerprints(args.d, args.fpe, args.npfp, args.verify_dataset_integrity, args.clean, args.verbose) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 46, in extract_fingerprints extract_fingerprint_dataset(d, fingerprint_extractor_class, num_processes, check_dataset_integrity, clean, File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 29, in extract_fingerprint_dataset verify_dataset_integrity(join(nnUNet_raw, dataset_name), num_processes) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/verify_dataset_integrity.py", line 140, in verify_dataset_integrity assert all([i in dataset_keys for i in required_keys]), 'not all required keys are present in dataset.json.' \ AssertionError: not all required keys are present in dataset.json. Required: ['labels', 'channel_names', 'numTraining', 'file_ending'] Present: ['name', 'description', 'reference', 'licence', 'release', 'modality', 'labels', 'numTraining', 'numTest', 'file_ending', 'training', 'test'] Missing: ['channel_names'] Unused by nnU-Net: ['name', 'description', 'reference', 'licence', 'release', 'modality', 'numTest', 'training', 'test']检查结果如上
08-20
jzuser@vpc87-3:~/Work_dir/Gn/pystudy/NnuNet$ nnUNetv2_plan_and_preprocess -d 3 -np 4 Fingerprint extraction... Traceback (most recent call last): File "/home/jzuser/.local/bin/nnUNetv2_plan_and_preprocess", line 8, in <module> sys.exit(plan_and_preprocess_entry()) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_entrypoints.py", line 173, in plan_and_preprocess_entry extract_fingerprints(args.d, args.fpe, args.npfp, args.verify_dataset_integrity, args.clean, args.verbose) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 46, in extract_fingerprints extract_fingerprint_dataset(d, fingerprint_extractor_class, num_processes, check_dataset_integrity, clean, File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 25, in extract_fingerprint_dataset dataset_name = convert_id_to_dataset_name(dataset_id) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/utilities/dataset_name_id_conversion.py", line 48, in convert_id_to_dataset_name raise RuntimeError(f"Could not find a dataset with the ID {dataset_id}. Make sure the requested dataset ID " RuntimeError: Could not find a dataset with the ID 3. Make sure the requested dataset ID exists and that nnU-Net knows where raw and preprocessed data are located (see Documentation - Installation). Here are your currently defined folders: nnUNet_preprocessed=/home/jzuser/Work_dir/Gn/pystudy/NnuNet/nnUNet_preprocessed nnUNet_results=/home/jzuser/Work_dir/Gn/pystudy/NnuNet/nnUNet_results nnUNet_raw=/home/jzuser/Work_dir/Gn/pystudy/NnuNet/nnUNet_raw If something is not right, adapt your environment variables.
08-15
进行上述修改后依然报错如下jzuser@vpc87-3:~/Work_dir/Gn/pystudy/NnuNet/nnUNet_raw/Dataset003_Liver$ nnUNetv2_plan_and_preprocess -d 3 --verify_dataset_integrity Fingerprint extraction... Dataset003_Liver Traceback (most recent call last): File "/home/jzuser/.local/bin/nnUNetv2_plan_and_preprocess", line 8, in <module> sys.exit(plan_and_preprocess_entry()) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_entrypoints.py", line 173, in plan_and_preprocess_entry extract_fingerprints(args.d, args.fpe, args.npfp, args.verify_dataset_integrity, args.clean, args.verbose) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 46, in extract_fingerprints extract_fingerprint_dataset(d, fingerprint_extractor_class, num_processes, check_dataset_integrity, clean, File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/plan_and_preprocess_api.py", line 29, in extract_fingerprint_dataset verify_dataset_integrity(join(nnUNet_raw, dataset_name), num_processes) File "/home/jzuser/.local/lib/python3.10/site-packages/nnunetv2/experiment_planning/verify_dataset_integrity.py", line 157, in verify_dataset_integrity assert len(training_identifiers) == expected_num_training, 'Did not find the expected number of training cases ' \ AssertionError: Did not find the expected number of training cases (131). Found 134 instead. Examples: ['._li' '._liv' '._live' 'liver_0' 'liver_1']
08-20
<think>首先,用户的问题是:“dataset_corpus.json如何生成”,意思是“如何生成dataset_corpus.json”。 我需要用中文回答这个问题,因为用户指定了“请使用中文回答问题”。 回答完后,我必须输出“§§相关问题§§”,然后提出3-5个相关问题。这些问题必须基于用户的问题和我的回答。 关键是理解“dataset_corpus.json”。这看起来像是一个用于数据集的文件,但在上下文中,它可能与之前的对话相关。回顾对话历史: - 第一个用户查询是关于安装faiss-gpu-cu12的错误。 - 我的第一个回答解决了那个错误,并提出了相关问题。 - 第二个用户查询是关于分析Poetry命令:poetry lock 和 poetry update。 - 我的第二个回答解释了那些命令,并提出了相关问题。 现在,用户问“dataset_corpus.json如何生成”。这似乎是一个新话题,可能与之前无关。但在上下文中,文件名“dataset_corpus.json”可能指的是一个数据集文件,通常用于语言模型或搜索系统中,比如可能是用于FAISS索引的语料库文件。 在第一个回答中,我讨论了FAISS,这是一个用于高效相似性搜索的库。FAISS通常需要一个数据集(语料库)来构建索引。所以,“dataset_corpus.json”可能就是这个语料库文件。 用户可能在问如何生成这样一个文件用于FAISS或其他目的。 我需要提供一个清晰的中文回答。 可能的步骤来生成dataset_corpus.json: 1. **定义语料库**: 确定数据来源,比如文本数据、图像特征等。 2. **收集数据**: 从数据库、文件中收集数据。 3. **预处理数据**: 清洗、规范化数据;对于文本,可能包括分词、去除停用词等。 4. **转换格式**: 将数据转换为JSON格式。JSON可能包含数组或对象,每个条目代表一个文档或数据点。 - 例如:{"documents": [{"id": 1, "text": "sample text"}, ...]} 5. **保存文件**: 使用编程语言如Python来写入JSON文件。 示例代码: ```python import json # 假设有一个文档列表 documents = [ {"id": 1, "text": "这是第一个文档。"}, {"id": 2, "text": "这是第二个文档。"}, # 添加更多文档 ] # 写入JSON文件 with open('dataset_corpus.json', 'w', encoding='utf-8') as f: json.dump({"documents": documents}, f, ensure_ascii=False, indent=4) ``` 在FAISS上下文中,这个文件可能用于创建向量索引。 现在,回答结构: - 用中文解释步骤。 - 提供示例代码- 然后,输出“§§相关问题§§”并提出3-5个相关问题。 相关问题应该基于用户的问题和我的回答: 1. 如何从文本文件或数据库中提取数据来生成语料库? 2.生成JSON文件时,如何处理大量数据以避免内存问题? 3. 如何使用FAISS基于这个JSON文件建立索引? 4. 如何验证生成JSON文件是否格式正确? 5. 有哪些工具或库可以自动化数据预处理? 确保问题数量在3-5个。 完整回答: - 先回答问题。 - 然后“§§相关问题§§”。 - 问题列表。 </think>### 如何生成 `dataset_corpus.json` 文件 `dataset_corpus.json` 是一个常见的 JSON 格式数据集文件,通常用于存储文本语料库(如文档、句子或其他结构化数据),广泛应用于自然语言处理(NLP)任务(如训练语言模型、构建搜索索引)。以下是生成该文件的详细步骤和示例代码: #### 生成步骤 1. **数据收集**:从源头获取数据,如: - 文本文件(TXT、CSV) - 数据库(SQL、MongoDB) - API 或网页爬取 - 示例:收集1000篇新闻文章文本。 2. **数据预处理**:清洗和标准化数据,确保格式统一: - 去除无关字符、HTML标签 - 分词、去除停用词 - 统一编码(如 UTF-8) 3. **数据结构设计**:定义 JSON 文件结构,常见格式包括: - **列表形式**:数组包含多个文档对象。 ```json [ {"id": 1, "text": "文档1内容..."}, {"id": 2, "text": "文档2内容..."} ] ``` - **键值对形式**:对象包含元数据和文档列表。 ```json { "metadata": {"source": "news", "version": "1.0"}, "documents": [ {"id": 1, "content": "文档1内容..."}, {"id": 2, "content": "文档2内容..."} ] } ``` 4. **代码实现生成**:使用 Python(推荐)或其他编程语言写入 JSON 文件。 **示例代码**: ```python import json # 步骤1: 模拟数据收集(实际中替换为真实数据源) documents = [ {"id": 1, "text": "示例文本1"}, {"id": 2, "text": "示例文本2"} ] # 步骤2: 定义数据结构 corpus_data = { "description": "示例语料库", "documents": documents } # 步骤3: 写入JSON文件 with open('dataset_corpus.json', 'w', encoding='utf-8') as f: json.dump(corpus_data, f, ensure_ascii=False, indent=4) # ensure_ascii=False支持中文 print("文件已生成: dataset_corpus.json") ``` 5. **验证与优化**: - 使用工具验证 JSON 格式(如 [JSONLint](https://jsonlint.com/))。 - 优化:分批处理大数据(使用 `json.dump` 迭代写入)。 - 集成到工作流:如结合 FAISS 索引构建(需先将文本转换为向量)。 #### 注意事项 - **文件大小**:对于大数据集(>1GB),使用分批处理或数据库导出工具。 - **工具替代**:可用命令行工具生成,如 `jq` 或 pandas 库导出: ```bash pandas 示例:df.to_json('dataset_corpus.json', orient='records') ``` - **典型应用**:在 RAG 系统中,此文件可作为 FAISS 索引的输入源。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十凯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值