一、最小二乘法
先來解釋幾個(gè)概念
擬合函數(shù)/估值函數(shù)
:在回歸問題中,當(dāng)給定一組樣本時(shí),找到一個(gè)最佳的函數(shù)來匹配所有的樣本,這個(gè)函數(shù)就是擬合函數(shù)/估值函數(shù)
損失函數(shù)
:判斷函數(shù)擬合的好不好的函數(shù),損失函數(shù)越小,說明擬合值與真實(shí)值越接近,誤差越小,就越能用擬合函數(shù)來進(jìn)行預(yù)測,損失函數(shù)的標(biāo)準(zhǔn)有以下幾種:
a) 殘差和: 指擬合值與真實(shí)值的差的和,有正有負(fù)會(huì)存在抵消的情況,不能反應(yīng)真實(shí)誤差
b) 殘差絕對值和:這個(gè)可以解決殘差和有正有負(fù)的問題,但是絕對值在后續(xù)的求導(dǎo)會(huì)異常麻煩
c) 殘差的平方和:這就是最小二乘法,通過殘差平方和求解極值,找到最佳的擬合函數(shù)
如何對損失函數(shù)求解呢?
① 代數(shù)求導(dǎo)法
假設(shè)擬合函數(shù)為一元線性函數(shù):
其中ei為樣本(Xi, Yi)的誤差
平方和損失函數(shù):
則通過Q最小確定這條直線,解決辦法:將兩個(gè)參數(shù)作為未知數(shù),分別求偏導(dǎo),代入所有的樣本值,當(dāng)偏導(dǎo)=0時(shí),就求得極值
解為:
② 矩陣法
當(dāng)樣本特征量較多時(shí),會(huì)有非常多參數(shù)需要一一求解,會(huì)相當(dāng)費(fèi)時(shí)間,這時(shí)可以用更快的矩陣方法來求解。
矩陣可以理解為多個(gè)方程組同時(shí)求解,當(dāng)我們用方程組表達(dá)時(shí)
將其轉(zhuǎn)化為矩陣形式:
損失函數(shù)就變?yōu)椋?
最優(yōu)解為:
python中有封裝好的最小二乘法的求解函數(shù) leastsq,可以直接用:
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
# 真實(shí)函數(shù)
def real_func(x):
return np.sin(2*np.pi*x)
# 擬合函數(shù)
def fit_func(p, x):
f = np.poly1d(p) # polyid是多項(xiàng)式函數(shù),p決定了多項(xiàng)式的次數(shù)
return f(x)
# 誤差函數(shù)
def residuals_func(p, y, x):
ret = fit_func(p,x) - y
return ret
np.random.seed(0) # 隨機(jī)數(shù)種子
x = np.linspace(0,2,20)
x_points = np.linspace(0,2,100)
y0 = real_func(x)
y1 = [np.random.normal(0, 0.5) + y for y in y0] # 制造噪音
n = 9
p_init = np.random.randn(n) # 隨機(jī)生成多項(xiàng)式參數(shù)
plsq = leastsq(residuals_func, p_init, args=(y0, x)) #最小二乘法黑箱計(jì)算,參數(shù)為(誤差函數(shù),誤差函數(shù)的參數(shù),樣本點(diǎn))
print(plsq)
plt.plot(x_points, real_func(x_points),c='r',label='real')
plt.plot(x_points,fit_func(plsq[0], x_points),c='b',label='fit')
plt.plot(x, y1,'bo', label='with noise')
plt.legend(loc='best') # 如果畫圖中有加lable,記得加上plt.legend(loc='best')
plt.show()
最小二乘法通過代數(shù)和矩陣兩種方法都能求得擬合函數(shù)的參數(shù),但是不是所有的擬合函數(shù)都能通過最小二乘法求解呢?No,比如非線性函數(shù)就失效了,那有沒有一種更通用的線性和非線性函數(shù)都能求參數(shù)的方法呢?那就是梯度下降法
二、梯度下降法
擬合函數(shù),損失函數(shù)模型以及求偏導(dǎo)與最小二乘法都一樣,唯一區(qū)別在于如何獲得最優(yōu)解,最小二乘法是直接令導(dǎo)數(shù)等于0求解,而梯度下降法是沿著梯度下降的方向逐步迭代,不斷逼近最小值來求解。
先解釋下梯度下降:梯度其實(shí)就是函數(shù)對各變量的偏導(dǎo)的元組,如果從圖上看,就是在特定點(diǎn)的切線,梯度是函數(shù)增加最快的方向,那么梯度下降的意思就是沿著梯度的反方向走,那么就是沿著函數(shù)減小最快的方向,就像在下山,每個(gè)路口都選擇一條最陡峭的路走(當(dāng)然懸崖峭壁就別考慮了),那么是不是就能以最快的速度到達(dá)山腳呢
可能有人會(huì)問:為什么不用最小二乘法直接求,多快呀,還要一步一步迭代?這個(gè)問題可以這么理解,有一些函數(shù)是無法通過通過求導(dǎo)=0這種方式獲得極值的,這就限制了最小二乘的使用;并且哪怕可以通過這種方式求,計(jì)算也相當(dāng)麻煩時(shí), 逐步迭代反而會(huì)更快。
梯度下降法求解過程:
①隨機(jī)給定一組初始參數(shù)值和學(xué)習(xí)率(學(xué)習(xí)率是控制每一次迭代的步長,太小了需要很長的時(shí)間才能收斂,太大了容易震蕩,可以無法獲得最優(yōu)解)
②對損失函數(shù)各參數(shù)求偏導(dǎo),得到梯度
③更新參數(shù):參數(shù) = 初始參數(shù)-學(xué)習(xí)率
梯度
④不斷迭代,直接誤差達(dá)到所要求的范圍停止
*
# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
x_train = np.array([[1, 2], [2, 1], [2, 3], [3, 5],[1, 3], [4, 2], [7, 3], [4, 5], [11, 3], [8, 7]])
y_train = np.array([7, 8, 10, 14, 8, 13, 20, 16, 28, 26])
x_test = np.array([[1, 4],[2, 2],[2, 5],[5, 3],[1, 5],[4, 1]])
a = np.random.normal()
b = np.random.normal()
c = np.random.normal()
error_list = []
# 擬合函數(shù)
def h(x):
return a*x[0] + b*x[1] + c
rate = 0.001 # 學(xué)習(xí)率
for i in range(8000):
sum_a = sum_b = sum_c = 0
for x, y in zip(x_train, y_train): # 將全部樣本代入求梯度
sum_a = sum_a + rate*(y - h(x))*x[0]
sum_b = sum_b + rate*(y - h(x))*x[1]
sum_c = sum_c + rate*(y - h(x))
a = a+sum_a
b = b+sum_b
c = c+sum_c
plt.plot([h(xi) for xi in x_test])
error = 0
for x, y in zip(x_train, y_train):
error += 0.5*((h(x) - y)**2)
error_list.append(error)
if error<0.000001: # 當(dāng)誤差小于0.00001 即可停止
break
print(error_list)
print(len(error_list))
print(a)
print(b)
print(c)
result = [h(xi) for xi in x_train]
print(result)
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax1.plot(y_train,label='標(biāo)簽')
ax2 = fig.add_subplot(122)
ax2.plot(result,label='預(yù)測')
plt.legend()
plt.show()
通過迭代調(diào)整參數(shù),曲線一開始變化很快,后面變得緩慢,等誤差小到一定程度時(shí),曲線不再變化,這就是最佳的擬合函數(shù)曲線
這個(gè)是誤差列表,可以看出共迭代了4508次,誤差一開始下降特別快,后面逐漸變慢
這個(gè)是真實(shí)曲線和擬合曲線,肉眼上基本已經(jīng)看不出分別了。
上面的例子只有10個(gè)樣本,所以每次迭代都使用所有的樣本來計(jì)算梯度,速度也還挺快的,這種方法叫
批量梯度下降
;但是如果樣本成千上萬,這樣計(jì)算的時(shí)間開銷就有點(diǎn)太大了,難道一定要每一次迭代都用所有的樣本才能獲得最優(yōu)解嗎?針對這個(gè)問題,提出了2個(gè)解決方案:
①
隨機(jī)梯度下降
:顧名思義,每次只挑選一個(gè)樣本進(jìn)行梯度計(jì)算然后更新參數(shù),這樣就可以大大節(jié)省時(shí)間了!是的,可是這樣真的可以嗎?還真的可以! 雖然正確度肯定比不上每次都用所有樣本,但是在迭代多次之后,仍然可能達(dá)能一個(gè)比較好的效果,但是也存在一個(gè)問題,就是噪音要更多,使得并不是每次迭代都向著整體最優(yōu)化方向
②
小批量梯度下降
:這是批量和隨機(jī)梯度下降兩種方法的折中,每次選取一組訓(xùn)練樣本進(jìn)行關(guān)于參數(shù)的梯度,即能減少批量帶來的計(jì)算冗余的問題,又能解決隨機(jī)帶來的震蕩問題。
總結(jié):
1、最小二乘法與梯度下降法的區(qū)別?
都是最小化風(fēng)險(xiǎn)函數(shù)、損失函數(shù)的方法,兩者都需要求偏導(dǎo),最小二乘法是以誤差平方和最小作為損失函數(shù),直接讓偏導(dǎo)等于0獲得全局最優(yōu)解,多用于處理一元或多元線性回歸問題,梯度下降法包括但不限于最小平方和作為損失函數(shù),是沿著負(fù)梯度方向不斷迭代逼近最優(yōu)解,線性和非線性問題都能處理
2、與批量梯度下降對比,隨機(jī)梯度下降求解的會(huì)是最優(yōu)解嗎?
(1)批量梯度下降—最小化所有訓(xùn)練樣本的損失函數(shù),使得最終求解的是全局的最優(yōu)解,即求解的參數(shù)是使得風(fēng)險(xiǎn)函數(shù)最小。
(2)隨機(jī)梯度下降—最小化每條樣本的損失函數(shù),雖然不是每次迭代得到的損失函數(shù)都向著全局最優(yōu)方向, 但是大的整體的方向是向全局最優(yōu)解的,最終的結(jié)果往往是在全局最優(yōu)解附近
3、梯度下降用來求最優(yōu)解,哪些問題可以求得全局最優(yōu)?哪些問題可能局部最優(yōu)解?
如果損失函數(shù)只有一個(gè)峰,那么可能獲得全局最優(yōu),如果有多個(gè)峰,則可能獲得局部最優(yōu)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

