回归目标怎么做对数变换?用 TransformedTargetRegressor 还原原尺度预测

配对使用 log1p 与 expm1,让 TransformedTargetRegressor 自动还原预测,并用同一测试集核对原尺度误差和逆变换一致性。

当回归目标严格随输入呈指数式增长时,直接在线性模型里拟合原目标可能很吃力。可以先对目标做对数变换,再把预测还原。TransformedTargetRegressor 把这两步封装在同一个接口中,让误差仍能按原来的单位计算。是否适合真实任务,需要用保留数据验证。

目标变换与特征缩放要分清

TransformedTargetRegressor 在fit时把y变成log1p(y),在predict时自动对内部预测执行expm1,返回原目标尺度。

回归目标怎么做对数变换?用 TransformedTargetRegressor 还原原尺度预测

X仍然是原来的输入特征,这里改变的是标签y。使用np.log1p和np.expm1是配对操作:log1p(y)计算log(1+y),expm1(z)计算exp(z)−1,不能错配成log1p后直接exp。

本文示例已在 Python 3.11、scikit-learn 1.7.2、NumPy 2.4.6、pandas 2.3.3、SciPy 1.17.1 的本地 CPU 环境运行;输入是人为生成的教学数据,不是客户案例。

python -m venv .venv
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
python -m pip install scikit-learn==1.7.2 pandas==2.3.3 numpy==2.4.6 scipy==1.17.1

跑通配对变换,并做原尺度对照

把代码保存为 target_log_demo.py 并运行 python target_log_demo.py;检查自动预测是否与手动expm1还原一致,再比较两种模型的原尺度MAE。

本例生成300条正值目标,它们由指数函数和对数尺度噪声构造;这个生成方式刻意适合展示对数变换,不是证明该方法普遍优于原尺度回归。两种模型使用完全相同的210条训练样本和90条测试样本。

import numpy as np
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split

rng = np.random.default_rng(42)
X = rng.uniform(0, 4, size=(300, 1))
y = np.expm1(1.0 + 0.8 * X[:, 0] + rng.normal(0, 0.15, 300))
if np.any(y <= -1) or not np.isfinite(y).all():
    raise ValueError("log1p要求目标大于-1且有限")
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)
raw_model = LinearRegression().fit(X_train, y_train)
transformed = TransformedTargetRegressor(
    regressor=LinearRegression(), func=np.log1p, inverse_func=np.expm1
).fit(X_train, y_train)
pred = transformed.predict(X_test)
manual = np.expm1(transformed.regressor_.predict(X_test))
assert np.allclose(pred, manual)
assert np.allclose(np.expm1(np.log1p(y_train)), y_train)
print("预测形状:", pred.shape)
print("直接回归原尺度MAE:", round(mean_absolute_error(
    y_test, raw_model.predict(X_test)), 4))
print("变换回归原尺度MAE:", round(mean_absolute_error(y_test, pred), 4))
print("前3条原尺度预测:", np.round(pred[:3], 4))
print("与手动逆变换一致:", np.allclose(pred, manual))

确认读到的是哪一个尺度

这次90条合成测试样本中,直接线性回归的原尺度MAE为5.6795,目标变换回归为2.9038;自动还原与手动逆变换一致的检查返回True。

调用 输出含义 可否直接与原y比较
transformed.regressor_.predict(X_test) log1p目标尺度的内部预测 不能
np.expm1(内部预测) 手动还原的原尺度预测 可以
transformed.predict(X_test) 自动逆变换的原尺度预测 可以

前3条自动预测约为3.2870、5.7087、3.2375,返回shape是(90,)。不要对transformed.predict的结果再次expm1;那会重复还原并改变数值。读取内部模型时使用拟合后的regressor_,不是初始化时传入的regressor对象。

MAE计算时,两个模型的预测都与同一份原y_test比较。对数尺度误差与原尺度误差单位不同,不能拿一个模型的对数MAE去和另一个模型的原尺度MAE直接比高低。

采用前检查目标域与统计含义

log1p要求有限目标且y大于−1;如果出现负值、无穷值或缺失标签,先核对目标含义和数据,不能为了让程序运行就随意加一个常数。

本文合成目标均为正。虽然−1到0之间的数在数学上也能做log1p,但是否有业务意义仍要判断;y=−1会导致无穷值,y<−1不在该实数函数的定义域。

逆变换后的预测也不自动成为原尺度条件均值。若模型学习的是变换后目标的平均趋势,非线性逆变换通常不等于对原目标直接求均值。需要无偏均值、风险金额或总量估计时,要另行检验偏差和聚合误差;本文没有实现偏差修正。

输入超出训练范围时,指数还原可能放大外推误差;先限制适用输入范围并检查负预测或不合理数量。树模型、线性模型和不同目标分布对变换的反应不同,本例的一次MAE下降不能外推为所有项目的收益。

换成自己的数据后怎样验收

明确目标单位、合法范围和零值含义,保留同一测试集,先运行逆变换一致性检查,再查看原尺度MAE及逐条大误差。模型调参和变换选择使用验证集完成,最终测试集用于独立验收;不要因为测试结果不好反复换变换直到它看起来够低。

官方资料与适用版本

本文于2026年10月1日核对下列官方资料,接口说明对应 scikit-learn 1.7;运行示例使用1.7.2。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30725.html

赞 (0)
AI小管家的头像AI小管家
训练数据有缺失值怎么办?用 SimpleImputer 填补特征并检查空列
上一篇 1天前
一个模型怎样预测两个数值目标?用 MultiOutputRegressor 对齐输出并逐列验收
下一篇 1天前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部