如何将非等宽分箱直方图用作线性回归预测变量?
解决暗物质晕Concentration参数预测模型的维度错误问题
问题背景
正在构建基于NFW剖面的暗物质晕粒子concentration参数c的预测模型:通过NFW剖面生成径向粒子位置,将每个粒子集转换为100分箱的直方图作为特征,对应c为标签。但存在两个核心问题:
- 不同c对应的直方图分箱边界不统一,无法将特征对齐为固定维度的一维数组
- 运行代码时触发
ValueError: Found array with dim 3. LinearRegression expected <= 2错误
错误根源
当前代码中,每个样本的特征被存储为包含Bin Edges和Histogram Values的DataFrame,最终X是由多个DataFrame组成的列表。经过train_test_split后,X_train会被解析为三维结构(样本数 × 100行 × 2列),而scikit-learn的线性模型要求输入特征为二维数组(样本数 × 特征数),维度不匹配导致报错。同时,分箱边界不统一意味着不同样本的直方图数值无法对应相同的径向区间,特征失去可比性。
解决思路
1. 统一全局分箱边界
先遍历所有样本生成径向位置,确定全局径向范围,基于该范围生成固定的100个分箱边界,所有样本都使用这套边界生成直方图,确保每个样本的直方图数值对应相同的径向区间。
2. 修正特征存储结构
仅保留直方图的数值作为特征,去掉分箱边界(边界是全局固定的,无需作为特征输入),将每个样本的直方图转换为一维数组,最终X为二维numpy数组(样本数 × 100)。
可选优化:径向位置归一化
NFW剖面的径向分布与特征半径r_s相关,可将所有径向位置除以r_s(由c和晕质量计算得到),让分箱基于归一化后的半径,更符合物理意义,避免不同c导致的径向范围差异过大。
修改后的代码
import numpy as np from halotools import empirical_models from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score # 参数定义 min_c = 4.0 max_c = 40.0 M = 1E15 # 晕质量,注意halotools的单位规范 z = 0.0 num_samples = 300 num_bins = 100 # 预先生成所有样本的径向位置,用于确定全局分箱边界 concentration_values = np.random.uniform(min_c, max_c, num_samples) all_radii = [] nfw_profile = empirical_models.NFWProfile() # 只初始化一次,提升效率 for c in concentration_values: # 计算NFW特征半径r_s,用于归一化(可选) r_s = nfw_profile.halo_mass_to_rs(halo_mass=M, conc=c, redshift=z) positions = nfw_profile.mc_generate_nfw_radial_positions(halo_mass=M, conc=c) normalized_positions = positions / r_s # 归一化到r_s尺度 all_radii.extend(normalized_positions) # 生成全局固定分箱边界(可选用对数分箱,适配NFW幂律分布) # 线性分箱 # bin_edges = np.linspace(min(all_radii), max(all_radii), num_bins + 1) # 对数分箱(更适合NFW分布) log_min = np.log10(min(all_radii[all_radii > 0])) # 避免log(0) log_max = np.log10(max(all_radii)) bin_edges = np.logspace(log_min, log_max, num_bins + 1) # 重新生成特征和标签 X = [] y = [] for c in concentration_values: r_s = nfw_profile.halo_mass_to_rs(halo_mass=M, conc=c, redshift=z) positions = nfw_profile.mc_generate_nfw_radial_positions(halo_mass=M, conc=c) normalized_positions = positions / r_s # 使用全局固定分箱生成直方图 hist, _ = np.histogram(normalized_positions, bins=bin_edges) X.append(hist) y.append(c) # 转换为二维numpy数组,符合scikit-learn输入要求 X = np.array(X) y = np.array(y) # 划分数据集 X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.3, random_state=42) # 训练模型 model = LinearRegression() model.fit(X_train, y_train) # 预测与评估 y_val_pred = model.predict(X_val) mse = mean_squared_error(y_val, y_val_pred) mae = mean_absolute_error(y_val, y_val_pred) r2 = r2_score(y_val, y_val_pred) print(f"Mean Squared Error (MSE): {mse:.2f}") print(f"Mean Absolute Error (MAE): {mae:.2f}") print(f"R-squared (R^2) Score: {r2:.2f}")
关键修改点
- 只初始化一次
NFWProfile对象,提升运行效率 - 预先生成所有归一化后的径向位置,确定全局分箱边界
- 使用固定分箱生成直方图,确保每个样本的特征维度统一
- 将X转换为二维numpy数组,满足scikit-learn模型的输入要求
- 可选使用对数分箱,适配NFW剖面的幂律密度分布
额外建议
- 增加样本量:300个样本对于回归模型来说偏少,建议增加到1000+以提升模型泛化能力
- 尝试非线性模型:线性回归可能无法捕捉c与直方图之间的复杂关系,可尝试随机森林、梯度提升树或神经网络
- 特征工程:可对直方图做归一化(如除以总粒子数),或提取统计特征(如均值、中位数、峰值位置)作为补充特征
内容的提问来源于stack exchange,提问作者Raeed Mundow
相关产品推荐
相关产品推荐

