原理
回归往往是对连续数据进行线形拟合的,用一条线尽可能的串起来所有的点。
大概就是如图所示,画线的方法有很多种,我们期待这条线具有非常好的泛化,显然绿色的线就有一点过拟合的情况,不符合我们的期待。我们期待的是像黑色的线,能够变现出数据的趋势。
这里作出回归主要有三个种回归
- 线性回归(基础版
- 局部加权线形回归
- 岭回归和逐步线形回归(这种两种比较少用归为一类)
回归原理
常见的基本函数
y
=
k
x
+
b
y = kx+b
y=kx+b我们会需要计算的参数有
k
,
b
k,b
k,b,计算的方法有很多,但是最终化简的结构都差不多的。
这里我们换一个为了书写方便的字母:
h
(
x
)
=
θ
0
+
θ
1
x
h
(
x
)
=
∑
i
=
0
n
θ
i
x
i
=
θ
T
x
h(x) = \theta_0+\theta_1x \\ h(x) = \sum_{i=0}^n\theta_ix_i=\theta^Tx
h(x)=θ0+θ1xh(x)=i=0∑nθixi=θTx
在现实世界里,我们没有办法保证每个等式都是成立的,就必然会产生一定的误差
ε
\varepsilon
ε,每个等式都会有一定的误差,我们希望整体的误差是最小的。
h
(
x
)
=
∑
i
=
0
n
(
θ
i
x
i
+
ε
i
)
h(x) = \sum_{i=0}^n(\theta_ix_i+\varepsilon_i)
h(x)=i=0∑n(θixi+εi)
在大自然中,事物的发生的概率会趋近于符合均值为0和一个标准的高斯分布。事件与事件都是独立 。我们对待一类事件往往是认为他们是独立同分布的(iid),有这样的性质将会大幅度推进计算。
预
测
值
与
误
差
:
y
i
=
θ
T
x
i
+
ε
i
由
于
误
差
服
从
高
斯
分
布
(
均
值
为
0
)
:
p
(
ϵ
i
)
=
1
2
π
σ
e
x
p
(
−
ϵ
i
2
2
σ
2
)
即
p
(
y
i
∣
x
i
,
θ
)
=
1
2
π
σ
e
x
p
(
−
(
y
i
−
θ
T
x
i
)
2
2
σ
2
)
预测值与误差: y_i = \theta^Tx_i+\varepsilon_i\\ 由于误差服从高斯分布(均值为0): p(\epsilon_i)=\frac{1}{\sqrt{2\pi}\sigma}exp(-\frac{\epsilon_i^2}{2\sigma^2}) \\ 即p(y_i|x_i,\theta) = \frac{1}{\sqrt{2\pi}\sigma}exp(-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})
预测值与误差:yi=θTxi+εi由于误差服从高斯分布(均值为0):p(ϵi)=2πσ1exp(−2σ2ϵi2)即p(yi∣xi,θ)=2πσ1exp(−2σ2(yi−θTxi)2)
我们希望每一个样本都能够符合这样子的条件,由于样本与样本之间是复合假设:独立同分布。构建似然函数
L
(
θ
)
=
∏
i
=
1
m
p
(
y
i
∣
x
i
,
θ
)
=
∏
i
=
1
m
1
2
π
σ
e
x
p
(
−
(
y
i
−
θ
T
x
i
)
2
2
σ
2
)
l
o
g
L
(
θ
)
=
m
l
o
g
1
2
π
σ
−
1
2
σ
2
∑
i
=
1
m
l
o
g
(
y
i
−
θ
T
x
i
)
2
即
求
:
max
(
J
(
θ
)
)
=
∑
i
=
1
m
l
o
g
(
y
i
−
θ
T
x
i
)
2
L(\theta)=\prod_{i=1}^mp(y_i|x_i,\theta)=\prod_{i=1}^m\frac{1}{\sqrt{2\pi}\sigma}exp(-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2}) \\ logL(\theta) =mlog\frac1{\sqrt{2\pi}\sigma}-\frac1{2\sigma^2} \sum_{i=1}^mlog(y_i-\theta^Tx_i)^2\\ 即求:\max(J(\theta))= \sum_{i=1}^mlog(y_i-\theta^Tx_i)^2
L(θ)=i=1∏mp(yi∣xi,θ)=i=1∏m2πσ1exp(−2σ2(yi−θTxi)2)logL(θ)=mlog2πσ1−2σ21i=1∑mlog(yi−θTxi)2即求:max(J(θ))=i=1∑mlog(yi−θTxi)2
在求最大最小值可以通过对
θ
\theta
θ进行求导,令导数值为0
▽
L
(
θ
)
=
▽
(
1
2
(
X
θ
−
y
)
T
(
X
θ
−
y
)
)
=
▽
(
1
2
(
θ
T
X
T
X
θ
−
θ
T
X
T
y
−
y
T
X
θ
+
y
T
y
)
)
=
1
2
(
2
X
T
X
θ
−
X
T
y
−
(
y
T
X
)
T
)
=
X
T
X
θ
−
X
T
y
=
0
θ
=
(
X
T
X
)
−
1
X
T
y
\bigtriangledown L(\theta)=\bigtriangledown(\frac12(X\theta-y)^T(X\theta-y)) \\ = \bigtriangledown(\frac12(\theta^TX^TX\theta-\theta^TX^Ty-y^TX\theta+y^Ty)) \\ =\frac12(2X^TX\theta-X^Ty-(y^TX)^T)=X^TX\theta-X^Ty=0 \\ \theta = (X^TX)^{-1}X^Ty
▽L(θ)=▽(21(Xθ−y)T(Xθ−y))=▽(21(θTXTXθ−θTXTy−yTXθ+yTy))=21(2XTXθ−XTy−(yTX)T)=XTXθ−XTy=0θ=(XTX)−1XTy
这边可以直接用这个结果就求得结果,也可以通过梯度下降的方法进行求解。他们有各自的优势,直接求解有一个前提是X本身是一个满秩的矩阵否则无法进行求逆的操作。梯度下降有一个学习的过程但可以避免进行求逆。
第一类回归
用上面求解的结果直接进行回归,就是最基本的回归,
def standRegression(x,y):
xTx = x.T@x
if np.linalg.det(xTx) == 0:
print('this matrix can not do inverse')
return
else:
return np.array(np.mat(xTx).I@(x.T@y))
w = standRegression(x,y)[0]
x_ = np.linspace(0,1,50)
y_ = w[0] + w[1]*x_
plt.xlabel('x')
plt.ylabel('y')
plt.plot(x_,y_,'r-')
sns.scatterplot(data[1],data[2])
我们通过一元的回归可以很明显的看出回归的趋势,但没有办法拟合出细节的内容,有时候我们需要关注局部的细节。为了解决这样的问题可以对需要关注的数据进行加权回归。
加权线性回归
θ
=
(
X
T
X
)
−
1
X
T
W
y
\theta = (X^TX)^{-1}X^TWy
θ=(XTX)−1XTWy
可以通过跟这个点的附近点权重高一些,就会更关注附近点点。权重是人为规定,一种比较好用的方法是高斯加权法。
w
(
i
,
i
)
=
e
x
p
(
∣
x
i
−
x
∣
−
2
k
2
)
w(i,i)=exp(\frac{|x_i-x|}{-2k^2})
w(i,i)=exp(−2k2∣xi−x∣)
k是来修改辐射范围,
k值越大给离越远的数据权重越高。k越小就越关注局部的点。
def lwlr(testPoint, x, y, k=0.1):
m = x.shape[0]
weight = np.eye(m)
for j in range(m):
diff = testPoint - x[j,:]
weight[j,j] = np.exp(diff@diff.T/(-2.0*k**2))
xTx = x.T@(weight@x)
if np.linalg.det(xTx) == 0:
print('matrax can not be inverse')
return
else:
ws = np.mat(xTx).I@(x.T@(weight@y))
#print(weight)
return testPoint@ws[0].T
def lwlrTest(test,x,y,k=0.1):
m = test.shape[0]
yhat = np.zeros(m)
for i in range(m):
yhat[i] = np.array(lwlr(test[i],x,y,k)).reshape(-1)
return yhat
x_ = np.linspace(0,1,50)
x_ = np.concatenate((np.ones(50).reshape(-1,1),x_.reshape(-1,1)),axis=1)
y_ = lwlrTest(x_,x,y,0.03)
plt.plot(x_[:,1],y_,'r')
sns.scatterplot(x[:,1],y)
当k=1时,
岭回归和逐步线形回归
其中逐步线形回归的方法和梯度下降类似。
岭回归主要是解决数据特征的个数高于数据本身,导致数据无法求逆,可以通过加入对角矩阵来解决无法求逆的问题
(
X
T
X
+
λ
)
−
1
X
T
y
(X^TX+\lambda)^{-1}X^Ty
(XTX+λ)−1XTy
实际应用中还是可以通过降维的方法来解决。