1. 程式人生 > 其它 >baselines演算法庫common/vec_env/subproc_vec_env.py模組分析

baselines演算法庫common/vec_env/subproc_vec_env.py模組分析

CNN理解

 

RNN

Why:

CNN都是水平方向延伸,沒有考慮單個隱藏層在時間上時序的變化。RNN關注每一個神經元在時間維度上的不斷成長

普通的結構

加入時序關聯的結構:表示隱藏層在不同時刻的狀態

其中每個時間段的UWV權重矩陣都是共享一個

參考資料:

LSTM

參考: 【LSTM長短期記憶網路】3D模型一目瞭然,帶你領略演算法背後的邏輯_嗶哩嗶哩_bilibili

Why:

就像人的記憶不能無線延伸, 機器也是,通常超過十步就不行了,為了解決這個問題

研究者在普通RNN的基礎上提出了LSTM(長短期記憶網路Long Short-term Memory)

RNN以三個時間點為例,簡化模型(xt是不同時間的輸入, St是不同時間的隱藏層, y輸出)

LSTM增加了一條新的時間鏈, 記錄Long Term Memory, 用C表示, 同時增加了兩條連結的關聯關係

新增加的鏈條相當於日記本.

當計算隱藏層St的資訊時, 除了輸入Xt, 前一刻資訊St-1 外還要包含當前的時刻記錄的日記資訊.

同時保持短期記憶鏈條St和長期記憶鏈條Ct, 並且相互更新, 這便是LSTM成功改的奧祕

Attention

參考: 【Attention 注意力機制】近年最流行的AI演算法,transformer它爹_嗶哩嗶哩_bilibili

RNN模型建立了網路隱藏層之間的時序關聯 , 每一時刻的隱藏層St, 不僅取決於輸入Xt, 還取決於上一時刻轉檯St-1

兩個RNN組合形成Encoder-Decoder模型

但是這種不管輸入多長, 都統一壓縮成形同長度編碼C的做法,(眉毛鬍子一把抓),會導致翻譯精度下降.

Attention機制:通過每個時間輸入不同的C解決這個問題, 其中ati表明了在t時刻所有輸入的權重, 以Ct

的視角看過去,a權重就是不同輸入的注意力, 因此也被稱為Attention分佈.

 

後來隨著GPU等大規模並行運算的發展 , 人們發現RNN的順序結構很不方便, 那以並行運算,效率太低

便去掉了RNN順序, 變為self-attention, 在Encoding階段計算每個單詞和其他所有單詞的關聯

Transformer

參考資料:

Transformer從零詳細解讀(可能是你見過最通俗易懂的講解)_嗶哩嗶哩_bilibili

Transformer的PyTorch實現_嗶哩嗶哩_bilibili

6(經驗而得)個encoder和decoder的結構一樣引數不一樣。

Encoder

輸入部分(Embedding, 位置嵌入)

Embedding

位置編碼(不進行訓練)

 

self-Attention

Layer Normalization

Decoder

Vision-transformer

參考: 11.1 Vision Transformer(vit)網路詳解_嗶哩嗶哩_bilibili

Patch embedding

程式碼

class PatchEmbed(nn.Module):

    """

    2D Image to Patch Embedding

    """

    def __init__(self, img_size=224, patch_size=16, in_c=3, embed_dim=768, norm_layer=None):

        '''

        patch_size: 2D圖片劃分成16個小塊

        embed_dim 每個小塊的channels=embed_dim=768

        grid_size 每個小塊的(w, h)

        '''

        super().__init__()

        img_size = (img_size, img_size)

        patch_size = (patch_size, patch_size)

        self.img_size = img_size

        self.patch_size = patch_size

        self.grid_size = (img_size[0// patch_size[0], img_size[1// patch_size[1])

        self.num_patches = self.grid_size[0* self.grid_size[1]  這個是為了展平小塊的一個向量,起了個這個名字

   

        self.proj = nn.Conv2d(in_c, embed_dim, kernel_size=patch_size, stride=patch_size)  利用卷積實現

        self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()

   

    def forward(self, x):

        B, C, H, W = x.shape

        不可以更改輸入圖片的大小224

        assert == self.img_size[0and == self.img_size[1], f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."

   

        # flatten: [B, C, H, W] -> [B, C, HW]  從第二個維度展平

        # transpose: [B, C, HW] -> [B, HW, C]  更換文職

        = self.proj(x).flatten(2).transpose(12)

        = self.norm(x)

        return x

 

encoder

Attention程式碼

class Attention(nn.Module):
def __init__(self,
dim, # 輸入token的dim
num_heads=8, # 8組共享Q, K, V的權重引數
qkv_bias=False,
qk_scale=None,
attn_drop_ratio=0., #
proj_drop_ratio=0.):
super(Attention, self).__init__()
self.num_heads = num_heads
head_dim = dim // num_heads # 根據head的數目, 將dim 進行均分, Q K V 深度上進行劃分多個head, 類似於組卷積
self.scale = qk_scale or head_dim ** -0.5 # 根號下dk分之一, 為了避免梯度過小
self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) # Q K V的計算是通過全連線層實現的?
self.attn_drop = nn.Dropout(attn_drop_ratio)
self.proj = nn.Linear(dim, dim)
self.proj_drop = nn.Dropout(proj_drop_ratio)
# 一個小塊中包14 x 14 = 197 個深度為768的單畫素向量,
def forward(self, x):
# [batch_size, num_patches + 1, total_embed_dim] torch.Size([2, 197, 768]) num_patches + 1是小塊的w * h + class, # total_embed_dim是一小塊的深度
B, N, C = x.shape

# qkv(): -> [batch_size, num_patches + 1, 3 * total_embed_dim]
# reshape: -> [batch_size, num_patches + 1, 3, num_heads, embed_dim_per_head]
# permute: -> [3, batch_size, num_heads, num_patches + 1, embed_dim_per_head]
qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
# [batch_size, num_heads, num_patches + 1, embed_dim_per_head]
q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)

# transpose: -> [batch_size, num_heads, embed_dim_per_head, num_patches + 1]
# @: multiply -> [batch_size, num_heads, num_patches + 1, num_patches + 1]
attn = (q @ k.transpose(-2, -1)) * self.scale
attn = attn.softmax(dim=-1) # 對每一行驚醒處理
attn = self.attn_drop(attn)

# @: multiply -> [batch_size, num_heads, num_patches + 1, embed_dim_per_head]
# transpose: -> [batch_size, num_patches + 1, num_heads, embed_dim_per_head]
# reshape: -> [batch_size, num_patches + 1, total_embed_dim]
x = (attn @ v).transpose(1, 2).reshape(B, N, C)
x = self.proj(x)
x = self.proj_drop(x)
return x


 

Swin-transform

參考:12.1 Swin-Transformer網路結構詳解_嗶哩嗶哩_bilibili

Vision transformer 和Swin-transformer的區別

整體模型結構

Patch

Shift Windows