lasso 回归 & 岭回归

来源:互联网 发布:姚明国家队数据 编辑:程序博客网 时间:2024/03/29 15:19

岭回归(ridge regression)

回忆 LR 的优化目标

L=(YXw)T(YXw)

为防止过拟合,增加正则化项 λ||w||2 ,目标函数就变成

L=(YXw)T(YXw)+λ||w||2

对其进行求导,得到

Lw=2XT(YXw)+2λw

令导数为0,得

w=(XTX+λI)1XTY

这就是岭回归的公式。

岭回归具有以下优点:

  • 在特征数M,而岭回归就可以。
  • 通过引入λ惩罚项,防止过拟合。

Lasso

与岭回归不同,lasso增加的正则化项是 λ||w||1 ,目标函数就变成

L=(YXw)T(YXw)+λ||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=2i=1Nxik(yiwTxi)=2i=1Nxik(yiwkTxik(wTxiwkTxik))=wk2i=1Nx2ik2i=1Nxik(yiwTxi+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=2i=1Nx2ik,ck=2i=1Nxik(yiwTxi+wkxik)
,

则可写成

L(w)wk=αkwkck

L(w,λ)=L(w)+λ||w||1

L(w,λ)wk=αkwkckλ[ckλ,ck+λ]αkwkck+λ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约束,等高线图与圆上任一点相切的概率相同,故起不到特征选择的效果。
这里写图片描述



原创粉丝点击