今天登龍跟大家分享下我對多維特征的讀取、縮放和多變量梯度下降算法的理解,文章不長,有理論也有實際的代碼,下面開始,Go!
一、如何表示多維特征?
1.1 特征縮放
實際項目中在讀取多維特征之前需要先對數(shù)據(jù)進行縮放,為什么呢?
因為在有了多維特征向量和多變量梯度下降法后,為了幫助算法更快地收斂,還需要對選用的特征進行尺度縮放,其實就是縮小特征值,將多個特征的值都縮小到同樣大小的區(qū)間,通常是縮小到 [-1, 1] 周圍。
以下圖為例:

在沒有進行特征縮放之前,兩參數(shù)梯度下降的等高線圖呈豎的橢圓形,這是因為橫軸和縱軸參數(shù)范圍不同,進而導(dǎo)致算法在尋找最小值時會迭代很多次。
而當(dāng)進行縮放使得橫縱軸范圍大致相同后,等高線圖基本呈圓形,算法在迭代的時候往一個方向很快就能找到最小值,大大減少迭代次數(shù)。
縮放的最終結(jié)果不一定非要準(zhǔn)確到 [-1, 1],比如 [-3, 3],[-2, 1] 這些范圍不是太大都是可以的,一個又常用有簡單的特征縮放計算方法是:
其中 是平均值,
是(max - min),比如用這個公式將所有的房屋面積和臥室數(shù)量進行縮放:
-
,其中 1000 是面積平均值,2000 是最大面積減最小面積。
-
,其中 2 是臥室數(shù)量平均值,5 個最大臥室數(shù)量減去最小臥室數(shù)量。
理論學(xué)會后,再來學(xué)習(xí)下實際的特征縮放代碼:
# 特征縮放
def normalize_feature(df):
# 對原始數(shù)據(jù)每一列應(yīng)用一個 lambda 函數(shù),mean() 求每列平均值,std() 求標(biāo)準(zhǔn)差
return df.apply(lambda column: (column - column.mean()) / column.std())
我們用這個函數(shù)來實際縮放一下含有 2 個特征的原始房價數(shù)據(jù):
# 讀取原始數(shù)據(jù)
raw_data = pd.read_csv('ex1data2.txt', names = ['square', 'bedrooms', 'price'])
# 顯示前 5 行
raw_data.head()

# 對原始數(shù)據(jù)進行特征縮放
data = normalize_feature(raw_data)
# 顯示縮放后的前 5 行數(shù)據(jù)
data.head()

可以看到縮放后的數(shù)據(jù)范圍基本都在 區(qū)間左右,說明我們的特征縮放成功了 _!下面來學(xué)習(xí)如何讀取多維特征!
1.2 讀取多維特征
還記得上篇文章我們介紹的第一個機器學(xué)習(xí)算法嗎?
即通過房屋面積來預(yù)測價格,這個問題中只使用一個輸入特征房屋面積,可現(xiàn)實生活中要解決的問題通常都含有多個特征,因為用多個特征訓(xùn)練出的模型準(zhǔn)確度更高。
那么如何機器學(xué)習(xí)算法如何處理多個特征的輸入呢?
我們還用預(yù)測房價的例子,不過這次要增加另外 3 個特征,臥室數(shù)量,房屋樓層,房屋年齡:

這樣一來,我們就有了 4 個輸入特征了,特征多了,表示的方法也要升升級了:
:輸入特征的數(shù)量,即特征矩陣列數(shù),也即特征向量的維度
:訓(xùn)練集中第
個實例向量,就是特征矩陣的第
行,比如列向量
:訓(xùn)練集中第
個實例的第
個特征,比如
特征數(shù)量增加了,之前的假設(shè)函數(shù)肯定也需要修改,要把增加的特征變量和參數(shù)加上:
雖然這樣表示沒問題,但是卻不方便利用向量來計算,因為參數(shù) 有 n + 1 個,但
只有 n 個,那怎么辦呢?
很簡單,我們額外增加一個 ,則上式變?yōu)椋?/p>
這樣一來就可以寫成向量相乘的形式:
你可能要問了為何要寫成向量的形式?主要因為 2 點:
- 使用向量方便程序編寫,一句計算特征向量的代碼就可以同時計算多個輸入?yún)?shù),因為一個特征向量中包含所有輸入?yún)?shù)
- 使用向量方便算法執(zhí)行,梯度下降算法要求參數(shù)同時更新,如果不使用向量,那更新起來非常麻煩。
通過增加一個維度 ,最終訓(xùn)練集的特征矩陣的大小為:
,其中 m 為行數(shù),n + 1 為列數(shù)。
那來看下讀取多維數(shù)據(jù)并添加一列全 1 向量的函數(shù)代碼:
# 讀取原始數(shù)據(jù),返回 m * (n + 1) 維特征矩陣
def get_X(df):
# 創(chuàng)建 m 行 1 列的數(shù)據(jù)幀
ones = pd.DataFrame({'ones': np.ones(len(df))})
# 合并全 1 向量作為元素數(shù)據(jù)第一列,axis = 0 按行合并,anix = 1 按列合并
data = pd.concat([ones, df], axis=1)
# 返回特征矩陣
return data.iloc[:, :-1].values
為了簡單點,這里假設(shè)原始房價數(shù)據(jù)只有 2 個輸入特征,即房屋面積和臥室數(shù)量:
[圖片上傳失敗...(image-4d05e3-1585821392478)]
我們用上面的函數(shù)來讀取下數(shù)據(jù)特征到向量 X:
# 讀取原始數(shù)據(jù),增加第一列全 1 向量
X = get_X(data)
# 輸出數(shù)據(jù)、維度和類型
print(X.shape, type(X))
print(X)
輸出結(jié)果如下:
# 47 行,3 列 = 47 * (2 + 1)
(47, 3) <class 'numpy.ndarray'>
可以看到特征矩陣的第一維列向量全為 1,后兩列不變(數(shù)據(jù)換成科學(xué)計數(shù)法表示),這與我們上面介紹的對多維特征的操作方法結(jié)果相同!
[圖片上傳失敗...(image-2f453e-1585821392478)]
讀取多維特征之后,我們就可以將特征矩陣 X 的每一行作為一個特征向量(就是特征組成的向量 =_=),并用它們來訓(xùn)練機器學(xué)習(xí)算法啦!
以上就是我對多維特征作為機器學(xué)習(xí)算法輸入的一些理解,非常感謝吳恩達(dá)老師的公開課 _。
上面的代碼都在文末我的 Github 倉庫,直接下載就能運行,記得給我個 star 哦!
二、多變量梯度下降法
多維特征讀取后,就可以學(xué)習(xí)多變量梯度下降法了,其實與上一篇博客的單變量梯度下降原理是一樣的,只不過增加了特征變量,相應(yīng)地參數(shù)也就增加了。
比如線性回歸的多變量假設(shè)函數(shù)、代價函數(shù)、梯度下降法分別如下:
- 假設(shè)函數(shù):
- 代價函數(shù):
- 多變量梯度下降法

因為參數(shù)增加到 n 個,所以梯度下降的偏導(dǎo)數(shù)也要分別對每個參數(shù)求一次,然后同時更新 n 個參數(shù):

比如當(dāng) 時更新前 3 個參數(shù):

我覺得挺好理解的,只需要按照單變量梯度下降的邏輯拓展下變量和參數(shù)的數(shù)量即可,前提一定要完全理解單變量的梯度下降。
那繼續(xù)來看下多變量梯度下降的算法代碼,與單變量梯度下降一毛一樣,先計算偏導(dǎo)數(shù):
# 計算偏導(dǎo)數(shù)
def gradient(theta, X, y):
m = X.shape[0]
inner = X.T @ (X @ theta - y)
return inner / m
再迭代下降:
# 批量梯度下降
# epoch: 下降迭代次數(shù)
# alpha: 初始學(xué)習(xí)率
def batch_gradient_decent(theta, X, y, epoch, alpha = 0.01):
# 計算初始成本:theta 都為 0
cost_data = [lr_cost(theta, X, y)]
# 創(chuàng)建新的 theta 變量,不與原來的混淆
_theta = theta.copy()
for _ in range(epoch):
# 新的 theta = 舊的 theta - 學(xué)習(xí)率 * 偏導(dǎo)數(shù)
_theta = _theta - alpha * gradient(_theta, X, y)
# 累加成本數(shù)據(jù),用于可視化
cost_data.append(lr_cost(_theta, X, y))
return _theta, cost_data
來調(diào)用下這個梯度下降函數(shù),初始學(xué)習(xí)率 alpha 設(shè)置為 0.01,迭代 epoch = 500 次:
final_theta, cost_data = batch_gradient_decent(theta, X, y, epoch, alpha = alpha)
這是最終的成本和迭代次數(shù)的曲線,可以看到成本 cost 最終基本趨于不變,說明梯度下降算法收斂啦!

話說我之前忘記講解單變量梯度下降的代碼了,下次一定補上!文章內(nèi)的代碼倉庫:
https://github.com/DLonng/AI-Notes/blob/master/MachineLearning/code/ex1-linear-regression/multi_feature.ipynb
OK,今天就跟大家分享這些,喜歡的小伙伴記得持續(xù)關(guān)注我哦!