问题描述
有一个函数,现在不知道函数的的具体形式,给定满足函数关系的一组训练样本,请使用线性回归模型拟合出函数y=f(x)。
(可尝试一种或几种不同的基函数,如多项式、高斯或sigmoid基函数)
要求:
i. 先完成最小二乘法的优化 (参考书中第二章 2.3节中的公式)
ii. 附加题:实现“多项式基函数”以及“高斯基函数”(可参考PRML)
iii. 附加题:完成梯度下降的优化 (参考书中第二章 2.3节中的公式)
使用训练集train.txt 进行训练,使用测试集test.txt 进行评估(标准差),训练模型时请不要使用测试集。
读取数据
我们先将采集到的数据个读出来:这里以txt的格式保存,利用numpy库从文本中读取数据(注意jupyter notebook中数据必须保存到所建立):
import numpy as np #导入numpy库
import matplotlib.pyplot as plt
train_dataset = np.loadtxt('train.txt')
test_dataset = np.loadtxt('test.txt')
#print(len(train_dataset))
#print(len(test_dataset))
#print(train_dataset)
#print(test_dataset)
在读出所给的数据之后,我们按照题目所给的要求完成最小二乘法的优化(参照书上2.3节公式)这里单单我们看书是很难理解的,因为合理给出了优化参数的方法,但是我拿到这道题目的时候被难住的是最开始的基本线性回归的知识。题目中提到了用到基函数(内心很是mengbi)下面将一些基础知识整理一下,然后自己再试着编程看一看。
线性回归(线性基函数)
最简单的线性回归模型的形式如下所示:
y
(
x
,
w
)
=
w
0
+
w
1
x
+
⋅
⋅
⋅
+
w
n
x
n
y\left( \mathbf{x,w} \right) =w_0+w_1x+···+w_nx_n
y(x,w)=w0+w1x+⋅⋅⋅+wnxn
其中
x
=
(
x
1
,
x
2
,
⋯
,
x
n
)
T
\mathbf{x}=\left( x_1,x_2,\cdots ,x_n \right) ^T
x=(x1,x2,⋯,xn)T,
y
y
y是输入变量
x
1
x_1
x1的线性组合,这种模型具有很大的局限性。
一般用向量形式写成:
f
(
x
)
=
w
T
x
+
b
f\left( x \right) =\mathbf{w}^Tx+b
f(x)=wTx+b
其中$\mathbf{w}=\left( w_1,w_2,\cdots ,w_n \right)
,
,
,w
和
和
和b$学得之后,模型就可以确定。
我们可以将其扩展为输入变量通过有限个非线性函数转换后的线性组合,如下式表示:
y
(
x
,
w
)
=
w
0
+
∑
j
=
1
n
−
1
w
j
ϕ
j
(
x
)
y\left( \mathbf{x,w} \right) =w_0+\sum_{j=1}^{n-1}{w_j\phi _j\left( \mathbf{x} \right)}
y(x,w)=w0+j=1∑n−1wjϕj(x)
这里$\phi \left( \mathbf{x} \right)
就
是
基
函
数
。
我
们
可
以
添
加
一
个
基
函
数
就是基函数。我们可以添加一个基函数
就是基函数。我们可以添加一个基函数\phi 0=1
,
则
上
式
就
可
以
改
为
,则上式就可以改为
,则上式就可以改为$y\left( \mathbf{x,w} \right) =\sum{j=0}^{M-1}{w_j\phi _j\left( \mathbf{x} \right)}=\mathbf{w}^T\phi \left( \mathbf{x} \right) $$
这里
w
=
(
w
0
,
w
1
,
⋯
w
n
−
1
)
T
\mathbf{w}=\left( w_0,w_1,\cdots w_{n-1} \right) ^T
w=(w0,w1,⋯wn−1)T
,
ϕ
=
(
ϕ
0
,
ϕ
1
,
⋯
ϕ
n
−
1
)
T
\phi =\left( \phi _0,\phi _1,\cdots \phi _{n-1} \right) ^T
ϕ=(ϕ0,ϕ1,⋯ϕn−1)T基函数$\phi _j\left( x \right) $可以有多种不同类型,常见的基函数有:
·多项式基函数: ϕ j ( x ) = x j \phi _j\left( x \right) =x^j ϕj(x)=xj
·高斯基函数:
ϕ
j
(
x
)
=
e
{
−
(
x
−
u
j
)
2
2
s
2
}
\phi _j\left( x \right) =e^{\left\{ -\frac{\left( x-u_j \right) ^2}{2s^2} \right\}}
ϕj(x)=e{−2s2(x−uj)2}
这里
u
u
u控制位置
s
s
s控制跨度
·
s
i
g
m
o
i
d
sigmoid
sigmoid基函数
ϕ
j
(
x
)
=
σ
(
x
−
u
j
s
)
\phi _j\left( x \right) =\sigma \left( \frac{x-u_j}{s} \right)
ϕj(x)=σ(sx−uj)
σ
(
a
)
=
1
1
+
e
(
−
a
)
\sigma \left( a \right) =\frac{1}{1+e^{\left( -a \right)}}
σ(a)=1+e(−a)1
参数估计
一般的情况是数据集 D i D_i Di样本是由 d d d个属性描述,此时我们试图学得 f ( x i ) = w T x i + b f\left( x_i \right) =\mathbf{w}^Tx_i+b f(xi)=wTxi+b使得 f ( x i ) ⋍ y i \ f\left( x_i \right) \backsimeq y_i f(xi)⋍yi,这称为“多元线性回归”(multivariate linear reegression)
类似的我们可以用最小二乘法对
w
w
w和
b
b
b进行估计,为了便于讨论我们将
w
w
w和
b
b
b吸入向量形式$\mathbf{\hat{w}}=\left( \mathbf{w:b} \right)
,
相
应
的
,
把
数
据
集
,相应的,把数据集
,相应的,把数据集D
表
示
为
一
个
表示为一个
表示为一个m×(d+1)
大
小
的
矩
阵
大小的矩阵
大小的矩阵X$,其中每行对应于一个示例表示为下述矩阵形式:
X
=
[
l
x
11
x
12
⋯
x
1
d
1
x
21
x
22
⋯
x
2
d
1
⋮
⋮
⋱
⋮
⋮
x
m
1
x
m
2
⋯
x
m
d
1
]
=
[
l
x
1
T
1
x
2
T
1
⋮
⋮
x
m
T
1
]
\mathbf{X}=\left[ \begin{matrix}{l} x_{11}& x_{12}& \cdots& x_{1d}& 1\\ x_{21}& x_{22}& \cdots& x_{2d}& 1\\ \vdots& \vdots& \ddots& \vdots& \vdots\\ x_{m1}& x_{m2}& \cdots& x_{md}& 1\\ \end{matrix} \right] =\left[ \begin{matrix}{l} x_{1}^{T}& 1\\ x_{2}^{T}& 1\\ \vdots& \vdots\\ x_{m}^{T}& 1\\ \end{matrix} \right]
X=⎣⎢⎢⎢⎡lx11x21⋮xm1x12x22⋮xm2⋯⋯⋱⋯x1dx2d⋮xmd11⋮1⎦⎥⎥⎥⎤=⎣⎢⎢⎢⎡lx1Tx2T⋮xmT11⋮1⎦⎥⎥⎥⎤
当
X
T
X
X^TX
XTX为满秩矩阵的时候或者为正定矩阵的时候令上式为零我们可以很快速的求得参数。
w
^
∗
=
(
X
T
X
)
−
1
X
T
y
\hat{w}^*=\left( X^TX \right) ^{-1}X^Ty
w^∗=(XTX)−1XTy
这里我们可以很快的求得多元线性回归模型为:
f
(
x
^
i
)
=
x
^
i
T
(
X
T
X
)
−
1
X
T
y
f\left( \hat{x}_i \right) =\hat{x}_{i}^{T}\left( X^TX \right) ^{-1}X^Ty
f(x^i)=x^iT(XTX)−1XTy然而现实中
X
T
X
X^TX
XTX往往不是满秩矩阵,例如很多任务中我们会遇到大量的变量,其数目超过了样例数,导致
X
X
X的列数多于行数,
X
T
X
X^TX
XTX显然不是满秩矩阵此时有多个
w
^
\hat{w}
w^,它们都能够是均方差最小化,这里将引入正则化(regularization)项。这里将先不论述正则化,待以后再写一篇正则化的博客。
下面我们根据上述的要求来进行编程实现。
按照最小二乘法进行处理
from numpy import mat
#先将训练集x数据导出来做成矩阵的形式
x_train_dataset=train_dataset[:,0]
#将一维数组转换为矩阵
x_train_dataset=mat(x_train_dataset).reshape(300,1)
a = np.ones(300)
x_train_dataset=np.column_stack((x_train_dataset,a))
#print(x_train_dataset)
print(x_train_dataset.shape)
#将训练集y数据导出来
y_train_dataset=train_dataset[:,1]
y_train_dataset=mat(y_train_dataset).reshape(300,1)
#print(y_train_dataset.shape)
#print(y_train_dataset)
#将训练集x进行转置
xt_train_dataset=np.transpose(x_train_dataset)
print(xt_train_dataset.shape)
#print(xt_train_dataset)
(300, 2)
(2, 300)
# 利用公式求参数w
w_predict = np.matmul(xt_train_dataset,x_train_dataset)
#print(w_predict)
w_predict = np.linalg.inv(w_predict)
#print(w_predict)
w_predict = np.matmul(w_predict,xt_train_dataset )
w_predict = np.matmul(w_predict,y_train_dataset )
print(w_predict)
[[0.94732599]
[0.62680273]]
我们已经计算出参数,现在利用matplotlib将其可视化(散点图和直线图)
#重新读取数据
x_train_dataset=train_dataset[:,0]
y_train_dataset=train_dataset[:,1]
#画散点图
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x_train_dataset,y_train_dataset,color='red',marker='o',s=1)
ax.plot(x, 0.94732599*x+0.62680273,color='green',ls='-')
#画直线图
上数我们计算出所需要的参数,这里利用测试集去测试所得参数的效果。我们计算出偏差和方差来对此种算法进行评估:
x_test_dataset=test_dataset[:,0]
#print(y_test_dataset)
x_test_dataset=mat(x_test_dataset).reshape(200,1)
#print(y_test_dataset)
y_test_dataset=test_dataset[:,1]
y_test_dataset=mat(y_test_dataset).reshape(200,1)
#print(y_test_dataset)
import math
bias2 = 0
#测试
#bias2=bias2+math.pow((x_test_dataset[1]*0.94732599+0.62680273)-y_test_dataset[1],2)
#print(bias2)
for i in range (0,200):
bias2=bias2+math.pow((x_test_dataset[i]*0.94732599+0.62680273)-y_test_dataset[i],2)
print(bias2)
#之前看吴恩达的视频其中讲到要尽量避免用到loop语句,
#下面我将对其进行修正
926.8174513840322