文章目录
线性回归之波士顿房价预测案例 欠拟合与过拟合
线性回归API 介绍:
波士顿房价预测
数据属性:
机器学习代码实现
1.导入库
from sklearn.preprocessing import StandardScaler # 特征处理
from sklearn.model_selection import train_test_split # 数据集划分
from sklearn.linear_model import LinearRegression # 正规方程的回归模型
from sklearn.linear_model import SGDRegressor # 梯度下降的回归模型
from sklearn.metrics import mean_squared_error # 均方误差评估
# from sklearn.datasets import load_boston # 数据
注意在新版本sklearn中上述读取数据方式失效通过下面方法读取数据
import pandas as pd
import numpy as np
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]
2.模型代码实现
# 正规方程法
def demo01():
# 数据集划分
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.2)
# 特征工程 特征预处理
transfer = StandardScaler() # 创建标准化对象
# 标准化 训练集 测试集
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 模型训练
estimator = LinearRegression() # 线性回归模型对象
estimator.fit(x_train, y_train)
# 模型预测
y_predict = estimator.predict(x_test)
# 和测试集的标签进行比较
# 1.均方误差
print("均方误差的误差为:", mean_squared_error(y_test, y_predict))
# 2.平均绝对误差
print("平均绝对误差的误差为:", mean_absolute_error(y_test, y_predict))
# 3.均方根误差
print("均方根误差的误差为:", root_mean_squared_error(y_test, y_predict))
# 梯度下降法
def demo02():
# 数据集划分
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.2)
# 特征工程 特征预处理
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 模型训练
estimator = SGDRegressor(max_iter=1000, learning_rate='constant',
eta0=0.001) # 获取梯度下降模型对象 max_iter 最大次数 eta0 学习率 ,learning_rate='constant' 设置学习率为常数
estimator.fit(x_train, y_train)
# 模型预测
y_predict = estimator.predict(x_test)
# 模型评估
# 1.均方误差
print("均方误差的误差为:", mean_squared_error(y_test, y_predict))
# 2.平均绝对误差
print("平均绝对误差的误差为:", mean_absolute_error(y_test, y_predict))
# 3.均方根误差
print("均方根误差的误差为:", root_mean_squared_error(y_test, y_predict))
运行结果 上为标准函数 下为梯度下降
拟合 过拟合 欠拟合 模拟 及处理方法(正则化处理)
导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error # 计算均方误差
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, Lasso
定义函数表示欠拟合
欠拟合出现的原因:学习到数据的特征过少
解决方法: 【从数据、模型、算法的角度去想解决方案】
添加其他特征
有时出现欠拟合是因为特征项不够导致的,可以添加其他特征项来解决
“组合”、“泛化”、“相关性”三类特征是特征添加的重要手段
添加多项式特征项
模型过于简单时的常用套路,例如将线性模型通过添加二次项或三次项使模型泛化能力更强
def demo01():
# 准备数据
# 准备噪声
np.random.seed(21)
# x 表示特征
x = np.random.uniform(-3, 3, size=100)
# y 表示目标值 线性关系 y = 0.5x^2 +x + 2 + 正态分布 + 噪声
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练
# 创建线性回归方程对象
estimator = LinearRegression()
# 训练
estimator.fit(x.reshape(-1, 1), y)
# 根据模型预测
y_predict = estimator.predict(x.reshape(-1, 1))
# 模型评估
print('均方误差', mean_squared_error(y, y_predict))
# 这里看到均方误差正常 但是实际上欠拟合 画图
plt.scatter(x, y) # x,y散点图
plt.plot(x, y_predict, color='red') # 拟合回归线 即预测值
plt.show()
根据数据可视化结果发现 均方误差正常,但是可视化结果表示模型欠拟合,用一次方程拟合二次
需要提升模型维度,增加特征值
定义函数表示拟合
在demo01 的基础上 对x 增加维度 即 拼接x和x^2 使得拟合回归线为2次方程
def demo02():
# 准备数据
# 准备噪声
np.random.seed(21)
# x 表示特征
x = np.random.uniform(-3, 3, size=100)
# y 表示目标值 线性关系 y = 0.5x^2 +x + 2 + 正态分布 + 噪声
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
x_reshape = x.reshape(-1, 1)
x2 = np.hstack([x_reshape, x_reshape ** 2]) # 拼接x和x的平方 增加模型维度
# 模型训练
# 创建线性回归方程对象
estimator = LinearRegression()
# 训练
estimator.fit(x2, y)
# 根据模型预测
y_predict = estimator.predict(x2)
# 模型评估
print('均方误差', mean_squared_error(y, y_predict))
# 这里看到均方误差正常 但是实际上欠拟合 画图
plt.scatter(x, y) # x,y散点图
plt.plot(x, y_predict, color='red') # 拟合回归线 即预测值
plt.show()
数据可视化结果虽然拟合曲线出来了,但是因为没有对散点排序,导致绘制时没有按顺序连接
def demo02():
# 准备数据
# 准备噪声
np.random.seed(21)
# x 表示特征
x = np.random.uniform(-3, 3, size=100)
# y 表示目标值 线性关系 y = 0.5x^2 +x + 2 + 正态分布 + 噪声
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
x_reshape = x.reshape(-1, 1)
x2 = np.hstack([x_reshape, x_reshape ** 2]) # 拼接x和x的平方 增加模型维度
# 模型训练
# 创建线性回归方程对象
estimator = LinearRegression()
# 训练
estimator.fit(x2, y)
# 根据模型预测
y_predict = estimator.predict(x2)
# 模型评估
print('均方误差', mean_squared_error(y, y_predict))
# 这里看到均方误差正常 但是实际上欠拟合 画图
plt.scatter(x, y) # x,y散点图
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='red') # 拟合回归线 即预测值
plt.show()
排序后正确的拟合线
定义函数表示过拟合
过拟合出现的原因:
- 原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点
解决办法:
- 重新清洗数据
- 对于过多异常点数据、数据不纯的地方再处理
- 增大数据的训练量
- 对原来的数据训练的太过了,增加数据量的情况下,会缓解
正则化
- 对原来的数据训练的太过了,增加数据量的情况下,会缓解
- 解决模型过拟合的方法,在机器学习、深度学习中大量使用
减少特征维度,防止维灾难 - 由于特征多,样本数量少,导致学习不充分,泛化能力差。
在demo02 函数上继续增加维度 会导致模型会兼顾每个测试点,导致过拟合
def demo03():
# 准备数据
# 准备噪声
np.random.seed(21)
# x 表示特征
x = np.random.uniform(-3, 3, size=100)
# y 表示目标值 线性关系 y = 0.5x^2 +x + 2 + 正态分布 + 噪声
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
x_reshape = x.reshape(-1, 1)
x2 = np.hstack(
[x_reshape, x_reshape ** 2, x_reshape ** 3, x_reshape ** 4, x_reshape ** 5, x_reshape ** 6, x_reshape ** 7,
x_reshape ** 8, x_reshape ** 9, x_reshape ** 10, x_reshape ** 11, x_reshape ** 12, x_reshape ** 13,
x_reshape ** 14, x_reshape ** 15, x_reshape ** 16, x_reshape ** 17, x_reshape ** 18,
x_reshape ** 19]) # 拼接x和x的平方 增加模型维度
# 模型训练
# 创建线性回归方程对象
estimator = LinearRegression()
# 训练
estimator.fit(x2, y)
# 根据模型预测
y_predict = estimator.predict(x2)
# 模型评估
print('均方误差', mean_squared_error(y, y_predict))
# 这里看到均方误差正常 但是实际上欠拟合 画图
plt.scatter(x, y) # x,y散点图
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='red') # 拟合回归线 即预测值
plt.show()
过拟合展示
正则化处理过拟合
L1正则化
在demo03基础上 将线性回归模型对象改为l1正则化线性回归模型对象
def demo04():
np.random.seed(21)
# x 表示特征
x = np.random.uniform(-3, 3, size=100)
# y 表示目标值 线性关系 y = 2x + 3 + 噪声
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练
# 创建 线性回归 L1 正则化 模型对象
estimator = Lasso(alpha=0.1) # alpha 正则化参数 值越大 正则化程度越大
# 对数据集做处理
# print("处理前:", x)
X = x.reshape(-1, 1)
# print("处理后:", X)
# 拼接 x 和 x 的平方
X2 = np.hstack(
[X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10, X ** 11, X ** 12, X ** 13, X ** 14,
X ** 15, X ** 16, X ** 17, X ** 18, X ** 19, X ** 20])
# print("处理后:", X2)
# 训练
estimator.fit(X2, y)
# 预测
y_predict = estimator.predict(X2)
print("预测值:", y_predict)
# 模型评估
print('均方误差', mean_squared_error(y, y_predict))
# 数据可视化 绘制图像
print(np.sort(x))
print(np.argsort(x))
plt.scatter(x, y) # 基于原始的x,y 绘制散点图
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='red') # 原始的x , y 预测值 绘制折线图(拟合回归线)
plt.show()
l1正则化过后的曲线
L1正则化通过改变权重,并将特殊点的权重完全改为0来避免过拟合问题
L2正则化
将模型改为L2正则化线性回归模型
def demo05():
# 准备数据
# 准备噪声
np.random.seed(21)
# x 表示特征
x = np.random.uniform(-3, 3, size=100)
# y 表示目标值 线性关系 y = 2x + 3 + 噪声
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练
# 创建 线性回归 L2 正则化 模型对象
estimator = Ridge(alpha=0.1) # alpha 正则化参数 值越大 正则化程度越大
# 对数据集做处理
# print("处理前:", x)
X = x.reshape(-1, 1)
# print("处理后:", X)
# 拼接 x 和 x 的平方
X2 = np.hstack(
[X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10, X ** 11, X ** 12, X ** 13, X ** 14,
X ** 15, X ** 16, X ** 17, X ** 18, X ** 19, X ** 20])
# print("处理后:", X2)
# 训练
estimator.fit(X2, y)
# 预测
y_predict = estimator.predict(X2)
print("预测值:", y_predict)
# 模型评估
print('均方误差', mean_squared_error(y, y_predict))
# 数据可视化 绘制图像
print(np.sort(x))
print(np.argsort(x))
plt.scatter(x, y) # 基于原始的x,y 绘制散点图
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='red') # 原始的x , y 预测值 绘制折线图(拟合回归线)
plt.show()