如何找到多项式的最佳次数?
How to find the best degree of polynomials?
我是机器学习的新手,目前遇到了这个问题。
首先,我使用线性回归来拟合训练集,但得到非常大的 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 吗?或任何其他方法?
如果你能帮我解决这个问题,我将不胜感激。
你下次应该提供X/Y的数据,或者一些虚拟的,它会更快并为你提供特定的解决方案。现在我已经创建了一个 y = X**4 + X**3 + X + 1
.
形式的虚拟方程
您可以通过多种方式对此进行改进,但快速迭代以找到最佳度数的方法是简单地将您的数据拟合到每个度数并选择具有最佳性能(例如,最低 RMSE)的度数。
您还可以尝试如何决定保留您的 train/test/validation 数据。
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')
这将打印:
Best degree 4 with RMSE 1.27689038706e-08
或者,您也可以构建一个新的 class 来执行多项式拟合,并使用一组参数将其传递给 GridSearchCV。
在我看来,找到最佳曲线拟合度或一般拟合模型的最佳方法是使用 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))])
使用 X
和 y
数据拟合模型并使用向量预测值:
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
完整代码片段:
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')
这就是贝叶斯模型选择真正发挥作用的地方。鉴于模型复杂性和数据拟合,这为您提供了最有可能的模型。我超级累所以快速的答案是使用 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 等)将为您提供最佳模型
我是机器学习的新手,目前遇到了这个问题。 首先,我使用线性回归来拟合训练集,但得到非常大的 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 吗?或任何其他方法?
如果你能帮我解决这个问题,我将不胜感激。
你下次应该提供X/Y的数据,或者一些虚拟的,它会更快并为你提供特定的解决方案。现在我已经创建了一个 y = X**4 + X**3 + X + 1
.
您可以通过多种方式对此进行改进,但快速迭代以找到最佳度数的方法是简单地将您的数据拟合到每个度数并选择具有最佳性能(例如,最低 RMSE)的度数。
您还可以尝试如何决定保留您的 train/test/validation 数据。
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')
这将打印:
Best degree 4 with RMSE 1.27689038706e-08
或者,您也可以构建一个新的 class 来执行多项式拟合,并使用一组参数将其传递给 GridSearchCV。
在我看来,找到最佳曲线拟合度或一般拟合模型的最佳方法是使用 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))])
使用 X
和 y
数据拟合模型并使用向量预测值:
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
完整代码片段:
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')
这就是贝叶斯模型选择真正发挥作用的地方。鉴于模型复杂性和数据拟合,这为您提供了最有可能的模型。我超级累所以快速的答案是使用 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 等)将为您提供最佳模型