代码之家  ›  专栏  ›  技术社区  ›  Jaxidian

scikit学习回归预测结果太好。我搞砸了什么?

  •  1
  • Jaxidian  · 技术社区  · 6 年前

    我们在Azure ML Studio平台(初始拖放系统)之上的Azure中运行了一些ML模型。一年多来一切都很好,但我们需要继续前进,这样我们才能更好地扩大规模。所以我正在使用scikit在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)
    

    列车:(300,17)

    列车:(300,)

    X_测试:(101,17)

    y_检验:(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.384354083863057

    决策树RMSE:0.32838969545222946

    随机森林RMSE:0.4304701784728594

    线性回归RMSE:7.971345895791494e-15

    岭RMSE:0.000139197344951183

    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.999016492769291

    决策树得分:0.999282165241745

    随机森林评分:0.998766521504593

    线性回归得分:1.0

    岭得分:0.999999898713534

    我想也许我做错了错误的度量,所以我只看了简单的分数(这就是为什么我把两者都包括在内)。然而,两者都表明,这些预测太好了,不可能是真的。请记住,输入量很小(总共约400项?)而这些数据基本上是根据天气模式对大宗商品消费做出预测,这是一个有点混乱的空间,因此应该存在很多错误。

    我在这里做错什么了?

    (另外,如果我能以更好的方式提出这个问题或提供更多有用的信息,我将非常感谢!)


    这是数据的热图。我指出了我们预测的价值。

    Seaborn heatmap of the data

    我还绘制了两个更重要的输入值与我们预测的值(用另一个维度进行颜色编码):

    A plot of values we're predicting

    以下是第2栏,如评论中所问 Another plot


    解决方案!

    正如@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.982594419361161

    决策树得分:0.9736274412836977

    随机森林评分:0.9807672396970707

    线性回归得分:0.95750985510281

    岭分:0.9574355079097321

    1 回复  |  直到 6 年前
        1
  •  1
  •   jwil    6 年前

    你说得对;我强烈怀疑你的X数据中有一个或多个与Y数据几乎完全相关的特性。通常这是不好的,因为这些变量不解释Y,而是由Y解释或与Y共同确定。要解决此问题,请考虑对X执行Y的线性回归,然后使用简单的p值或AIC/BIC来确定哪个X变量最不相关。放下这些,重复这个过程,直到你的R^2开始严重下降(尽管每次都会下降一点)。剩下的变量在预测中将是最相关的,希望您能够从该子集中识别出哪些变量与Y紧密相关。