1. 线性回归: 寻找一种能预测的趋势, 线性回归通过一个或者多个自变量(特征值)与因变量(目标值)之间进行建模的回归分析
1.1. 线性关系
- 二维:直线关系
- 三维:特征, 目标值, 平面当中
1.2. 线性关系定义
- 单个特征
-
y = kx + b
加b是为了对于单个特征的情况更加通用
- 多个特征
y = k1房子面积 + k2房子位置 + b
1.3. 线性模型
-
f(x) = w1 * x1 + w2 * x2 +... + wd * xd + b = wT * x
, 其中w为权重, b称为偏置项, 可以理解为 w0 x 1,
2. 数组和矩阵的对比
2.1. 数组
- 0维:5
- 1维:[5,2,1]
- 2维:[[5,2,1],[1,2,3]] [[5,2,1]]
- 3维:[[[]]] [[[5,2,1]]]
- 数组的运算 加法 乘法
- 数组在numpy中以ndarray存在,在运算上可以理解为两者是一样的
2.2. 矩阵
- 大多数算法计算的基础,
矩阵乘法必须是二维的
- 矩阵乘法:满足了特定运算需求
- (m行,l列)*(l行,n列)= (m行,n列)
2.3. 代码实现
import numpy as np
a = [[1,2,3,4],[5,6,7,8],[2,3,7,9]]
b = [2,2,2,2]
# 数组的乘法(广播机制)
np.multiply(a, b)
# 矩阵的乘法,必须是二维的
c = [[2],[2],[2],[2]]
np.dot(a, c)
3. 损失函数(误差大小)
3.1. 回归是一种迭代算法
3.2. 最小二乘法
- yi为第i个训练样本的真实值
- hw(xi)为第i个训练样本特征值组合预测函数
- 总损失定义:
J(θ) = (hw(x1) - y1)2 + (hw(x1) - y1)2 + … + (hw(xm) - ym)2, (尽量去减少这个损失)
3.3. 优化损失函数
- 目的:
- 通过迭代,找到模型中最优的w值,使得损失函数最小
- 方法:
- 正规方程(不做要求)
- 缺点: 当特征过于复杂, 求解速度太慢,对于复杂的算法, 不能使用正规方程求解(逻辑回归等)
- 一次运算得出, 小数据集可以使用(<10000)
- 不能解决拟合问题
- 梯度下降(重要)
- 理解: 沿着损失函数下降的方向找,就能够找到山谷的最低点, 然后更新w的值。 学习速率α需要手动指定
- 使用:面对训练数据规模十分庞大的任务
- 不断迭代
- 回归系数coef_指的就是w
4. sklearn线性回归正规方程、梯度下降API
4.1. 正规方程
- sklearn.linear_model.LinearRegression
4.2. 梯度下降
- sklearn.liner_model.SRDRegressor
4.3. 波士顿房价数据案例分析流程
- 波士顿地区房价数据获取
- 波士顿地区房价数据分割
训练与测试数据标准化处理
- 使用最简单的线性回归模型LinearRegression和梯度下降估计SGDRegressor对房价进行预测
5. 回归行能评估
- 均方误差(Mean Squared Error)
- 公式:
MES = ( (y1 - yx)^2 + (y2 - yx)^2 + ... + (ym - yx)^2 ) / m
注意: ym为预测值, yx为真实值 - API:sklearn.metrics.mean_squared_error
- mean_squared_error(y_true,y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
- 注意:真实值,预测值为标准化之前的值
6. 代码实现
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train,x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# estimator预测
# 正规方程求解预测结果
lr = LinearRegression()
lr.fit(x_train, y_train)
print(lr.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(lr.predict(x_test))
print(y_predict)
print("正规方程的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))
# 梯度下降求解预测结果
sgd = SGDRegressor()
sgd.fit(x_train, y_train.reshape(-1, ))
print(sgd.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(sgd.predict(x_test))
print(y_predict)
print("梯度下降的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))
7. 过拟合和欠拟合
- 过拟合
- 一个假设在训练数据上能够获得比其他假设更好的拟合,但是在训练数据外的数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
- 模型复杂的原因:数据的特征和目标值之间的关系不仅仅是线性关系
- 原因:原始特征过多,存在一些嘈杂特征,模型过于复杂是因为模型尝试去兼顾各个测试数据点
- 解决办法:
- 进行特征选择,消除关联性大的特征(很难做)
- 交叉验证(让所有数据都有过训练), 没有解决过拟合问题,能够检验
- 正则化
- 尽可能减小高次项特征的影响
- 欠拟合
- 一个假设在训练数据上不能获得更好的拟合,但是在训练数据外的数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
- 原因: 学习到数据的特征过少
- 解决办法:增加数据的特征数量
8. 带有正则化的线性回归-Ridge
- 正则化:尽量减少高次项的影响
- L2正则化:可以使得W的每个元素都很小,都接近于0
- 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
- 岭回归Ridge
- sklearn.linear_model.Ridge(alpha=1.0)
- 具有l2正则化的线性最小二乘法
- alpha:正则化力度
- coef_:回归系数
- 代码实现
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train,x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# estimator预测
# 正规方程求解预测结果
lr = LinearRegression()
lr.fit(x_train, y_train)
print(lr.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(lr.predict(x_test))
print(y_predict)
print("正规方程的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))
# 梯度下降求解预测结果
sgd = SGDRegressor()
sgd.fit(x_train, y_train.reshape(-1, ))
print(sgd.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(sgd.predict(x_test))
print(y_predict)
print("梯度下降的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))
# 岭回归求解预测结果
rd = Ridge()
rd.fit(x_train, y_train.reshape(-1, ))
print(rd.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(rd.predict(x_test))
print(y_predict)
print("岭回归的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))
- 线性回归 LinearRegression与Ridge对比
- 岭回归:回归得到的回归系数更符合实际,更可靠。另外,能让估计参数的波动范围变小,变的更稳定。在存在病态数据偏多的研究中有较大的实用价值。
9. 模型的保存于加载
- 保存模型
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.externals import joblib
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train,x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# 岭回归求解预测结果
rd = Ridge()
rd.fit(x_train, y_train.reshape(-1, ))
print(rd.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(rd.predict(x_test))
print(y_predict)
print("岭回归的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))
# 保存模型
joblib.dump(rd, "./tmp/test.pkl")
- 加载模型
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.externals import joblib
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train,x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# 加载保存模型
model = joblib.load("./tmp/test.pkl")
model.fit(x_train, y_train.reshape(-1, ))
print(model.coef_)
# 预测测试集的房子价格
y_predict = std_y.inverse_transform(model.predict(x_test))
print(y_predict)
print("加载保存模型岭回归的均方误差:", mean_squared_error(y_true=std_y.inverse_transform(y_test), y_pred=y_predict))