實(shí)驗(yàn)?zāi)康?/h1>
梯度下降法是一個(gè)最優(yōu)化算法九火,通常也稱為最速下降法赚窃。最速下降法是求解無(wú)約束優(yōu)化問(wèn)題最簡(jiǎn)單和最古老的方法之一,雖然現(xiàn)已不具有實(shí)用性岔激,但是許多有效算法都是以它為基礎(chǔ)進(jìn)行改進(jìn)和修正而得到的勒极。最速下降法是用負(fù)梯度方向?yàn)樗阉鞣较虻模钏傧陆捣ㄔ浇咏繕?biāo)值虑鼎,步長(zhǎng)越小辱匿,前進(jìn)越慢。
線性回歸是利用數(shù)理統(tǒng)計(jì)中回歸分析震叙,來(lái)確定兩種或兩種以上變量間相互依賴的定量關(guān)系的一種統(tǒng)計(jì)分析方法掀鹅,運(yùn)用十分廣泛。其表達(dá)形式為y = w'*x+e媒楼,e為誤差服從均值為0的正態(tài)分布乐尊。[1]
回歸分析中,只包括一個(gè)自變量和一個(gè)因變量划址,且二者的關(guān)系可用一條直線近似表示扔嵌,這種回歸分析稱為一元線性回歸分析。如果回歸分析中包括兩個(gè)或兩個(gè)以上的自變量夺颤,且因變量和自變量之間是線性關(guān)系痢缎,則稱為多元線性回歸分析。
本次實(shí)驗(yàn)將驗(yàn)證梯度下降法可以求解線性回歸的參數(shù)世澜。
實(shí)驗(yàn)環(huán)境
本次實(shí)驗(yàn)独旷,使用的程序語(yǔ)言為Python3.5,依賴的工具包為:
import matplotlib.pyplot as plt
import csv
import numpy as np
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D
實(shí)驗(yàn)內(nèi)容及步驟
- 畫(huà)出樣本分布圖寥裂;
- 畫(huà)出線性回歸假設(shè)模型;
- 畫(huà)出成本函數(shù)收斂曲線
- 使用梯度下降法更新參數(shù)
在詳細(xì)了解梯度下降的算法之前嵌洼,我們先看看相關(guān)的一些概念。
步長(zhǎng)(Learning rate):步長(zhǎng)決定了在梯度下降迭代的過(guò)程中封恰,每一步沿梯度負(fù)方向前進(jìn)的長(zhǎng)度麻养。用上面下山的例子,步長(zhǎng)就是在當(dāng)前這一步所在位置沿著最陡峭最易下山的位置走的那一步的長(zhǎng)度诺舔。
特征(feature):指的是樣本中輸入部分鳖昌,比如樣本(x0,y0),(x1,y1),則樣本特征為x,樣本輸出為y低飒。
假設(shè)函數(shù)(hypothesis function):在監(jiān)督學(xué)習(xí)中许昨,為了擬合輸入樣本,而使用的假設(shè)函數(shù)褥赊,記為hθ(x)车要。
損失函數(shù)(loss function):為了評(píng)估模型擬合的好壞,通常用損失函數(shù)來(lái)度量擬合的程度崭倘。損失函數(shù)極小化翼岁,意味著擬合程度最好类垫,對(duì)應(yīng)的模型參數(shù)即為最優(yōu)參數(shù)。在線性回歸中琅坡,損失函數(shù)通常為樣本輸出和假設(shè)函數(shù)的差取平方悉患。
預(yù)測(cè)值:
誤差:
優(yōu)化目標(biāo):
參數(shù)更新:
實(shí)驗(yàn)結(jié)果及分析
對(duì)數(shù)據(jù)進(jìn)行了歸一化處理。
對(duì)1維數(shù)據(jù)榆俺,迭代了300次0.02步長(zhǎng)售躁,500次0.01步長(zhǎng)。最終結(jié)果如圖:
對(duì)2維數(shù)據(jù)茴晋,迭代了700次0.01步長(zhǎng)陪捷。最終結(jié)果如圖:
如何調(diào)優(yōu)?步長(zhǎng)诺擅,初始參數(shù)市袖,歸一化。
方法變種:批量梯度下降烁涌,隨機(jī)梯度下降苍碟,小批量。在每次選取樣本的數(shù)量上有區(qū)別撮执。
橫向比較:梯度下降法和最小二乘法相比微峰,梯度下降法需要選擇步長(zhǎng),而最小二乘法不需要抒钱。梯度下降法是迭代求解蜓肆,最小二乘法是計(jì)算解析解。如果樣本量不算很大谋币,且存在解析解仗扬,最小二乘法比起梯度下降法要有優(yōu)勢(shì),計(jì)算速度很快瑞信。但是如果樣本量很大,用最小二乘法由于需要求一個(gè)超級(jí)大的逆矩陣穴豫,這時(shí)就很難或者很慢才能求解解析解了凡简,使用迭代的梯度下降法比較有優(yōu)勢(shì)。梯度下降法和牛頓法/擬牛頓法相比精肃,兩者都是迭代求解秤涩,不過(guò)梯度下降法是梯度求解,而牛頓法/擬牛頓法是用二階的海森矩陣的逆矩陣或偽逆矩陣求解司抱。相對(duì)而言筐眷,使用牛頓法/擬牛頓法收斂更快。但是每次迭代的時(shí)間比梯度下降法長(zhǎng)习柠。
總結(jié)
通過(guò)這次實(shí)驗(yàn)匀谣,我驗(yàn)證了經(jīng)典優(yōu)化算法照棋。體會(huì)到了這些優(yōu)化方法的巧妙,加深了對(duì)梯度下降法的理解武翎。鍛煉了編程實(shí)踐的能力烈炭。更加堅(jiān)定了我在未來(lái)的學(xué)習(xí)道路上求真篤行的態(tài)度。
程序
import scipy.io as sio
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import KFold
import matplotlib.pyplot as plt
def predict(theta,x):
'''
theta:(d,1)
x:(n,d)
'''
x=x.reshape((-1,1))
return x.dot(theta).reshape((-1,1))
def const_error(h,y):
return h-y
# 均方誤差
# h:pred_y
def cost(h,y,con):
return (np.mean(con**2))/2
def grad(x,con):
return np.mean(con*x,axis=0,keepdims=True).transpose()
matfn='shuju.mat'
data=sio.loadmat(matfn)
print()
XY,epsilon=data['shuju'],data['epsilon'].ravel()[0]
gamma=0.01
epoch=10000
epsilon=1e-8
# np.savetxt('parameters.txt',[epsilon,gamma])
# np.save('data.npy',XY)
# print(type(XY),epsilon)
np.random.seed(2)
np.random.shuffle(XY)
X,Y=XY[:,:1],XY[:,1:]
min_max_scaler=MinMaxScaler()
X,Y=list(map(min_max_scaler.fit_transform,[X,Y]))
kfold=KFold(5)
thetas=[]#每一次的參數(shù)
for j,(train_index,test_index) in enumerate(kfold.split(X)):
train_x,test_x,train_y,test_y=X[train_index],X[test_index],Y[train_index],Y[test_index]
sc = [] # 訓(xùn)練集誤差
vc = [] # 交叉集預(yù)測(cè)誤差
theta = np.random.randn()#每次都要隨機(jī)初始化
this_time_con=100000#損失
# if j!=3:
# continue
for i in range(epoch):
h = predict(theta, train_x)
con = const_error(h, train_y)
g = grad(train_x, con)
pre_y = predict(theta, test_x)
if gamma>=500:
gamma*=0.95
theta = theta - gamma * g#更新公式
#存一下?lián)p失
valdation_cost=cost(pre_y, test_y, const_error(pre_y, test_y))
sc.append(cost(h, train_y, con))
vc.append(valdation_cost)
if abs(this_time_con-valdation_cost)<=epsilon:
break
else:
this_time_con = valdation_cost
plt.plot(np.arange(len(sc)), np.array(sc), label="training_cost")
plt.legend()
plt.plot(np.arange(len(vc)), np.array(vc), label="validating_cost")
plt.legend()
plt.xlabel("epoch")
plt.ylabel("cost")
plt.title(str(j)+'time_cost.png')
# print(i,valdation_cost)
plt.text(i,valdation_cost,'val_cost:\n(%d,%.3f)'%(i,valdation_cost),fontsize=8)
# plt.show()
plt.savefig(str(j)+'time_cost.png')
plt.clf()
thetas.append(theta.reshape(-1)[0])
plt.scatter(X, Y, marker='x')
plt.grid()
x = np.arange(-0.2, 1.2, 0.001)
y = predict(theta, x)
plt.plot(x, y)
plt.title("%dtime_predict" % (j))
# plt.savefig("%dtime_predict" % (j))
plt.clf()
import json
json.dump(thetas,open('thetas.json','w'))
'''
我們可以看到第3次出現(xiàn)了損失上升的情況宝恶,這是學(xué)習(xí)率過(guò)大導(dǎo)致的
所以我們?cè)?00次迭代時(shí)符隙,降低學(xué)習(xí)率
'''