回归指的是对于训练数据集 {xi,yi} ,其中, yi 是连续值。用过学习,找到函数 fθ(x) ,使得:
此时,为了度量找到的函数的优劣,设计了度量的函数,称为损失函数:
最小二乘法是对 Loss 函数为最小时的参数进行学习,即:
对于函数 fθ(x) ,若使用线性模型,即:
注意: Θ 和 Φ 表示的向量。
此时,损失函数的形式为:
其中, y=(y1,⋯,yn)T 是训练输出的 n 维向量, Φ 是一个 n×b 的矩阵,即:
为了能够求出 JLS(Θ) 最小值时对应的参数 Θ :
令其为 0 ,可求得最小值时对应的参数 Θ :
即:
其中, (ΦTΦ)−1ΦT 与广义逆 Φ† 等价。
对于如下的数据集:
画图的代码如下:
#coding:UTF-8
''' Date:20160423 @author: zhaozhiyong '''
from pylab import *
f =open("data.txt")
x = []
y = []
for line in f.readlines():
lines = line.strip().split("\t")
if len(lines) == 3:
x.append(float(lines[1]))
y.append(float(lines[2]))
f.close()
plot(x,y,".")
plt.title("data")
show()
利用最小二乘法求得的结果为:
[[ 3.00774324]
[ 1.69532264]]
代码如下:
#coding:UTF-8
''' Date:20160423 @author: zhaozhiyong '''
from numpy import *
def load_data():
f = open("data.txt")
x = []
y = []
for line in f.readlines():
lines = line.strip().split("\t")
x_tmp = []
if len(lines) == 3:
x_tmp.append(float(lines[0]))
x_tmp.append(float(lines[1]))
y.append(float(lines[2]))
x.append(x_tmp)
f.close()
return mat(x), mat(y).T
def lr(x, y):
if linalg.det(x.T * x) != 0:
return ((x.T * x)**(-1) * (x.T) * y)
if __name__ == "__main__":
x, y = load_data()
#核心的最小二乘
w = lr(x,y)
print w
最终的图形如下:
在上图中,我们发现直线并不能很好的拟合数据点,我们可以通过对数据点的局部进行加权,即:
通常对于权值,可以取为高斯核函数:
则此时,最优的参数 Θ 为:
对于矩阵 Φ ,对其进行奇异值分解:
其中, κk 称为奇异值,具有非负性, ψk 称为左奇异向量, ϕk 称为右奇异向量,对于左奇异向量和右奇异向量,其满足正交性:
此时,矩阵 Φ 的广义逆矩阵 Φ† 可以表示为:
其中:
对于训练样本的输入 {xi} ,其预测值为:
其中, ΦΦ† 是 Φ 在 R(Φ) 上的正交投影矩阵。由此可见,最小二乘法的输出向量 y 是由 R(Φ) 的正交投影得到的。
对于上述的最小二乘的求解方法,需要将训练数据以矩阵的形式全部存入内容中才能进行计算,这样的方法不利于大规模的数据集,在大规模的数据集的情况下,通常使用的方法是基于梯度下降的方法,如随机梯度下降法,由于损失函数 J 是一个凸函数:
(凸函数) J(θ) 是凸函数,指的是对任意的两地点 θ1 和 θ2 和任意的 t∈[0,1] ,有:
J(tθ1+(1−t)θ2)⩽tJ(θ1)+(1−t)J(θ2)
随机梯度下降法的基本步骤如下:
其中:
对于上述的回归问题,随机梯度下降法的求解结果为:
[[ 3.02488533 1.68122429]]
回归的结果如下:
程序代码如下:
#coding:UTF-8
''' Date:20160423 @author: zhaozhiyong '''
from numpy import *
def sgd(n, p):
f = open("data.txt")
w = mat(zeros((1, n)))#初始化
for line in f.readlines():
lines = line.strip().split("\t")
x_tmp = []
y = 0.0
if len(lines) == 3:
x_tmp.append(float(lines[0]))
x_tmp.append(float(lines[1]))
y = float(lines[2])
x = mat(x_tmp).T
w = w - p * (w * x - y) * x.T
f.close()
return w
if __name__ == "__main__":
w = sgd(2, 0.1)
print w