scikit-learn 回归预测结果太好了。我搞砸了啥?
Posted
技术标签:
【中文标题】scikit-learn 回归预测结果太好了。我搞砸了啥?【英文标题】:scikit-learn regression prediction results are too good. What did I mess up?scikit-learn 回归预测结果太好了。我搞砸了什么? 【发布时间】:2019-01-08 08:49:02 【问题描述】:我们在 Azure ML Studio 平台(最初的拖放系统)之上的 Azure 中运行了一些 ML 模型。一年多来一切都很好,但我们需要继续前进,这样我们才能更好地扩展。因此,我正在使用 scikit-learn 在 Python 中重写这些内容,并在 Jupyter 笔记本中对其进行测试。
好消息/坏消息是我们要训练的数据相当小(数据库中有数百条记录)。这是非常不完美的数据,做出了非常不完美的回归预测,所以错误是可以预料的。这很好。对于这个问题,很好。因为问题是,当我测试这些模型时,预测太完美了。我不明白我做错了什么,但我显然做错了某事。
(在我看来)显而易见的事情是我正在对测试数据进行训练,或者通过相关性发现了明显/完美的因果关系。我对train_test_split
的使用告诉我,我没有在我的测试数据上进行训练,我保证第二个是错误的,因为这个空间非常混乱(我们大约 15 年前开始对这些数据进行手动线性回归,并且仍然保持Excel 电子表格能够在紧要关头手动完成,即使它的准确度远低于我们的 Azure ML Studio 模型)。
让我们看一下代码。这是我的 Jupyter 笔记本的相关部分(抱歉,如果有更好的格式化方法):
X = myData
y = myData.ValueToPredict
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
train_size = 0.75,
test_size = 0.25)
print("X_train: ", X_train.shape)
print("y_train: ", y_train.shape)
print("X_test: ", X_test.shape)
print("y_test: ", y_test.shape)
X_train: (300, 17)
y_train: (300,)
X_test: (101, 17)
y_test: (101,)
ESTIMATORS =
"Extra Trees": ExtraTreesRegressor(criterion = "mse",
n_estimators=10,
max_features=16,
random_state=42),
"Decision Tree": DecisionTreeRegressor(criterion = "mse",
splitter = "best",
random_state=42),
"Random Forest": RandomForestRegressor(criterion = "mse",
random_state=42),
"Linear regression": LinearRegression(),
"Ridge": RidgeCV(),
y_test_predict = dict()
y_test_rmse = dict()
for name, estimator in ESTIMATORS.items():
estimator.fit(X_train, y_train)
y_test_predict[name] = estimator.predict(X_test)
y_test_rmse[name] = np.sqrt(np.mean((y_test - y_test_predict[name]) ** 2)) # I think this might be wrong but isn't the source of my problem
for name, error in y_test_rmse.items():
print(name + " RMSE: " + str(error))
额外树 RMSE:0.3843540838630157
决策树 RMSE:0.32838969545222946
随机森林 RMSE:0.4304701784728594
线性回归 RMSE:7.971345895791494e-15
岭 RMSE:0.0001390197344951183
y_test_score = dict()
for name, estimator in ESTIMATORS.items():
estimator.fit(X_train, y_train)
y_test_predict[name] = estimator.predict(X_test)
y_test_score[name] = estimator.score(X_test, y_test)
for name, error in y_test_score.items():
print(name + " Score: " + str(error))
额外树分数:0.9990166492769291
决策树分数:0.999282165241745
随机森林得分:0.998766521504593
线性回归分数:1.0
岭分数:0.9999999998713534
我想我可能做错了错误指标,所以我只查看了简单的分数(这就是我将两者都包括在内的原因)。然而,两者都表明这些预测好得令人难以置信。请记住,输入量很小(总共约 400 项?)。运行的数据本质上是根据天气模式对商品消费进行预测,这从一开始就是一个混乱的空间,因此应该存在很多错误。
我在这里做错了什么?
(另外,如果我能以更好的方式提出这个问题或提供更多有用的信息,我将不胜感激!)
这是数据的热图。我指出了我们预测的值。
我还绘制了一些更重要的输入与我们预测的值(按另一个维度进行颜色编码):
这是第 2 列,正如 cmets 中所询问的那样
解决方案!
正如@jwil 所指出的,我没有将ValueToPredict
列从X
变量中拉出。解决方案是添加一行以删除该列:
X = myData
y = myData.ValueToPredict
X = X.drop("ValueToPredict", 1) # <--- ONE-LINE FIX!
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
train_size = 0.75,
test_size = 0.25)
有了这个,我的错误和分数会比我预期的要多:
额外树 RMSE:1.6170428819849574
决策树 RMSE:1.990459810552763
随机森林 RMSE:1.699801032532343
线性回归 RMSE:2.5265108241534397
岭 RMSE:2.528721533965162
额外树分数:0.9825944193611161
决策树分数:0.9736274412836977
随机森林得分:0.9807672396970707
线性回归分数:0.9575098985510281
岭分数:0.9574355079097321
【问题讨论】:
您能提供您实际使用的数据吗?您的回归/树中的系数或特征重要性(分别)是什么? 看起来是由于一些过度拟合。请分享数据集。 我不知道如何回答@user3014097 的问题。至于数据,我不能分享它,因为它是非公开数据。如果这是一个过度拟合的问题,我怎样才能让它不太容易做到这一点?我一直在自学这一点——Python 和 ML,总的来说,对我来说还是很新的。我会看看是否可以附上数据的 sns.heatmap - 我认为这可能有助于在一定程度上满足您的要求。 对于线性/岭回归,请查看“estimator.coeff_”,对于树,请查看“estimator.feature_importances_”。我的猜测是一个会比其他的要高得多(在上面的图中显示基本上相关性为 1 的那个) 您正在初始化 X = myData 和 y = my.ValueToPredict。这对我来说看起来很奇怪。你的意思是写 X = my.Data 还是 y = myData.ValueToPredict ? 【参考方案1】:你是对的;我强烈怀疑您的 X 数据中有一个或多个与 Y 数据几乎完全相关的特征。通常这很糟糕,因为这些变量不能解释 Y,而是由 Y 解释或与 Y 共同确定。要解决此问题,请考虑对 X 执行 Y 的线性回归,然后使用简单的 p 值或 AIC/BIC 来确定哪些 X 变量是最不相关的。放下这些并重复这个过程,直到你的 R^2 开始严重下降(尽管每次都会下降一点)。其余变量将与预测最相关,希望您能够从该子集中确定哪些变量与 Y 密切相关。
【讨论】:
那么你是说我对框架的使用,将训练数据与测试数据分开,所有这些都是正确的吗?如果您可以肯定地确认这里的内容是正确的,那么这就是我正在寻找的答案。 等待。在您的代码中,您似乎没有从 X 中删除 ValueToPredict。将该数据分配给 Y 后,您需要确保将其从 X 中删除。这肯定会解决您的问题。 就是这样!!这样做使我的分数下降到 ~95-97% 的水平,这正是我所期望的(99.99999-100% 令人难以置信)。我认为那是正是我的问题。所以我认为train_test_split
知道不在y
列上训练(由y
定义)。我不知道我必须从X
中删除它。
我很高兴这有效! train_test_split
所做的只是将您的观察结果随机分成两组,但两组的所有特征都保持不变。
这绝对是我的错误假设所在。我现在要回顾一些其他的概念验证,在那里我遇到了同样的问题,这解决了很多令人头疼的问题!非常感谢!我大约一个月前第一次打这个,纺了一天,然后把它放在桌子上。从那以后尝试了几次以找出问题所在,但没有成功。希望我能给你买杯啤酒什么的。你为我节省了很多时间!谢谢你,随机聪明的互联网人!以上是关于scikit-learn 回归预测结果太好了。我搞砸了啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Python scikit-learn 中输出随机森林中每棵树的回归预测?