代码之家  ›  专栏  ›  技术社区  ›  Billy Chow

如何找到多项式的最佳阶?

  •  5
  • Billy Chow  · 技术社区  · 8 年前

    我是机器学习新手,目前一直在学习。 首先,我使用线性回归拟合训练集,但得到非常大的均方根误差。然后我尝试使用多项式回归来减少偏差。

    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
    

    然后我得到了比线性回归稍好的结果,然后我继续设置度=3/4/5,结果不断变好。但随着学位的提高,这可能有点过分了。

    多项式的最佳阶数应该是在交叉验证集中生成最低均方根误差的阶数。但我不知道如何做到这一点。我应该使用GridSearchCV吗?或者其他方法?

    如果你能告诉我这个,我将不胜感激。

    3 回复  |  直到 8 年前
        1
  •  6
  •   PythonNoob    8 年前

    在我看来,找到最佳曲线拟合度或一般拟合模型的最佳方法是使用scikit学习库中的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_测试),用于测试和可视化:

    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')
    
        2
  •  4
  •   Community Mohan Dere    6 年前

    下次你应该提供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')
    

    这将打印:

    RMSE 1.27689038706e-08的最佳学位4

    enter image description here

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

        3
  •  0
  •   monkey    7 年前

    这就是贝叶斯模型选择真正发挥作用的地方。鉴于模型复杂性和数据拟合,这将为您提供最可能的模型。我太累了,所以快速的答案是使用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等)将为您提供最佳模型