摘要:給大家簡單介紹了多變量線性回歸,還附贈在處理梯度下降過程中通用的兩個小技巧。
本文分享自華為雲社區《【跟着小Mi一起機器學習吧!】多變量線性回歸(一)》,原文作者:Skytier。
1 多維特征
既然是多變量線性回歸,那么肯定是存在多個變量或者多個特征的情況啦。就拿之前研究的線性回歸來說,只有一個單一的特征變量即x表示房屋面積,我們希望用這個特征量來預測Y,也就是房屋的價格。當然,實際情況肯定並非如此,大伙在買房的時候是不是還要考慮房屋的數量、樓層數、房子的年齡等等各種信息呀,那么我們就可以用
來表示這四個特征,仍然可以用Y來表示我們所想要預測的輸出變量。
現在我們有四個特征變量,如下圖:

小寫n可以用來表示特征量的數目,這里例子中n=4,有4個特征。這里的n和之前的符號m是不一樣的概念,之前我們用m來表示樣本的數量,所以如果你有47行,那么m就是這個表格里面的行數或者說是訓練樣本數。然后我們要用
來表示第i個訓練樣本的輸入特征值。舉個具體的例子,
就表示第二個訓練樣本的特征向量,所以這里的
=
,即預測第二套房子價格的四個特征量。小tips,這里的上標2就是訓練集的一個索引,可千萬不要給它看作是x的二次平方哦,而是對應着你所看到的表格中的第二行,也就是第二個訓練樣本,是一個四維向量。事實上更普遍地來說,這是一個n維的向量。而
則表示第i個訓練樣本中第j特征量的值,對應表格中,
代表着第二個訓練樣本中第三個特征量的值,也就是2。
好了,表達形式搞清楚了,那么假設由於變量的增多,當然也會有所改變啦。單變量的假設函數是
,這么一類比,小Mi要考考大家啦!多變量又是什么情況呢,又是多變量,又是線性的。沒錯,支持多變量假設形式就是:
。
舉個例子:![]()
詳細來說,這個假設是為了預測以萬為單位的房屋價格,一個房子的基本的價格可能是80w,加上每平方米1000元,然后價格會隨着樓層數的增加繼續增長,隨着卧室數的增加而增加,但是呢,隨着使用年數的增加而貶值,這么一看這個例子是不是很有道理!
不過強迫症的小Mi還想隊伍形式更加統一一點,為了表示方便,我們可以假定
的值為1,具體而言,這意味着對於第i個樣本都有一個向量
,並且
。也可以說額外定義了第0個特征量。因此,現在的特征向量x是一個從0開始標記的n+1維的向量。而參數
也是一個從0開始標記的向量,它也是n+1維的特征量向量。
由此假設就可以搖身一變簡化為:
,其中上標T代表矩陣的轉置,是不是很巧妙!
![]()
這里小Mi還真不得不誇下這個
,是它是它就是它,幫助我們可以以這種非常簡潔的形式寫出假設。這就是多特征量情況下的假設形式,也就是所謂的多元線性回歸。多元一詞就是表示我們用多個特征量或者變量來預測Y值。
2 多變量梯度下降
好了,多變量線性回歸假設的形式已經有了,也就是說料已經有了,接下來就要開始炒菜啦!
在多元回歸的假設形式中,我們已經按慣例假設
。此模型的參數包括
,但在這里我們不把它看作n個獨立參數,而是考慮把這些參數看作一個n+1維的
向量,因此代價函數
的表達式表示為:
其中,![]()
我們的目標和單變量線性回歸問題中一樣,是要找出使得代價函數最小的一系列參數。 多變量線性回歸的批量梯度下降算法為:

即:

求導數后可得到:

我們要不斷更新每個
參數,通過
減去
乘以導數項,我們再整理好寫成
,從而將會得到可行的用於多元線性回歸的梯度下降法。

代碼示例:
計算代價函數:
。其中,![]()
Python 代碼:
def computeCost(X, y, theta): inner = np.power(((X * theta.T) - y), 2) return np.sum(inner) / (2 * len(X))
3 梯度下降法實踐-特征縮放
接下來,我們將學習一些在梯度下降運算中的實用技巧,首先給大家介紹一個稱為特征縮放的方法,這個方法如下:
如果你有一個機器學習問題,這個問題有多個特征,而你能確保這些特征都處在一個相近的范圍內,也就是說確保不同特征的取值在相近的范圍內,這樣梯度下降法就能更快地收斂。具體來說,假如你有一個具有兩個特征的問題,其中
是房屋面積大小,它的取值在0~2000之間,
是卧室的數量,可能取值在1~5之間,如果你要畫出代價函數
的等值線,那么看起來應該是像這樣的,是一個關於參數
和
的函數,這里要忽略
,並假想這個函數的變量只有
和
,但如果
的取值范圍遠遠大於
的取值范圍的話,那么最終畫出來的代價函數
的等值線就會呈現出這樣一種非常歪斜並且橢圓的形狀,其實2000比5的比例會讓這個橢圓更加瘦長。所以這個又瘦又高的橢圓形等值線圖就是這些非常高大細長的橢圓形構成了代價函數
的等值線。如果你在這種代價函數上運行梯度下降的話,你的梯度最終可能需要花很長一段時間,並且可能會來回波動,然后會經過很長時間,最終才會收斂到全局最小值。

事實上,你可以想象,如果這些等值線更誇張一些,就是把它畫的更細更長,可能就比這更誇張,結果就是梯度下降的過程可能更加緩慢,反復來回振盪需要更長的時間,才找到一條通往全局最小值的路。在這樣的情況下,一種有效的方法就是進行特征縮放。具體來說,如果把特征
定義為房子的面積大小除以2000,並且把
定義為卧室的數量除以5,那么代價函數
的等值線就會偏移得沒那么嚴重,看起來更圓一些了。如果你在這樣的代價函數上來執行梯度下降的話,那么梯度下降算法可以從數學上來證明,就會找到一條更直接的路徑,通向全局最小,而不是像剛才那樣,沿着一條復雜得多的路徑來找全局最小值。因此,通過這些特征縮放,它們的值的范圍變得相近,在這個例子中,我們最終使兩個特征
和
都在0和1之間,這樣你得到的梯度下降法就會更快地收斂。

更一般地,我們執行特征縮放時,我們通常的目的是將特征的取值約束到-1到+1的范圍內。具體來說,你的特征
總是等於1。因此,這已經是在這個范圍內,但對其他的特征,你可能需要通過除以不同的數,來讓它們處於同一范圍內。-1和+1這兩個數字並不是太重要,所以,如果你有一個特征
,它的取值在0~3之間,這沒問題;如果你有另外一個特征
,取值在-2到+0.5之間,這也非常接近-1到+1的范圍,這些都是可以的;但如果你有另一個特征比如
,假如它的單位在-100~+100之間,那么這個范圍跟-1~+1就有很大不同了。所以,這可能是一個范圍不太合適的特征。類似地,如果你的特征在一個非常非常小的范圍內,比如一個特征
的范圍在-0.0001~+0.0001之間,那么這同樣是一個比-1~+1小得多的范圍。因此,我同樣會認為,這個特征的范圍不合適。所以,可能你認可的范圍,也許可以大於+1或者小於+1,但是也別太大,比如+100,或者也別太小,比如這里的0.001,不同的人有不同的經驗。但是,正常可以這么考慮,如果一個特征是在-3~+3范圍內,這個范圍是可以接受的,但如果這個范圍大於了-3~+3的范圍,我可能就要開始注意了,如果它的取值在-1/3~+1/3的話,我也覺得還不錯,可以接受,或者是0~1/3或者-1/3~0,這些典型的范圍我都覺得是可以接受的,但如果特征的范圍取得很小的話,比如剛剛提及的
,就要開始考慮。因此,總的來說,不用過於擔心你的特征是否在完全相同的范圍或區間內,但是只要它們足夠接近的話,梯度下降法就會正常地工作。除了將特征除以最大值以外,在特征縮放中,有時候我們也會進行一個稱之為均值歸一化的工作,也就是說你有一個特征
,就可以用
來替換,讓你的特征值具有為0的平均值。
很明顯,我們不需要把這一步應用到
中,因為
總是等於1,所以它不可能有為0的平均值,但是對其他的特征來說,比如房子的大小取值介於0~2000之間,並且假如房子面積的平均值是等於1000,那么你可以用如下公式,將
的值變為size,減去平均值,再除以2000。類似地,如果這些房子有1~5卧室,並且平均一套房子有兩間卧室,那么你可以使用這個公式來均值歸一化你的第二個特征
,在這兩種情況下,你可以算出新的特征
和
,這樣它們的范圍可以在-0.5~+0.5之間。當然這不一定對,
的值可以略大於0.5,但很接近。更一般的規律是,你可以把
替代為
,其中,定義
是訓練接中特征
的平均值,而這個
是該特征值的范圍,范圍指的是最大值減去最小值。或者對於學過標准差的同學來說,把
設為變量的標准差也是可以的,但是其實用最大值減最小值就可以了。類似地,對於第二個特征
,也可以同樣的減去平均值再除以范圍,也就是最大值減最小值。這類公式將你的特征也許並不是這樣,但是大概是這樣范圍,順便提一下,只需要將特征轉換為相近似的范圍就都是可以的,特征縮放其實並不需要太精確,只是為了讓梯度下降能夠運行得更快一點而已,收斂所需的迭代次數更少就行了。

4 梯度下降法實踐-學習率
另一種技巧可以使梯度下降在實踐中工作地更好,也就是有關學習率
。具體而言,這是梯度下降算法的更新規則,我們需要認識的是所謂的調試是什么,還有一些小技巧來確保梯度下降是正常工作的,另外,還需要知道如何選擇學習率
。
通常做的事是確保梯度下降正常工作。梯度下降所做的事情就是為你找到一個
值,並且希望它能夠最小化代價函數
。因此,通常可以在梯度下降算法運行時,畫出代價函數
的值。

這里的x軸表示的是梯度下降算法的迭代次數。隨着梯度下降算法的運行,你可能會得到這樣一條曲線,注意x軸是迭代次數,之前我們給出的
中,x軸表示的是參數向量
,與當前圖像不同。具體來說,第一個紅點的含義是運行100次的梯度下降迭代后得到某個
值,對於這個點,表示梯度下降算法100步迭代后,得到的
值算出的
。而第二個紅點對應的是梯度下降算法200步迭代后得到的
值算出的
。所以這個曲線表示的是梯度下降的每步迭代后代價函數的值。如果梯度下降算法正常工作的話,每一步迭代之后
都應該下降。這條曲線的一個用處在於它可以告訴你,當你達到300步迭代后,300-400步迭代之間,
並沒有下降多少,所以當你達到400步迭代時,這條曲線看起來已經很平坦了。在這里400步迭代的時候,梯度下降算法差不多已經收斂了。通過這條曲線可以幫助你判斷梯度下降算法是否已經收斂。順便提一下,對於每一個特定的問題,梯度下降算法所需的迭代次數可能會相差很大,所以對於某一個問題,梯度下降算法只需要30步迭代就可以達到收斂,然而換一個問題,也許梯度下降算法需要3000步迭代或者是3000000步甚至更多,實際上我們很難提前判斷,梯度下降算法需要多少步才能收斂。另外,也可以進行一些自動的收斂測試,也就是說讓一種算法來告訴你梯度下降算法是夠已經收斂。
梯度下降算法收斂所需要的迭代次數根據模型的不同而不同,我們不能提前預知,我們可以繪制迭代次數和代價函數的圖表來觀測算法在何時趨於收斂。
也有一些自動測試是否收斂的方法,例如將代價函數的變化值小於某個閥值(例如0.001),那么測試就判定函數已經收斂,但是選擇一個合適的閾值是相當困難的,因此,為了檢測梯度下降算法是否收斂,更傾向於通過看曲線圖,而不是依靠自動收斂測試。


此外,這種曲線圖還可以提前告知我們算法沒有正常工作,具體地說,代價函數
隨迭代步數的變化曲線,實際上在不斷上升,就表明梯度下降算法沒有正常工作,而這樣的曲線圖意味着我應該使用較小的學習率。先前也已經推理過學習率大小的問題,梯度下降算法的每次迭代受到學習率的影響,如果學習率過小,則達到收斂所需的迭代次數會非常高,會收斂得很慢;如果學習率過大,每次迭代可能不會減小代價函數,可能會越過局部最小值導致無法收斂。所以如果畫出代價函數的曲線,我們可以清楚知道到底發生了什么
具體來說,我們通常可以嘗試一系列
值:
比如:0.001,0.003,0.01,0.03,0.1,0.3,1,...,每3倍取一個值,然后對這些不同的
值繪制
隨迭代步數變化的曲線,從而選擇的是
快速下降的一個
值。
