1.5 欠拟合和过拟合

1.5 欠拟合和过拟合

欠拟合(Underfitting):选择的模型过于简单,以致于模型对训练集和未知数据的预测都很差的现象。

过拟合(Overfitting):选择的模型过于复杂(所包含的参数过多),以致于模型对训练集的预测很好,但对未知数据预测很差的现象(泛化能力差)。
在这里插入图片描述

过拟合可以通过观测训练集和验证集的loss变化判断:随着epoch或step的增加,训练集 loss不断下降,而验证集loss先下降后抬升。

解决过拟合和欠拟合的方法

解决欠拟合的方法
增加特征数
高斯特征
组合特征
增加模型复杂度
或者采用拟合能力更强的模型
神经网络
解决过拟合的方法
增加训练数据量
减小模型复杂度
在目标函数中添加正则项
提前终止 EARLY STOPPING
DROP OUT

过拟合常见解决方法

1. 增加训练样本数目

从理论上说,只要有足够多的样本数量,任何模型都不会出现过拟合的情况。

生成200个训练样本
# 设置随机种子
np.random.seed(34)

sample_num = 200

# 从-10到10中随机抽取100个浮点数
x_train = np.random.uniform(-5, 5, size=sample_num)

# 将x从shape为(sample_num,)变为(sample_num,1)
X_train = x_train.reshape(-1,1)

# 生成y值的实际函数
y_train_real = 0.5 * x_train ** 3 + x_train ** 2 + 2 * x_train + 1

# 生成误差值
err_train = np.random.normal(0, 5, size=sample_num)

# 真实y值加上误差值,得到样本的y值
y_train = y_train_real + err_train

# 画出样本的散点图
plt.scatter(x_train, y_train, marker='o', color='g')

# 画出实际函数曲线
plt.plot(np.sort(x_train), y_train_real[np.argsort(x_train)], color='b', label='real curve')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

在这里插入图片描述

30阶多项式模型训练
# 生成多项式数据
poly = PolynomialFeatures(degree=30, include_bias=False)
X_train_poly = poly.fit_transform(X_train)

# 数据标准化(减均值除标准差)
scaler  = StandardScaler()
X_train_poly_scaled = scaler.fit_transform(X_train_poly)

# 线性回归模型训练
reg30 = LinearRegression()
reg30.fit(X_train_poly_scaled, y_train)

# 模型预测
y_train_pred30 = reg30.predict(X_train_poly_scaled)

# 画出样本的散点图
plt.scatter(x_train, y_train, marker='o', color='g')

# 画出实际函数曲线
plt.plot(np.sort(x_train), y_train_real[np.argsort(x_train)], color='b', label='real curve')

# 画出预测函数曲线
plt.plot(np.sort(x_train), y_train_pred30[np.argsort(x_train)], color='r', label='prediction curve')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

# 计算MSE
mse = mean_squared_error(y_train_pred30, y_train)
print('MSE: {}'.format(mse))

在这里插入图片描述

MSE: 24.92469385931622

明显过拟合的情况相较于100个数据点时候,要好很多,MSE也小了不少

30阶多项式模型预测
# 生成多项式数据
poly = PolynomialFeatures(degree=30, include_bias=False)
X_test_poly = poly.fit_transform(X_test)

# 数据标准化(减均值除标准差)
scaler  = StandardScaler()
X_test_poly_scaled = scaler.fit_transform(X_test_poly)

# 模型预测
y_test_pred30 = reg30.predict(X_test_poly_scaled)

# 画出样本的散点图
plt.scatter(x_test, y_test, marker='o', color='c', label='test dataset')

# 画出预测函数曲线
plt.plot(np.sort(x_test), y_test_pred30[np.argsort(x_test)], color='r', label='30 order')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

在这里插入图片描述

计算MSE
mse30 = mean_squared_error(y_test_pred30, y_test)

# 打印结果
print('MSE:')
print('30 order polynomial: {:.2f}'.format(mse30))

输出结果:

MSE:
30 order polynomial: 32.32

2. 在目标函数中增加正则项

多项式拟合:
y = w 0 + w 1 x + w 2 x 2 + w 3 x 3 + ⋯ + w n x n y=w_0+w_1x+w_2x^2+w_3x^3+\cdots+w_nx^n y=w0+w1x+w2x2+w3x3++wnxn

查看回归系数 w w w

将结果转换为pd.DataFrame表格形式

coef1 = pd.DataFrame(reg1.coef_, index=['w1'], columns=['coef'])
coef3 = pd.DataFrame(reg3.coef_, index=['w1', 'w2', 'w3'], columns=['coef'])
coef10 = pd.DataFrame(reg10.coef_, index=['w'+str(i) for i in range(1,11)], columns=['coef'])
coef30 = pd.DataFrame(reg30.coef_, index=['w'+str(i) for i in range(1,31)], columns=['coef'])

1阶多项式模型参数

coef1
coef1
w19.900252

3阶多项式模型参数

coef3
coef3
w17.789175
w27.000036
w325.295452

10阶多项式模型参数

coef10
coef10
w17.998547
w24.203915
w320.728305
w415.694967
w510.679321
w6-53.302415
w7-5.051154
w872.956004
w9-1.464603
w10-32.583643

30阶多项式模型参数

coef30
coef
w11.274825e+01
w2-1.515071e+02
w3-2.784062e+02
w49.881947e+03
w58.313355e+03
w6-2.294226e+05
w7-1.443295e+05
w82.805398e+06
w91.540533e+06
w10-2.094909e+07
w11-1.036432e+07
w121.035820e+08
w134.594186e+07
w14-3.558672e+08
w15-1.390464e+08
w168.741809e+08
w172.938075e+08
w18-1.558118e+09
w19-4.373421e+08
w202.020758e+09
w214.563577e+08
w22-1.888828e+09
w23-3.264643e+08
w241.240156e+09
w251.523610e+08
w26-5.429771e+08
w27-4.173929e+07
w281.424089e+08
w295.084136e+06
w30-1.693219e+07

可以发现30阶的模型系数 w w w绝对值已经到了 1 0 8 10^8 108量级


模型太复杂(阶数过多),发生过拟合时,系数 w w w绝对值往往会很大,输入 x x x的很小变化都可能带来输出 y y y较大的变化,导致函数变化剧烈。


添加正则项的实质就是限制系数 w w w的大小,使得输入 x x x的变化尽量小的影响输出 y y y的变化

训练Ridge回归(加L2正则)

使用到的api:

加L2正则的线性回归sklearn.linear_model.Ridge

用到的参数:

  • alpha:惩罚项,默认1.0。
# 生成多项式数据
poly = PolynomialFeatures(degree=30, include_bias=False)
X_train_poly = poly.fit_transform(X_train)

# 数据标准化(减均值除标准差)
scaler  = StandardScaler()
X_train_poly_scaled = scaler.fit_transform(X_train_poly)

# 线性回归模型训练
ridge30 = Ridge(alpha=1e-5)
ridge30.fit(X_train_poly_scaled, y_train)

# 模型预测
y_train_pred30 = ridge30.predict(X_train_poly_scaled)

# 画出样本的散点图
plt.scatter(x_train, y_train, marker='o', color='g')

# 画出实际函数曲线
plt.plot(np.sort(x_train), y_train_real[np.argsort(x_train)], color='b', label='real curve')

# 画出预测函数曲线
plt.plot(np.sort(x_train), y_train_pred30[np.argsort(x_train)], color='r', label='prediction curve')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

# 计算MSE
mse = mean_squared_error(y_train_pred30, y_train)
print('MSE: {}'.format(mse))
查看加正则后的回归系数

将结果转换为pd.DataFrame表格形式

coef30 = pd.DataFrame(ridge30.coef_, index=['w'+str(i) for i in range(1,31)], columns=['coef'])
coef30
coef
w110.011475
w23.557561
w3-4.055929
w47.173610
w5100.444037
w626.619616
w7-75.014554
w8-90.566477
w9-182.926719
w10-16.985566
w11172.986261
w12101.786157
w13257.743920
w14114.148736
w1514.865359
w1611.446064
w17-256.410161
w18-117.329198
w19-313.210520
w20-169.444870
w21-113.923504
w22-95.081605
w23205.527434
w2473.135599
w25413.318846
w26222.862258
w27261.405745
w28183.223254
w29-458.772049
w30-248.055649

可以发现,系数 w w w的确小了很多

模型检验
# 生成多项式数据
poly = PolynomialFeatures(degree=30, include_bias=False)
X_test_poly = poly.fit_transform(X_test)

# 数据标准化(减均值除标准差)
scaler  = StandardScaler()
X_test_poly_scaled = scaler.fit_transform(X_test_poly)

# 模型预测
y_test_pred30 = ridge30.predict(X_test_poly_scaled)

# 画出样本的散点图
plt.scatter(x_test, y_test, marker='o', color='c', label='test dataset')

# 画出预测函数曲线
plt.plot(np.sort(x_test), y_test_pred30[np.argsort(x_test)], color='r', label='30 order')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

在这里插入图片描述

计算MSE
mse30 = mean_squared_error(y_test_pred30, y_test)

# 打印结果
print('MSE:')
print('30 order polynomial: {:.2f}'.format(mse30))
MSE:
30 order polynomial: 43.50

添加正则项是有效的

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值