【问题标题】:How to use GridSearchCV for polynomials of different degrees?如何将 GridSearchCV 用于不同次数的多项式?
【发布时间】:2020-10-18 18:19:32
【问题描述】:

我想要做的是检查一些 OLS 与不同程度的多项式拟合,看看在给定 horsepower 的情况下哪个程度在预测 mpg 方面表现更好(同时使用 LOOCV 和 KFold)。我写了代码,但我不知道如何使用GridSearchCvPolynomialFeatures 函数应用于每次迭代,所以我最终写了这个:

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import LeaveOneOut, KFold
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error



df = pd.read_csv('http://web.stanford.edu/~oleg2/hse/auto/Auto.csv')[['horsepower','mpg']].dropna()

pows = range(1,11)
first, second, mse = [], [], 0     # 'first' is data for the first plot and 'second' is for the second one

for p in pows:
  mse = 0
  for train_index, test_index in LeaveOneOut().split(df):
      x_train, x_test = df.horsepower.iloc[train_index], df.horsepower.iloc[test_index]
      y_train, y_test = df.mpg.iloc[train_index], df.mpg.iloc[test_index]
      polynomial_features = PolynomialFeatures(degree = p)
      x = polynomial_features.fit_transform(x_train.values.reshape(-1,1))   #getting the polynomial
      ft = LinearRegression().fit(x,y_train)
      x1 = polynomial_features.fit_transform(x_test.values.reshape(-1,1))   #getting the polynomial
      mse += mean_squared_error(y_test, ft.predict(x1))
  first.append(mse/len(df))
    
for p in pows: 
    temp = []   
    for i in range(9):      # this is to plot a few graphs for comparison
        mse = 0
        for train_index, test_index in KFold(10, True).split(df):
            x_train, x_test = df.horsepower.iloc[train_index], df.horsepower.iloc[test_index]
            y_train, y_test = df.mpg.iloc[train_index], df.mpg.iloc[test_index]
            polynomial_features = PolynomialFeatures(degree = p)
            x = polynomial_features.fit_transform(x_train.values.reshape(-1,1))   #getting the polynomial
            ft = LinearRegression().fit(x,y_train)
            x1 = polynomial_features.fit_transform(x_test.values.reshape(-1,1))   #getting the polynomial
            mse += mean_squared_error(y_test, ft.predict(x1))
        temp.append(mse/10)
    second.append(temp)      


f, pt = plt.subplots(1,2,figsize=(12,5.1))
f.tight_layout(pad=5.0)
pt[0].set_ylim([14,30])
pt[1].set_ylim([14,30])
pt[0].plot(pows, first, color='darkblue', linewidth=1)
pt[0].scatter(pows, first, color='darkblue')
pt[1].plot(pows, second)
pt[0].set_title("LOOCV", fontsize=15)
pt[1].set_title("10-fold CV", fontsize=15)
pt[0].set_xlabel('Degree of Polynomial', fontsize=15)
pt[1].set_xlabel('Degree of Polynomial', fontsize=15)
pt[0].set_ylabel('Mean Squared Error', fontsize=15)
pt[1].set_ylabel('Mean Squared Error', fontsize=15)
plt.show()

它产生:

这是完全有效的,你可以在你的机器上运行它来测试它。这正是我想要的,但它似乎真的过分了。我正在寻求有关如何使用GridSearchCv 或其他任何东西来改进它的建议,真的。我尝试将PolynomialFeatures 作为LinearRegression() 的管道传递,但它无法即时更改x。一个工作示例将不胜感激。

【问题讨论】:

  • 也许您可以说明为什么您的管道方法不起作用?这似乎是“正确”的方法,从网格搜索的cv_results_ 中提取结果以进行绘图。
  • @BenReiniger 老实说,我真的不知道管道是如何工作的,但我尝试将多项式的次数作为参数传递给我的函数,我将其包含在管道中。问题是我希望将x 参数(在这种情况下为df.horsepower)传递给这个函数,以便我可以修改它,然后在编辑后的版本上进行拟合,但似乎没有办法这样做。

标签: python python-3.x scikit-learn gridsearchcv k-fold


【解决方案1】:

这种事情似乎是这样做的:

pipe = Pipeline(steps=[
    ('poly', PolynomialFeatures(include_bias=False)),
    ('model', LinearRegression()),
])

search = GridSearchCV(
    estimator=pipe,
    param_grid={'poly__degree': list(pows)},
    scoring='neg_mean_squared_error',
    cv=LeaveOneOut(),
)

search.fit(df[['horsepower']], df.mpg)

first = -search.cv_results_['mean_test_score']

(最后一行是负数,因为记分员是负数)

然后绘图可以或多或少地以相同的方式进行。 (我们在这里依赖cv_results_ 将条目与pows 的顺序相同;您可能希望使用pd.DataFrame(search.cv_results_) 的适当列来代替。)

您可以使用RepeatedKFoldKFold 上模拟您的循环,尽管那样您只会得到一个情节;如果你真的想要单独的图,那么你仍然需要外循环,但是cv=KFold(...)的网格搜索可以替换内循环。

【讨论】:

  • 这正是我想要的。谢谢你。虽然,这需要两倍的时间来计算(与我的示例相比)。我不明白为什么。我什至添加了参数n_jobs = -1,但这并没有帮助。我知道计算额外的统计数据需要一些时间,但差异应该不会那么大。
  • 明确地说,“时间”是指“墙上时间”。 CPU 时间实际上比我的示例中的要好,这在 4 核 CPU 上更没有意义。
  • 时间问题很奇怪。唯一真正的区别是网格搜索将重新调整“最佳”k;您可以使用refit=False 删除它。其他一切都是小补充,例如您提到的额外统计信息...
  • 其实我已经试过了。只是再次确定,但不幸的是,这并没有什么不同
  • 在拟合之前从数据帧转换为 numpy 数组(在搜索的 fit 中添加 .values)有很大帮助,但在 colab 实例上仍然慢一些;我想反复转换是相当昂贵的。奇怪的是,即使在那之后我们还是变慢了。
猜你喜欢
  • 2021-03-09
  • 2018-05-05
  • 2021-12-02
  • 2016-04-13
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 2021-08-26
相关资源
最近更新 更多