發布時間: 2018-10-18 21:24:56
?4.1最小二乘法實現
4.1.1算法介紹
最小二乘法(Least Square Method),做為分類回歸算法的基礎,有著悠久的歷史。它通過最小化誤差的平方和尋找數據的最佳函數匹配。利用最小二乘法可以簡便地求得未知的參數,并使得預測的數據與實際數據之間誤差的平方和為最小。
4.1.2代碼實現
# 代碼輸入:
import numpy as np # 引 入 numpy
import scipy as sp import pylab as pl
from scipy.optimize import leastsq # 引入最小二乘函數
n = 9 # 多項式次數
# 目標函數
def real_func(x):
return np.sin(2 * np.pi * x)
# 多項式函數
def fit_func(p, x):
f = np.poly1d(p) return f(x)
# 殘差函數
def residuals_func(p, y, x): ret = fit_func(p, x) - y return ret
x = np.linspace(0, 1, 9) # 隨機選擇 9 個點作為 x
x_points = np.linspace(0, 1, 1000) # 畫圖時需要的連續點
y0 = real_func(x) # 目標函數
y1 = [np.random.normal(0, 0.1) + y for y in y0] # 添加正太分布噪聲后的函數
p_init = np.random.randn(n) # 隨機初始化多項式參數
plsq = leastsq(residuals_func, p_init, args=(y1, x))
print('Fitting Parameters: ', plsq[0]) # 輸出擬合參數
pl.plot(x_points, real_func(x_points), label='real') pl.plot(x_points, fit_func(plsq[0], x_points), label='fitted curve') pl.plot(x, y1, 'bo', label='with noise')
pl.legend() pl.show()
# 結果輸出:
Fitting Parameters: [-1.22007936e+03 5.79215138e+03 -1.10709926e+04 1.08840736e+04
-5.81549888e+03 1.65346694e+03 -2.42724147e+02 1.96199338e+01
-2.14013567e-02]
# 可視化圖像:
4.2 梯度下降法實現
4.2.1 算法介紹
梯度下降法(gradient descent),又名最速下降法,是求解無約束最優化問題最常用的方法,它是一種迭代方法,每一步主要的操作是求解目標函數的梯度向量,將當前位置的負梯度方向作為搜索方向(因為在該方向上目標函數下降最快,這也是最速下降法名稱的由來)。
梯度下降法特點:越接近目標值,步長越小,下降速度越慢。
4.2.2 代碼實現
# 代碼輸入:
# 訓練集
# 每個樣本點有 3 個分量 (x0,x1,x2)
x = [(1, 0., 3), (1, 1., 3), (1, 2., 3), (1, 3., 2), (1, 4., 4)]
# y[i] 樣本點對應的輸出
y = [95.364, 97.217205, 75.195834, 60.105519, 49.342380]
# 迭代閥值,當兩次迭代損失函數之差小于該閥值時停止迭代
epsilon = 0.0001
# 學習率
alpha = 0.01
diff = [0, 0]
max_itor = 1000
error1 = 0
error0 = 0
cnt = 0
m = len(x)
# 初始化參數
theta0 = 0
theta1 = 0
theta2 = 0
while True:
cnt += 1
# 參數迭代計算
for i in range(m):
# 擬合函數為 y = theta0 * x[0] + theta1 * x[1] +theta2 * x[2]
# 計算殘差
diff[0] = (theta0 + theta1 * x[i][1] + theta2 * x[i][2]) - y[i]
# 梯 度 = diff[0] * x[i][j]
theta0 -= alpha * diff[0] * x[i][0] theta1 -= alpha * diff[0] * x[i][1] theta2 -= alpha * diff[0] * x[i][2]
# 計算損失函數
error1 = 0
for lp in range(len(x)):
error1 += (y[lp]-(theta0 + theta1 * x[lp][1] + theta2 * x[lp][2]))**2/2
if abs(error1-error0) < epsilon: break
else:
error0 = error1
print(' theta0 : %f, theta1 : %f, theta2 : %f, error1 : %f' % (theta0, theta1, theta2, error1) )
print('Done: theta0 : %f, theta1 : %f, theta2 : %f' % (theta0, theta1, theta2) )
print('迭代次數: %d' % cnt )
# 結果輸出:
theta0 : 2.782632, theta1 : 3.207850, theta2 : 7.998823, error1 : 5997.941160
theta0 : 4.254302, theta1 : 3.809652, theta2 : 11.972218, error1 : 3688.116951
theta0 : 5.154766, theta1 : 3.351648, theta2 : 14.188535, error1 : 2889.123934
theta0 : 5.800348, theta1 : 2.489862, theta2 : 15.617995, error1 : 2490.307286
theta0 : 6.326710, theta1 : 1.500854, theta2 : 16.676947, error1 : 2228.380594
theta0 : 6.792409, theta1 : 0.499552, theta2 : 17.545335, error1 : 2028.776801
… …
theta0 : 97.717864, theta1 : -13.224347, theta2 : 1.342491, error1 : 58.732358
theta0 : 97.718558, theta1 : -13.224339, theta2 : 1.342271, error1 : 58.732258
theta0 : 97.719251, theta1 : -13.224330, theta2 : 1.342051, error1 : 58.732157
Done: theta0 : 97.719942, theta1 : -13.224322, theta2 : 1.341832
迭代次數: 2608
上一篇: {HTML5}進階選擇器-第三節