python机器学习系列:线性回归算法的实现

本来不想写太多关于这方面的基础知识的,但是为了加强理解,我想不妨直接写博文记录也是一个好的选择,也可以顺便帮助需要的人,何乐而不为呢?

那么开始吧。我在原课程的基础上进行那么一点点修改。

这是我学习的相应的课程地址:https://pythonprogramming.net/how-to-program-best-fit-line-machine-learning-tutorial/?completed=/how-to-program-best-fit-line-slope-machine-learning-tutorial/

这不是一个小白教程,需要自行取了解一些基础知识,基础知识我仅仅是一笔带过。

算法原理

众所周知,线性回归算法是以一条直线来将一些散点进行分类的算法,而这条直线通常可理解为y(x)=mx+b/y=mx+b这样的函数(这是最简单的线性回归算法实例),其中m为直线的斜率,而y为直线的截距,而x为直线的自变量。

如下图,我们要将图1的散点,通过图2一条直线进行适当良好的分类开来:

  • 图1

  • 图2

求解m:

如图:

求解b:

如图:

实际上这与所谓的感知机是一样的原理(相关的知识可见李航老师的书籍《统计需诶下方法》)。再者,经过python实现编写对应的公式再进行可视化验证即可完成任务了。

算法实现

因为仅仅是为了说明算法的实现,所以数值就随便取的来用了。

数值取值:

1
2
3
4
import numpy as np
xs = np.array([1,2,3,4,5,6],dtype=np.float64)
ys = np.array([5,4,6,5,6,7],dtype=np.float64)

代码实现公式原理

1
2
3
4
5
6
7
8
9
10
11
from statistics import mean
def best_fit_slope_and_intercept(xs,ys):
#实现m参数,两种实现方法
#m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)*mean(xs) - mean(xs*xs))
m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)**2 - mean(xs**2))
#实现b参数
b = mean(ys)-m*mean(xs)
return m,b

画图预测展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import matplotlib.pyplot as plt
plt.style.use('ggplot')
m,b = best_fit_slope_and_intercept(xs,ys)
regression_line = [(m*x)+b for x in xs] #y(x)的实现
#趋势直线点向
predict_x = 9
predict_y = (m*predict_x)+b
#散点图
plt.scatter(xs,ys)
plt.scatter(predict_x,predict_y)
plt.plot(xs,regression_line) #直线描绘
plt.show()

如图:

这样就完成任务了。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
xs = np.array([1,2,3,4,5,6],dtype=np.float64)
ys = np.array([5,4,6,5,6,7],dtype=np.float64)
# print(xs,ys)
def best_fit_slope_and_intercept(xs,ys):
#m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)*mean(xs) - mean(xs*xs))
m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)**2 - mean(xs**2))
b = mean(ys)-m*mean(xs)
return m,b
m,b = best_fit_slope_and_intercept(xs,ys)
regression_line = [(m*x)+b for x in xs] #y(x)的实现
predict_x = 9
predict_y = (m*predict_x)+b
plt.scatter(xs,ys)
plt.scatter(predict_x,predict_y)
plt.plot(xs,regression_line) #直线描绘
plt.show()

铺助理解链接

补充R平方理论以及检验假设

强烈建议查看书籍学习了解相关的统计知识:

商务与经济统计:https://pan.baidu.com/s/1O9G7l4QbeqOPsPs_90lFGA

这是一本好书。

关于R平方理论

又称决定系数/判定系数。这是检验一个线性回归中y变量的变差与x变量的变差比例的系数,比例越大说明这个线性方程的拟合效果越好(可简单的理解为,它就是衡量一个线性回归算法的拟合精确度的)。它与相关系数也是有关系的。

可查看百度文库的解释

就不再多说了,这篇文章不是给小白看的教程,只注重实践部分。

公式

图一:

这个公式还可变换为:

其中r^2 = SSR/SST = 1 - SSE/SST亦成立,所以这里的r^2 = SSR/SST = 1 - SSE/SST公式即对应着图一的公式,这样就好理解下面写的代码了。

目的是检验上方的ys取值(即测试数据点的坐标y轴线的取值点)与训练得出的y(x)(即上方程序中的regression_line)的拟合效果如何(会有一个量化值出现)。

可参考:

线性回归中的相关度和决定系数

Coefficient of Determination (R-Squared)

代码实现演示

1
2
3
4
5
6
7
8
9
10
11
12
13
#平方误差函数
def squared_error(ys_orig, ys_line):
return sum((ys_line-ys_orig)**2)
def coefficient_of_determination(ys_orig, ys_line):
y_mean_line = [mean(ys_orig) for y in ys_orig]
squared_error_regr = squared_error(ys_orig, ys_line) #SSE
squared_error_y_mean = squared_error(y_mean_line, ys_orig) #SST
return 1 - (squared_error_regr / squared_error_y_mean)
print(y_mean_line)
r_squared = coefficient_of_determination(ys, regression_line)
print(r_squared)

代入以上完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
xs = np.array([1,2,3,4,5,6],dtype=np.float64)
ys = np.array([5,4,6,5,6,7],dtype=np.float64)
# print(xs,ys)
def best_fit_slope_and_intercept(xs,ys):
#m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)*mean(xs) - mean(xs*xs))
m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)**2 - mean(xs**2))
b = mean(ys)-m*mean(xs)
return m,b
def squared_error(ys_orig, ys_line):
return sum((ys_line-ys_orig)**2)
def coefficient_of_determination(ys_orig, ys_line):
y_mean_line = [mean(ys_orig) for y in ys_orig]
squared_error_regr = squared_error(ys_orig, ys_line) #SSE
squared_error_y_mean = squared_error(y_mean_line, ys_orig) #SST
return 1 - (squared_error_regr / squared_error_y_mean)
print(y_mean_line)
m,b = best_fit_slope_and_intercept(xs,ys)
regression_line = [(m*x)+b for x in xs] #y(x)的实现
r_squared = coefficient_of_determination(ys, regression_line)
print(r_squared)
#predict_x = 9
#predict_y = (m*predict_x)+b
#plt.scatter(xs,ys)
#plt.scatter(predict_x,predict_y)
#plt.plot(xs,regression_line) #直线描绘
#plt.show()

将会输出一个R的平方值,用以衡量拟合效果如何。

关于检验假设

关于检验假设,这是一个可检验数据是否符合相关算法的一个验证,也可理解为先假设,然后去验证对不对(验证假设对不对)。这可与关于R平方理论(输出效果量化值)结合,从而可得出算法对于多类不同数据的拟合效果如何。

在此之后将通过伪随机生成器(可理解只要是计算机生成的随机数都是伪随机数)来进行一段实例演示。

随机数:真随机数和伪随机数

代码实现演示

这里既是一个简单的随机数据生成器,与相关性、方差有关,为其中的参数选择。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import random
#数据量的多少,方差,平均每个点步骤(与相关性的取值有关),相关性设定,默认无相关性
def create_dataset(hm, variance, step=2, correlation=False):
val = 1 #初始值
ys = []
for i in range(hm):
y = val + random.randrange(-variance,variance)
ys.append(y)
#若为正相关
if correlation and correlation == 'pos':
val += step
elif correlation and correlation =='neg':
val -= step
xs = [i for i in range(len(ys))] #xs为平常的顺序取值数
return np.array(xs, dtype=np.float64), np.array(ys, dtype=np.float64)
xs, ys = create_dataset(40, 40, 2, correlation='pos')

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
import random
plt.style.use('ggplot')
# xs = np.array([1,2,3,4,5,6],dtype=np.float64)
# ys = np.array([5,4,6,5,6,7],dtype=np.float64)
#数据量的多少,方差,平均每个点步骤(与相关性的取值有关),相关性设定,默认无相关性
def create_dataset(hm, variance, step=2, correlation=False):
val = 1 #初始值
ys = []
for i in range(hm):
y = val + random.randrange(-variance,variance)
ys.append(y)
#若为正相关
if correlation and correlation == 'pos':
val += step
elif correlation and correlation =='neg':
val -= step
xs = [i for i in range(len(ys))] #xs为平常的顺序取值数
return np.array(xs, dtype=np.float64), np.array(ys, dtype=np.float64)
def best_fit_slope_and_intercept(xs,ys):
#实现m参数
#m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)*mean(xs) - mean(xs*xs))
m = (mean(xs)*mean(ys) - mean(xs*ys)) / (mean(xs)**2 - mean(xs**2))
#实现b参数
b = mean(ys)-m*mean(xs)
return m,b
#平方误差函数
def squared_error(ys_orig, ys_line):
return sum((ys_line-ys_orig)**2)
def coefficient_of_determination(ys_orig, ys_line):
y_mean_line = [mean(ys_orig) for y in ys_orig]
squared_error_regr = squared_error(ys_orig, ys_line) #SSE
squared_error_y_mean = squared_error(y_mean_line, ys_orig) #SST
return 1 - (squared_error_regr / squared_error_y_mean)
print(y_mean_line)
xs, ys = create_dataset(40, 40, 2, correlation='pos')
m,b = best_fit_slope_and_intercept(xs,ys)
regression_line = [(m*x)+b for x in xs] #y(x)的实现
r_squared = coefficient_of_determination(ys, regression_line)
print(r_squared)
#趋势点向
predict_x = 9
predict_y = (m*predict_x)+b
#散点图
plt.scatter(xs,ys)
plt.scatter(predict_x,predict_y)
plt.plot(xs,regression_line) #直线描绘
plt.show()

Python randrange() 函数

结果展示

会输出一个R平方值和一张由于随机数据为基础的训练图表。

---------------本文终---------------

文章作者:刘俊

最后更新:2019年01月02日 - 14:01

许可协议: 转载请保留原文链接及作者。