日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人工智能 > pytorch >内容正文

pytorch

PyTorch深度学习实践

發(fā)布時(shí)間:2023/12/4 pytorch 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PyTorch深度学习实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

根據(jù)學(xué)習(xí)情況隨時(shí)更新。
2020.08.14更新完成。

參考課程-劉二大人《PyTorch深度學(xué)習(xí)實(shí)踐》

文章目錄

    • (一)課程概述
    • (二)線性模型
    • (三)梯度下降算法
    • (四)反向傳播
    • (五)用PyTorch實(shí)現(xiàn)線性回歸
    • (六)Logistic回歸
    • (七)多維特征輸入的分類(lèi)問(wèn)題
    • (八)加載數(shù)據(jù)集
    • (九)多分類(lèi)問(wèn)題
    • (十)卷積神經(jīng)網(wǎng)絡(luò)
    • (十一)循環(huán)神經(jīng)網(wǎng)絡(luò)

(一)課程概述

本章知識(shí)部分涉及到計(jì)算圖的正向傳播(表達(dá)式計(jì)算)和反向傳播(表達(dá)式求導(dǎo)),無(wú)需贅述。

(二)線性模型

  • 機(jī)器學(xué)習(xí)的過(guò)程
    訓(xùn)練時(shí)如果y值已知的學(xué)習(xí)是監(jiān)督學(xué)習(xí)。
    數(shù)據(jù)分為訓(xùn)練集(用于學(xué)習(xí))和測(cè)試集(用于比對(duì))。
    在訓(xùn)練過(guò)程中,為了避免過(guò)擬合,將訓(xùn)練集中的一部分劃分為開(kāi)發(fā)集。

  • 樣本函數(shù)、代價(jià)函數(shù)(吳課程筆記已經(jīng)記錄)

  • (三)梯度下降算法

  • 核心公式
    梯度下降法的本質(zhì)是貪心法。由于函數(shù)是凸函數(shù),可以保證貪心法求解得到的是最優(yōu)解,此時(shí)局部最優(yōu)解即是全局最優(yōu)解。
    此外,學(xué)習(xí)率α不能過(guò)大,否則可能造成不收斂。

  • 梯度下降算法的例子(還是要自己寫(xiě)寫(xiě)才學(xué)得會(huì))

  • def compute(x):return w * xdef cost(xs, ys):sum = 0for x, y in zip(xs, ys):sum += (compute(x) - y) ** 2return sum / len(xs)def gradient(xs, ys):grad = 0for x, y in zip(xs, ys):grad += 2 * x * (w * x - y)return grad / len(xs)w = 1.0 xs = [1.0, 2.0, 3.0] ys = [2.0, 4.0, 6.0] print('f(4) before training:' + str(compute(4))) for i in range(1000):tempCost = cost(xs, ys)tempGradient = gradient(xs, ys)w -= 0.01 * tempGradientprint('cost:' + str(tempCost) + '\t' + 'w:' + str(w)) print('f(4) after training:' + str(compute(4)))
  • 隨機(jī)梯度下降
    采用單個(gè)輸入而不是所有輸入的均值。
    梯度下降法計(jì)算x(i),x(i+1)的梯度時(shí)可以并行計(jì)算(因?yàn)椴捎镁?#xff09;,而隨機(jī)梯度下降法計(jì)算x(i),x(i+1)的梯度時(shí)w存在前后依賴關(guān)系,不能并行。
    和梯度下降法相比,性能更好但時(shí)間復(fù)雜度也更高。因此通常采用折中的方案(Batch:批量隨機(jī)梯度下降)。
  • (四)反向傳播

  • 直觀概念
    正向傳播是從輸入向輸出計(jì)算,反向傳播是從輸出向輸入逐步求梯度(本質(zhì)是求導(dǎo)鏈?zhǔn)椒▌t)。
    得到dL/dx后,x作為輸出可以繼續(xù)向前傳播。
  • 圖中是一個(gè)兩層的神經(jīng)網(wǎng)絡(luò),在每層的輸出中添加一個(gè)非線性函數(shù)(此處是sigmoid函數(shù),在吳課程中有介紹)。

  • 利用PyTorch構(gòu)建計(jì)算圖
    PyTorch中,Tensor類(lèi)是最基本的單元,主要存放 權(quán)值w(data) 和損失函數(shù)對(duì)w的導(dǎo)數(shù) dLoss/dw(grad)。
    需要注意的是,grad也是Tensor類(lèi)型。Tensor類(lèi)型在運(yùn)算時(shí)會(huì)建立計(jì)算圖,并在反向傳播完成后釋放計(jì)算圖。如果單純地使用x的grad的數(shù)值進(jìn)行計(jì)算時(shí),要寫(xiě)成x.grad.data的形式。
  • import torchdef compute(x):return w * x # 此處的w是Tensor類(lèi)型,x由整型自動(dòng)轉(zhuǎn)為T(mén)ensor類(lèi)型,并最終返回Tensordef loss(x, y):return (compute(x) - y) ** 2 # 返回Tensor類(lèi)型x_data = [1.0, 2.0, 3.0] y_data = [2.0, 4.0, 6.0] w = torch.Tensor([1.0]) # 為T(mén)ensor賦初值時(shí)需要帶方括號(hào) w.requires_grad = True # 標(biāo)明需要計(jì)算該權(quán)值的梯度值,則計(jì)算圖中,w參與運(yùn)算的結(jié)果同樣具有梯度值 for i in range(100):for x, y in zip(x_data, y_data): # 采用隨機(jī)梯度下降lossResult = loss(x, y)lossResult.backward() # 反向傳播w.data -= 0.01 * w.grad.dataw.grad.data.zero_() # 對(duì)于每個(gè)輸入數(shù)據(jù),使用后將w梯度置0,避免梯度累加print('Time:' + str(i+1) + '\tw:' + str(w.data) + '\tresult:' + str(compute(4).data))

    (五)用PyTorch實(shí)現(xiàn)線性回歸

    設(shè)計(jì)步驟:
    -準(zhǔn)備數(shù)據(jù)集
    -設(shè)計(jì)模型,計(jì)算y的估計(jì)值(構(gòu)造計(jì)算圖)
    -使用PyTorch API構(gòu)造損失函數(shù)、優(yōu)化器
    -訓(xùn)練:前饋算損失、反饋算梯度、更新權(quán)值

    一個(gè)Python傳遞參數(shù)的語(yǔ)法:

    實(shí)例:

    import torch# Step 1 x_data = torch.Tensor([[1.0], [2.0], [3.0]]) y_data = torch.Tensor([[2.0], [4.0], [6.0]])# Step 2 class LinearModule(torch.nn.Module): # 一定要繼承自 神經(jīng)網(wǎng)絡(luò)模塊基類(lèi) nn.Module類(lèi),并實(shí)現(xiàn)__init__()、forward()def __init__(self):super(LinearModule, self).__init__()self.linear = torch.nn.Linear(1, 1) # 參數(shù)分別代表初始的 權(quán)值w和偏移b(都是Tensor類(lèi))def forward(self, x):y_pred = self.linear(x) # linear是Linear類(lèi)的實(shí)例,且該類(lèi)實(shí)現(xiàn)了__call__()方法,在實(shí)例化后可以像函數(shù)一樣調(diào)用,通常調(diào)用forward()return y_predmodel = LinearModule() # 實(shí)例化,model是可調(diào)用的 # model(1) 計(jì)算x=1時(shí)的估計(jì)值# Step 3 criterion = torch.nn.MSELoss(size_average=False) # 設(shè)置為T(mén)rue也可 optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # lr即學(xué)習(xí)率# Step 4 for epoch in range(1000):# 前饋y_pred = model(x_data)loss = criterion(y_pred, y_data)print(epoch, loss.data)# 反饋optimizer.zero_grad() # 將梯度清零loss.backward()# 更新optimizer.step()# 輸出結(jié)果 print(model.linear.weight.item()) # 輸出w print(model.linear.bias.item()) # 輸出b

    (六)Logistic回歸

    分類(lèi)問(wèn)題
    -Logistic回歸屬于分類(lèi)問(wèn)題。分類(lèi)問(wèn)題求解是對(duì)應(yīng)情況的概率,并取最大值作為分類(lèi)結(jié)果。
    -對(duì)于前例,輸出由多少分轉(zhuǎn)為能否通過(guò)/通過(guò)考試的概率。
    -使用Logistic函數(shù)(標(biāo)記為σ),將實(shí)數(shù)空間的輸出值映射到 [0,1] 中。此時(shí)損失函數(shù)也需要改變-(ylog(y’)+(1-y)log(1-y’))。

    # 記錄LogisticRegressionModel的特點(diǎn) import torchclass LogisticModel(torch.nn.Module):def __init__(self):super(LogisticModel, self).__init__()self.linear = torch.nn.Linear(1, 1)def forward(self, x):y_pred = torch.nn.functional.sigmoid(self.linear(x)) # 對(duì)原y'進(jìn)行Sigmoid處理return y_predcriterion = torch.nn.BCELoss(size_average=False) # 二分類(lèi)交叉熵,是否取平均值影響學(xué)習(xí)率大小

    (七)多維特征輸入的分類(lèi)問(wèn)題

  • 多維輸入的Logistic模型:每個(gè)樣本對(duì)應(yīng)一個(gè)向量,單個(gè)樣本的輸出y’仍然是概率(即y’∈[0,1])。相比一維輸入,w*x由實(shí)數(shù)運(yùn)算變?yōu)橄蛄績(jī)?nèi)積運(yùn)算。

    將N個(gè)方程合并成矩陣的運(yùn)算,利用向量化的特性加速訓(xùn)練過(guò)程。

  • Sigmoid函數(shù)按向量計(jì)算的形式,依次應(yīng)用到每個(gè)元素。

  • 分層構(gòu)造實(shí)例

  • import torch import numpy as npxy = np.loadtxt('diabetes.csv.gz', delimiter=',', dtype=np.float32) x_data = torch.from_numpy(xy[:, :-1]) y_data = torch.from_numpy(xy[:, [-1]])class MultiDimensionLogisticModel(torch.nn.Module):def __init__(self):super(MultiDimensionLogisticModel, self).__init__()self.linear1 = torch.nn.Linear(8, 6) # 輸入維度為8(每個(gè)樣本有8個(gè)特征),輸出維度為6(每個(gè)結(jié)果有6個(gè)特征)self.linear2 = torch.nn.Linear(6, 4)self.linear3 = torch.nn.Linear(4, 1) # 經(jīng)過(guò)三層處理最終輸出一維self.sigmoid = torch.nn.Sigmoid() # Sigmoid函數(shù)為模型添加非線性變換,構(gòu)建計(jì)算圖def forward(self, x):x = self.sigmoid(self.linear1(x))x = self.sigmoid(self.linear2(x))x = self.sigmoid(self.linear3(x))return xmodel = MultiDimensionLogisticModel() criterion = torch.nn.BCELoss(size_average=False) optimizer = torch.optim.SGD(model.parameters(), lr=0.1)for epoch in range(1000):# 前饋y_pred = model(x_data) # 每次處理所有數(shù)據(jù)集,而下一章每次處理一個(gè)Batchloss = criterion(y_pred, y_data)print(epoch, loss.data)# 反饋optimizer.zero_grad()loss.backward()# 更新optimizer.step()

    (八)加載數(shù)據(jù)集

    采用DataLoader處理輸入時(shí),需要額外定義一個(gè)繼承自Dataset(該類(lèi)是抽象類(lèi))的類(lèi),并實(shí)現(xiàn)_init_(), _getitem_(), _len_()方法。

  • 概念定義
    -Epoch:對(duì)所有樣本的一次正向傳播和反向傳播。
    -Batch Size:每次正向傳播的樣本數(shù)。
    -Iteration:Mini Batch的進(jìn)行次數(shù)。
    如:樣本數(shù)為10000,BatchSize為1000,則Iteration為10
    在Mini Batch下的訓(xùn)練步驟:
  • # Step 4 for epoch in range(training_epochs): # 對(duì)所有數(shù)據(jù),共進(jìn)行training_epochs次的訓(xùn)練for i in range(total_batch): # 對(duì)每個(gè)Batch進(jìn)行處理#TODO
  • Dataset和DataLoader
    DataLoader迭代時(shí)以Batch為基本元素,其中Batch的大小在創(chuàng)建Loader時(shí)指定。
    Dataset每次獲取一個(gè)樣本,DataLoader每次獲取Batch個(gè)樣本。

  • 實(shí)例

  • import torch import numpy as np from torch.utils.data import Dataset from torch.utils.data import DataLoader# Step 1 class DiabetesDataset(Dataset):def __init__(self, filepath):xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)self.x_data = torch.from_numpy(xy[:, :-1])self.y_data = torch.from_numpy(xy[:, [-1]])self.len = xy.shape[0] # 和不采用Dataset相比增加的步驟def __getitem__(self, index):return self.x_data[index], self.y_data[index]def __len__(self):return self.lendataset = DiabetesDataset('diabetes.csv.gz') # dataset是傳入數(shù)據(jù)集,batch_size規(guī)定一個(gè)batch的樣本數(shù),shuffle代表是否打亂樣本順序,num_workers代表并行數(shù)目 train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)# Step 2(未發(fā)生變化) class MultiDimensionLogisticModel(torch.nn.Module):def __init__(self):super(MultiDimensionLogisticModel, self).__init__()self.linear1 = torch.nn.Linear(8, 6)self.linear2 = torch.nn.Linear(6, 4)self.linear3 = torch.nn.Linear(4, 1)self.sigmoid = torch.nn.Sigmoid() # Sigmoid函數(shù)為模型添加非線性變換,構(gòu)建計(jì)算圖def forward(self, x):x = self.sigmoid(self.linear1(x))x = self.sigmoid(self.linear2(x))x = self.sigmoid(self.linear3(x))return xmodel = MultiDimensionLogisticModel()# Step 3(未發(fā)生變化) criterion = torch.nn.BCELoss(size_average=False) optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# Step 4 for epoch in range(100):for i, data in enumerate(train_loader, 0): # 每次獲取index和一個(gè)Batchx, y = data # 其中x和y都是Tensor類(lèi)型,x代表Batch個(gè)輸入,y代表Batch個(gè)輸出# 前饋y_pred = model(x)loss = criterion(y_pred, y)print(epoch, i, loss.item())# 反饋optimizer.zero_grad()loss.backward()# 更新optimizer.step()

    (九)多分類(lèi)問(wèn)題

  • Softmax層的引入
    相比較二分類(lèi)問(wèn)題,多分類(lèi)需要輸出每種情況的對(duì)應(yīng)概率。如果按照二分類(lèi)的方法,可能造成所有情況概率之和不為1的情況。改進(jìn)措施是,將輸出最終結(jié)果前的Sigmoid層轉(zhuǎn)換成Softmax層。

  • 引入Softmax層的具體操作
    ①使用numpy直接計(jì)算

  • import numpy as npy = np.array([1, 0, 0]) # 標(biāo)簽值 z = np.array([0.2, 0.1, -0.1]) # Softmax輸入值 y_pred = np.exp(z)/np.exp(z).sum() loss = (-y * np.log(y_pred)).sum()

    ②使用NLLLoss損失函數(shù),輸入Softmax和Log處理后的數(shù)據(jù),以及標(biāo)簽值,輸出Loss。

    ③使用CrossEntropyLoss(交叉熵?fù)p失)函數(shù)。

    import torchy = torch.LongTensor([2, 0, 1]) # 注意此處是LongTensor # z_1和z_2是最后一層輸出,進(jìn)入Softmax之前的值,所以每個(gè)分類(lèi)之和不為1 # 每行元素代表對(duì)一個(gè)對(duì)象的分類(lèi)情況,共三個(gè)對(duì)象 z_1 = torch.Tensor([[0.1, 0.2, 0.9],[1.1, 0.1, 0.2],[0.2, 2.1, 0.1]]) z_2 = torch.Tensor([[0.9, 0.2, 0.1],[0.1, 0.1, 0.5],[0.2, 0.1, 0.7]]) criterion = torch.nn.CrossEntropyLoss() print(criterion(z_1, y), criterion(z_2, y))
  • PyTorch圖像多分類(lèi)問(wèn)題
    ①數(shù)據(jù)輸入
    一般讀入形式為whc,在PyTorch中為了便于處理,將其轉(zhuǎn)為cwh。
  • # 將PIL轉(zhuǎn)為T(mén)ensor transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307, ), (0.3081, )) ])

    ②設(shè)計(jì)模型
    view將 N個(gè) 1維 28*28的輸入,轉(zhuǎn)化為 N個(gè) 1行 的數(shù)據(jù)(每行784個(gè))。
    注意最后一層不進(jìn)行激活。

    (十)卷積神經(jīng)網(wǎng)絡(luò)

  • 圖像存儲(chǔ)形式
    RGB:輸入圖片是3*w*h的形式,頻道對(duì)應(yīng)紅/綠/藍(lán),每個(gè)元素取值0~255.
    矢量:存儲(chǔ)圖像的繪制信息。特點(diǎn)是放大不會(huì)出現(xiàn)像素塊。

  • 圖像的卷積概述
    對(duì)圖像進(jìn)行卷積操作,本質(zhì)上是對(duì)圖像的某塊的所有頻道(即一個(gè)Batch)進(jìn)行操作。操作會(huì)改變圖像的c,w,h值。

  • 單通道的卷積操作
    用Kernel陣遍歷輸入陣,對(duì)應(yīng)進(jìn)行數(shù)值乘法再求和,得到輸出陣的一個(gè)元素。

  • 多通道的卷積操作
    本質(zhì)上是將單通道的卷積累加。需要注意的是,輸入Kernel的通道數(shù)要和輸入的通道數(shù)相等。
    該操作將n通道的輸入轉(zhuǎn)化成1通道的輸出。

  • 如果需要得到m通道的輸出,則要準(zhǔn)備m份的卷積陣。此時(shí)對(duì)應(yīng)的權(quán)值是 m*n*k_width*k_height的四維量。

  • 卷積操作實(shí)例
  • import torchin_channels, out_channels= 5, 10 width, height = 100, 100 kernel_size = 3 batch_size = 1input = torch.randn(batch_size, in_channels, width, height) conv_layer = torch.nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size) output = conv_layer(input)
  • 卷積層的Padding操作
    在輸入陣的周?chē)M(jìn)行填充(一般是0),以得到目標(biāo)形狀的輸出。
  • import torchinput = [3,4,6,5,7,2,4,6,8,2,1,6,7,8,4,9,7,4,6,2,3,7,5,4,1] input = torch.Tensor(input).view(1, 1, 5, 5) # 分別對(duì)應(yīng)Batch、Channel、Width、Height conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1, bias=False) # 分別對(duì)應(yīng)輸入Channel、輸出Channel kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3) #輸出Channel、輸入Channel、Width、Height conv_layer.weight.data = kernel.data output = conv_layer(input)
  • 步長(zhǎng)stride
    將上述代碼的padding=1改為stride=2,即可得到2*2的結(jié)果。

  • Max Pooling層
    kernel_size為2的MaxPooling可以將輸入的行和列都減少為原來(lái)的1/2.
    該操作和通道數(shù)無(wú)關(guān),操作前后不改變通道數(shù)。

  • import torchinput = [3,4,6,5,2,4,6,8,1,6,7,8,9,7,4,6,] input = torch.Tensor(input).view(1, 1, 4, 4) maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2) output = maxpooling_layer(input)
  • 卷積神經(jīng)網(wǎng)絡(luò)實(shí)例
    注意:進(jìn)行最后一次 Conv-Pooling-ReLU后進(jìn)入線性層。
  • import torch import torch.nn.functional as Fclass Net(torch.nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5) # 卷積層1self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5) # 卷積層2self.pooling = torch.nn.MaxPool2d(2)self.linear = torch.nn.Linear(320, 10) # 輸入320個(gè)數(shù)據(jù),輸出10個(gè)數(shù)據(jù)(對(duì)應(yīng)十種分類(lèi)情況)def forward(self, x):batch_size = x.size(0)x = self.pooling(F.relu(self.conv1(x)))x = self.pooling(F.relu(self.conv2(x)))x = x.view(batch_size, -1) # 全連接網(wǎng)絡(luò)輸入x = self.linear(x)return xmodel = Net()
  • 使用GPU進(jìn)行計(jì)算
  • # 在上述代碼添加 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model.to(device) # 并在訓(xùn)練、測(cè)試時(shí),在 input, target = data的基礎(chǔ)上增加 input, target = input.to(device), target.to(device)
  • 1x1卷積
    本質(zhì)上是將多個(gè)通道的對(duì)應(yīng)元素進(jìn)行信息融合。
    目的是,只改變通道數(shù),不改變輸入的寬度和高度,以減小運(yùn)算量。

  • Inception Module
    對(duì)同一輸入進(jìn)行不同卷積,合并最終結(jié)果,取最優(yōu)解。
    不同路徑只能改變頻道數(shù),不能改變寬度和高度(因?yàn)樽罱K需要合并)。
    Concatenate操作將不同的卷積結(jié)果沿著通道方向合并。

  • # 上半部分是__init__的操作,下半部分是forward的操作 # 分支1 self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1) branch_pool = self.branch_pool(branch_pool)# 分支2 self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)branch1x1 = self.branch1x1(x)# 分支3 self.branch5x5_1 = nn.Conv2d(in_channels,16, kernel_size=1) self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)branch5x5 = self.branch5x5_1(x) branch5x5 = self.branch5x5_2(branch5x5)# 分支4 self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1) self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1) self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)branch3x3 = self.branch3x3_1(x) branch3x3 = self.branch3x3_2(branch3x3)# Concatenate outputs = [branch1x1, branch5x5, branch3x3, branch_pool] return torch.cat(outputs, dim=1) # (batch, channel, width, height)中channel對(duì)應(yīng)index為1,按照channel對(duì)齊

    使用實(shí)例

    import torch from torch import nn import torch.nn.functional as F# 圖中的Inception示例 class InceptionA(nn.Module):def __init__(self, in_channels):super(InceptionA, self).__init__()# 定義各分支的卷積部分:# 分支2self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)# 分支3self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)# 分支4self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)# 分支1self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)def forward(self, x):# 分支2branch1x1 = self.branch1x1(x)# 分支3branch5x5 = self.branch5x5_1(x)branch5x5 = self.branch5x5_2(branch5x5)# 分支4branch3x3 = self.branch3x3_1(x)branch3x3 = self.branch3x3_2(branch3x3)branch3x3 = self.branch3x3_3(branch3x3)# 分支1branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)branch_pool = self.branch_pool(branch_pool)# Concatenateoutputs = [branch1x1, branch5x5, branch3x3, branch_pool]return torch.cat(outputs, dim=1)# 采用Inception的模型 class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(88, 20, kernel_size=5) # 88是經(jīng)過(guò)Inception1后的通道數(shù)self.incep1 = InceptionA(in_channels=10)self.incep2 = InceptionA(in_channels=20)self.mp = nn.MaxPool2d(2) # pooling操作不改變通道數(shù)self.linear = nn.Linear(1408, 10)def forward(self, x):in_size = x.size(0)x = F.relu(self.mp(self.conv1(x))) # 先后進(jìn)行卷積、池化、激活x = self.incep1(x)x = F.relu(self.mp(self.conv2(x)))x = self.incep2(x)x = x.view(in_size, -1)x = self.linear(x)return x
  • Residual Block
    不改變輸入的c,w,h.
    例:進(jìn)行兩次卷積操作的網(wǎng)絡(luò)
  • from torch import nn import torch.nn.functional as Fclass ResidualBlock(nn.Module):def __init__(self, channel):super(ResidualBlock, self).__init__()self.conv1 = nn.Conv2d(channel, channel, kernel_size=3, padding=1)self.conv2 = nn.Conv2d(channel, channel, kernel_size=3, padding=1)def forward(self, x):y = F.relu(self.conv1(x))y = self.conv2(y) # 注意此處需要求和后再激活y = F.relu(x + y)return yclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 16, kernel_size=5)self.conv2 = nn.Conv2d(16, 32, kernel_size=5)self.rb1 = ResidualBlock(16)self.rb2 = ResidualBlock(32)self.mp = nn.MaxPool2d(2)self.linear = nn.Linear(512, 10)def forward(self, x):in_size = x.size(0)x = self.mp(F.relu(self.conv1(x)))x = self.rb1(x)x = self.mp(F.relu(self.conv2(x)))x = self.rb2(x)x = x.view(in_size, -1)x = self.linear(x)return x

    (十一)循環(huán)神經(jīng)網(wǎng)絡(luò)

  • RNN用于處理輸入具有序列關(guān)系,且前項(xiàng)對(duì)后項(xiàng)有影響的問(wèn)題。比如根據(jù)前幾天的溫度、氣壓、天氣對(duì)未來(lái)的天氣進(jìn)行預(yù)測(cè)。

  • RNNCell
    本質(zhì)是線性層。同一個(gè)Cell在RNN中循環(huán)使用。
    構(gòu)造RNNCell需要輸入inputSize和hiddenSize。

  • 使用時(shí)需要明確輸入、輸出的維度關(guān)系。
    設(shè) batchSize=1,seqLen=3,inputSize=4,hiddenSize=2
    則有 input.shape=(batchSize, inputSize),output.shape=(batchSize, hiddenSize),dataset.shape=(seqLen, batchSize, inputSize)

    import torchbatch_size = 1 seq_len = 3 input_size = 4 hidden_size = 2 cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)dataset = torch.randn(seq_len, batch_size, input_size) hidden = torch.zeros(batch_size, hidden_size)
  • RNN
  • input.shape=(seqLen, batchSize, inputSize)
    h0.shape=(numLayers, batchSize, hiddenSize)
    output.shape=(seqLen, batchSize, hiddenSize)
    hn.shape=(numLayers, batchSize, hiddenSize)

    import torchbatch_size = 1 seq_len = 3 input_size = 4 hidden_size = 2 num_layers = 1 cell = torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers)inputs = torch.randn(seq_len, batch_size, input_size) hidden = torch.zeros(num_layers, batch_size, hidden_size)
  • 實(shí)例:使用RNNCell的字符串轉(zhuǎn)化
    對(duì)于每個(gè)輸入字符,求解問(wèn)題的整體結(jié)構(gòu):
  • 將字符串"hello"轉(zhuǎn)化為"ohlol"
    首先將輸入字符的每個(gè)字符進(jìn)行向量化,得到RNNCell的輸入。
    此時(shí)inputSize=4,seqLen=5。

    import torch# 處理輸入 input_size = 4 hidden_size = 4 batch_size = 1 idx2char = ['e', 'h', 'l', 'o'] x_data = [1, 0, 2, 2, 3] # 'hello' y_data = [3, 1, 2, 3, 2] # 'ohlol' one_hot_lookup = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]x_one_hot = [one_hot_lookup[x] for x in x_data] # 得到RNNCell的輸入 inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size) # input.shape=(seqLen, batchSize, inputSize) labels = torch.LongTensor(y_data).view(-1, 1) # labels.shape=(seqLen, 1)# 處理單個(gè)字符輸入的RNNCell class Model(torch.nn.Module):def __init__(self, input_size, hidden_size, batch_size):super(Model, self).__init__()self.batch_size = batch_sizeself.input_size = input_sizeself.hidden_size = hidden_sizeself.rnncell = torch.nn.RNNCell(input_size=self.input_size, hidden_size=self.hidden_size)def forward(self, input, hidden):hidden = self.rnncell(input, hidden) # input.shape=(batchSize, inputSize); hidden.shape=(batch, hiddenSize)return hiddendef init_hidden(self):return torch.zeros(self.batch_size, self.hidden_size) # h0net = Model(input_size, hidden_size, batch_size) criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam(net.parameters(), lr=0.1)for epoch in range(15):loss = 0optimizer.zero_grad()hidden = net.init_hidden()# 每輪對(duì)所有輸入進(jìn)行訓(xùn)練# inputs.shape=(𝒔𝒆𝒒𝑳𝒆𝒏, 𝒃𝒂𝒕𝒄𝒉𝑺𝒊𝒛𝒆,𝒊𝒏𝒑𝒖𝒕𝑺𝒊𝒛𝒆) ; input.shape(𝒃𝒂𝒕𝒄𝒉𝑺𝒊𝒛𝒆, 𝒉𝒊𝒅𝒅𝒆𝒏𝑺𝒊𝒛𝒆)for input, label in zip(inputs, labels):hidden = net(input, hidden)loss += criterion(hidden, label) # 需要構(gòu)建計(jì)算圖,因此需要求和loss.backward()optimizer.step()
  • 實(shí)例:使用RNN的字符串轉(zhuǎn)化
  • import torchinput_size = 4 hidden_size = 4 num_layers = 1 batch_size = 1 seq_len = 5idx2char = ['e', 'h', 'l', 'o'] x_data = [1, 0, 2, 2, 3] y_data = [3, 1, 2, 3, 2] one_hot_lookup = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]] x_one_hot = [one_hot_lookup[x] for x in x_data] inputs = torch.Tensor(x_one_hot).view(seq_len, batch_size, input_size) labels = torch.LongTensor(y_data) # (seqLen*batchSize, 1)class Model(torch.nn.Module):def __init__(self, input_size, hidden_size, num_layers, batch_size, seq_len):super(Model, self).__init__()self.input_size = input_sizeself.num_layers = num_layersself.hidden_size = hidden_sizeself.batch_size = batch_sizeself.seq_len = seq_lenself.rnn = torch.nn.RNN(self.input_size, self.hidden_size, self.num_layers)def forward(self, input):hidden = torch.zeros(self.num_layers, self.batch_size, self.hidden_size) # h0out, _ = self.rnn(input, hidden)return out.view(-1, self.hidden_size) # (𝒔𝒆𝒒𝑳𝒆𝒏 × 𝒃𝒂𝒕𝒄𝒉𝑺𝒊𝒛𝒆, 𝒉𝒊𝒅𝒅𝒆𝒏𝑺𝒊𝒛𝒆)net = Model(input_size, hidden_size, batch_size, num_layers) criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam(net.parameters(), lr=0.05)for epoch in range(15):optimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()

    總結(jié)

    以上是生活随笔為你收集整理的PyTorch深度学习实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。