【问题标题】:How to find the best degree of polynomials?如何找到多项式的最佳次数?
【发布时间】:2018-05-06 15:05:28
【问题描述】:

我是机器学习的新手,目前陷入了困境。 首先,我使用线性回归来拟合训练集,但得到非常大的 RMSE。然后我尝试使用多项式回归来减少偏差。

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error

poly_features = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly_features.fit_transform(X)
poly_reg = LinearRegression()
poly_reg.fit(X_poly, y)

poly_predict = poly_reg.predict(X_poly)
poly_mse = mean_squared_error(X, poly_predict)
poly_rmse = np.sqrt(poly_mse)
poly_rmse

然后我得到比线性回归稍微好一点的结果,然后我继续设置 degree = 3/4/5,结果越来越好。但随着度数的增加,它可能会有些过拟合。

多项式的最佳次数应该是在交叉验证集中生成最低 RMSE 的次数。但我不知道如何实现这一目标。我应该使用 GridSearchCV 吗?还是其他方法?

如果您能帮我解决这个问题,我们将不胜感激。

【问题讨论】:

  • 你考虑过使用正则化方法吗?
  • 还没有,因为我还没有弄清楚应该选择哪个多项式次数。
  • 在添加正则化之前,我会说选择特征工程来了解系统是否看起来是多项式的(如果手头的特征空间可行的话)。

标签: python machine-learning linear-regression polynomials


【解决方案1】:

您下次应该提供 X/Y 的数据,或者一些虚拟的数据,它会更快并为您提供特定的解决方案。现在我已经创建了一个y = X**4 + X**3 + X + 1 形式的虚拟方程。

您可以通过多种方式对此进行改进,但找到最佳度数的快速迭代方法是简单地将您的数据拟合到每个度数上,然后选择性能最佳的度数(例如,最低 RMSE)。

您还可以决定如何保留训练/测试/验证数据。

import numpy as np
import matplotlib.pyplot as plt 

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

X = np.arange(100).reshape(100, 1)
y = X**4 + X**3 + X + 1

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

rmses = []
degrees = np.arange(1, 10)
min_rmse, min_deg = 1e10, 0

for deg in degrees:

    # Train features
    poly_features = PolynomialFeatures(degree=deg, include_bias=False)
    x_poly_train = poly_features.fit_transform(x_train)

    # Linear regression
    poly_reg = LinearRegression()
    poly_reg.fit(x_poly_train, y_train)

    # Compare with test data
    x_poly_test = poly_features.fit_transform(x_test)
    poly_predict = poly_reg.predict(x_poly_test)
    poly_mse = mean_squared_error(y_test, poly_predict)
    poly_rmse = np.sqrt(poly_mse)
    rmses.append(poly_rmse)
    
    # Cross-validation of degree
    if min_rmse > poly_rmse:
        min_rmse = poly_rmse
        min_deg = deg

# Plot and present results
print('Best degree {} with RMSE {}'.format(min_deg, min_rmse))
        
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(degrees, rmses)
ax.set_yscale('log')
ax.set_xlabel('Degree')
ax.set_ylabel('RMSE')

这将打印:

最佳 4 级,RMSE 1.27689038706e-08

或者,您还可以构建一个执行多项式拟合的新类,并将其传递给带有一组参数的 GridSearchCV。

【讨论】:

  • 非常感谢。我在项目开始时进行了训练/测试集拆分,但是如果使用测试集来帮助选择多项式次数,我应该如何确定全训练模型的整体性能?
  • 鉴于您当前的用例,我认为没有必要做任何更复杂的事情。对于适合多项式的每个模型,您都会看到它在看不见的(测试)数据上的表现,并以此为基础进行选择。如果需要,您可以设置训练/测试/开发集,并在开发集上比较您的最终选择以获得“整体”性能。您还可以考虑使用不同的保留方法(K-folds、LOOV 等)。
  • 接受回答?还是您还想澄清一些事情?
【解决方案2】:

在我看来,找到最佳曲线拟合度或一般拟合模型的最佳方法是使用 scikit-learn 库中的 GridSearchCV 模块。

这是一个如何使用这个库的例子:

首先让我们定义一个随机数据采样的方法:

def make_data(N, err=1.0, rseed=1):

    rng = np.random.RandomState(rseed)
    X = rng.rand(N, 1) ** 2
    y = 1. / (X.ravel() + 0.3)
    if err > 0:
        y += err * rng.randn(N)
    return X, y

构建管道:

def PolynomialRegression(degree=2, **kwargs):
    return make_pipeline(PolynomialFeatures(degree), LinearRegression(**kwargs))

为测试和可视化目的创建一个数据和一个向量(X_test):

X, y = make_data(200)
X_test = np.linspace(-0.1, 1.1, 200)[:, None]

定义 GridSearchCV 参数:

param_grid = {'polynomialfeatures__degree': np.arange(20),
'linearregression__fit_intercept': [True, False],
'linearregression__normalize': [True, False]}
grid = GridSearchCV(PolynomialRegression(), param_grid, cv=7)
grid.fit(X, y)

从我们的模型中获取最佳参数:

model = grid.best_estimator_
model

Pipeline(memory=None,
     steps=[('polynomialfeatures', PolynomialFeatures(degree=4, include_bias=True, interaction_only=False)), ('linearregression', LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False))])

Xy 数据拟合模型并使用向量预测值:

y_test = model.fit(X, y).predict(X_test)

可视化结果:

plt.scatter(X, y)
plt.plot(X_test.ravel(), y_test, 'r')

The best fit result

完整代码sn-p:

from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV

def make_data(N, err=1.0, rseed=1):

    rng = np.random.RandomState(rseed)
    X = rng.rand(N, 1) ** 2
    y = 1. / (X.ravel() + 0.3)
    if err > 0:
        y += err * rng.randn(N)
    return X, y

def PolynomialRegression(degree=2, **kwargs):
    return make_pipeline(PolynomialFeatures(degree), LinearRegression(**kwargs))


X, y = make_data(200)
X_test = np.linspace(-0.1, 1.1, 200)[:, None]

param_grid = {'polynomialfeatures__degree': np.arange(20),
'linearregression__fit_intercept': [True, False],
'linearregression__normalize': [True, False]}
grid = GridSearchCV(PolynomialRegression(), param_grid, cv=7)
grid.fit(X, y)

model = grid.best_estimator_

y_test = model.fit(X, y).predict(X_test)

plt.scatter(X, y)
plt.plot(X_test.ravel(), y_test, 'r')

【讨论】:

    【解决方案3】:

    这就是贝叶斯模型选择真正发挥作用的地方。考虑到模型复杂性和数据拟合,这将为您提供最有可能的模型。我很累,所以快速回答是使用 BIC(贝叶斯信息标准):

    k = number of variables in the model
    n = number of observations
    sse = sum(residuals**2)
    BIC = n*ln(sse/n) + k*ln(n) 
    

    此 BIC(或 AIC 等)将为您提供最佳模型

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-30
      • 1970-01-01
      • 2010-09-29
      • 2017-12-20
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      相关资源
      最近更新 更多