You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线性回归模型预测值出现负值的问题排查请求

线性回归预测出现负值的成因及解决办法

一、核心问题成因分析

1. 代码中的致命错误

你对连续目标变量y(CPM)使用了pd.get_dummies(),这是完全错误的操作:

  • CPM是数值型连续变量,而pd.get_dummies()是用于处理分类变量的one-hot编码工具。
  • 该操作会把原本连续的CPM值拆分成多个二进制列,将回归任务错误转换成多分类任务,直接导致模型训练逻辑混乱,预测结果必然异常,包括出现负值。

另外代码中存在冗余且可能引发问题的操作:

X = dataFrame.astype(object)
y = dataFrame.astype(object)

这段代码把整个数据集强制转为object类型,后续又重新赋值X和y,不仅无意义还可能引入类型冲突。

2. 线性回归模型的固有特性

即使代码修正后,标准线性回归(LinearRegression)是无约束模型:它通过最小化均方误差拟合参数,不会主动限制预测值符合数据的非负特性。当特征组合的线性加权加上截距后计算结果为负时,模型就会输出负值,这是这类模型的正常表现。

二、修正方案

第一步:修复代码中的错误

先纠正目标变量的处理逻辑,清理冗余代码,确保模型训练符合回归任务的要求:

import numpy as np
import pandas as pd
from sklearn import metrics
import matplotlib.pyplot as plt
import seaborn as sns
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
from sklearn import linear_model
%matplotlib inline

# 数据读取与预处理
dataFrame = pd.read_csv("fskning/Data cleaned.csv", delimiter=";")
# 直接选择特征与目标变量,无需先转object类型
X = dataFrame[['Alder','Eksponeringer','Køn']]
y = dataFrame['CPM (pris pr. 1000 eksponeringer)']
# 仅对分类特征做one-hot编码,加drop_first避免多重共线性
X = pd.get_dummies(X, drop_first=True)

# 数据集拆分
X_train,X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 100)

# 训练线性回归模型
reg_model = LinearRegression().fit(X_train, y_train)
print('截距:',reg_model.intercept_)
print('特征系数:', list(zip(X.columns, reg_model.coef_)))

# 预测与评估
y_pred= reg_model.predict(X_test)
x_pred= reg_model.predict(X_train)

mse = mean_squared_error(y_test,y_pred)
print("均方误差:{:.2f}".format(mse))
print("均方根误差:{:.2f}".format(np.sqrt(mse)))

第二步:解决预测负值的问题

修复代码后如果仍出现负值,可采用以下几种方案:

1. 使用带非负约束的回归模型

Scikit-learn的Lasso或ElasticNet支持设置positive=True,强制所有系数为正,结合截距约束减少负值输出:

# 使用带非负约束的Lasso回归
reg_model = linear_model.Lasso(alpha=0.1, positive=True, random_state=100)
reg_model.fit(X_train, y_train)
y_pred = reg_model.predict(X_test)

2. 对目标变量做变换

如果CPM分布偏态,可先对y做对数变换,预测后再反变换,自然避免负值:

# 对数变换目标变量(log1p避免0值问题)
y_log = np.log1p(y)
reg_model = LinearRegression().fit(X_train, y_log)
y_pred_log = reg_model.predict(X_test)
# 反变换得到原始尺度的预测值
y_pred = np.expm1(y_pred_log)

3. 截断预测值

若上述方法不适用,可直接将预测负值替换为0或数据集中CPM的最小值:

# 将负值设为0
y_pred = np.maximum(y_pred, 0)
# 或者设为数据集的最小CPM值
min_cpm = dataFrame['CPM (pris pr. 1000 eksponeringer)'].min()
y_pred = np.maximum(y_pred, min_cpm)

内容的提问来源于stack exchange,提问作者ems111111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:45:25