多项式回归

多项式回归

什么是多项式回归?

​ 多项式回归是一种回归算法(多项式回归是基于线性回归的扩展,多项式回归是用于解决非线性的回归问题).

img

对于这样的数据,虽然我们可以使用线性回归来拟合这些数据,但是这些数据更像是一条二次曲线,相应的方程是
y = a x 2 + b x + c y = ax^2+ bx + c y=ax2+bx+c
这是式子虽然可以理解为二次方程,但是我们呢可以从另外一个角度来理解这个式子:
如果将 x2 理解为一个特征,将 x 理解为另外一个特征,换句话说,本来我们的样本只有一个特征 x ,现在我们把他看成有两个特征的一个数据集。多了一个特征 x2 ,那么从这个角度来看, 这个式子依旧是一个线性回归的式子,但是从 x的角度来看,它就是一个二次的方程。

以上这样的方式,就是所谓的多项式回归相当于我们为样本多添加了一些特征,这些特征是原来样本的多项式项,增加了这些特征之后,我们可以使用线性回归的思路来更好的处理我们的数据。

多项式回归的应用场景

​ 多项式回归模型一般都是处理非线性的数据。

多项式回归的实现原理

  1. 做出数据的散点图

    1. 观察图形,确定拟合模型
    2. 加入多项式项,进行拟合

多项式回归的特点

  1. 能够拟合非线性可分的数据,更加灵活的处理复杂的关系
  2. 因为需要设置变量的指数,所以它是完全控制要素变量的建模
  3. 需要一些数据的先验知识才能选择最佳指数
  4. 如果指数选择不当容易出现过拟合

过拟合和欠拟合

欠拟合

​ 算法不能够很好的所有样本数据,算法所训练的模型不能完整的描述数据之间的关系。

​ (例: 一个二次曲线的数据 用一次曲线来拟合,就会造成欠拟合)

​ 解决方法:

​ 1. 添加多项式特征,这个在机器学习算法里面用的很普遍,例如将线性模型通过添加二次项或者三次项使模型泛化能力更强;

	2. 减少正则化参数,正则化的目的是用来防止过拟合的,但是模型出现了欠拟合,则需要减少正则化参数;
		3. 更换模型    ,使用非线性模型,比如核SVM 、决策树、深度学习等模型;
  		4. 调整模型的容量(capacity),模型的容量是指其拟合各种函数的能力。通俗地,就是增加数据量;

过拟合

​ 算法过度拟合了所有数据,过度表达了数据间的噪音关系。

​ (就是你使用训练数据拟合模型完美,一用测试数据,就MSE很大,这就是过拟合)

​ 解决方法:

  1. 进行交叉验证

    1. 正则化,即在进行目标函数或代价函数优化时,在目标函数或代价函数后面加上一个正则项,一般有L1正则与L2正则等。
    2. 扩大数据集,增加更多的数据样本

交叉验证与验证数据集

交叉验证主要分为两种: K-折交叉验证 和 留一法

普通情况:训练集+测试集 --> 模型 问题:可能过拟合

K-折交叉验证(k表示训练集拆成k份)

​ 缺点:每次训练k个模型,相当于整体性能满了k倍

实现代码:

#实现K近邻算法的一个类,一般都使用欧式距离进行测量。          这里仅仅是完成交叉验证,不完整
knn_clf_cv = KNeighborsClassifier()

#导入交叉验证的类 cross_val_score
from sklearn.model_selection import cross_val_score

#进行交叉验证。     参数为(训练出的模型 , train_data , train_label )
cross_val_score(knn_clf_cv,train_data,train_label)

对knn算法进行练习:


import numpy as np
from sklearn import datasets

digits = datasets.load_digits()# 导入数据集

X = digits.data
Y = digits.target

# 数据集训练集分割
from sklearn.model_selection import train_test_split
train_data,test_data ,train_label,test_label =train_test_split(X,Y,test_size=0.2,random_state=666)

from sklearn.neighbors import KNeighborsClassifier
best_k = 0
best_score = 0.0
best_p = 0
for k in range(1,11):
    for p in range(1,6):
        knn_clf = KNeighborsClassifier(n_neighbors = k,weights='distance',p=p)
        knn_clf.fit(train_data,train_label)
        scores = cross_val_score(knn_clf_cv,train_data,train_label)
        score = np.mean(score)
        if score > best_score:
            best_p = p
            best_score = score
            best_k = k

print('best_k',best_k)
print('best_p',best_p)
print('best_score ',best_score)

留一法

​ 留一法就是每次留下一个样本做测试集,其他样本做训练集,如果有k个样本,则需要训练k次,测试k次。

​ 优点:完全不受随机影响,最接近模型真实性能指标。

​ 缺点:计算量巨大

学习曲线

​ 随着训练样本的逐渐增多,算法训练出的模型的表现能力。
​ 通过学习曲线,可以查看模型的欠拟合和过拟合情况

image-20200212194144243

通常对于这样一个图,会有两根曲线:

  1. 一个是对于训练数据集来说的,模型越复杂,模型准确率越高,因为模型越复杂,对训练数据集的拟合就越好,相应的模型准确率就越高

  2. 对于测试数据集来说,在模型很简单的时候,模型的准确率也比较低,随着模型逐渐变复杂,对测试数据集的准确率在逐渐的提升,提升到一定程度后,如果模型继续变复杂,那么我们的模型准确率将会进行下降(欠拟合->正合适->过拟合)

from sklearn.linear_model import LinearRegression   #导入最小二乘线性回归模型

train_score = []    
test_score = []

for i in range(1,len(train_data)+1):
    #获取模型对象
    lin_reg = LinearRegression()
    #随着样本集的逐渐增加,来观察模型的学习能力
    #训练模型
    lin_reg.fit(train_data[:i],train_label[:i])
    
    
    #训练集评测
    # predict(x):预测方法,将返回值y_pred
    predict_train = lin_reg.predict(train_data[:i])
    #将均方误差存起来
    train_score.append(mean_squared_error(train_label[:i],predict_train))
    
    
    #测试集评测
    predict_test = lin_reg.predict(test_data)
    test_score.append(mean_squared_error(test_label,predict_test))

plt.plot(
    [i for i in range(1,len(train_data)+1)],np.sqrt(train_score),label='train_score')

plt.plot([i for i in range(1,len(train_data)+1)],np.sqrt(test_score),label='test_score')
plt.show()

Pipline(管道机制)

流水线的输入为一连串的数据挖掘步骤,其中最后一步必须是估计器(Estimator),可理解成分类器。前几步是转换器(Transformer)。输入的数据集经过转换器的处理后,输出的结果作为下一步的输入。最后,用位于流水线最后一步的估计器对数据进行分类。

from sklearn.pipeline import Pipeline				#导入各种类
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

x = np.random.uniform(-3,3,size = 100)
y = 0.5 - x **2 + x + 3 +np.random.normal(0,1,size=100)
X = x.reshape(-1,1)

'''
Pipeline创建流水线的功能:
跟踪记录各步骤的操作(以方便地重现实验结果)
对各步骤进行一个封装
确保代码的复杂程度不至于超出掌控范围
'''

poly = Pipeline([
    # PolynomialFeatures()	生成多项式特征项      例:如果有a,b两个特征,
    #	degree:控制多项式的度					  那么它的2次多项式为(1,a,b,a^2,ab, b^2)       
    ('poly', PolynomialFeatures(degree=2)),
    # StandardScaler()   标准化
    ('std_scaler', StandardScaler()),
    # 导入最小二乘线性回归模型
    ('lin_reg', LinearRegression())
])
#训练模型
poly.fit(X,y)
#预测
poly.predict(X)

多项式回归实战

polynomial=PolynomialFeatures(degree=2) # 构建多项式回归器对象 # degree是多项式的次数,此处初步的设置为2



import numpy as np
import matplotlib.pyplot as plt

x = np.random.uniform(-3,3,size = 100)
y = 0.5 - x **2 + x + 3 +np.random.normal(0,1,size=100)

plt.scatter(x,y)
plt.show()

from sklearn.linear_model import LinearRegression
X = x.reshape(-1,1)

from sklearn.model_selection import train_test_split

train_data,test_data ,train_label,test_label =train_test_split(X,y,test_size=0.2,random_state=666)
#模型对象
lin_reg = LinearRegression()
#训练模型
lin_reg.fit(train_data,train_label)

lin_reg.score(test_data,test_label)

#添加多项式

X2 = np.hstack([X , X**2])

lin_reg2 = LinearRegression()
#重新训练
lin_reg2.fit(X2,y)

predict_X2 = lin_reg2.predict(X2)

plt.scatter(x,y)
plt.plot(np.sort(x),predict_X2[np.argsort(x)],color='r')
plt.show()


你可能感兴趣的:(多项式回归)