线性回归的优点:
- 速度快:一旦训练完毕,就不再需要数据集
- 线性回归时多有机器学习的基础,概念非长重要
线性回归的缺点
- 不是特别容易理解,要多敲代码,多思考
1.为什么需要线性回归
- 试图找到自变量与因变量之间的关系
-
线性回归就是求解m和b的过程
注意:自变量可以有多个
2.初步理解梯度下降
-
梯度下降基本上是所有复杂极其学习框架的基石
-
初始数据集
面积 | 房价 |
---|---|
80 | 200 |
95 | 230 |
104 | 245 |
112 | 247 |
125 | 259 |
135 | 262 |
- Excel显示散点图
-
python拟合过程
(1)绘制散点图
import numpy as np import matplotlib.pyplot as plt data = np.array([ [80,200], [95,230], [104,245], [112,247], [125,259], [135,262] ]) fig = plt.figure(figsize=(6,6),dpi=80) plt.xlim(70,140) plt.ylim(0,300) plt.scatter(data[:,0],data[:,1],c='r',marker='o',label='like') plt.show()
绘制结果:
-
函数介绍
(1)figure语法说明
figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)
- num:图像编号或名称,数字为编号 ,字符串为名称
- figsize:指定figure的宽和高,单位为英寸
- dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80 1英寸等于2.5cm,A4纸是 21*30cm的纸张
- facecolor:背景颜色
- edgecolor:边框颜色
- frameon:是否显示边框
(2)scatter语法说明
scatter(x,y,s=20,c='b',marker='o',cmap=None,norm=None,vmin=None,vmax=None,alpha=None,linewidths=None,verts=None,hold=None,**kwargs)
颜色:
b–blue c–cyan g–green k–black
m–magenta r–red w–white y–yellow
(2)模拟拟合过程
- 第一次模拟拟合过程(改变b的值)
# 第一次模拟拟合过程 fig = plt.figure(figsize=(6,6),dpi=80) plt.xlim(70,140) plt.ylim(0,300) X = np.linspace(70,140,8)# 70到140之间创建8个点 Y = np.ones(8) * 200 plt.plot(X,Y) plt.scatter(data[:,0],data[:,1],c='r',marker='o') plt.show()
- 第二次模拟拟合过程
# 第二次模拟拟合过程 fig = plt.figure(figsize=(6,6),dpi=80) plt.xlim(70,140) plt.ylim(0,300) X = np.linspace(70,140,8)# 70到140之间创建8个点 Y = np.ones(8) * 200 plt.plot(X,Y) plt.scatter(data[:,0],data[:,1],c='r',marker='o') plt.show()
- 第三次模拟拟合过程
# 第三次模拟拟合过程 fig = plt.figure(figsize=(6,6),dpi=80) plt.xlim(70,140) plt.ylim(0,300) X = np.linspace(70,140,8)# 70到140之间创建8个点 Y = np.ones(8) * 246 plt.plot(X,Y) plt.scatter(data[:,0],data[:,1],c='r',marker='o') plt.show()
- 主要函数介绍
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
- start:返回样本数据开始点
- stop:返回样本数据结束点
- num:生成的样本数据量,默认为50
- endpoint:True则包含stop;False则不包含stop
- retstep:即如果为True则结果会给出数据间隔
- dtype:输出数组类型
- axis:0(默认)或-1
-
-
如何用数据证明哪一次模拟拟合过程更好
-
第一次模拟拟合
面积 预测价 真实价 差价 80 100 200 100 95 100 230 130 104 100 245 145 112 100 247 147 125 100 259 159 135 100 262 162 总计误差843万
-
第二次模拟拟合
面积 预测价 真实价 差价 80 200 200 0 95 200 230 33 104 200 245 45 112 200 247 47 125 200 259 59 135 200 262 62 总计误差243万
- 第三次模拟拟合
面积 预测价 真实价 差价 80 246 200 -46 95 246 230 -16 104 246 245 -1 112 246 247 1 125 246 259 13 135 246 262 16 总计误差(绝对值)93万
- 第四次模拟拟合
面积 预测价 真实价 差价 80 250 200 -50 95 250 230 -20 104 250 245 -5 112 250 247 -3 125 250 259 9 135 250 262 12 总计误差(绝对值)99万
-
3.MAE vs MSE
- MAE:最小绝对差
- MSE:最小均方差
最小绝对差的缺陷:
比对以下凉组数据
面积 | 预测价 | 真实价 | 差价 |
---|---|---|---|
80 | 246 | 200 | -46 |
95 | 246 | 230 | -16 |
104 | 246 | 245 | -1 |
112 | 246 | 247 | 1 |
125 | 246 | 259 | 13 |
135 | 246 | 262 | 16 |
总计误差为39万
面积 | 预测价 | 真实价 | 差价 |
---|---|---|---|
80 | 246.5 | 200 | -46.5 |
95 | 246.5 | 230 | -16.5 |
104 | 246.5 | 245 | -1.5 |
112 | 246.5 | 247 | 0.5 |
125 | 246.5 | 259 | 12.5 |
135 | 246.5 | 262 | 15.5 |
总计误差为93万
- 通过以上对比发现,利用MAE方法计算误差会出现以上现像
- 解决办法:均方差(MSE)
MSE计算公式
M S E = 1 n ∑ i = 1 n ( 预 测 值 i − 真 实 值 i ) 2 MSE=\cfrac 1n \sum_{i=1}^n(预测值_i -真实值_i)^2 MSE=n1i=1∑n(预测值i−真实值i)2
-
MSE就是红色和蓝色正方形的面积
-
excel计算MSE过程
- y = mx + b 令b = 0(简化模型)
-
代码实现过程
# 绘制拟合b过程
fig = plt.figure(figsize=(6,6),dpi=80)
b = np.linspace(1,400,400)# b从1变化到400
for i in b:
MSE = np.sum(np.square(i - data[:,1]))
plt.scatter(i,MSE,c='r',marker = 'o')
plt.show()
4.求导与梯度之间的关系
求导
- 求导后的值为正,增加自变量,误差变大。减少自变量,误差变小
- 求导后的值为负,增加自变量,误差减少。减少自变量,误差变大
- 求导后的值,绝对值大,变化的幅度大,绝对值小,变化的幅度小
梯度下降公式推导
M
S
E
=
∑
i
=
1
n
(
预
测
值
i
−
真
实
值
i
)
2
MSE= \sum_{i=1}^n(预测值_i -真实值_i)^2
MSE=i=1∑n(预测值i−真实值i)2
M S E = ∑ i = 1 n ( m ∗ 面 积 i + b − 真 实 值 i ) 2 MSE= \sum_{i=1}^n(m * 面积_i + b -真实值_i)^2 MSE=i=1∑n(m∗面积i+b−真实值i)2
- 假设m=0
M S E = ∑ i = 1 n ( b − 真 实 值 i ) 2 MSE= \sum_{i=1}^n(b -真实值_i)^2 MSE=i=1∑n(b−真实值i)2
- 对MSE关于b进行求导
M S E Δ b = ∑ i = 1 n 2 ∗ ( b − 真 实 值 i ) \cfrac {MSE}{Δb}= \sum_{i=1}^n2*(b -真实值_i) ΔbMSE=i=1∑n2∗(b−真实值i)
python实现求导过程
from sympy import * # 导入计算库
# 求导
i, n, b, Actual_i = symbols('i,n,b,Actual_i')#声明变量
init_printing(pretty_print=True)#初始化latex显示
expr = Sum((b-Actual_i)**2,(i,1,10)) # Σ(b-真实值)^2(i = [1,10])
print(diff(expr,b))
5.代码实现梯度下降
步骤:
(1)随机选取一个b值
(2)计算这个b值对应的MSE的斜率
(3)如果MSE的斜率非常大,那要根据MSE的斜率去修改b的值
(4)MSE值越大,b的修改值越大。MSE斜率为正,b需要减小。MSE斜率为负,b需要增加
(5)选取一个很小的值,叫learning_rate,学习速率,可以理解为迈开的步伐
(6)用learning_rate和MSE的信号取更新b的值
(7)重复(2)-(6)的步骤,直到MSE的斜率接近于0
pyhon实现
import numpy as np
import matplotlib.pyplot as plt
# 准备数据
data = np.array([
[80,200],
[95,230],
[104,245],
[112,247],
[125,259],
[135,262]
])
# 随机选取一个b值
b = 1
# 设置学习速率
learning_rate = 0.01
# b的变化历史
b_history=[]
# mse的变化历史
mse_history=[]
def gradientDecent():
global b
slop = 0# 斜率
mse = 0
for item in data[:,1]:
slop += (b - item)
mse += (b - item) ** 2
b -= (learning_rate * slop)
b_history.append(b)
mse_history.append(mse)
print("b={},mse的变化率={},mse={}".format(b,slop,mse))
for i in range(300):
gradientDecent()
# 以图表的方式绘制mse与b的关系
fig = plt.figure(figsize = (6,6),dpi=60)
plt.scatter(b_history,mse_history)
plt.show()
C++实现
//梯度下降算法
void gradientDecent(const std::vector<std::vector<int>> & inputData,float & b,const float learningRate) {
//(1)随机选取一个b值
//(2)计算这个b值对应的MSE
//(3)如果MSE的斜率非常大,那要根据MSE的斜率取修改b的值
//(4)MSE值越大,b的修改值越大。MSE斜率为正,b需要减小。MSE斜率为负,b需要增加
//(5)选取一个learning_rate
//(6)用learning_rate和MSE信号更新b的值
//(7)重复(2)—(6)步骤,直到MSE的斜率接近于0
int size = inputData[0].size();
//斜率
float slop = 0;
//MSE
float MSE = 0;
for (int i = 0; i < size; i++)
{
slop += (b - inputData[1][i]);
MSE += std::pow(b - inputData[1][i], 2);
}
b -= (learningRate * slop);
std::cout << "slop = " << slop << " MSE = " << MSE <<" b = "<<b<< std::endl;
}