社会责任
pytorch 进修 | 应用pytorch着手完成LSTM模块
2019-05-21 17:04:32 来源:www.gyyhd.com 作者:格兰特软件开发有限公司

LSTM 简介


LSTM是RNN中一个较为流行的收集模块。重要包含输入,输入门,输入门,忘记门,激活函数,全衔接层(Cell)和输入。其布局如下:






上述公式不做说明,咱们只需也许记得如下几个点就能够了:




以后时候LSTM模块的输入有来自以后时候的输入值,上一时候的输入值,输入值和隐含层输入值,便是一共有四个输入值,这意味着一个LSTM模块的输入量是本来通俗全衔接层的四倍阁下,盘算量多了很多。


所谓的门便是前一时候的盘算值输入到sigmoid激活函数获得一个几率值,这个几率值决定了以后输入的强弱水平。 这个几率值和以后输入停止矩阵乘法获得经过门控处置后的现实值。


门控的激活函数都是sigmoid,范围在(0,1),而输入输入单位的激活函数都是tanh,范围在(-1,1)。


Pytorch完成如下:


import torch


import torch.nn as nn


from torch.nn import Parameter


from torch.nn import init


from torch import Tensor


import math




class NaiveLSTM(nn.Module):


   """Naive LSTM like nn.LSTM"""


   def __init__(self, input_size: int, hidden_size: int):


       super(NaiveLSTM, self).__init__()


       self.input_size = input_size


       self.hidden_size = hidden_size




       # input gate


       self.w_ii = Parameter(Tensor(hidden_size, input_size))


       self.w_hi = Parameter(Tensor(hidden_size, hidden_size))


       self.b_ii = Parameter(Tensor(hidden_size, 1))


       self.b_hi = Parameter(Tensor(hidden_size, 1))




       # forget gate


       self.w_if = Parameter(Tensor(hidden_size, input_size))


       self.w_hf = Parameter(Tensor(hidden_size, hidden_size))


       self.b_if = Parameter(Tensor(hidden_size, 1))


       self.b_hf = Parameter(Tensor(hidden_size, 1))




       # output gate


       self.w_io = Parameter(Tensor(hidden_size, input_size))


       self.w_ho = Parameter(Tensor(hidden_size, hidden_size))


       self.b_io = Parameter(Tensor(hidden_size, 1))


       self.b_ho = Parameter(Tensor(hidden_size, 1))


       


       # cell


       self.w_ig = Parameter(Tensor(hidden_size, input_size))


       self.w_hg = Parameter(Tensor(hidden_size, hidden_size))


       self.b_ig = Parameter(Tensor(hidden_size, 1))


       self.b_hg = Parameter(Tensor(hidden_size, 1))




       self.reset_weigths()




   def reset_weigths(self):


       """reset weights


       """


       stdv = 1.0 / math.sqrt(self.hidden_size)


       for weight in self.parameters():


           init.uniform_(weight, -stdv, stdv)




   def forward(self, inputs: Tensor, state: Tuple[Tensor]) \


       -> Tuple[Tensor, Tuple[Tensor, Tensor]]:


       """Forward


       Args:


           inputs: [1, 1, input_size]


           state: ([1, 1, hidden_size], [1, 1, hidden_size])


       """


#         seq_size, batch_size, _ = inputs.size()




       if state is None:


           h_t = torch.zeros(1, self.hidden_size).t()


           c_t = torch.zeros(1, self.hidden_size).t()


       else:


           (h, c) = state


           h_t = h.squeeze(0).t()


           c_t = c.squeeze(0).t()




       hidden_seq = []




       seq_size = 1


       for t in range(seq_size):


           x = inputs[:, t, :].t()


           # input gate


           i = torch.sigmoid(self.w_ii @ x + self.b_ii + self.w_hi @ h_t +


                             self.b_hi)


           # forget gate


           f = torch.sigmoid(self.w_if @ x + self.b_if + self.w_hf @ h_t +


                             self.b_hf)


           # cell


           g = torch.tanh(self.w_ig @ x + self.b_ig + self.w_hg @ h_t


                          + self.b_hg)


           # output gate


           o = torch.sigmoid(self.w_io @ x + self.b_io + self.w_ho @ h_t +


                             self.b_ho)


           


           c_next = f * c_t + i * g


           h_next = o * torch.tanh(c_next)


           c_next_t = c_next.t().unsqueeze(0)


           h_next_t = h_next.t().unsqueeze(0)


           hidden_seq.append(h_next_t)




       hidden_seq = torch.cat(hidden_seq, dim=0)


       return hidden_seq, (h_next_t, c_next_t)




def reset_weigths(model):


   """reset weights


   """


   for weight in model.parameters():


       init.constant_(weight, 0.5)




### test


inputs = torch.ones(1, 1, 10)


h0 = torch.ones(1, 1, 20)


c0 = torch.ones(1, 1, 20)


print(h0.shape, h0)


print(c0.shape, c0)


print(inputs.shape, inputs)




# test naive_lstm with input_size=10, hidden_size=20


naive_lstm = NaiveLSTM(10, 20)


reset_weigths(naive_lstm)




output1, (hn1, cn1) = naive_lstm(inputs, (h0, c0))




print(hn1.shape, cn1.shape, output1.shape)


print(hn1)


print(cn1)


print(output1)


1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42


43


44


45


46


47


48


49


50


51


52


53


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72


73


74


75


76


77


78


79


80


81


82


83


84


85


86


87


88


89


90


91


92


93


94


95


96


97


98


99


100


101


102


103


104


105


106


107


108


109


110


111


112


113


114


115


运转上述代码,其输入为:




比较民间完成:




# Use official lstm with input_size=10, hidden_size=20


lstm = nn.LSTM(10, 20)


reset_weigths(lstm)


output2, (hn2, cn2) = lstm(inputs, (h0, c0))


print(hn2.shape, cn2.shape, output2.shape)


print(hn2)


print(cn2)


print(output2)


1


2


3


4


5


6


7


8


能够看到与民间的完成有些许的分歧,然则输入的成果仍然同等。




---------------------


作者:yh&hy


起源:CSDN


原文:https://blog.csdn.net/CVSvsvsvsvs/article/details/90300647


版权申明:本文为博主原创文章,转载请附上博文链接!