梯度下降是除了線性回歸的另一個線性模型擬合算法。核心思想是由隨機值開始,不斷的重復(fù)迭代,在每一次迭代中,在使成本函數(shù)降低最大的方向上前進一步,以不斷的逼近最小值。
梯度下降算法的重要參數(shù):
- 學(xué)習(xí)率 eta: 決定了每一步的梯度下降步長,學(xué)習(xí)率過高時,有可能出現(xiàn)結(jié)果不收斂的情況,學(xué)習(xí)率過低時,無法得到最優(yōu)值。
梯度下降分為批量梯度下降和隨機梯度下降。
批量梯度下降
根據(jù)數(shù)學(xué)推導(dǎo),可通過代碼直接實現(xiàn)。
X_b = np.c_[np.ones((100, 1)), X]
eta = 0.1 #learning rate
n_iterations = 1000
m = 100
theta = np.random.randn(2, 1) #random initialization
for iteration in range(n_iterations):
gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
theta = theta - eta * gradients
print(theta)
[[4.02040005]
[3.04161372]]
可以發(fā)現(xiàn),與線性回歸標(biāo)準(zhǔn)公式得到的結(jié)果完全一致。這種算法由于每次迭代都對樣本進行全量的計算,所以在樣本數(shù)量很多時會變得很慢。但梯度下降對處理多特征的情況具有效率上的優(yōu)勢。
學(xué)習(xí)率與梯度下降
我們來看看前10次迭代時不同學(xué)習(xí)率的效果。
X_b = np.c_[np.ones((100, 1)), X]
plt.plot(X, y, "b.")
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
eta = 0.5 #learning rate
n_iterations = 10
m = 100
theta = np.random.randn(2, 1) #random initialization
for iteration in range(n_iterations):
gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
theta = theta - eta * gradients
y_predict = X_new_b.dot(theta)
plt.plot(X_new, y_predict, "r-")

學(xué)習(xí)率0.02

學(xué)習(xí)率0.1

學(xué)習(xí)率0.5
可以看到學(xué)習(xí)率過低時,收斂速度很慢,學(xué)習(xí)率過高時,直接越過了最優(yōu)解而無法收斂。
隨機梯度下降
隨機梯度下降與批量梯度下降最大的區(qū)別在于,每次迭代只選擇一個樣本來優(yōu)化參數(shù)。這樣可以彌補批量梯度下降在樣本數(shù)過高時計算代價過大的缺點,當(dāng)成本函數(shù)非常不規(guī)則時,隨機梯度下降可以逃離局部最優(yōu),但缺點是它永遠定位不到最優(yōu)解,只能獲得近似最優(yōu)解。
scikit-learning庫中有隨機梯度下降的相應(yīng)函數(shù)。
from sklearn.linear_model import SGDRegressor
sgd_reg = SGDRegressor(max_iter = 100, eta0 = 0.1)
sgd_reg.fit(X, y.ravel())
sgd_reg.intercept_, sgd_reg.coef_
(array([3.99629727]), array([3.01429477]))
本節(jié)需要記憶的語法:
1. np.ones() #創(chuàng)建所有取值都為1的數(shù)組
2. np.c_[] #將數(shù)組銜接為矩陣
3. a.dot(b) #求矩陣內(nèi)積
4. sgd_reg = SGDRegressor(max_iter = 100, eta0 = 0.1) #創(chuàng)建一個SGD回歸模型
5. sgd_reg.fit(X, y.ravel()) #模型參數(shù)擬合