最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

萌新的卷積神經(jīng)網(wǎng)絡學習筆記--pytorch搭建Vit Transformer

2023-02-11 18:27 作者:YM學渣  | 我要投稿


一些函數(shù)的使用

tensor.chunk(劃分為多少份,dim= 按哪個維度劃分)

from einops import rearrange

from einops.layers.torch import Rearrange


類似reshape( ),view( ), 但更直觀,前者為方法,后者為類

from einops import?repeat

復制矩陣里的元素生成新矩陣,且屬于淺拷貝


einsum()

求兩個矩陣的點積

patch + position embedding

Position Embedding 中位置編碼,cls token的解讀: http://t.csdn.cn/twonr

# patch + position embedding
class Patch_embed(nn.Module):
 ? ?def __init__(self, img_size, patch_size,dim,P):
 ? ? ? ?super(Patch_embed,self).__init__()
 ? ? ? ?
 ? ? ? ?self.unfold = nn.Sequential(nn.Unfold(kernel_size = (patch_size,patch_size),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?dilation=(1,1),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?padding=(0,0),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?stride=(patch_size,patch_size)),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Rearrange("b i j -> b j i"),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?nn.Linear(patch_size**2*3,dim)
 ? ? ? ?)
 ? ? ? ?self.dropout = nn.Dropout(p=P)
 ? ? ? ?n = (img_size//patch_size)**2
 ? ? ? ?
 ? ? ? ?# nn.Parameter()將變量轉化為可學習的參數(shù)
 ? ? ? ?# 可學習的參數(shù)做位置編碼,編碼過程直接相加
 ? ? ? ?self.pos = nn.Parameter(torch.randn(1, n+1 ?,dim))# [1,197,dim]
 ? ? ? ?
 ? ? ? ?# 其他部分都是圖像本身各個patch間在計算,單獨在首行加一條可學習的向量(cls token)做為輸出預測的依據(jù)
 ? ? ? ?self.cls = nn.Parameter(torch.randn(1,1, dim))# [1,1,dim]
 ? ? ? ?
 ? ?def forward(self,x): # 輸入[1,3,224,224]
 ? ? ? ?
 ? ? ? ?# patch_size=(16,16) 224/16=14
 ? ? ? ?# [1,16*16*3,14*14] -> [1,14*14,16*16*3] ->[1,14*14,dim] ?
 ? ? ? ?# [1,768, 196] -> [1,196,768] ->[1,196,dim] 
 ? ? ? ?x = self.unfold(x) 
 ? ? ? ?b, _, _ = x.shape
 ? ? ? ?cls_token = repeat(self.cls, "() n d -> b n d",b=b) # ->[batch_size, 1, dim]
 ? ? ? ?# cls token加在首行
 ? ? ? ?x = torch.cat((cls_token,x),dim=-2) # [b,196,dim]->[b,197,dim]
 ? ? ? ?#position embedding
 ? ? ? ?x += self.pos
 ? ? ? 
 ? ? ? ?x=self.dropout(x)
 ? ? ? ?
 ? ? ? ?return x


主要部分:

MSA(Multi-head Attention部分)

多頭自注意力機制(大概是這樣吧)

class MSA(nn.Module):
 ? ?'''多頭自注意力機制,輸入輸出維度不變'''
 ? ?def __init__(self,dim_in, # 輸入向量(token)的維度
 ? ? ? ? ? ? ? ? heads, # 頭數(shù)
 ? ? ? ? ? ? ? ? head_dim, # 每個頭的維度
 ? ? ? ? ? ? ? ? P=0.
 ? ? ? ? ? ? ? ? ):
 ? ? ? ?super().__init__()
 ? ? ? ?self.heads = heads
 ? ? ? ?dim_inner = heads * head_dim
 ? ? ? ?self.scale = head_dim ** (-0.5) # 1/(dk**0.5)
 ? ? ? ?self.to_qkv = nn.Linear(dim_in, dim_inner*3) # 生成Q,K,V三個矩陣,所以乘三
 ? ? ? ?self.softmax = nn.Softmax(dim=-1)
 ? ? ? 
 ? ? ? ?# 統(tǒng)一輸出向量的維度, 與輸入一致
 ? ? ? ?# 判斷要輸出的向量維度是否和輸入一致,當頭數(shù)為1并且每個頭的維度與輸入相同時 直接輸出
 ? ? ? ?project_out = not (heads == 1 and head_dim == dim_in) 
 ? ? ? ?self.to_out = nn.Sequential(
 ? ? ? ? ? ?nn.Linear(dim_inner, dim_in),
 ? ? ? ? ? ?nn.Dropout(P)
 ? ? ? ?) if project_out else nn.Identity()
 ? ?
 ? ?def forward(self,x):
 ? ? ? ?# x.shape:[b, n, l], 
 ? ? ? ?# 表示同時傳入b個數(shù)據(jù),一個數(shù)據(jù)包含n個長度為l的向量(token)
 ? ? ? ?b, n, _ = *x.shape, 
 ? ? ? ?h = self.heads
 ? ? ? ?
 ? ? ? ?# 通過一個全鏈層獲得Q,K,V矩陣, 
 ? ? ? ?QKV = self.to_qkv(x).chunk(3,dim=-1) ?# chunk(3,dim=-1)按最后一個維度分為三份,打包成元組
 ? ? ? ?# map(func,iterable)
 ? ? ? ?Q, K, V = map(lambda t: rearrange(t,"b n (heads head_dim) -> b heads n head_dim", heads=h), QKV)
 ? ? ? ?
 ? ? ? ?# attention(q,k,v) = softmax((q*k)/dk**0.5)*v
 ? ? ? ?# einsum()里維度的描述只能用字母a~z, 或A~Z,不然會報錯
 ? ? ? ?# ? ? ? ? ? ?b heads n head_dim, b heads n head_dim -> b heads n n # -> b heads n n 的話有兩個n會報錯
 ? ? ? ?QK = einsum("b h i d, b h j d -> b h i j", Q, K)*self.scale # einsum('i j, k j->i k', A, B),求兩矩陣的點積
 ? ? ? ?
 ? ? ? ?A = self.softmax(QK) 
 ? ? ? ?
 ? ? ? ?# ? ? ? ? ? ? b heads n n, b heads n head_dim -> b heads n head_dim
 ? ? ? ?att = einsum("b h i j, b h j d -> b h i d", A, V) # einsum('i j, j k->i k', A, B)
 ? ? ? ?
 ? ? ? ?# ? ? ? ? ? ? ? ?b heads n head_dim -> b n ?heads*head_dim (即dim_inner)
 ? ? ? ?out = rearrange(att, "b heads n head_dim -> b n (heads head_dim)")
 ? ? ? ?
 ? ? ? ?out = self.to_out(out) # 統(tǒng)一輸出的向量(token)維度與輸入維度相同
 ? ? ? ?
 ? ? ? ?return out


MLP:多層感知機(即全連接層)

class MLP(nn.Module):
 ? ?'''通過兩層全連接層 向量維度 放大再縮小后輸出'''
 ? ?def __init__(self, dim_in, dim_out, P=0.3):
 ? ? ? ?super(MLP,self).__init__()
 ? ? ? ?
 ? ? ? ?self.mlp =nn.Sequential(
 ? ? ? ? ? ?nn.Linear(dim_in,dim_out),
 ? ? ? ? ? ?nn.GELU(),
 ? ? ? ? ? ?nn.Dropout(p=P),
 ? ? ? ? ? ?nn.Linear(dim_out,dim_in),
 ? ? ? ? ? ?nn.Dropout(p=P) ? ? ? ? 
 ? ? ? ?)
 ? ?
 ? ?def forward(self,x):
 ? ? ? ?
 ? ? ? ?x = self.mlp(x)
 ? ? ? ?
 ? ? ? ?return x ?

Transformer Encoder

class Transformer_encoder(nn.Module):
 ? ?def __init__(self, dim_in, #輸入向量的維度 
 ? ? ? ? ? ? ? ? heads, # 多頭自注意力機制頭數(shù)
 ? ? ? ? ? ? ? ? head_dim, # 每個頭的維度
 ? ? ? ? ? ? ? ? P, # dropout的概率
 ? ? ? ? ? ? ? ? mlp_dim # MLP里隱藏層的神經(jīng)元個數(shù)
 ? ? ? ? ? ? ? ? ) :
 ? ? ? ?super().__init__()
 ? ? ? ?
 ? ? ? ?self.Norm = nn.LayerNorm(dim_in) # Norm
 ? ? ? ?self.MSA = MSA(dim_in,heads=heads, head_dim=head_dim,P=P) # MSA
 ? ? ? ?self.MLP = MLP(dim_in=dim_in,mlp_dim=mlp_dim,P=P) # MLP
 ? ? ? ?
 ? ?def forward(self,x):
 ? ? ? ?
 ? ? ? ?x1 = self.Norm(x)
 ? ? ? ?x2 = self.MSA(x1)
 ? ? ? ?x3 = x + x2
 ? ? ? ?x4 = self.Norm(x3)
 ? ? ? ?x5 = self.MLP(x4)
 ? ? ? ?out = x3 + x5
 ? ? ? ?
 ? ? ? ?return out

VIT

class vit(nn.Module):
 ? ?def __init__(self, img_size, # 圖片尺寸
 ? ? ? ? ? ? ? ? depth, # 多少層transformer encoder
 ? ? ? ? ? ? ? ? dim_in, # 輸入向量的維度
 ? ? ? ? ? ? ? ? patch_size, #分塊的大小
 ? ? ? ? ? ? ? ? heads, # 多頭自注意力機制頭數(shù)
 ? ? ? ? ? ? ? ? head_dim, # 每個頭的維度P, # dropout的概率
 ? ? ? ? ? ? ? ? mlp_dim, # MLP里隱藏層的神經(jīng)元個數(shù)
 ? ? ? ? ? ? ? ? P,
 ? ? ? ? ? ? ? ? class_num
 ? ? ? ? ? ? ? ? ):
 ? ? ? ?super(vit,self).__init__()
 ? ? ? ?self.patch_embed = Patch_embed(img_size,patch_size,dim_in,P)
 ? ? ? ?self.layers = nn.ModuleList()
 ? ? ? ?self.MLP_Head = nn.Sequential(nn.LayerNorm(dim_in),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?nn.Linear(dim_in, class_num),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?nn.Softmax(dim=-1)
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?)
 ? ? ? ?
 ? ? ? ?for i in range(depth):
 ? ? ? ? ? ?self.layers.append(Transformer_encoder(dim_in,heads,head_dim,mlp_dim,P))
 ? ? ? ?
 ? ?def forward(self,x): # [1, 3, 224, 224]
 ? ? ? ?x = self.patch_embed(x) # [[1, 197, 1000]]
 ? ? ? ?
 ? ? ? ?# 通過depth層 transformer encoder
 ? ? ? ?for transformer_encoder in self.layers:
 ? ? ? ? ? ?x = transformer_encoder(x)
 ? ? ? ?
 ? ? ? ?x = x[:,0] # 取首行的cls token
 ? ? ? ?
 ? ? ? ?x = self.MLP_Head(x) # 經(jīng)過MLP Head后輸出類別

 ? ? ? ?return x


test

if __name__ == "__main__":
 ? ?x = torch.rand(1,3,224,224)

 ? ?model = vit(img_size=224, # 圖片尺寸
 ? ? ? ? ? ? ? ? depth=3, # 多少層transformer encoder
 ? ? ? ? ? ? ? ? dim_in=1000, # patch_embed后的向量維度
 ? ? ? ? ? ? ? ? patch_size=16, #分塊的大小
 ? ? ? ? ? ? ? ? heads=3, # 多頭自注意力機制頭數(shù)
 ? ? ? ? ? ? ? ? head_dim=2000, # 每個頭的維度P
 ? ? ? ? ? ? ? ? mlp_dim=2000, # MLP里隱藏層的神經(jīng)元個數(shù)
 ? ? ? ? ? ? ? ? P=0.3,# dropout的概率即全連接層的神經(jīng)元不參與訓練的概率(防過擬合)
 ? ? ? ? ? ? ? ? class_num=2 # 最后輸出幾維向量(多少類)
 ? ? ? ? ? ? ? ? ) 

 ? ?y = model(x)
 ? ?
 ? ?print(f"x.shape: {x.shape}")
 ? ?print(f"y.shape: {y.shape}")
 ? ?print(f"y: {y}")
 ? ?print(f"y.sum():{y.sum()}")

輸出:

不知道對不對,至少能跑通!

參考:

https://zhuanlan.zhihu.com/p/445122996

https://blog.csdn.net/weixin_44966641/article/details/118733341

萌新的卷積神經(jīng)網(wǎng)絡學習筆記--pytorch搭建Vit Transformer的評論 (共 條)

分享到微博請遵守國家法律
防城港市| 红安县| 镇平县| 隆尧县| 正宁县| 易门县| 太原市| 延吉市| 松江区| 崇文区| 会理县| 开平市| 珠海市| 文化| 沾益县| 特克斯县| 连城县| 贵定县| 虞城县| 县级市| 沽源县| 社旗县| 青河县| 平和县| 阳高县| 张家口市| 宁晋县| 青阳县| 西平县| 东港市| 岑巩县| 宣汉县| 石台县| 辰溪县| 泰兴市| 汾西县| 延边| 肥东县| 天津市| 中山市| 富阳市|