梯度下降法是一種迭代最佳化演算法,目標是找到函式的區域性最小值。它透過沿著函式梯度的反方向逐步調整引數,最終逼近最小值。學習率控制每次迭代的步長,影響演算法的收斂速度和精確度。程式碼範例中,使用 Python 實作了梯度下降法,並以多項式函式和 Sigmoid 函式為例,展示瞭如何應用該演算法。程式碼中包含了函式定義、導數計算、迭代更新和結果輸出等關鍵步驟,並使用 matplotlib 繪製了函式圖形和梯度下降過程,方便理解演算法的執行機制。此外,Pandas 資料預處理的範例展示瞭如何在梯度下降法之前對資料進行整理和計算,例如計算平均值等。多維梯度下降法則涉及到向量運算和歐幾裡得距離,程式碼中展示瞭如何在三維空間中應用梯度下降法,並使用蒙特卡羅模擬提高結果的穩定性。
梯度下降法(Gradient Descent)簡介與實作
梯度下降法是一種用於最小化(或最大化)函式的最佳化演算法,廣泛應用於機器學習領域。該演算法透過迭代更新引數值,使其趨近於函式的區域性最小值。本文將介紹梯度下降法的基本原理,並透過例項展示其在函式最小化中的應用。
簡單函式最小化
梯度下降法是一種一階迭代最佳化演算法,用於尋找函式的區域性最小值。該演算法的基本思想是:從初始引數值開始,沿著函式梯度的負方向進行迭代更新,直到收斂到區域性最小值。
梯度下降法的數學原理
對於函式 $f(x)$,其梯度(導數)代表了函式在某一點的變化率。梯度下降法的更新規則如下:
$x_{new} = x_{old} - \gamma \cdot f’(x_{old})$
其中,$\gamma$ 是學習率,控制每次更新的步長。
程式碼實作:梯度下降法求函式區域性最小值
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return x**4 - 3 * x**3 + 2
def df(x):
return 4 * x**3 - 9 * x**2
if __name__ == "__main__":
x = np.arange(-5, 5, 0.2)
y, y_dx = f(x), df(x)
# 繪製子圖
f, axarr = plt.subplots(3, sharex=True)
axarr[0].plot(x, y, color='mediumspringgreen')
axarr[0].set_xlabel('x')
axarr[0].set_ylabel('f(x)')
axarr[0].set_title('f(x)')
axarr[1].plot(x, y_dx, color='coral')
axarr[1].set_xlabel('x')
axarr[1].set_ylabel('dy/dx(x)')
axarr[1].set_title('derivative of f(x)')
axarr[2].set_xlabel('x')
axarr[2].set_ylabel('GD')
axarr[2].set_title('local minimum')
# 梯度下降法引數設定
iterations, cur_x, gamma, precision = 0, 6, 0.01, 0.00001
previous_step_size = cur_x
while previous_step_size > precision:
prev_x = cur_x
cur_x += -gamma * df(prev_x)
previous_step_size = abs(cur_x - prev_x)
iterations += 1
axarr[2].plot(prev_x, cur_x, "o")
f.subplots_adjust(hspace=0.3)
f.tight_layout()
plt.show()
print('minimum:', cur_x, '\niterations:', iterations)
內容解密:
- 函式定義:程式碼首先定義了目標函式
f(x)及其導數df(x)。 - 資料生成:使用
np.arange生成一系列x值,並計算對應的f(x)和f'(x)值。 - 繪圖:利用
matplotlib繪製三個子圖,分別展示f(x)、f'(x)和梯度下降法的迭代過程。 - 梯度下降法實作:設定初始值、學習率和精確度閾值,透過迭代更新
cur_x直到收斂。 - 結果輸出:最終輸出局部最小值和迭代次數。
Pandas 資料處理範例
在進行梯度下降法之前,通常需要對資料進行預處理。以下是一個使用 Pandas 處理資料的範例:
import pandas as pd
import numpy as np
if __name__ == "__main__":
data = [
[41, 72, 180], [27, 66, 140],
[18, 59, 101], [57, 72, 160],
[21, 59, 112], [29, 77, 250],
[55, 60, 120], [28, 72, 110],
[19, 59, 99], [32, 68, 125],
[31, 79, 322], [36, 69, 111]
]
key1 = ['age', 'height', 'weight']
df1 = pd.DataFrame(data, columns=key1)
# 計算欄位平均值
avg_cols = df1.apply(np.mean, axis=0)
print('average by columns:')
print(avg_cols)
# 計算體重平均值
avg_wt = df1[['weight']].apply(np.mean, axis='index')
print('average weight:')
print(avg_wt)
內容解密:
- 資料建立:將資料存入
data清單中,並定義欄位名稱key1。 - DataFrame 建立:使用
pd.DataFrame將data清單轉換為 DataFramedf1。 - 平均值計算:利用
apply方法計算各欄位的平均值和特定欄位(如體重)的平均值。
梯度下降法在函式最佳化中的應用
梯度下降法(Gradient Descent, GD)是一種廣泛應用於機器學習和深度學習的最佳化演算法,主要用於找到函式的區域性最小值或最大值。本文將透過具體的程式碼範例,探討梯度下降法在不同函式最佳化問題中的應用。
多項式函式的最佳化
考慮一個多項式函式 $f(x) = x^3 - 6x^2 + 9x + 15$,其導數為 $f’(x) = 3x^2 - 12x + 9$。我們將使用梯度下降法來找到該函式的區域性最小值和最大值。
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return x**3 - 6 * x**2 + 9 * x + 15
def df(x):
return 3 * x**2 - 12 * x + 9
if __name__ == "__main__":
x = np.arange(-0.5, 5, 0.2)
y = f(x)
plt.figure('f(x)')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('f(x)')
plt.plot(x, y, color='blueviolet')
iterations, cur_x, gamma, precision = 0, 6, 0.01, 0.00001
previous_step_size = cur_x
while previous_step_size > precision:
prev_x = cur_x
cur_x += -gamma * df(prev_x)
previous_step_size = abs(cur_x - prev_x)
iterations += 1
local_min = cur_x
print('minimum:', local_min, 'iterations:', iterations)
iterations, cur_x, gamma, precision = 0, 0.5, 0.01, 0.00001
previous_step_size = cur_x
while previous_step_size > precision:
prev_x = cur_x
cur_x += -gamma * -df(prev_x)
previous_step_size = abs(cur_x - prev_x)
iterations += 1
local_max = cur_x
print('maximum:', local_max, 'iterations:', iterations)
plt.show()
程式碼解析:
- 函式定義:首先定義了目標函式
f(x)和其導數df(x)。 - 資料生成:使用
np.arange生成x的一系列值,並計算對應的y值。 - 梯度下降法實作:透過迭代更新
cur_x的值,逐步逼近區域性最小值或最大值。 - 結果輸出:輸出找到的區域性最小值和最大值,以及迭代次數。
Sigmoid 函式的最佳化
Sigmoid 函式是一種具有 S 型曲線的數學函式,在機器學習中有著廣泛的應用。考慮 Sigmoid 函式 $f(x) = \frac{1}{1 + e^{-x}}$,其導數為 $f’(x) = x(1-x)$。我們將使用梯度下降法來找到該函式的區域性最小值。
import matplotlib.pyplot as plt
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def df(x):
return x * (1-x)
if __name__ == "__main__":
x = np.arange(-10., 10., 0.2)
y, y_dx = sigmoid(x), df(x)
f, axarr = plt.subplots(3, sharex=True)
axarr[0].plot(x, y, color='lime')
axarr[0].set_title('Sigmoid Function')
axarr[1].plot(x, y_dx, color='coral')
axarr[1].set_title('Derivative of f(x)')
axarr[2].set_title('local minimum')
iterations, cur_x, gamma, precision = 0, 0.01, 0.01, 0.00001
previous_step_size = cur_x
while previous_step_size > precision:
prev_x = cur_x
cur_x += -gamma * df(prev_x)
previous_step_size = abs(cur_x - prev_x)
iterations += 1
print('minimum:', cur_x, '\niterations:', iterations)
plt.show()
程式碼解析:
- Sigmoid 函式定義:定義了 Sigmoid 函式
sigmoid(x)和其導數df(x)。 - 子圖繪製:使用
plt.subplots繪製 Sigmoid 函式、其導數和梯度下降法的迭代過程。 - 梯度下降法實作:與前一範例類別似,使用梯度下降法找到 Sigmoid 函式的區域性最小值。
- 結果輸出:輸出局部最小值和迭代次數。
梯度下降法(Gradient Descent)深度解析與應用
梯度下降法是一種在機器學習和深度學習中廣泛使用的最佳化演算法,主要用於找到函式的區域性最小值或最大值。本文將探討梯度下降法的基本原理、實作方法以及在不同場景下的應用。
梯度下降法的基本原理
梯度下降法的基本思想是透過迭代地調整引數,以最小化或最大化目標函式。這個過程涉及到計算目標函式的梯度(導數),並根據梯度的方向調整引數。
數學表達
給定一個目標函式 $f(x)$,其梯度為 $\nabla f(x)$。梯度下降法的更新規則如下:
$x_{t+1} = x_t - \gamma \nabla f(x_t)$
其中,$x_t$ 是當前引數,$\gamma$ 是學習率,控制每次更新的步長。
實作梯度下降法
一維梯度下降法範例
import matplotlib.pyplot as plt
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def df(x):
return x * (1-x)
if __name__ == "__main__":
x = np.arange(-10., 10., 0.2)
y, y_dx = sigmoid(x), df(x)
f, axarr = plt.subplots(3, sharex=True)
axarr[0].plot(x, y, color='lime')
axarr[0].set_xlabel('x')
axarr[0].set_ylabel('f(x)')
axarr[0].set_title('Sigmoid Function')
axarr[1].plot(x, y_dx, color='coral')
axarr[1].set_xlabel('x')
axarr[1].set_ylabel('dy/dx(x)')
axarr[1].set_title('Derivative of f(x)')
axarr[2].set_xlabel('x')
axarr[2].set_ylabel('GD')
axarr[2].set_title('local maximum')
iterations, cur_x, gamma, precision = 0, 0.01, 0.01, 0.00001
previous_step_size = cur_x
while previous_step_size > precision:
prev_x = cur_x
cur_x += -gamma * -df(prev_x)
previous_step_size = abs(cur_x - prev_x)
iterations += 1
axarr[2].plot(prev_x, cur_x, "o")
f.subplots_adjust(hspace=0.3)
f.tight_layout()
print ('maximum:', cur_x, '\niterations:', iterations)
plt.show()
內容解密:
- 匯入必要的函式庫:程式碼首先匯入了
matplotlib.pyplot和numpy,這兩個函式庫分別用於繪圖和數值運算。 - 定義 Sigmoid 函式及其導數:Sigmoid 函式是一種常用的啟用函式,其導數用於梯度下降法的更新規則中。
- 生成資料並繪製 Sigmoid 函式及其導數的圖形:程式碼生成了一系列的 x 值,並計算對應的 Sigmoid 函式值和導數值,然後繪製了三個子圖,分別顯示 Sigmoid 函式、其導數以及梯度下降法的迭代過程。
- 實作梯度下降法:程式碼透過一個 while 迴圈實作了梯度下降法,不斷更新
cur_x直到收斂。 - 輸出結果:最終輸出局部最大值的近似值以及迭代次數。
多維梯度下降法與歐幾裡得距離最小化
在多維空間中,梯度下降法同樣適用,但需要考慮向量之間的距離,通常使用歐幾裡得距離來衡量。
三維梯度下降法範例
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import random
import numpy as np
from scipy.spatial import distance
def step(v, direction, step_size):
return [v_i + step_size * direction_i for v_i, direction_i in zip(v, direction)]
def sigmoid_gradient(v):
return [v_i * (1-v_i) for v_i in v]
def mod_vector(v):
for i, v_i in enumerate(v):
if v_i == float("inf") or v_i == float("-inf"):
v[i] = random.randint(-1, 1)
return v
if __name__ == "__main__":
v = [random.randint(-10, 10) for i in range(3)]
tolerance = 0.0000001
iterations = 1
fig = plt.figure('Euclidean')
ax = fig.add_subplot(111, projection='3d')
while True:
gradient = sigmoid_gradient(v)
next_v = step(v, gradient, -0.01)
xs, ys, zs = gradient[0], gradient[1], gradient[2]
ax.scatter(xs, ys, zs, c='lime', marker='o')
v = mod_vector(v)
next_v = mod_vector(next_v)
test_v = distance.euclidean(v, next_v)
if test_v < tolerance:
break
v = next_v
iterations += 1
print ('minimum:', test_v, '\niterations:', iterations)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
plt.tight_layout()
plt.show()
內容解密:
- 定義向量運算函式:程式碼定義了
step函式來更新向量,sigmoid_gradient函式來計算 Sigmoid 函式的梯度,以及mod_vector函式來處理無窮大或無窮小的向量元素。 - 初始化隨機向量並設定容忍度:程式碼隨機生成了一個三維向量作為起始點,並設定了一個很小的容忍度來控制迭代停止。
- 迭代更新向量直到收斂:程式碼透過一個無限迴圈不斷更新向量,直到前後兩次迭代之間的歐幾裡得距離小於設定的容忍度。
- 繪製三維散點圖:程式碼使用
matplotlib的三維繪圖功能顯示了迭代過程中的梯度向量。 - 輸出結果:最終輸出局部最小值的近似值以及迭代次數。
蒙特卡羅模擬穩定歐幾裡得距離最小化
由於初始向量的隨機性,每次執行梯度下降法得到的結果可能不同。為了穩定結果,可以使用蒙特卡羅模擬進行多次實驗,並計算平均迭代次數。