机器学习建模

本节介绍如何使用 HABIT 进行机器学习建模,包括特征选择、模型训练和模型评估。

使用场景

在 HABIT 中,机器学习通常有两种主要使用场景:

1. 训练场景 (Train Mode)
  • 目的:基于已有的带标签数据(如良恶性、生存期等),通过特征筛选和算法拟合,构建预测模型。

  • 操作:使用训练配置(MLConfig)运行 habit model --mode train

2. 预测场景 (Predict Mode)
  • 目的:将训练好的模型应用于全新的、未见过的数据,获取预测结果(如 Radscore)。

  • 操作:使用预测配置(PredictionConfig)运行 habit model --mode predict,并在配置中指定 model_pathdata_path

概述

机器学习建模是生境分析的最终步骤,使用提取的生境特征进行预测模型训练和评估。

备注

在开始之前,请确保您的数据已整理为 CSV 或 Excel 格式,且您已清楚哪一列是 ID,哪一列是标签(Label)。HABIT 会根据文件后缀自动识别格式。

核心指标说明

在 HABIT 的机器学习结果中,经常会遇到以下核心指标:

1. Radscore (影像组学评分)

  • 定义: Radscore 是机器学习模型(如 Logistic Regression, Random Forest 等)对每个样本计算出的预测概率或线性组合得分。

  • 意义: 它代表了影像特征与目标标签(如恶性程度)之间的相关性强度。Radscore 越高,通常代表样本属于阳性类别的概率越大。

  • 输出: 在预测结果文件中,概率列(由 output_prob_col 指定)可作为对应模型的 Radscore。

如何训练融合模型

在医学影像研究中,"融合模型"(Fusion Model)通常指结合了**影像特征(如 Radscore)**和**临床特征**的模型。

训练融合模型通常有两种方式:

方式 1:早期融合 (Early Fusion) - 推荐

将生境特征(Habitat Features)与临床特征(Clinical Features)在进入模型前直接进行表格合并。

  1. 准备影像特征: 运行生境特征提取,导出 CSV。

  2. 准备临床特征: 准备包含相同 PatientID 的临床特征 CSV/Excel。

  3. 合并表格: 使用 CSV 合并工具 (habit merge-csv) 按 ID 合并,得到单一融合特征表。

  4. 训练模型: 在 habit model 配置中,将合并后的表写入 input 列表,按常规流程训练模型。

方式 2:晚期融合 (Late Fusion)

分别训练影像模型和临床模型,再对两者的预测概率进行融合(加权平均或训练 Meta-Model)。

  1. 训练影像模型: 得到影像模型在训练集/验证集的预测分数(Radscore)。

  2. 训练临床模型: 得到临床模型在训练集/验证集的预测分数。

  3. 融合分数: 将两个分数合并为新的特征表,再训练一个简单模型(如 Logistic Regression)作为 Meta-Model。

严格的训练集控制(避免数据泄露)

  • 融合所用的特征或分数必须来自训练集内部的流程。

  • 早期融合时,特征选择与模型训练应在训练集内完成;测试集仅用于最终评估。

  • 晚期融合时,融合权重或 Meta-Model 只能用训练集拟合,测试集只能用已固定的权重或模型进行推断。

推荐做法:

大多数研究推荐使用**方式 1**,因为它能让模型自动学习影像特征与临床特征之间的交互关系。您可以利用 HABIT 的特征选择模块(如 LASSO)自动从融合后的特征空间中挑选出最有意义的特征子集。

早期融合示例:多数据源就是多张表合并

本质上和常规机器学习一样,只是把多个数据源(影像特征、临床信息、实验室指标等)合并成一张表再训练。

示例数据文件:

  • habitat_features.csv: 影像/生境特征表

  • clinical_features.csv: 临床特征表

  • lab_features.csv: 实验室指标表

表头示例(每张表都必须包含相同的 ID 列):

PatientID

Feature_A

Feature_B

...

sub-001

1.23

4.56

...

sub-002

2.34

5.67

...

合并步骤:

  1. 使用 CSV 合并工具 (habit merge-csv) 依次合并三张表,按 PatientID 对齐。

  2. 得到融合后的 `fusion_features.csv`(包含所有特征 + Label)。

融合后的表头示例:

PatientID

Label

Habitat_F1

Habitat_F2

Clinical_Age

Lab_CRP

...

sub-001

1

0.12

0.34

56

2.1

...

sub-002

0

0.45

0.78

63

5.4

...

训练配置示例(与常规机器学习完全一致):

input:
  - path: ./demo_data/ml_data/fusion_features.csv
    subject_id_col: PatientID
    label_col: Label
output: ./results/ml/train

数据准备指南

这是医生用户最关心的部分。您的输入数据应为一个标准的表格文件,HABIT 支持以下格式:

  • CSV 文件 (.csv)

  • Excel 文件 (.xlsx, .xls)

HABIT 会根据文件后缀自动识别格式。

表格文件示例 (data.csv 或 data.xlsx):

PatientID

Label

Feature_1

Feature_2

...

Feature_N

sub-001

0

12.5

0.45

...

102.3

sub-002

1

14.2

0.67

...

98.1

sub-003

2

11.8

0.33

...

105.4

关键要求:

  1. ID 列 (PatientID): 每一行代表一个病人,ID 必须唯一。

  2. 标签列 (Label): 您要预测的目标。 * 二分类: 通常用 0 (阴性/良性) 和 1 (阳性/恶性) 表示。 * 多分类: 支持 3 个及以上类别,如 0 (良性), 1 (低度恶性), 2 (高度恶性)。HABIT 会自动检测并计算多分类指标(Macro-Average)。 * 回归: 可以是连续数值(如生存时间)。

  3. 特征列: 除了 ID 和 Label 外的其他列,HABIT 会自动将其识别为特征用于训练。

  4. 无中文: 表头和内容尽量避免中文,以免出现编码错误。

如何在配置文件中指定列名?

您需要在数据配置文件(通常是 files_ml.yaml 或直接在主配置中)指定:

# 方式1:CSV文件
- path: ./demo_data/ml_data/clinical_feature.csv
  subject_id_col: PatientID
  label_col: Label

# 方式2:Excel文件
- path: ./demo_data/ml_data/clinical_feature.xlsx
  subject_id_col: PatientID
  label_col: Label

HABIT 提供了完整的机器学习工作流程:

  • 特征选择: 选择最相关的特征

  • 模型训练: 训练各种机器学习模型

  • 模型评估: 评估模型性能

  • 模型保存: 保存训练好的模型

  • 模型预测: 使用训练好的模型进行预测

支持的模型类型:

  • 传统机器学习模型: 逻辑回归、随机森林、SVM、KNN 等

  • 集成学习模型: XGBoost、LightGBM、AutoGluon 等

  • 深度学习模型: 神经网络(可选)

Pipeline 机制:

HABIT 使用 scikit-learn 的 Pipeline 机制,确保特征选择、模型训练等步骤在交叉验证中正确应用,避免数据泄露。

CLI 使用方法

基本语法:

habit model --config <config_file> [--mode <mode>]

参数说明:

  • --config, -c: 配置文件路径(必需)

  • --mode, -m: 运行模式(train 或 predict),覆盖配置文件中的设置

使用示例:

# 训练模式
habit model --config ./demo_data/config_machine_learning.yaml --mode train

# 预测模式
habit model --config ./demo_data/config_machine_learning.yaml --mode predict

输出:

训练好的模型和评估结果将保存在配置文件中指定的输出目录。

Python API 使用方法

基本用法:

from habit.core.common.service_configurator import ServiceConfigurator
from habit.core.machine_learning.config_schemas import MLConfig

# 加载配置
config = MLConfig.from_file('./config_machine_learning.yaml')

# 创建配置器
configurator = ServiceConfigurator(config=config)

# 创建机器学习工作流
workflow = configurator.create_ml_workflow()

# 运行工作流
workflow.run_pipeline()

详细示例:

import logging
from habit.core.common.service_configurator import ServiceConfigurator
from habit.core.machine_learning.config_schemas import MLConfig
from habit.utils.log_utils import setup_logger
from pathlib import Path

# 设置日志
output_dir = Path('./results/ml')
output_dir.mkdir(parents=True, exist_ok=True)
logger = setup_logger(
    name='machine_learning',
    output_dir=output_dir,
    log_filename='machine_learning.log',
    level=logging.INFO
)

# 加载配置
config = MLConfig.from_file('./config_machine_learning.yaml')

# 创建配置器
configurator = ServiceConfigurator(config=config, logger=logger, output_dir=str(output_dir))

# 创建机器学习工作流
workflow = configurator.create_ml_workflow()

# 运行工作流
logger.info("开始训练模式")
workflow.run_pipeline()
logger.info("模型训练完成!")

YAML 配置详解

配置文件结构:

# 训练模式配置(MLConfig)
input:
  - path: ./demo_data/ml_data/clinical_feature.csv
    name: clinical_
    subject_id_col: PatientID
    label_col: Label
output: ./results/ml/train
random_state: 42

split_method: stratified
test_size: 0.3

normalization:
  method: z_score
  params: {}

feature_selection_methods:
  - method: variance
    params:
      threshold: 0.0
      before_z_score: true
  - method: correlation
    params:
      threshold: 0.95
      method: spearman
      before_z_score: false

models:
  LogisticRegression:
    params:
      C: 1.0
      penalty: l2
      solver: lbfgs
      max_iter: 1000
      random_state: 42
  RandomForest:
    params:
      n_estimators: 100
      random_state: 42
  XGBoost:
    params:
      n_estimators: 100
      max_depth: 6
      learning_rate: 0.1
      random_state: 42
  SVM:
    params:
      C: 1.0
      kernel: rbf
      gamma: scale
      probability: true
      random_state: 42
  KNN:
    params:
      n_neighbors: 5
      weights: uniform
      algorithm: auto
  AutoGluonTabular:
    params:
      path: ./results/ml/autogluon_models
      label: Label
      time_limit: 3600
      presets: high_quality

# 开关
is_visualize: true
is_save_model: true

visualization:
  enabled: true
  plot_types: [roc, dca, calibration, pr, confusion, shap]
  dpi: 600
  format: pdf

字段说明:

input: 输入数据配置(训练模式)

  • 列表结构,每个元素至少包含 pathsubject_id_collabel_col

  • 支持 CSV/Excel;可通过 name 给特征加前缀,避免多表融合时重名

output: 输出目录路径(训练模式)

  • 训练结果、模型与图表会保存到该目录

split_method / test_size: 数据划分策略

  • split_method 支持 randomstratifiedcustom

  • split_method: custom 时,需提供 train_ids_filetest_ids_file

feature_selection_methods: 特征选择设置

  • 列表结构,可串联多个选择器

  • 每个选择器格式为 - method: <name> + params: {...}

  • 常见方法包括 variancecorrelationanovachi2lassorfecvvif

models: 模型配置

  • 支持配置多个模型,所有模型都会被训练和评估

  • 每个模型以字典形式配置,包含 params 参数

  • 支持的模型类型:LogisticRegression、RandomForest、XGBoost、SVM、KNN、AutoGluonTabular 等

is_visualize / visualization: 可视化设置

  • is_visualize 控制是否执行可视化回调

  • visualization 可进一步设置图类型、DPI、格式

is_save_model: 模型保存开关

  • 控制是否保存训练得到的模型文件

特征选择方法详解

Variance (variance)

基于方差的特征选择,移除方差低于阈值的特征。

适用场景: - 移除低方差特征 - 减少特征数量

参数说明: - threshold: 方差阈值,低于此阈值的特征将被移除

配置示例:

feature_selection_methods:
  - method: variance
    params:
      threshold: 0.0

Correlation (correlation)

基于相关性的特征选择,移除高度相关的特征。

适用场景: - 移除冗余特征 - 减少特征数量

参数说明: - threshold_correlation: 相关性阈值,高于此阈值的特征对中一个将被移除

配置示例:

feature_selection_methods:
  - method: correlation
    params:
      threshold: 0.95
      method: spearman

ANOVA (anova)

基于 ANOVA F 值的特征选择,选择与目标变量最相关的特征。

适用场景: - 分类任务 - 选择与目标变量最相关的特征

参数说明: - k_features: 要选择的特征数量

配置示例:

feature_selection_methods:
  - method: anova
    params:
      p_threshold: 0.05

Chi2 (chi2)

基于卡方检验的特征选择,选择与目标变量最相关的特征。

适用场景: - 分类任务 - 非负特征

参数说明: - k_features_chi2: 要选择的特征数量

配置示例:

feature_selection_methods:
  - method: chi2
    params:
      p_threshold: 0.05

LASSO (lasso)

基于 LASSO 回归的特征选择,使用 L1 正则化进行特征选择。

适用场景: - 线性模型 - 自动特征选择

参数说明: - alpha: L1 正则化强度

配置示例:

feature_selection_methods:
  - method: lasso
    params:
      cv: 10

RFECV (rfecv)

递归特征消除与交叉验证,通过递归地移除特征并评估模型性能来选择最佳特征子集。

适用场景: - 需要精确的特征选择 - 计算资源充足

参数说明: - estimator: 估计器类型 - cv: 交叉验证折数 - scoring: 评分指标

配置示例:

feature_selection_methods:
  - method: rfecv
    params:
      estimator: LogisticRegression
      cv: 5
      scoring: accuracy

模型类型详解

LogisticRegression

逻辑回归,适用于二分类和多分类任务。

适用场景: - 二分类任务 - 需要概率输出 - 解释性要求高

优点: - 简单快速 - 可解释性强 - 提供概率输出

缺点: - 假设线性关系 - 对异常值敏感

参数说明: - C: 正则化强度的倒数 - penalty: 正则化类型(l1、l2、elasticnet) - solver: 优化算法 - max_iter: 最大迭代次数

配置示例:

models:
  LogisticRegression:
    params:
      C: 1.0
      penalty: l2
      solver: lbfgs
      max_iter: 1000
      random_state: 42

RandomForest

随机森林,适用于分类和回归任务。

适用场景: - 分类和回归任务 - 高维数据 - 非线性关系

优点: - 性能强大 - 不易过拟合 - 提供特征重要性

缺点: - 计算复杂度高 - 内存消耗大

参数说明: - n_estimators: 树的数量 - max_depth: 树的最大深度 - min_samples_split: 分裂节点所需的最小样本数 - min_samples_leaf: 叶节点所需的最小样本数

配置示例:

models:
  RandomForest:
    params:
      n_estimators: 100
      max_depth: null
      min_samples_split: 2
      min_samples_leaf: 1
      random_state: 42

XGBoost

梯度提升决策树,适用于分类和回归任务。

适用场景: - 分类和回归任务 - 大规模数据 - 高性能要求

优点: - 性能强大 - 计算效率高 - 支持并行计算

缺点: - 参数较多 - 需要调优

参数说明: - n_estimators: 树的数量 - max_depth: 树的最大深度 - learning_rate: 学习率

配置示例:

models:
  XGBoost:
    params:
      n_estimators: 100
      max_depth: 6
      learning_rate: 0.1
      random_state: 42

SVM

支持向量机,适用于分类和回归任务。

适用场景: - 二分类任务 - 高维数据 - 小样本数据

优点: - 理论基础扎实 - 泛化能力强 - 适合高维数据

缺点: - 对大规模数据效率低 - 对参数敏感

参数说明: - C: 正则化参数 - kernel: 核函数类型(linear、poly、rbf、sigmoid) - gamma: 核函数系数

配置示例:

models:
  SVM:
    params:
      C: 1.0
      kernel: rbf
      gamma: scale
      random_state: 42

KNN

K 近邻,适用于分类和回归任务。

适用场景: - 分类和回归任务 - 简单快速 - 非线性关系

优点: - 简单易用 - 无训练过程 - 适合非线性关系

缺点: - 预测速度慢 - 对异常值敏感 - 需要存储所有训练数据

参数说明: - n_neighbors: 近邻数量 - weights: 权重计算方式(uniform、distance) - algorithm: 算法类型(auto、ball_tree、kd_tree、brute)

配置示例:

models:
  KNN:
    params:
      n_neighbors: 5
      weights: uniform
      algorithm: auto

AutoGluonTabular

AutoML 框架,自动选择和优化模型。

适用场景: - 快速原型 - 不需要调参 - 多模型比较

优点: - 自动化程度高 - 性能优秀 - 易于使用

缺点: - 计算资源消耗大 - 黑盒模型

参数说明: - time_limit: 训练时间限制(秒) - presets: 预设模式(best_quality、high_quality、good_quality、medium_quality)

配置示例:

models:
  AutoGluonTabular:
    params:
      path: ./results/ml/autogluon_models
      label: Label
      time_limit: 3600
      presets: high_quality

Pipeline 机制

HABIT 使用 scikit-learn 的 Pipeline 机制,这是避免数据泄露的关键设计。

什么是数据泄露?

数据泄露是指在模型训练过程中,测试集的信息意外地泄露到训练集中,导致模型性能被高估。

Pipeline 如何避免数据泄露?

  1. 特征选择: 在交叉验证的每个 fold 内进行特征选择

  2. 模型训练: 在交叉验证的每个 fold 内进行模型训练

  3. 严格分离: 训练集和测试集完全分离,避免测试集信息泄露

机器学习中的 Pipeline:

from sklearn.pipeline import Pipeline
from habit.core.machine_learning import ModelFactory

# 创建 Pipeline,包含特征选择和模型训练
pipeline = Pipeline([
    ('feature_selection', feature_selector),
    ('model', ModelFactory.create_model('RandomForest', config))
])

# 训练阶段
pipeline.fit(X_train, y_train)

# 测试阶段:使用训练好的 Pipeline 进行预测
y_pred = pipeline.predict(X_test)

关键要点:

  • 特征选择和模型训练必须在同一个 Pipeline 中

  • 不要在整个数据集上进行特征选择

  • 使用交叉验证时,每个 fold 的训练和预测必须严格分离

实际示例

示例 1: 基本训练配置(MLConfig)

input:
  - path: ./ml_data/clinical_feature.csv
    subject_id_col: PatientID
    label_col: Label
output: ./results/ml/train

split_method: stratified
test_size: 0.3

feature_selection_methods:
  - method: variance
    params:
      threshold: 0.0

models:
  RandomForest:
    params:
      n_estimators: 100
      random_state: 42

is_visualize: true
is_save_model: true
random_state: 42

示例 2: 多模型训练配置(MLConfig)

input:
  - path: ./ml_data/clinical_feature.csv
    subject_id_col: PatientID
    label_col: Label
output: ./results/ml/train

feature_selection_methods:
  - method: rfecv
    params:
      estimator: LogisticRegression
      cv: 5
      scoring: accuracy

models:
  LogisticRegression:
    params:
      max_iter: 1000
      random_state: 42
  XGBoost:
    params:
      n_estimators: 100
      max_depth: 6
      learning_rate: 0.1
      random_state: 42

is_visualize: true
is_save_model: true
random_state: 42

示例 3: 预测配置(PredictionConfig)

model_path: ./results/ml/train/models/LogisticRegression_final_pipeline.pkl
data_path: ./ml_data/new_data.csv
output_dir: ./results/ml/predict
evaluate: true
label_col: Label
output_label_col: predicted_label
output_prob_col: predicted_probability

输出结构

机器学习输出会保存在配置中指定目录,典型包括:

  • 训练阶段:模型文件、训练/测试性能汇总、可视化图表、日志文件

  • 预测阶段:`prediction_results.csv`(含预测标签与概率列)、可选评估结果、日志文件

常见问题

Q1: 如何选择特征选择方法?

A: 根据您的数据特点选择: - 快速原型: 使用 variance 或 correlation - 分类任务: 使用 anova 或 chi2 - 线性模型: 使用 lasso - 精确选择: 使用 rfecv

Q2: 如何选择模型类型?

A: 根据您的任务和数据特点选择: - 二分类: LogisticRegression、SVM - 高维数据: RandomForest、XGBoost - 快速原型: KNN - 自动调优: AutoGluon

Q3: 训练和预测模式有什么区别?

A: - 训练模式 (Train):

  • 输入:带标签的特征表。

  • 过程:执行数据标准化、特征筛选(如 LASSO)、模型拟合(如 Random Forest)以及交叉验证评估。

  • 输出:模型性能指标(AUC, ACC 等)和保存的 Pipeline 文件 (.pkl)。

  • 预测模式 (Predict):
    • 输入:新数据的特征表 + 已训练的 Pipeline 文件

    • 过程:直接加载 Pipeline,对新数据应用完全相同的标准化和筛选逻辑,并输出预测得分。

    • 输出:每个样本的预测概率(Radscore)或类别。

Q4: 如何避免数据泄露?

A: 遵循以下原则:

  1. 特征选择和模型训练必须在同一个 Pipeline 中。

  2. 不要在整个数据集上进行特征选择。

  3. 使用交叉验证时,每个 fold 的训练和预测必须严格分离。

Q5: 模型训练失败怎么办?

A: 检查以下几点: 1. 配置文件是否正确 2. 数据路径是否正确 3. 特征文件是否存在 4. 标签文件是否存在 5. 查看日志文件了解详细错误信息

Q6: 如何提高模型性能?

A: 可以尝试以下方法: 1. 尝试不同的特征选择方法 2. 尝试不同的模型类型 3. 调整模型参数 4. 增加训练数据 5. 特征工程

下一步

机器学习建模完成后,您可以: