convLSTM 理解與實現

2021-09-25 23:52:28 字數 3137 閱讀 3340

本文主要是有關convlstm的pytorch實現**的理解,原理請移步其他部落格。

在pytorch中實現lstm或者gru等rnn一般需要重寫cell,每個cell中包含某乙個時序的計算,也就是以下:

在傳統lstm中,lstm每次要呼叫t次cell,t就是時序的總長度,如果是n層lstm就相當於一共呼叫了n*t次cell

class convlstmcell(nn.module):

def __init__(self, input_size, input_dim, hidden_dim, kernel_size, bias):

"""initialize convlstm cell.

parameters

----------

input_size: (int, int)

height and width of input tensor as (height, width).

input_dim: int

number of channels of input tensor.

hidden_dim: int

number of channels of hidden state.

kernel_size: (int, int)

size of the convolutional kernel.

bias: bool

whether or not to add the bias.

"""super(convlstmcell, self).__init__()

self.height, self.width = input_size

self.input_dim = input_dim

self.hidden_dim = hidden_dim

self.kernel_size = kernel_size

self.padding = kernel_size[0] // 2, kernel_size[1] // 2

self.bias = bias

self.conv = nn.conv2d(in_channels=self.input_dim + self.hidden_dim,

out_channels=4 * self.hidden_dim,

kernel_size=self.kernel_size,

padding=self.padding,

bias=self.bias)

def forward(self, input_tensor, cur_state):

''':param input_tensor:[batch,dim,inp_height,inp_width]

:param cur_state: [h,c] h:[batch,dim,h,w]

:return:

'''h_cur, c_cur = cur_state

combined = torch.cat([input_tensor, h_cur], dim=1)

combined_conv = self.conv(combined)

cc_i, cc_f, cc_o, cc_g = torch.split(combined_conv, self.hidden_dim, dim=1)

i = torch.sigmoid(cc_i)

f = torch.sigmoid(cc_f)

o = torch.sigmoid(cc_o)

g = torch.tanh(cc_g)

c_next = f * c_cur + i * g

h_next = o * torch.tanh(c_next)

return h_next, c_next

def init_hidden(self, batch_size):

return (variable(torch.zeros(batch_size, self.hidden_dim, self.height, self.width)),

variable(torch.zeros(batch_size, self.hidden_dim, self.height, self.width)))

cell的實現主要如上,其中可以看出來,引數是通過一次conv2d的呼叫就申請好的,這裡是這樣理解的:

in_channels=self.input_dim + self.hidden_dim

out_channels=4 * self.hidden_dim

由於在計算 i f c o 時我們都引入了卷積運算,且運算的物件都是一樣的,要麼是對當前時序的輸入input要麼是對上一時刻的輸出h,所以wxi wxf wcf wxo的卷積核規模或者說引數的規模是相同的,是相同size的tensor,同理whi whf whc wco也是一樣。

在當前時刻,我們的輸入有input[batch,input_dim,h,w],h[batch,hidden_dim,h,w](這裡的input和h的hw是相同的,因為在設定卷積padding的時候約定了輸入的規模)然後我們通過torch.cat將輸入合併為[batch,input_dim+hidden_dim,h,w]

此時我們的核規模是[4*hidden_dim,input_dim+hidden_dim,kh,kw]

在卷積過程中,這裡參考pytorc**檔

這個公式可以理解為矩陣乘運算,不過矩陣乘運算中進行的是每個元素相乘相加,這裡的矩陣乘運算是矩陣中每個核和每個輸入的tensor進行卷積操作再相加。

舉個栗子

假設我們的輸入是28*28的手寫體,為了符合時序的要求,我們將手寫體劃分為16個時序的7*7,核大小設定為(3,3),此時我們的輸入輸出的dim都是1,所以以上的input=[batch,1,7,7] h=[batch,1,7,7] core=[4,2,3,3]

不考慮bias結果就如圖所示了,所以再經過一次split切割,就能拿到很多中間步驟的結果啦。 

DFT 理解與python實現

我們知道傅利葉變換能夠將時域的訊號變換到頻域分析,但是我們在計算機應用時,常常是離散的訊號。如,用adc採集回來的模擬訊號,就變成了離散的訊號。這時我們要對訊號進行分析,就不能再使用傅利葉變換了,而要使用離散傅利葉變換,dft x k n 0n 1x n e j 2 k n nx k sum x n...

kmp演算法的理解與實現

kmp演算法曾被我戲稱為看毛片演算法,當時笑噴.大三那個時候硬著頭皮把演算法導論的kmp演算法啃完,弄懂了kmp演算法 的原理,甚至還寫出了 這幾天再次溫習的時候,發現忘得比較徹底。我總結,學演算法不能只對著書本學理論,而應該 用自己的理解去看清演算法的本質,最好用文字把你的理解記錄下來,這樣才能做...

java 多型的理解與實現

1 物件導向的三大特性 封裝 繼承 多型。從一定角度來看,封裝和繼承幾乎都是為多型而準備的。這是我們最後乙個概念,也是最重要的知識點。2 多型的定義 指允許不同類的物件對同一訊息做出響應。即同一訊息可以根據傳送物件的不同而採用多種不同的行為方式。傳送訊息就是函式呼叫 3 實現多型的技術稱為 動態繫結...