動手學深度學習——層和塊

1. 層

層是一個將輸入數據轉換為輸出數據的神經網絡組件。每個層都會對輸入數據進行一定的操作,例如線性變換、非線性激活函數等,以產生輸出數據。

torch.nn模塊提供了各種預定義的層,如線性層、卷積層、池化層等,

  • nn.Linear:線性層
  • nn.MaxPool2d:二維池化層
  • nn.Conv2d:二維卷積層
  • nn.ReLu:激活函數層

也支持基于nn.Module自定義層。

1.1 自定義簡單層

import torch
import torch.nn.functional as F
from torch import nnclass CenteredLayer(nn.Module):def __init__(self):super().__init__()def forward(self, X):return X - X.mean()

這個層的功能是對每個輸入減去均值,運行示例:

layer = CenteredLayer()
layer(torch.FloatTensor([1, 2, 3, 4, 5]))> tensor([-2., -1.,  0.,  1.,  2.])

這個層沒有定義需要訓練的參數,這一類的層往往用于特定的功能轉換,例如數據重排、裁剪、歸一化等。

1.2 定義帶參數的層

使用nn.Parameter來創建需要訓練的參數,以線性全連接層為例

  • 需要兩個參數:權重和偏置
  • 需要兩個參數in_units和units來指明輸入維度和輸出維度
class MyLinear(nn.Module):def __init__(self, in_units, units):super().__init__()self.weight = nn.Parameter(torch.randn(in_units, units))self.bias = nn.Parameter(torch.randn(units,))def forward(self, X):return torch.matmul(X, self.weight.data) + self.bias.data

實例化MyLinear類實例并用其進行前向傳播計算:

linear = MyLinear(5, 3)
linear(torch.rand(2, 5))> tensor([[ 1.9813, -0.1214,  0.1627],[ 2.6518, -0.8198,  0.6513]])

2. 塊

在神經網絡中,塊可以表示為多個層組成的組件,將多個塊組合能構成復雜的網絡模型。

在這里插入圖片描述
從編程的角度(以pytorch為例),塊也是由繼承nn.Module的類來表示,它必須具有的組成部分:

  1. 組成塊的層
  2. 前向傳播函數forward,用于將輸入轉換為輸出;
  3. 反向傳播函數backward,用于計算梯度;
  4. 待訓練的參數;

由于pytorch支持反向傳播自動求導,已經由pytorch內部封裝了反向傳播函數的實現,另外pytorch會自動根據層的大小來初始化模型參數w和b,所以我們在定義塊時只需要考慮前向傳播函數和組成塊的層。

2.1 自定義塊

以前一篇文章中的多層感知機為例,可以封裝為一個塊:

class MLP(nn.Module):# 用模型參數聲明層。這里,我們聲明兩個全連接的層def __init__(self):# 調用MLP的父類Module的構造函數來執行必要的初始化。# 這樣,在類實例化時也可以指定其他函數參數,例如模型參數params(稍后將介紹)super().__init__()self.hidden = nn.Linear(20, 256)  # 隱藏層self.out = nn.Linear(256, 10)  # 輸出層# 定義模型的前向傳播,即如何根據輸入X返回所需的模型輸出def forward(self, X):# 注意,這里我們使用ReLU的函數版本,其在nn.functional模塊中定義。return self.out(F.relu(self.hidden(X)))

2.2 組合塊

前篇文章用到的nn.Sequential其實也是一個塊,只不過它的作用是將其它塊按順序組合到一起,形成一個串行執行的有序列表。

class MySequential(nn.Module):def __init__(self, *args):super().__init__()for idx, module in enumerate(args):# module是Module子類的一個實例,這里將它保存在'Module'類型的成員變量_modules中,_modules的類型是OrderedDictself._modules[str(idx)] = moduledef forward(self, X):# OrderedDict保證了按照成員添加的順序遍歷它們for block in self._modules.values():X = block(X)return X

每個nn.Module都有一個內置的_modules屬性,目的是方便系統查找需要初始化參數的子塊

3. 參數管理

訓練模型的目的是為了找到使損失函數最小化的模型參數值,這個訓練過程就如同我們調試程序一樣,有時候需要打印中間結果以輔助我們進行問題的分析和診斷,所以我們有必要知道如何訪問參數。

3.1 參數訪問

當通過Sequential類定義模型時, 我們可以通過索引來訪問模型的任意層,通過每層的state_dict()來獲取該層的參數。

print(net[2].state_dict())
OrderedDict([('weight', tensor([[-0.0427, -0.2939, -0.1894,  0.0220, -0.1709, -0.1522, -0.0334, -0.2263]])), ('bias', tensor([0.0887]))])

可以看出,該層包含權重weight和偏置bias兩個參數。

我們還可以直接訪問權重或偏置。

print(type(net[2].weight)) # 類型
print(net[2].weight)       # 直接訪問參數,包含參數值和梯度信息
print(net[2].weight.data)  # 訪問參數值
# print(net[2].weight.grid)  # 訪問參數的梯度,還沒有訓練,所以梯度還沒值
<class 'torch.nn.parameter.Parameter'>
Parameter containing:
tensor([[ 0.0986,  0.2894,  0.3461,  0.2734, -0.3395, -0.0719, -0.3348, -0.0305]],requires_grad=True)
tensor([[ 0.0986,  0.2894,  0.3461,  0.2734, -0.3395, -0.0719, -0.3348, -0.0305]])

3.2 嵌套塊參數訪問

我們可以將多個塊相互嵌套,組成更大的塊。

  • block1有4層, linear, relu, linear, relu
  • block2嵌套了3個block1塊
  • 最后將block2與一個線性輸出層組合,構成一個網絡
def block1():return nn.Sequential(nn.Linear(4, 2), nn.ReLU(),nn.Linear(2, 4), nn.ReLU())def block2():net = nn.Sequential()# block2中嵌套3個block1for i in range(3):net.add_module(f'block {i}', block1())return netrgnet = nn.Sequential(block2(), nn.Linear(4, 1))
print(rgnet)

這個包含嵌套塊的網絡結構如下:

Sequential((0): Sequential((block 0): Sequential((0): Linear(in_features=4, out_features=2, bias=True)(1): ReLU()(2): Linear(in_features=2, out_features=4, bias=True)(3): ReLU())(block 1): Sequential((0): Linear(in_features=4, out_features=2, bias=True)(1): ReLU()(2): Linear(in_features=2, out_features=4, bias=True)(3): ReLU())(block 2): Sequential((0): Linear(in_features=4, out_features=2, bias=True)(1): ReLU()(2): Linear(in_features=2, out_features=4, bias=True)(3): ReLU()))(1): Linear(in_features=4, out_features=1, bias=True)
)

嵌套塊的參數訪問:

rgnet[0][1][0].bias.data> tensor([ 0.4917, -0.3920])

3.3 參數初始化

對于參數的初始化,不明確指定時,pytorch會使用默認的隨機初始化方法。PyTorch的nn.init模塊也提供了多種可供選擇的預置初始化方法。

  1. 指定使用正態分布的隨機變量來初始化:
# 定義初始化函數
def init_normal(m):if type(m) == nn.Linear:nn.init.normal_(m.weight, mean=0, std=0.01)nn.init.zeros_(m.bias)
# 使用指定函數對整個網絡的參數進行初始化
net.apply(init_normal)  
net[0].weight.data[0], net[0].bias.data[0]> (tensor([-0.0101, -0.0117, -0.0116, -0.0016]), tensor(0.))
  1. 使用常數進行初始化:
def init_constant(m):if type(m) == nn.Linear:nn.init.constant_(m.weight, 1)nn.init.zeros_(m.bias)
net.apply(init_constant)
net[0].weight.data[0], net[0].bias.data[0]> (tensor([1., 1., 1., 1.]), tensor(0.))
  1. 對不同的塊使用不同的初始化:
net[0].apply(init_normal)
net[2].apply(init_constant)
print(net[0].weight.data[0])
print(net[2].weight.data)> tensor([ 0.0054, -0.0188, -0.0112,  0.0097])
tensor([[1., 1., 1., 1., 1., 1., 1., 1.]])

4.4 參數綁定

含義:通過將一個層共享,可以實現相同的參數權重用于神經網絡中的多個層。目的在于兩方面:

  1. 減少模型的參數量:通過共享參數,可以大大減少需要學習的參數數量,從而減小模型的復雜度。
  2. 加速訓練:參數共享可以減少內存占用和計算量,特別是在具有大量參數的深層網絡中,可以顯著提高計算效率。

下面是一個參數共享的代碼示例:

# 給共享層一個名稱,以便可以引用它的參數
shared = nn.Linear(8, 8)
# 第二層和第四層共享shared層的參數
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),shared, nn.ReLU(),shared, nn.ReLU(),nn.Linear(8, 1))

輸出第二層和第四層指定位置的初始參數,兩者是相同的。

print(net[2].weight.data[0, 0])
print(net[4].weight.data[0, 0])> tensor(-0.0253)
tensor(-0.0253)  

修改第二層的參數:

net[2].weight.data[0, 0] = 100

再次輸出第二層和第四層指定位置的參數,兩者都變成了修改后的參數:

print(net[2].weight.data[0, 0])
print(net[4].weight.data[0, 0])> tensor(100.)
tensor(100.)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/14821.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/14821.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/14821.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BLE學習筆記(0.0) —— 基礎概念(0)

前言 &#xff08;1&#xff09;本章節主要是對BLE技術進行簡單的介紹&#xff0c;熟悉藍牙技術的發展過程&#xff0c;了解相關術語方便后續的學習。 &#xff08;2&#xff09;為了防止單篇博客太長以至于看不下去&#xff0c;因此我基礎概念章節分為兩篇來寫。 &#xff08;…

直播回放| 機器人任務挑戰賽線上培訓資料合集

大賽培訓回顧 5月22日&#xff0c;卓翼飛思實驗室為全國各賽區精心組織的機器人任務挑戰賽&#xff08;無人協同系統&#xff09;線上培訓第三期順利落下帷幕&#xff0c;吸引300余人參與。本次培訓主要針對仿真平臺的基本使用&#xff0c;從仿真平臺獲取激光雷達/視覺數據&am…

Mysql教程(0):學習框架

1、Mysql簡介 MySQL 是一個開放源代碼的、免費的關系型數據庫管理系統。在 Web 開發領域&#xff0c;MySQL 是最流行、使用最廣泛的關系數據庫。MySql 分為社區版和商業版&#xff0c;社區版完全免費&#xff0c;并且幾乎能滿足全部的使用場景。由于 MySQL 是開源的&#xff0…

選擇排序,改進冒泡排序,快速排序的查找和計數排序

簡單選擇排序 數據結構:單鏈表 實現方法:n為鏈表長度, 第1趟先選出1到n-1個元素中的最小值和0號元素交換, 第2趟從2到n-1號元素選出最小值和1號元素交換, … 第n-2趟從n-2到n-1號元素中選出最小值和n-2號元素交換. 第n-1趟n-1號元素即為最小值。比較結束。 代碼:…

1075: 求最小生成樹(Prim算法)

解法&#xff1a; 總結起來&#xff0c;Prim算法的核心思想是從一個頂點開始&#xff0c;一步一步地選擇與當前最小生成樹相鄰的且權值最小的邊&#xff0c;直到覆蓋所有的頂點&#xff0c;形成一個最小生成樹。 #include<iostream> #include<vector> using names…

算法-跳馬

bfs類的應用題。 解法&#xff1a; 每一個點都可能作為匯集的那個點&#xff0c;因此采用遍歷的方式&#xff0c;對每個點進行處理&#xff0c;得出每個點的“所有馬跳到本點的最小步數和“&#xff0c;取最小值即可。 邏輯1&#xff1a;以該點作為源點出發&#xff0c;求處…

springboot基于Web前端技術的java養老院管理系統_utbl7

3.普通用戶模塊包括&#xff1a;普通會員的注冊、養老院客房查詢、養老院留言查詢、預約老人基本信息登記、選擇房間、用戶繳費的功能。 4.數據信息能夠及時進行動態更新&#xff0c;增刪&#xff0c;用戶搜素方便&#xff0c;使用戶可以直接瀏覽相關信息&#xff0c;要考慮便于…

Vue3實戰筆記(35)—集成炫酷的粒子特效

文章目錄 前言一、vue3使用tsparticles二、使用步驟總結 前言 學習一個有趣炫酷的玩意開心一下。 tsparticles&#xff0c;可以方便的實現各種粒子特效。支持的語言框架也是相當的豐富. 官網&#xff1a;https://particles.js.org/ 一、vue3使用tsparticles 先來個vue3使用…

Go 語言逃逸分析:內存管理的關鍵

文章目錄 前言1 逃逸分析是什么&#xff1f;2 逃逸分析的基本思想是什么&#xff1f;3 逃逸分析的分配原則是什么&#xff1f;4 如何進行逃逸分析&#xff1f;5 逃逸分析案例5.1 變量在函數外存在引用5.2 引用類型的逃逸5.3 閉包捕獲變量5.4 變量占用內存較大 6 變量會逃逸到堆…

代碼隨想錄訓練營打卡第36天:動態規劃解決子序列問題

1.300最長遞增子序列 1.問題描述 找到其中最長嚴格遞增子序列的長度。 子序列 是由數組派生而來的序列&#xff0c;刪除&#xff08;或不刪除&#xff09;數組中的元素而不改變其余元素的順序。 2.問題轉換 從nums[0...i]的最長的遞增的子序列 3.解題思路 每一個位置的n…

經濟學問題

問題1 1916年&#xff0c;福特汽車公司以440美元的價格生產了50萬輛T型福特汽車。該公司當年盈利6000萬美元。亨利福特告訴一位報紙記者&#xff0c;他打算把T型車的價格降至360美元&#xff0c;他希望在這個價格上能賣出80萬輛汽車。福特說&#xff1a;“每輛車的利潤減少&am…

Flutter 中的 CupertinoPicker 小部件:全面指南

Flutter 中的 CupertinoPicker 小部件&#xff1a;全面指南 在Flutter中&#xff0c;CupertinoPicker是一個用于創建iOS風格的選擇器的組件&#xff0c;它允許用戶通過滾動來選擇一個值。CupertinoPicker可以用于選擇日期、時間或者任何可枚舉的值。本文將詳細介紹CupertinoPi…

C++多態詳解

目錄 一、多態的概念 二、多態的定義及實現 1.多態的構成條件 2.虛函數 3.虛函數的重寫 4.例題理解&#xff08;超級重要&#xff0c;強烈建議做一下&#xff09; 5.C11 override和 final 6.重載、覆蓋&#xff08;重寫&#xff09;、隱藏&#xff08;重定義&#xff0…

【yijiej】mysql報錯 之 報錯:Duplicate entry 字段 for key ‘表名.idx_字段’

一、問題操作 Mysql 進行insert 操作&#xff0c;報錯&#xff1a;Duplicate entry 字段 for key ‘表名.idx_字段’ 原因解析&#xff1a;idx 是做的索引鍵&#xff0c;是具有唯一性二、問題原因&#xff08;三種情況&#xff0c;當前我遇到的情況是第一種&#xff09; 1、當 …

零基礎代碼隨想錄【Day42】|| 1049. 最后一塊石頭的重量 II,494. 目標和,474.一和零

目錄 DAY42 1049.最后一塊石頭的重量II 解題思路&代碼 494.目標和 解題思路&代碼 474.一和零 解題思路&代碼 DAY42 1049.最后一塊石頭的重量II 力扣題目鏈接(opens new window) 題目難度&#xff1a;中等 有一堆石頭&#xff0c;每塊石頭的重量都是正整…

(Qt) 默認QtWidget應用包含什么?

文章目錄 ?前言?創建&#x1f6e0;?選擇一個模板&#x1f6e0;?Location&#x1f6e0;?構建系統&#x1f6e0;?Details&#x1f6e0;?Translation&#x1f6e0;?構建套件(Kit)&#x1f6e0;?匯總 ?項目??概要??構建步驟??清除步驟 ?Code&#x1f526;untitled…

【EasyX】快速入門——消息處理,音頻

1.消息處理 我們先看看什么是消息 1.1.獲取消息 想要獲取消息,就必須學會getmessage函數 1.1.1.getmessage函數 有兩個重載版本,它們的作用是一樣的 參數filter可以篩選我們需要的消息類型 我們看看參數filter的取值 當然我們可以使用位運算組合這些值 例如,我們…

華為CE6851-48S6Q-HI升級設備版本及補丁

文章目錄 升級前準備工作筆記本和交換機設備配置互聯地址啟用FTP設備訪問FTP設備升級系統版本及補丁 升級前準備工作 使用MobaXterm遠程工具連接設備&#xff0c;并作為FTP服務器準備升級所需的版本文件及補丁文件 筆記本和交換機設備配置互聯地址 在交換機接口配置IP&#…

Facebook隱私保護:數據安全的前沿挑戰

在數字化時代&#xff0c;隨著社交媒體的普及和應用&#xff0c;個人數據的隱私保護問題日益受到關注。作為全球最大的社交平臺之一&#xff0c;Facebook承載了數十億用戶的社交活動和信息交流&#xff0c;但與此同時&#xff0c;也面臨著來自內外部的數據安全挑戰。本文將深入…

AWS Elastic Beanstalk 監控可觀測最佳實踐

一、概述 Amazon Web Services (AWS) 包含一百多種服務&#xff0c;每項服務都針對一個功能領域。服務的多樣性可讓您靈活地管理 AWS 基礎設施&#xff0c;然而&#xff0c;判斷應使用哪些服務以及如何進行預配置可能會非常困難。借助 Elastic Beanstalk&#xff0c;可以在 AW…