多项式回归与模型泛化(1)
1.多项式回归
当数据之间不具有线性关系时,采用非线性回归进行拟合
处理思想:将 x 2 x^2 x2 当作一个新的特征,再应用线性回归
from sklearn.linear_model import LinearRegression
X2 = np.hstack([X, X**2]) # 添加一个新的特征
lin_reg = LinearRegression()
lin_reg.fit(X2, y)
y_predict = lin_reg.predict(X2)
2.scikit-learn中的多项式回归
导入PolynomialFeatures
,构造一个有两个特征的数据
X
X
X
from sklearn.preprocessing import PolynomialFeatures
X = np.arange(1, 11).reshape(-1, 2)
X.shape
# (5, 2)
(1)构造
d
e
g
r
e
e
=
2
degree=2
degree=2 的PolynomialFeatures
对象,表示多项式回归中应用的特征最高次数为2
poly = PolynomialFeatures(degree=2) # 添加最多二次幂的特征
poly.fit(X)
X2 = poly.transform(X)
X2.shape
# (5, 6)
可见,目前特征数扩大到6个,分别为 1 , x 1 , x 2 , x 1 2 , x 2 2 , x 1 x 2 1, x_1, x_2, x_1^2, x_2^2, x_1x_2 1,x1,x2,x12,x22,x1x2
(2)构造
d
e
g
r
e
e
=
3
degree=3
degree=3 的PolynomialFeatures
对象,表示多项式回归中应用的特征最高次数为3
poly = PolynomialFeatures(degree=3) # 添加最多三次幂的特征
poly.fit(X)
X3= poly.transform(X)
X3.shape
# (5, 10)
可见,目前特征数扩大到10个,分别为 1 , x 1 , x 2 , x 1 2 , x 2 2 , x 1 x 2 , x 1 3 , x 2 3 , x 1 2 x 2 , x 1 x 2 2 1, x_1, x_2, x_1^2, x_2^2, x_1x_2, x_1^3, x_2^3, x_1^2x_2, x_1x_2^2 1,x1,x2,x12,x22,x1x2,x13,x23,x12x2,x1x22
使用Pipeline
多项式回归的步骤:扩充特征——归一化——线性回归
使用管道(Pipeline)可以将这三步进行封装
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
poly_reg = Pipeline([
("poly", PolynomialFeatures(degree=2)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])
poly_reg.fit(X, y)
y_predict = poly_reg.predict(X)
3.欠拟合与过拟合
对于一个使用二次方程+噪声生成的数据,分别用 d e g r e e = 1 , 10 , 100 degree=1, 10, 100 degree=1,10,100 的多项式回归进行拟合
d e g r e e = 1 degree=1 degree=1:欠拟合
d e g r e e = 10 degree=10 degree=10:过拟合
d e g r e e = 100 degree=100 degree=100:过拟合
欠拟合与过拟合
欠拟合(underfitting):算法所训练的模型不能完整表述数据关系
过拟合(overfitting):算法所训练的模型过多地表达了数据间的噪音关系
4.模型的泛化能力
模型的泛化能力:模型对新鲜样本的适应能力
过拟合的模型虽然在训练集上的损失低,但是对新数据的预测效果差,即泛化能力差
用测试数据集来衡量模型的泛化能力
5.学习曲线
欠拟合模型与最佳模型相比,无论是训练集还是测试集,误差都更大
过拟合模型与最佳模型相比,训练集的误差十分接近甚至更好,但测试集的误差很大,且测试集训练集差距较大,即模型的泛化能力弱
6.验证数据集与交叉验证
在真实场景下,模型的建立应该与测试数据集无关
将训练数据集分离出一部分作为验证数据集,用于调整超参数
为保证验证集的随机性,可采用交叉验证(cross validation)
scikit-learn中的交叉验证
from sklearn import datasets
from sklearn.model_selection import train_test_split
digits = datasets.load_digits()
X = digits.data
y = digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4)
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
knn_clf = KNeighborsClassifier()
cross_val_score(knn_clf, X_train, y_train, cv=5) # 5折交叉验证
# array([0.95833333, 0.98611111, 0.99074074, 0.99069767, 0.96744186])
两种交叉验证
-
k-folds交叉验证(K-folds Cross Validation)
把训练数据分成k份
缺点:每次训练k个模型,整体性能慢了k倍
-
留一法 LOO-CV(Leave-One-Cross Validation)
把训练数据集分成m份,每份只有一行数据
优点:完全不受随机的影响,最接近模型真正的性能指标
缺点:计算量巨大