线性回归的概念
给定一个数据集D={(x1,y1),(x2,y2),(x3,y3)…},所谓线性回归就是模拟出一个线性模型
f
(
X
)
=
k
∗
X
+
b
f(X) = k * X + b
f(X)=k∗X+b,使得对所有的x
∈
\in
∈D得到 f(X)
≈
\approx
≈ y
∈
\in
∈ D,即尽可能准确的预测真实的y值。
问题主要集中在我们该如何得到k、b的值呢?
关键在于如何度量f(X)与真实的y之间的差别,将误差控制在最小。
具体实现过程
首先便是loss(误差)函数的设定与引入,不妨仅仅考虑样本属性的数目只有一个(即X是标量)。我们使用均方误差最小化(最小二乘法)的方法:
E
(
k
,
b
)
=
a
r
g
(
k
,
b
)
m
i
n
∑
i
=
1
n
(
f
(
x
i
)
−
y
i
)
2
=
a
r
g
(
k
,
b
)
m
i
n
∑
i
=
1
n
(
y
i
−
k
∗
x
i
−
b
)
2
E_{(k , b)} = arg_{(k, b)} min\sum_{i=1}^n(f(x_i) - y_i)^2=arg_{(k, b)} min\sum_{i=1}^n(y_i - k * x_i- b )^2
E(k,b)=arg(k,b)mini=1∑n(f(xi)−yi)2=arg(k,b)mini=1∑n(yi−k∗xi−b)2
这个式子有很好的几何意义,代表着每个样本点到拟合曲线的距离平方值最小。使得
E
(
k
,
b
)
E_{(k , b)}
E(k,b)的值最小,就是所谓的参数估计。我们可以将
E
(
k
,
b
)
E_{(k , b)}
E(k,b)分别对k和b分别求偏导数,令得到的式子为零。便可以得到k、b的最优解。
因为我们经常遇到的问题很大可能是多维的,因此将属性值拓展为向量,则运算变为矩阵(矩阵X的最后一列是1):
E
(
k
^
)
=
(
y
−
X
k
^
)
T
(
y
−
X
k
^
)
E_{(\hat{k})}= (y-X\hat{k}) ^T(y-X\hat{k})
E(k^)=(y−Xk^)T(y−Xk^)
k
^
=
(
k
;
b
)
\hat{k} = (k;b)
k^=(k;b)
之后我们将 E ( k ^ ) E_{(\hat{k})} E(k^)对 k ^ \hat{k} k^求偏导便得到了 k ^ \hat{k} k^的最优解类似于一元的情况。但是矩阵并不一定是满秩的,即解不一定唯一,这时便要考虑到用户的归纳偏好问题,留在以后讨论。
实例的引入
有这样一个例子:
我们用numpy包生成一百个随机的x值,并且设定y值与x有一定的线性关系(k=0.1,b=0.2),然后把这样的线性关系绘制出来:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
%matplotlib inline
# 使用numpy生成100个随机点 样本
x_data = np.random.rand(100)
y_data = x_data * 0.1 + 0.2
fig, ax = plt.subplots()
ax.scatter(x_data, y_data)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
绘制出来的图是这样的:
之后我们用tensorflow(一个深度学习框架)的内置api直接构造一个线性回归的模型(采用梯度下降的方法),进行预测,设置迭代次数为201次,每当20的倍数时便将学习结果输出、绘制出来,会发现我们最终得到的图与原图相似(即斜率基本一致,偏置值基本一致)。
# 构造一个线性模型
b = tf.Variable(1.1)
k = tf.Variable(0.5)
y = k * x_data + b
# 二次代价函数
loss = tf.reduce_mean( tf.square(y_data - y) )
# 定义一个梯度下降法来进行训练的优化器
optimizer = tf.train.GradientDescentOptimizer(0.2) # 梯度下降 学习率是0.2
# 定义一个最小化代价函数
train = optimizer.minimize(loss)
# 初始化变量
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for step in range(201):
sess.run(train)
if step % 20 == 0:
data1 = np.random.rand(100)
data2 = data1 * sess.run(k) + sess.run(b)
fig, ax = plt.subplots()
ax.scatter(data1,data2)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
print(step, sess.run([k, b]))
最终的图如下:
且斜率值和偏置值分别问:[0.099538416, 0.20024595]。与初始的基本一致。
(代码看不懂或不了解 tensorflow 没关系,只要明白线性回归就好了)