欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

pytorch搭建模型的五大層次級(jí)別解讀(由淺入深)

 更新時(shí)間:2023年06月15日 08:57:02   作者:LoveMIss-Y  
這篇文章主要介紹了pytorch搭建模型的五大層次級(jí)別(由淺入深),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

神經(jīng)網(wǎng)絡(luò)的搭建本身是一個(gè)較為復(fù)雜的過程,但是現(xiàn)在有非常多的、非常人性化的開源框架提供給我們使用,但是即便如此,網(wǎng)絡(luò)的搭建也是有多種方法可以選擇,本文以pytorch為例子加以說(shuō)明。

神經(jīng)網(wǎng)絡(luò)的基本流程可以分為兩大步驟,即

網(wǎng)絡(luò)結(jié)構(gòu)搭建+參數(shù)的梯度更新(后者又包括  “前向傳播+計(jì)算參數(shù)的梯度+梯度更新”)

這其實(shí)也是后面pytorch搭建神經(jīng)網(wǎng)絡(luò)的一個(gè)基本思路

1 、原始搭建——使用numpy實(shí)現(xiàn)

# -*- coding: utf-8 -*-
import numpy as np
# N是訓(xùn)練的batch size; D_in 是input輸入數(shù)據(jù)的維度;
# H是隱藏層的節(jié)點(diǎn)數(shù); D_out 輸出的維度,即輸出節(jié)點(diǎn)數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建輸入、輸出數(shù)據(jù)
x = np.random.randn(N, D_in)  #(64,1000)
y = np.random.randn(N, D_out) #(64,10)可以看成是一個(gè)10分類問題
# 權(quán)值初始化
w1 = np.random.randn(D_in, H)  #(1000,100),即輸入層到隱藏層的權(quán)重
w2 = np.random.randn(H, D_out) #(100,10),即隱藏層到輸出層的權(quán)重
learning_rate = 1e-6   #學(xué)習(xí)率
for t in range(500):
    # 第一步:數(shù)據(jù)的前向傳播,計(jì)算預(yù)測(cè)值p_pred
    h = x.dot(w1)
    h_relu = np.maximum(h, 0)
    y_pred = h_relu.dot(w2)
    # 第二步:計(jì)算計(jì)算預(yù)測(cè)值p_pred與真實(shí)值的誤差
    loss = np.square(y_pred - y).sum()
    print(t, loss)
    # 第三步:反向傳播誤差,更新兩個(gè)權(quán)值矩陣
    grad_y_pred = 2.0 * (y_pred - y)     #注意:這里的導(dǎo)函數(shù)也是自己求的,因?yàn)檫@個(gè)地方是很簡(jiǎn)答的函數(shù)表達(dá)式
    grad_w2 = h_relu.T.dot(grad_y_pred)
    grad_h_relu = grad_y_pred.dot(w2.T)
    grad_h = grad_h_relu.copy()
    grad_h[h < 0] = 0
    grad_w1 = x.T.dot(grad_h)
    # 更新參數(shù)
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

缺點(diǎn):

(1)沒辦法搭建復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)(網(wǎng)絡(luò)的結(jié)構(gòu)搭建太底層);

(2)梯度需要自己求導(dǎo)函數(shù),如果函數(shù)太復(fù)雜,網(wǎng)絡(luò)太深就很難求了;

(3)沒有辦法使用GPU加速

2、使用torch的Tensor原始實(shí)現(xiàn)

import torch
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # 這里使用CPU,但實(shí)際上可以使用GPU
# N是訓(xùn)練的batch size; D_in 是input輸入數(shù)據(jù)的維度;
# H是隱藏層的節(jié)點(diǎn)數(shù); D_out 輸出的維度,即輸出節(jié)點(diǎn)數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建輸入、輸出數(shù)據(jù)
x = torch.randn(N, D_in, device=device, dtype=dtype)  #(64,1000)
y = torch.randn(N, D_out, device=device, dtype=dtype) #(64,10)可以看成是一個(gè)10分類問題
# 權(quán)值初始化
w1 = torch.randn(D_in, H, device=device, dtype=dtype) #(1000,100),即輸入層到隱藏層的權(quán)重
w2 = torch.randn(H, D_out, device=device, dtype=dtype)#(100,10),即隱藏層到輸出層的權(quán)重
learning_rate = 1e-6
for t in range(500):
    # 第一步:數(shù)據(jù)的前向傳播,計(jì)算預(yù)測(cè)值p_pred
    h = x.mm(w1)
    h_relu = h.clamp(min=0)
    y_pred = h_relu.mm(w2)
    # 第二步:計(jì)算計(jì)算預(yù)測(cè)值p_pred與真實(shí)值的誤差
    loss = (y_pred - y).pow(2).sum().item()
    print(t, loss)
    # 第三步:反向傳播誤差,更新兩個(gè)權(quán)值矩陣
    grad_y_pred = 2.0 * (y_pred - y)    #注意:這里的導(dǎo)函數(shù)也是自己求的,因?yàn)檫@個(gè)地方是很簡(jiǎn)答的函數(shù)表達(dá)式
    grad_w2 = h_relu.t().mm(grad_y_pred)
    grad_h_relu = grad_y_pred.mm(w2.t())
    grad_h = grad_h_relu.clone()
    grad_h[h < 0] = 0
    grad_w1 = x.t().mm(grad_h)
    # 參數(shù)更新(梯度下降法)
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

缺點(diǎn):

(1)沒辦法搭建復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)(網(wǎng)絡(luò)的結(jié)構(gòu)搭建太底層);

(2)梯度需要自己求導(dǎo)函數(shù),如果函數(shù)太復(fù)雜,網(wǎng)絡(luò)太深就很難求了;

解決了GPU計(jì)算問題、少了一個(gè)缺點(diǎn)。

3、torch的自動(dòng)求導(dǎo)autograd

import torch
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # 這里使用CPU,但實(shí)際上可以使用GPU
# N是訓(xùn)練的batch size; D_in 是input輸入數(shù)據(jù)的維度;
# H是隱藏層的節(jié)點(diǎn)數(shù); D_out 輸出的維度,即輸出節(jié)點(diǎn)數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建輸入、輸出數(shù)據(jù)
x = torch.randn(N, D_in, device=device, dtype=dtype)  #(64,1000)
y = torch.randn(N, D_out, device=device, dtype=dtype) #(64,10)可以看成是一個(gè)10分類問題
# 權(quán)值初始化
w1 = torch.randn(D_in, H, device=device, dtype=dtype) #(1000,100),即輸入層到隱藏層的權(quán)重
w2 = torch.randn(H, D_out, device=device, dtype=dtype)#(100,10),即隱藏層到輸出層的權(quán)重
learning_rate = 1e-6
for t in range(500):
    # 第一步:數(shù)據(jù)的前向傳播,計(jì)算預(yù)測(cè)值p_pred
    y_pred = x.mm(w1).clamp(min=0).mm(w2)
    # 第二步:計(jì)算計(jì)算預(yù)測(cè)值p_pred與真實(shí)值的誤差
    loss = (y_pred - y).pow(2).sum()
    print(t, loss.item())
    # 第三步:反向傳播誤差,更新兩個(gè)權(quán)值矩陣,這就是關(guān)鍵了,不再需要自己寫出導(dǎo)函數(shù),求導(dǎo)是自動(dòng)完成的
    loss.backward()  #一步到位、自動(dòng)求導(dǎo)
    # 參數(shù)梯度更新
    with torch.no_grad():
        w1 -= learning_rate * w1.grad  #grad屬性獲取梯度,其實(shí)這個(gè)地方就是相當(dāng)于是梯度下降法,優(yōu)化的過程可以自己定義,因?yàn)檫@里參數(shù)很少
        w2 -= learning_rate * w2.grad
        求完一次之后將梯度歸零
        w1.grad.zero_()
        w2.grad.zero_()

缺點(diǎn):

(1)沒辦法搭建復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)(網(wǎng)絡(luò)的結(jié)構(gòu)搭建太底層);

解決了GPU計(jì)算問題、而且梯度導(dǎo)數(shù)也不用自己求了,少了兩個(gè)缺點(diǎn)。那現(xiàn)在就只剩一個(gè)問題沒解決了,那就是怎么快速搭建更復(fù)雜、更深層的網(wǎng)絡(luò)結(jié)構(gòu)。

(2)上面更新參數(shù)w1和w2的過程其實(shí)就是一個(gè)優(yōu)化過程,這里是用的就是簡(jiǎn)單的頭下降法,這樣做有一個(gè)很大的缺點(diǎn),那就是這里只有兩個(gè)參數(shù)需要優(yōu)化,所以可以自己寫,但是現(xiàn)在的網(wǎng)絡(luò)有很多的參數(shù)需要優(yōu)化,都自己寫的話實(shí)在是太麻煩了。于是就有了后面的方法,參見下面

4、使用pytorch.nn模塊

可以將它理解為一個(gè)較高層次的API封裝

# -*- coding: utf-8 -*-
import torch
# N是訓(xùn)練的batch size; D_in 是input輸入數(shù)據(jù)的維度;
# H是隱藏層的節(jié)點(diǎn)數(shù); D_out 輸出的維度,即輸出節(jié)點(diǎn)數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建輸入、輸出數(shù)據(jù)
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
#模型搭建:這是與前面關(guān)鍵的區(qū)別,不再需要自己手動(dòng)進(jìn)行矩陣相乘,而是這種一步到位的方法
model = torch.nn.Sequential(
    torch.nn.Linear(D_in, H),
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out),
)
#定義損失函數(shù)
loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
for t in range(500):
    # 第一步:數(shù)據(jù)的前向傳播,計(jì)算預(yù)測(cè)值p_pred
    y_pred = model(x)
    # 第二步:計(jì)算計(jì)算預(yù)測(cè)值p_pred與真實(shí)值的誤差
    loss = loss_fn(y_pred, y)
    print(t, loss.item())
    # 在反向傳播之前,將模型的梯度歸零
    model.zero_grad()
    # 第三步:反向傳播誤差,更新兩個(gè)權(quán)值矩陣,這就是關(guān)鍵了,不再需要自己寫出導(dǎo)函數(shù),求導(dǎo)是自動(dòng)完成的
    loss.backward()
    #更新參數(shù)的梯度
    with torch.no_grad():
        for param in model.parameters():
            param -= learning_rate * param.grad #這其實(shí)就是梯度下降法,優(yōu)化參數(shù),通過循環(huán)自動(dòng)實(shí)現(xiàn),不要再一個(gè)一個(gè)寫了,相較于上面的參數(shù)更新方法簡(jiǎn)單了很多。但是還不夠

總結(jié):

到這一步,基本解決了前面的三個(gè)致命問題,即解決了GPU計(jì)算問題、而且梯度導(dǎo)數(shù)也不用自己求了,并且可以搭建復(fù)雜的網(wǎng)絡(luò),不需要自己進(jìn)行一個(gè)一個(gè)的矩陣相乘,少了三個(gè)缺點(diǎn)。

使用這里的層次,一些簡(jiǎn)單的網(wǎng)絡(luò)類型就沒什么問題了,當(dāng)然我們還可以進(jìn)一步優(yōu)化,因?yàn)樯厦嫖覀儗?duì)loss進(jìn)行自動(dòng)求導(dǎo)之后,還需要通過一個(gè)循環(huán)來(lái)對(duì)模型的各個(gè)參數(shù)逐個(gè)進(jìn)行參數(shù)的更新,所以下面提供了兩個(gè)層次方面的優(yōu)化措施:

5、使用torch.optim

來(lái)進(jìn)一步簡(jiǎn)化訓(xùn)練過程——進(jìn)一步省略手動(dòng)的參數(shù)更新,更加一步到位

# -*- coding: utf-8 -*-
import torch
# N是訓(xùn)練的batch size; D_in 是input輸入數(shù)據(jù)的維度;
# H是隱藏層的節(jié)點(diǎn)數(shù); D_out 輸出的維度,即輸出節(jié)點(diǎn)數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建輸入、輸出數(shù)據(jù)
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
#模型搭建:這是與前面關(guān)鍵的區(qū)別,不再需要自己手動(dòng)進(jìn)行矩陣相乘,而是這種一步到位的方法
model = torch.nn.Sequential(
    torch.nn.Linear(D_in, H),
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out),
)
#定義損失函數(shù)
loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
#構(gòu)造一個(gè)optimizer對(duì)象
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
    # 第一步:數(shù)據(jù)的前向傳播,計(jì)算預(yù)測(cè)值p_pred
    y_pred = model(x)
    # 第二步:計(jì)算計(jì)算預(yù)測(cè)值p_pred與真實(shí)值的誤差
    loss = loss_fn(y_pred, y)
    print(t, loss.item())
    # 在反向傳播之前,將模型的梯度歸零,這
    optimizer.zero_grad()
    # 第三步:反向傳播誤差
    loss.backward()
    # 直接通過梯度一步到位,更新完整個(gè)網(wǎng)絡(luò)的訓(xùn)練參數(shù),一句話優(yōu)化所有的參數(shù),是不是很牛逼
    optimizer.step()

這是不是更加簡(jiǎn)單了?

如果是使用過keras這樣高層次的API,所以到這里應(yīng)該發(fā)現(xiàn),他們實(shí)在是太像了,現(xiàn)在來(lái)總結(jié)一下使用pytorch搭建神經(jīng)網(wǎng)路的一般步驟:

(1)第一步:搭建網(wǎng)絡(luò)的結(jié)構(gòu),得到一個(gè)model。網(wǎng)絡(luò)的結(jié)構(gòu)可以是上面這種最簡(jiǎn)單的序貫?zāi)P?,?dāng)然還可以是多輸入-單輸出模型、單輸入-多輸出模型、多輸入-多輸出模型、跨層連接的模型等,我們好可以自己定義模型,后面再講。

(2)第二步:定義損失函數(shù)。

loss?= torch.nn.MSELoss(reduction='sum')

(3)第二步:定義優(yōu)化方式。構(gòu)造一個(gè)optimizer對(duì)象

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

上面是模型以及模型相關(guān)的配置三步走,下面是訓(xùn)練的五步走。

(1)第一步:計(jì)算y_pred;

(2)第二步:根據(jù)損失函數(shù)計(jì)算loss

(3)第三步:梯度歸零,

optimizer.zero_grad()

(4)第四步:反向傳播誤差

loss.backward()

(5)更新參數(shù),使用step()

optimizer.step()

個(gè)人觀點(diǎn):

深度學(xué)習(xí)框架最大的地方在于兩個(gè)點(diǎn),正是這兩個(gè)點(diǎn)大大簡(jiǎn)化了我們自己的實(shí)現(xiàn)思路,當(dāng)然這兩個(gè)點(diǎn)不在于一層一層的搭建,個(gè)人認(rèn)為最重要的在于以下兩個(gè):

(1)第一,自動(dòng)求導(dǎo)。設(shè)想一下,如果一個(gè)如此復(fù)雜的“高維度”、“非線性”的函數(shù),需要自己寫出求導(dǎo)公式,在進(jìn)行矩陣運(yùn)算,這一項(xiàng)就很不現(xiàn)實(shí)了。

(2)第二,參數(shù)的優(yōu)化。即所謂的optimizer的作用,它是每一個(gè)參數(shù)的更新規(guī)則,由于模型參數(shù)眾多,不可能一個(gè)一個(gè)來(lái)更新,而且沒一個(gè)更新的原理是重復(fù)的,深度學(xué)習(xí)框架正好提供了一步到位的方法,不管是tensorflow還是pytorch。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Qt自定義Plot實(shí)現(xiàn)曲線繪制的詳細(xì)過程

    Qt自定義Plot實(shí)現(xiàn)曲線繪制的詳細(xì)過程

    這篇文章主要介紹了Qt自定義Plot實(shí)現(xiàn)曲線繪制,包含arm觸摸屏多點(diǎn)觸控縮放(只支持兩點(diǎn)),實(shí)時(shí)曲線繪制,數(shù)據(jù)點(diǎn)根據(jù)繪制寬度優(yōu)化,跟蹤點(diǎn)數(shù)據(jù)獲取,雙坐標(biāo)等功能,需要的朋友可以參考下
    2021-11-11
  • pytorch torch.expand和torch.repeat的區(qū)別詳解

    pytorch torch.expand和torch.repeat的區(qū)別詳解

    這篇文章主要介紹了pytorch torch.expand和torch.repeat的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 詳解Python調(diào)試神器之PySnooper

    詳解Python調(diào)試神器之PySnooper

    在程序開發(fā)過程中,代碼的運(yùn)行往往會(huì)和我們預(yù)期的結(jié)果有所差別。于是,我們需要清楚代碼運(yùn)行過程中到底發(fā)生了什么?代碼哪些模塊運(yùn)行了,哪些模塊沒有運(yùn)行?輸出的局部變量是什么樣的?PySnooper,能夠大大減少調(diào)試過程中的工作量
    2021-11-11
  • 淺談python中的變量默認(rèn)是什么類型

    淺談python中的變量默認(rèn)是什么類型

    python中的變量默認(rèn)是什么類型呢?還有很多新手不太明白。下面小編就為大家介紹一下python中的變量默認(rèn)是什么類型。一起跟隨小編過來(lái)看看吧
    2016-09-09
  • 從基礎(chǔ)到高階探索Python中的文件操作

    從基礎(chǔ)到高階探索Python中的文件操作

    文件操作在Python編程中是不可或缺的一部分,在本篇博客中,我們將全面、深入地探討Python中的文件操作,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2023-06-06
  • Python3.5 創(chuàng)建文件的簡(jiǎn)單實(shí)例

    Python3.5 創(chuàng)建文件的簡(jiǎn)單實(shí)例

    下面小編就為大家分享一篇Python3.5 創(chuàng)建文件的簡(jiǎn)單實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2018-04-04
  • Python爬取網(wǎng)頁(yè)信息的示例

    Python爬取網(wǎng)頁(yè)信息的示例

    這篇文章主要介紹了Python爬取網(wǎng)頁(yè)信息的示例,幫助大家更好的理解和學(xué)習(xí)python 爬蟲,感興趣的朋友可以了解下
    2020-09-09
  • Python標(biāo)準(zhǔn)庫(kù)中隱藏的利器(示例詳解)

    Python標(biāo)準(zhǔn)庫(kù)中隱藏的利器(示例詳解)

    在命令行中直接使用Python標(biāo)準(zhǔn)庫(kù)的模塊,最大的好處就是就是不用寫代碼,就能使用其中的功能,當(dāng)臨時(shí)需要一些某些功能的時(shí)候,用這種方式會(huì)快捷,方便很多,這篇文章主要介紹了Python標(biāo)準(zhǔn)庫(kù)中隱藏的利器,需要的朋友可以參考下
    2023-11-11
  • 使用python制作一個(gè)解壓縮軟件

    使用python制作一個(gè)解壓縮軟件

    這篇文章主要介紹了python制作一個(gè)解壓縮軟件的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Python?第三方庫(kù)?Pandas?數(shù)據(jù)分析教程

    Python?第三方庫(kù)?Pandas?數(shù)據(jù)分析教程

    這篇文章主要介紹了Python?第三方庫(kù)?Pandas?數(shù)據(jù)分析教程的相關(guān)資料,需要的朋友可以參考下
    2022-09-09

最新評(píng)論