本篇文章來(lái)源于專欄《Python從入門到人工智能》,更多內(nèi)容可復(fù)制鏈接到此查看:https://blog.csdn.net/qq_44731019/category_11717408.html 對(duì)于一個(gè)算法(模型)。在深度學(xué)習(xí)中,簡(jiǎn)要的處理方式是: 準(zhǔn)備數(shù)據(jù)集(Datasets)—>> Model(選擇模型) —>> Training (模型訓(xùn)練) —>> 推理(進(jìn)行推理預(yù)測(cè))。 至于優(yōu)化等,可以理解為后續(xù)的補(bǔ)充。 監(jiān)督學(xué)習(xí):數(shù)據(jù)集需要 交付給算法模型 進(jìn)行訓(xùn)練,利用所訓(xùn)練的模型,在獲得 新的數(shù)據(jù)時(shí) 可以得到相應(yīng)的輸出。 線性模型的基本模型如下,其中的ω和 ![]() 在模型訓(xùn)練中 會(huì)先隨機(jī)取得一個(gè)值,繼而 計(jì)算其和標(biāo)準(zhǔn)量之間的 偏移量,從而判斷 當(dāng)前模型 是否符合預(yù)期。 記實(shí)際值為 通常,該公式定義為Training Loss (Error) 本例中,原題目中的幾種 其中的每行 為 對(duì)于單個(gè)樣本,loss 可用于 指代樣本誤差。對(duì)于所有樣本,可同理用Mean Square Error (MSE)來(lái)指代 整體樣本的平均平方誤差(均方差cost) MSE:均方誤差(Mean Square Error)。,即 每個(gè)樣本對(duì)應(yīng)的損失值 (平方) 求和,再除以樣本總個(gè)數(shù)。 由cost的計(jì)算公式可知,當(dāng)平均損失為0時(shí),模型最佳,但由于 僅當(dāng)數(shù)據(jù)無(wú)噪聲 且 模型完美貼合數(shù)據(jù) 的情況下才會(huì)出現(xiàn)這種情況,因此 模型訓(xùn)練的目的 應(yīng)當(dāng)是 誤差(損失)盡可能小,而非找到 誤差為0的情況。 不同 1.1.1 基礎(chǔ)練習(xí) 根據(jù)上面的分析,code如下:注釋我已經(jīng)寫的比較清楚啦。 # 昵 稱:XieXu # 時(shí) 間: 2023/2/12/0012 21:10
# 導(dǎo)入必要的工具包 import numpy as np import matplotlib.pyplot as plt
# 自定義 簡(jiǎn)單數(shù)據(jù)集。x與y 一一對(duì)應(yīng) (訓(xùn)練集) x_data = [1.0, 2.0, 3.0] y_data = [2.0, 4.0, 6.0]
# 模型,(前饋) def forward(x): return x * w
# 損失函數(shù) def loss(x, y): y_pred = forward(x) # 即 y_hat。相當(dāng)于 預(yù)測(cè)的值 return (y_pred - y) * (y_pred - y) # 平方(均方誤差)。簡(jiǎn)單形式的均方誤差。這個(gè)計(jì)算的 為單個(gè)樣本的誤差
# 【窮舉法】 # 如下兩個(gè)列表 保存 權(quán)重 及其對(duì)應(yīng)的損失值 w_list = [] mse_list = []
# [0.0,4.1),間隔為0.1。即 0.0, 0.1, 0.2, 0.3 ... 4.0 起始值(含),停止值(不含),步長(zhǎng) for w in np.arange(0.0, 4.1, 0.1): # 外層循環(huán) 控制權(quán)重 2023.2.13 08:20 print('w=', w) l_sum = 0 # zip 將x_data 和 y_data 打包為一個(gè)tuple(元組),方便同時(shí)遍歷。 for x_val, y_val in zip(x_data, y_data): # 內(nèi)層循環(huán)控制進(jìn)行 權(quán)重:調(diào)用forward函數(shù) 對(duì)應(yīng)的預(yù)測(cè),以及 調(diào)用上面定義的loss函數(shù) 進(jìn)行損失值計(jì)算 y_pred_val = forward(x_val) # 計(jì)算 每個(gè)樣本的 預(yù)測(cè)值 loss_val = loss(x_val, y_val) # 計(jì)算 每個(gè)樣本的 損失值 l_sum += loss_val # 將 所有樣本的 損失求和(這里沒(méi)做均值) print('\t', x_val, y_val, y_pred_val, loss_val) # 打印出 每一個(gè)樣本:x,x對(duì)應(yīng)的y,預(yù)測(cè)值y_hat,損失值 print('MSE=', l_sum / 3) # 這里 除以樣本總數(shù),進(jìn)行均值,即 均方誤差 w_list.append(w) # 將每次 用完的 權(quán)重添加到列表中,用以 下面畫圖 的橫坐標(biāo)~ mse_list.append(l_sum / 3) # 除以樣本總數(shù)。每個(gè)權(quán)重 對(duì)應(yīng)的 所有樣本的平均誤差(均方誤差) MSE,也叫均值吧。下面繪圖的縱坐標(biāo)
# 繪制圖形 plt.plot(w_list, mse_list) # 橫坐標(biāo)、縱坐標(biāo) 的取值 plt.ylabel('Loss') # 縱坐標(biāo)y的標(biāo)簽 plt.xlabel('w') # 橫坐標(biāo)w的標(biāo)簽 plt.show()
可以得到結(jié)果:紅色為我做的標(biāo)注~ 從下面 控制臺(tái)打印的日志中,我們 可以 很容易看出來(lái)上圖 的由來(lái): 開始時(shí),隨著W增加,平均損失MSE逐漸減小,
1.1.2 練習(xí) 同樣地,基于上面的例子,練習(xí): 實(shí)現(xiàn)線性模型 不同之處在于,定義的模型,與上面相比,加了個(gè) 偏置項(xiàng)B。
可以得到如下圖形:這就是 ( 其中,控制臺(tái)輸出的日志中,含有警告:
ax = Axes3D(fig) 翻譯一下上面的警告:大意即 由于版本不同,可暫時(shí)忽略。 1.1.3 其它:在深度學(xué)習(xí)訓(xùn)練中,橫軸往往是Epoch在深度學(xué)習(xí)訓(xùn)練的可視化圖形中,一般橫軸是Epoch,即訓(xùn)練輪數(shù):往往在訓(xùn)練集上表現(xiàn)是,隨著訓(xùn)練輪數(shù)增多,損失越來(lái)越低;而在測(cè)試集(老師讀 開發(fā)集)上的效果是,損失在剛開始會(huì)下降,而后到某個(gè)點(diǎn),又會(huì)逐漸上升。而我們的目標(biāo)就是,想找到損失最低的那個(gè)點(diǎn);從而進(jìn)一步 對(duì)超參數(shù)進(jìn)行處理等其它操作。 深度學(xué)習(xí)中可能需要考慮更多問(wèn)題,比如 老師提到了 Pytorch可視化工具——Visdom。目前我沒(méi)有用到…稍微大型的項(xiàng)目可能會(huì)用到吧??梢栽诎俣人阉鱒isdom并查看它的相關(guān)信息,以及其GitHub官網(wǎng)。 ??1.2 Gradient Descent(梯度下降)1.2.1 梯度下降法 的由來(lái):?jiǎn)栴}背景在上面 線性模型的方法中,所使用的思想是基于窮舉,即 但是,這種思想 在多維的情況下,即多個(gè)參數(shù)的時(shí)候,會(huì)引起 那么,使用 分治法 如何? 即:大化小,小化無(wú),先對(duì)整體 進(jìn)行分割采樣,在相對(duì)最低點(diǎn)進(jìn)行進(jìn)一步采樣,直到其步長(zhǎng)與誤差符合條件。 但是,分治法有兩個(gè)缺點(diǎn):
同時(shí),由于以上問(wèn)題的存在,引起了參數(shù)優(yōu)化的問(wèn)題,即求解使loss最小時(shí)的參數(shù)的值。 簡(jiǎn)言之,即求得 如何優(yōu)化,求得符合條件的 1.2.2 何為梯度?梯度,即 導(dǎo)數(shù)變化最大的值,其方向為 這里,可以使用高等數(shù)學(xué)中關(guān)于 一個(gè)點(diǎn)處 導(dǎo)數(shù)的定義: (這里僅簡(jiǎn)單理解,并非嚴(yán)謹(jǐn)數(shù)學(xué)推導(dǎo))對(duì)于 下面的圖將便于理解: 1.2.3 梯度下降在深度學(xué)習(xí)中,所說(shuō)的凸函數(shù),是與高等數(shù)學(xué)定義中的 凸函數(shù),完全反過(guò)來(lái)的,知道這一點(diǎn)就好。如下圖所示,在深度學(xué)習(xí)中,將其看做一個(gè)凸函數(shù)。 當(dāng)前, 那么,取值點(diǎn) 需要 向下更新,所取的梯度即為 局限性:
1.2.4 梯度下降的公式 如何得來(lái)的?(理解)通過(guò)線性模型,我們知道 均方誤差的公式即:其中 進(jìn)一步地,可以對(duì) 根據(jù)數(shù)學(xué)知識(shí),由于是對(duì) 而( 因此,梯度下降的更新公式為: 下圖即上述公式的推導(dǎo)過(guò)程: 梯度的求解公式,應(yīng)用到code中的示例: 1.2.5 隨機(jī)梯度下降(Stochastic gradient descent,SGD);Mini-batch!平時(shí)用的比較多的,是隨機(jī)梯度下降(SGD)。 SGD采用單個(gè)訓(xùn)練樣本的損失來(lái)近似平均損失,故 SGD 用單個(gè)訓(xùn)練數(shù)據(jù)即可對(duì)模型參數(shù)進(jìn)行一次更新,大大加快了訓(xùn)練速度。 隨機(jī)梯度下降 每次 只需要計(jì)算 一個(gè)樣本關(guān)于
同時(shí),為了降低隨機(jī)梯度的方差,使迭代算法更加穩(wěn)定,在真實(shí)操作中,會(huì)同時(shí)處理若干訓(xùn)練數(shù)據(jù),該方法叫做小批量隨機(jī)梯度下降法(Mini_Batch Gradient Densent)。,這才是真正地運(yùn)用了 隨機(jī)梯度下降(SGD),目前,在實(shí)際應(yīng)用中,我們所說(shuō)的 小結(jié)
將若干個(gè)樣本分為一組,記錄一組的梯度 用以代替隨機(jī)梯度下降中的單個(gè)樣本。 該方法最為常用,也是默認(rèn)接口。一般,mini-batch可以在2的冪次中挑選最優(yōu)取值。例如16、32、64、128、256等。 1.2.6 梯度下降練習(xí):方法一(推薦 完全 自己 多手寫幾遍)給定一個(gè)數(shù)據(jù)集,x_data、y_data。尋找y=wx模型的w最優(yōu)解。 code練習(xí)如下,注釋中,我已經(jīng)介紹的比較詳細(xì)啦!我想這可以幫助絕大多數(shù)朋友理解。
得到結(jié)果:可以看到,在20輪左右,損失值就已經(jīng)很接近0了。
1.2.7 方法二(與法一類似,不過(guò)這里 縱軸 是 權(quán)值的第二種方式:與第一種類似,只不過(guò)這里縱坐標(biāo)取的是 權(quán)值,另外,直接把梯度下降 放到Epoch訓(xùn)練里面了。代碼如下: # 方法二 import numpy as np import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0] y_data = [2.0, 4.0, 6.0]
scope_list = [] # 輪數(shù) w_list = [] # 權(quán)值W
w = 60 # 我們給W一個(gè)初始值
# 學(xué)習(xí)率 k = 0.01 # 定義學(xué)習(xí)率
# 開始訓(xùn)練 for i in range(1,201,1): # 計(jì)算cost(loss的和) loss_sum = 0
# 求梯度 for x_val, y_val in zip(x_data, y_data): loss_sum += 2 * x_val * (w * x_val - y_val) cost = loss_sum / 3
# 計(jì)算本輪w w = w - k * cost print('Epoch:',i,'W:',w) scope_list.append(i) w_list.append(w)
# 按說(shuō)縱坐標(biāo)不應(yīng)該取權(quán)值的,既然取了,那么可以從圖形中,看出來(lái)大概 50左右,權(quán)值就收斂了 plt.plot(scope_list, w_list) # 橫坐標(biāo) 取值 依然是 輪數(shù),縱坐標(biāo)取值是按照W來(lái)取的值 plt.xlabel('scope') plt.ylabel('W') plt.show() 結(jié)果如下所示:
1.2.8 隨機(jī)梯度下降練習(xí)(一),可視化這里,即普通的隨機(jī)梯度下降,每輪訓(xùn)練中,每次計(jì)算的 關(guān)于 即 注:這里,隨機(jī)梯度主要是指,每次拿一個(gè)訓(xùn)練數(shù)據(jù)來(lái)訓(xùn)練,然后更新梯度參數(shù)。
1.2.9 隨機(jī)梯度下降練習(xí)(二),可視化上面的隨機(jī)梯度下降算法中,貌似僅僅 是只計(jì)算了 每一個(gè)樣本的梯度,好像沒(méi)有體現(xiàn)“隨機(jī)”。 這里再換個(gè)類似的算法,基本一樣,但用到了random隨機(jī)。 該方法與目錄1.2.6類似。 # 方法二 import random import numpy as np import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0] y_data = [2.0, 4.0, 6.0]
scope_list = [] # 訓(xùn)練輪數(shù) w_list = [] # 權(quán)值
w = 60
# 學(xué)習(xí)率 k = 0.01
for i in range(1, 201, 1): # 計(jì)算cost(即隨機(jī)一個(gè)loss當(dāng)cost用) rand = random.randint(0, 2) # 取值為[0,2],即 隨機(jī)生成0~2內(nèi)的 某個(gè) 整數(shù),包含0和2。(三個(gè)樣本,隨機(jī)取一個(gè)) cost = 2 * x_data[rand] * (w * x_data[rand] - y_data[rand]) # 從而計(jì)算得到 關(guān)于W的偏導(dǎo)數(shù)
# 計(jì)算本輪w w = w - k * cost # 更新W print('Epoch=', i, 'W=', w) # 本輪更新后的W 2023.2.13 20:30 scope_list.append(i) w_list.append(w)
plt.plot(scope_list, w_list) # 橫坐標(biāo)為輪數(shù),縱坐標(biāo)為權(quán)值。 plt.xlabel('scope') plt.ylabel('W') plt.show() 如下圖所示,可以看出,75輪左右,權(quán)值就已經(jīng)逐漸收斂了~
|
|
來(lái)自: taotao_2016 > 《數(shù)學(xué)》