lasso 回归 & 岭回归
程序员文章站
2022-05-02 16:35:14
...
岭回归(ridge regression)
回忆 LR 的优化目标
L=(Y−Xw)T(Y−Xw)
为防止过拟合,增加正则化项 λ||w||2 ,目标函数就变成
L=(Y−Xw)T(Y−Xw)+λ||w||2
对其进行求导,得到
∂L∂w=−2XT(Y−Xw)+2λw
令导数为0,得
w=(XTX+λI)−1XTY
这就是岭回归的公式。
岭回归具有以下优点:
- 在特征数M,而岭回归就可以。
- 通过引入λ惩罚项,防止过拟合。
Lasso
与岭回归不同,lasso增加的正则化项是 λ||w||1 ,目标函数就变成
L=(Y−Xw)T(Y−Xw)+λ||w||1
这个细微的变化,极大增加了计算复杂度,因为其不可直接求导。
前向逐步回归(Forward Stagewise Linear Regression)
前向逐步回归的伪代码:
相关代码:
datas = []
values = []
with open('abalone','r') as f:
for line in f:
linedata = line.split('\t')
datas.append(linedata[0:-1]) #前4列是4个属性的值
values.append(linedata[-1].replace('\n','')) #最后一列是类别
datas = np.array(datas)
datas = datas.astype(float)
values = np.array(values)
values = values.astype(float)
N,M = datas.shape #N是样本数,M是参数向量的维
means = datas.mean(axis=0) #各个属性的均值
stds = datas.std(axis=0) #各个属性的标准差
datas = (datas-means)/stds #标准差归一化
values = (values-values.mean())/values.std() #标准差归一化
fig,axes = plt.subplots(nrows=2,ncols=2,figsize=(8,8))
plt.suptitle(u'Forward Stepwise Regression Example',fontsize = 18) #用中文会出错,不知为何
plt.subplots_adjust(wspace = 0.25,hspace=0.25)
lambds = [0.05,0.5,1.0,3.0]
axes = axes.flatten()
for i in range(4):
numIt = 600 #迭代次数
delta = 0.01 # 调整系数
wlog = np.zeros((numIt,M)) #记录weights的变化
weights = np.zeros(M) #系数向量
lambd = lambds[i]
for it in range(1,numIt):
Lmin = {'value':np.inf,'loc':np.nan,'sign':np.nan} #记录本次迭代的目标函数最小值
for m in range(M-1,0,-1):
for sign in (-1,1):
wbak = cp.deepcopy(weights)
wbak[m] += delta*sign
Lcur = np.linalg.norm(values-np.dot(datas,wbak),2)+ lambd*np.linalg.norm(wbak,1)
#print m,sign,Lcur
if Lmin['value'] > Lcur: # 如果目标函数值比当前最优值小
Lmin['value'] = Lcur
Lmin['loc'] = m
Lmin['sign'] = sign
weights[Lmin['loc']] += delta*Lmin['sign']
wlog[it,:] = weights[:]
ax = axes[i]
for m in range(M):
ax.plot(wlog[:,m])
ax.set_title('lambda='+np.str(lambd),{'fontname':'STFangsong','fontsize':10})
ax.set_xlabel(u'迭代次数',{'fontname':'STFangsong','fontsize':10})
ax.set_ylabel(u'各权值系数',{'fontname':'STFangsong','fontsize':10})
savefig('lasso1.png',dpi=300,bbox_inches='tight')
- 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
Lasso Shooting Algorithm
如下求导
∂L(w)∂wk=−2∑i=1Nxik(yi−wTxi)=−2∑i=1Nxik(yi−wkTxik−(wTxi−wkTxik))=wk⋅2∑i=1Nx2ik−2∑i=1Nxik(yi−wTxi+wkxik)
\frac{\partial L({\bf w})}{\partial {\bf w}_k} = -2\sum_{i=1}^{N}{\bf x}_{ik}\left(y_i-{\bf w}^T{\bf x}_i\right)\qquad\qquad\qquad\qquad\\
\qquad = -2\sum_{i=1}^{N}{\bf x}_{ik}\left(y_i-{\bf w_k}^T{\bf x}_{ik}-\left({\bf w}^T{\bf x}_i-{\bf w_k}^T{\bf x}_{ik}\right)\right)\\
令其中
αk=2∑i=1Nx2ik,ck=2∑i=1Nxik(yi−wTxi+wkxik)
,
则可写成
∂L(w)∂wk=αk⋅wk−ck
令L(w,λ)=L(w)+λ||w||1
则
∂L(w,λ)∂wk=⎧⎩⎨αk⋅wk−ck−λ[−ck−λ,−ck+λ]αk⋅wk−ck+λwk<0wk=0wk>0
\begin{eqnarray*}
\frac{\partial L(w,\lambda)}{{\partial \bf w}_k}=
\begin{cases}
\alpha_k\cdot {\bf w}_k-c_k-\lambda \!&{\bf w}_k<0\\
\left[-c_k-\lambda,-c_k+\lambda\right]\!&{\bf w}_k=0 \\
\alpha_k\cdot {\bf w}_k-c_k+\lambda \!&{\bf w}_k>0
\end{cases}
进而可得wk的更新公式
wk=⎧⎩⎨(ck+λ)/αk0(ck−λ)/αkck<−λck∈[−λ,λ]ck>−λ
\begin{eqnarray*}
{\bf w}_k=
\begin{cases}
\left(c_k+\lambda\right)/\alpha_k \!& c_k<-\lambda\\
0\!&c_k\in [-\lambda,\lambda] \\
\left(c_k-\lambda\right)/\alpha_k \!&c_k>-\lambda
\end{cases}
fig,axes = plt.subplots(nrows=2,ncols=2,figsize=(8,8))
plt.suptitle(u'Lasso Shooting Algorithm Example',fontsize = 18) #用中文会出错,不知为何
plt.subplots_adjust(wspace = 0.25,hspace=0.25)
lambds = [0.05,3.5,50,100]
axes = axes.flatten()
for i in range(4):
lambd = lambds[i]
numIt = 600 #迭代次数
wlog = np.zeros((numIt,M)) #记录weights的变化
weights = np.zeros(M) #系数向量
XX2 = 2*np.dot(datas.transpose(),datas)
XY2 = 2*np.dot(datas.transpose(),values)
for it in range(numIt):
for k in range(M):
ck = XY2[k]-np.dot(XX2[k,:],weights)+XX2[k,k]*weights[k]
ak = XX2[k,k]
#print ck,lambd
if ck < -lambd:
weights[k] = (ck+lambd)/ak
elif ck > lambd:
weights[k] = (ck-lambd)/ak
else:
weights[k] = 0
wlog[it,:] = weights[:]
ax = axes[i]
for m in range(M):
ax.plot(wlog[:,m])
ax.set_title('lambda='+np.str(lambd),{'fontname':'STFangsong','fontsize':10})
ax.set_xlabel(u'迭代次数',{'fontname':'STFangsong','fontsize':10})
ax.set_ylabel(u'各权值系数',{'fontname':'STFangsong','fontsize':10})
savefig('lasso2.png',dpi=300,bbox_inches='tight')
- 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
L1 vs L2
岭回归正则化项是L2约束。
下表展示了L1,L2的区别。
L1 具有的特征选择(稀疏性)的作用可以用下图来解释:
左侧的正方形表示L1约束,等高线图与圆上任一点相切的概率相同,故起不到特征选择的效果。
上一篇: 决策树(Decision Tree)