1. 程式人生 > >專家觀點:L1正則稀疏?

專家觀點:L1正則稀疏?

原創:輪迴Pan  Refinitiv創新實驗室ARGO 

      

        機器學習中為了防止模型過擬合,通常會引入正則化(也稱之為懲罰項)。常見的正則化有L1正則和L2正則,兩者各有優缺點,而這裡我們的關注點是為什麼L1正則能導致模型引數稀疏化,而L2不能?

        以線性迴歸為例,其損失函式Loss加上正則項後的形式

L1的形式為:

 

L2的形式:

I . 形象解釋 

 

        首先咱們來看看網上流傳的一種形象化的解釋,大家一定見過下面這兩幅圖:

1 L1正則化Loss Function

2 L2正則化Loss Function

 

假設有如下帶L1正則化的損失函式:

其中J0是原始的損失函式,後面的一項是L1正則化項,α是正則化係數。因為L1正則化是權值的絕對值之和J0是帶有絕對值符號的函式,因此J是不完全可微的。機器學習的任務就是要通過一些方法(比如梯度下降)求出損失函式的最小值。當在原始損失函式J後新增L1正則化項時,相當於對J0做了一個約束。令L=α∑|w|

J=J0+L,此時變成在L約束下求出J0取最小值的解。考慮二維的情況,即只有兩個權值w1和w2,此時L=|w1|+|w2|,對於梯度下降法,求解J0的過程可以畫出等值線,同時L1正則化的函式L也可以在w1w2的二維平面上畫出來。如圖1所示。圖中等值線是J0的等值線,黑色方形是L函式的圖形。在圖中,當J0等值線與L圖形首次相交的地方就是最優解。上圖中J0與L在L的一個頂點處相交,這個頂點就是最優解。注意到這個頂點的值是(w1,w2)=(0,w)。可以直觀想象,因為L函式有很多『突出的角』(二維情況下四個,多維情況下更多),J0與這些角接觸的機率會遠大於與L其它部位接觸的機率,而在這些角上,會有很多權值等於0
這就是為什麼L1正則化可以產生稀疏模型,進而可以用於特徵選擇。

        而正則化前面的係數α,可以控制L圖形的大小。α越小,L的圖形越大(上圖中的黑色方框) ;α越大,L的圖形就越小,可以小到黑色方框只超出原點範圍一點點,這是最優點的值(w1,w2)=(0,w)中的w可以取到很小的值。

同樣可以畫出帶L2正則化的損失函式如圖2所示。二維平面下L2正則化的函式圖形是個圓,與方形相比,被磨去了稜角。因此J0與L相交時使得w1或w2等於零的機率小了許多,這就是為什麼L2正則化不具有稀疏性的原因。

        也許你已經發現,L1範數下可以導致稀疏,並不是L1範數下一定導致稀疏,還得看原問題的最優解到底在哪個地方取值。

 

 

II .數學推導

 

        當然以上只是形象的理解,現在咱們試圖從其數學推導上對L1,L2進行分析。我們的目的是最小化損失函式:

 

,有

的鄰域內,有

又因為,所以

(公式1)

 

根據proximal operator,

i)  當時, 有

ii)當時,維度分開,有,於是,式1 可以寫成如下形式

 

因為w在各個維度上互不影響,所以求整體最小可轉化成求每個維度上最小,即

求導  

當 ,

 

,

那麼,    ?  答案是 0,至此,我們就推出了L1正則會導致稀疏。

 

補充說明:

 

claim   ,因此當=0 時等式左邊取得最小值。

 

同樣的方法可以用到L2正則,因為L2正則損失函式可導,所以可推出w取不到0,因此L2正則無法實現權重稀疏和特徵選擇。

 

 

III . 程式碼實現部分

 

        我們看到在tensorflow程式碼關於LASSO實現部分中它註釋到當A小於0.9時,heavyside_step變為0,直接實現稀疏性,簡單粗暴,而L2則沒有。

 

if regression_type == 'LASSO':

 

# Declare Lasso loss function

# Lasso Loss = L2_Loss + heavyside_step,

# Whereheavyside_step ~ 0 if A < constant, otherwise ~ 99

lasso_param = tf.constant(0.9)

heavyside_step = tf.truediv(1., tf.add(1., tf.exp(tf.multiply(-50.,tf.subtract(A, lasso_param)))))

regularization_param = tf.multiply(heavyside_step, 99.)

loss = tf.add(tf.reduce_mean(tf.square(y_target - model_output)),regularization_param)

elif regression_type == 'Ridge':

# Declare the Ridge loss function

# Ridge loss = L2_loss + L2 norm of slope

ridge_param = tf.constant(1.)

ridge_loss = tf.reduce_mean(tf.square(A))

loss = tf.expand_dims(tf.add(tf.reduce_mean(tf.square(y_target -model_output)), tf.multiply(ridge_param, ridge_loss)), 0)

 

 

參考資料:

CSDN的 https://blog.csdn.net/jinping_shi/article/details/52433975