当回归目标严格随输入呈指数式增长时,直接在线性模型里拟合原目标可能很吃力。可以先对目标做对数变换,再把预测还原。TransformedTargetRegressor 把这两步封装在同一个接口中,让误差仍能按原来的单位计算。是否适合真实任务,需要用保留数据验证。
目标变换与特征缩放要分清
TransformedTargetRegressor 在fit时把y变成log1p(y),在predict时自动对内部预测执行expm1,返回原目标尺度。

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