日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

深度学习笔记2:关于LSTM神经网络输入输出的理解

發(fā)布時(shí)間:2023/12/10 pytorch 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度学习笔记2:关于LSTM神经网络输入输出的理解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們在理解RNN或者LSTM的時(shí)候,對它們的輸入和輸出的維度都很迷惑,下面是我結(jié)合代碼和網(wǎng)上的一些資料進(jìn)行理解
首先,正常的全連接層網(wǎng)絡(luò)拓?fù)涫沁@樣的:

有輸入層、隱層和輸出層,隱層中有神經(jīng)元,無論是CNN還是RNN都可以這樣概括,圖中每個(gè)參數(shù)都跟全部的神經(jīng)元有鏈接。關(guān)于RNN的理解可以看我上一篇的文章
接下來看下LSTM的拓?fù)鋱D:

LSTM的精華就來了,就是如下公式:

在拓?fù)鋱D中,我們看到的是不同時(shí)刻的X輸入到LSTM,還可以看到中間的 cell 里面有四個(gè)黃色小框,你如果理解了那個(gè)代表的含義一切就明白了,其中每一個(gè)小黃框代表一個(gè)前饋網(wǎng)絡(luò)層,對,就是經(jīng)典的神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu),num_units就是這個(gè)層的隱藏神經(jīng)元個(gè)數(shù),就這么簡單。其中1、2、4的激活函數(shù)是 sigmoid,第三個(gè)的激活函數(shù)是 tanh。
我們只需要記住:
1)cell的狀態(tài)是一個(gè)向量,是一個(gè)多值,而我們訓(xùn)練的網(wǎng)絡(luò)的目的就是為了得到這個(gè)值
2)[ht?1,xt][h_{t-1},x_{t}][ht?1?,xt?]是通過concat結(jié)合起來的,也就是拼接,比如,如果x為28向量,h為128位,結(jié)合后就是156位向量
3)cell是共享權(quán)重,雖然上圖中我們看到的是三個(gè)重復(fù)的結(jié)構(gòu)圖,但實(shí)際上是每個(gè)結(jié)構(gòu)圖是不同時(shí)序的輸入情況,不同時(shí)序的x不斷輸入該結(jié)構(gòu)中不斷更新cell的值。
4)LSTM的參數(shù)數(shù)量就是把Wf、Wi、Wc、WoW_{f}、W_{i}、W_{c}、W_{o}Wf?Wi?Wc?Wo?bf、bi、bc、bob_{f}、b_{i}、b_{c}、b_{o}bf?bi?bc?bo?的元素加起來,假設(shè)num_units是128,輸入x是28位,h的向量維度也是128,所以LSTM的神經(jīng)元個(gè)數(shù)為:
( 128 + 25 ) x ( 128 x 4 ) + 4 x 128

源碼如下(參考這篇博客)

LSTM 關(guān)鍵代碼:@tf_export("nn.rnn_cell.BasicLSTMCell") class BasicLSTMCell(LayerRNNCell):"""Basic LSTM recurrent network cell.The implementation is based on: http://arxiv.org/abs/1409.2329.We add forget_bias (default: 1) to the biases of the forget gate in order toreduce the scale of forgetting in the beginning of the training.It does not allow cell clipping, a projection layer, and does notuse peep-hole connections: it is the basic baseline.For advanced models, please use the full @{tf.nn.rnn_cell.LSTMCell}that follows."""def __init__(self,num_units,forget_bias=1.0,state_is_tuple=True,activation=None,reuse=None,name=None,dtype=None):"""Initialize the basic LSTM cell.Args:num_units: int, The number of units in the LSTM cell.forget_bias: float, The bias added to forget gates (see above).Must set to `0.0` manually when restoring from CudnnLSTM-trainedcheckpoints.state_is_tuple: If True, accepted and returned states are 2-tuples ofthe `c_state` and `m_state`. If False, they are concatenatedalong the column axis. The latter behavior will soon be deprecated.activation: Activation function of the inner states. Default: `tanh`.reuse: (optional) Python boolean describing whether to reuse variablesin an existing scope. If not `True`, and the existing scope already hasthe given variables, an error is raised.name: String, the name of the layer. Layers with the same name willshare weights, but to avoid mistakes we require reuse=True in suchcases.dtype: Default dtype of the layer (default of `None` means use the typeof the first input). Required when `build` is called before `call`.When restoring from CudnnLSTM-trained checkpoints, must use`CudnnCompatibleLSTMCell` instead."""super(BasicLSTMCell, self).__init__(_reuse=reuse, name=name, dtype=dtype)if not state_is_tuple:logging.warn("%s: Using a concatenated state is slower and will soon be ""deprecated. Use state_is_tuple=True.", self)# Inputs must be 2-dimensional.self.input_spec = base_layer.InputSpec(ndim=2)self._num_units = num_unitsself._forget_bias = forget_biasself._state_is_tuple = state_is_tupleself._activation = activation or math_ops.tanh@propertydef state_size(self):# 隱藏層的 size:return (LSTMStateTuple(self._num_units, self._num_units)if self._state_is_tuple else 2 * self._num_units)@propertydef output_size(self):# 輸出層的size:Hidden_sizereturn self._num_unitsdef build(self, inputs_shape):if inputs_shape[1].value is None:raise ValueError("Expected inputs.shape[-1] to be known, saw shape: %s"% inputs_shape)#inputs的維度為:[batch_size,input_size]#如果是第一層每個(gè)時(shí)刻詞語的輸入,則這個(gè)input_size 就是 embedding_size,就等于詞向量的維度;# 所以 此時(shí) input_depth,就是input_sizeinput_depth = inputs_shape[1].value# h_depth 就是 Hidden_size,隱藏層的維度h_depth = self._num_units# self._kernel == W;則此時(shí) W的維度 為【input_size + Hidden_size,4* Hidden_size】# 此處定義四個(gè) W 和 B,是為了,一次就把 i,j,f,o 計(jì)算出來;相當(dāng)于圖中的 ft,it,ct‘,otself._kernel = self.add_variable(_WEIGHTS_VARIABLE_NAME,shape=[input_depth + h_depth, 4 * self._num_units])# 此時(shí)的B的維度為【4 * Hidden_size】self._bias = self.add_variable(_BIAS_VARIABLE_NAME,shape=[4 * self._num_units],initializer=init_ops.zeros_initializer(dtype=self.dtype))self.built = Truedef call(self, inputs, state):"""Long short-term memory cell (LSTM).Args:inputs: `2-D` tensor with shape `[batch_size, input_size]`.state: An `LSTMStateTuple` of state tensors, each shaped`[batch_size, num_units]`, if `state_is_tuple` has been set to`True`. Otherwise, a `Tensor` shaped`[batch_size, 2 * num_units]`.Returns:A pair containing the new hidden state, and the new state (either a`LSTMStateTuple` or a concatenated state, depending on`state_is_tuple`)."""sigmoid = math_ops.sigmoidone = constant_op.constant(1, dtype=dtypes.int32)# Parameters of gates are concatenated into one multiply for efficiency.# 每一層的第0時(shí)刻的 c 和 h,元素全部初始化為0;if self._state_is_tuple:c, h = stateelse:c, h = array_ops.split(value=state, num_or_size_splits=2, axis=one)# 此時(shí)刻的 input:Xt 和 上一時(shí)刻的輸出:Ht-1,進(jìn)行結(jié)合;# inputs shape : [batch_size,input_size],第一層的時(shí)候,input_size,就相當(dāng)于 embedding_size# 結(jié)合后的維度為【batch_size,input_size + Hidden_size】,W的維度為【input_size + Hidden_size,4*hidden_size】# 兩者進(jìn)行矩陣相乘后的維度為:【batch_size,4*hidden_size】gate_inputs = math_ops.matmul(array_ops.concat([inputs, h], 1), self._kernel)# B 的shape 為:【4 * Hidden_size】,[Xt,Ht-1] * W 計(jì)算后的shape為:[batch_size, 4 * Hidden_size]# nn_ops.bias_add,這個(gè)函數(shù)的計(jì)算方法是,讓每個(gè) batch 得到的值,都加上這個(gè) B;# 這一步,加上B后,得到的是,i,j,f,o 的結(jié)合, [Xt,Ht-1] * W + B,得到的 shape 還是: [batch_size, 4 * Hidden_size]# 加上偏置B后的維度為:【batch_size,4 * Hidden_size】gate_inputs = nn_ops.bias_add(gate_inputs, self._bias)# i = input_gate, j = new_input, f = forget_gate, o = output_gate# 從以上的矩陣相乘后,分割出來四部分,就是 i,j,f,o的值;# 每個(gè)的維度為【batch_size,Hidden_size】i, j, f, o = array_ops.split(value=gate_inputs, num_or_size_splits=4, axis=one)forget_bias_tensor = constant_op.constant(self._forget_bias, dtype=f.dtype)# Note that using `add` and `multiply` instead of `+` and `*` gives a# performance improvement. So using those at the cost of readability.add = math_ops.add# 此處加上遺忘的 bias,選擇遺忘元素;# 以下計(jì)算是:對應(yīng)元素相乘:因?yàn)樗膫€(gè)參數(shù)的維度都是【batch_size,hidden_size】,計(jì)算后維度不變;# new_c = c*sigmoid(f+bias) + sigmoid(i)*tanh(o)# 計(jì)算后的維度為【batch_size,hidden_size】multiply = math_ops.multiplynew_c = add(multiply(c, sigmoid(add(f, forget_bias_tensor))),multiply(sigmoid(i), self._activation(j)))# 以下計(jì)算是:對應(yīng)元素相乘:因?yàn)?個(gè)參數(shù)的維度都是【batch_size,hidden_size】,計(jì)算后維度不變;#new_h = sigmoid(o) * tanh(new_c)new_h = multiply(self._activation(new_c), sigmoid(o))# 計(jì)算后的維度是(值不相等):new_c == new_h == 【batch_size,hidden_size】if self._state_is_tuple:new_state = LSTMStateTuple(new_c, new_h)else:new_state = array_ops.concat([new_c, new_h], 1)# new_h:最后一個(gè)時(shí)刻的H,new_state:最后一個(gè)時(shí)刻的 H和C;循環(huán)執(zhí)行該函數(shù),執(zhí)行 num_step次(即 最大的步長),則該層計(jì)算完全;# 此時(shí)的 new_c 和 new_h,作為下一時(shí)刻的輸入,new_h 和下一時(shí)刻的,Xt+1 進(jìn)行連接,連接后的維度為,【batch_size,input_size + Hidden_size】# 如果還有下一層的話,那么此刻的 new_h,變身為下一時(shí)刻的 Xtreturn new_h, new_state

在知乎上,找到一個(gè)例子非常形象,
RecurrentNNs的結(jié)構(gòu)圖(RNN與LSTM等同)我認(rèn)為應(yīng)該這樣畫,在理解上才會更清晰些,對比MLP,也一目了然。(自己畫的為了簡約,只畫了4個(gè)time-steps )……

看圖。每個(gè)時(shí)序 的輸入 我是一次time_step一張input tensor,隱狀態(tài) 也就代表了一張MLP的hidden layer的一個(gè)cell。輸出 理解無異。注意,紅色的箭頭指向indicates the tensor’s flow at time-sequential order。再結(jié)合一個(gè)操作實(shí)例說明。如果我有一條長文本,我給句子事先分割好句子,并且進(jìn)行tokenize, dictionarize,接著再由look up table 查找到embedding,將token由embedding表示,再對應(yīng)到上圖的輸入。流程如下:

step1, raw text:
接觸LSTM模型不久,簡單看了一些相關(guān)的論文,還沒有動手實(shí)現(xiàn)過。然而至今仍然想不通LSTM神經(jīng)網(wǎng)絡(luò)究竟是怎么工作的。……

step2, tokenize (中文得分詞): sentence1: 接觸 LSTM 模型 不久 ,簡單 看了 一些 相關(guān)的 論文 , 還 沒有 動手 實(shí)現(xiàn)過 。 sentence2: 然而 至今 仍然 想不通 LSTM 神經(jīng)網(wǎng)絡(luò) 究竟是 怎么 工作的。 ……

step3, dictionarize:
sentence1: 1 34 21 98 10 23 9 23
sentence2: 17 12 21 12 8 10 13 79 31 44 9 23
……

step4, padding every sentence to fixed length: sentence1: 1 34 21 98 10 23 9 23 0 0 0 0 0 sentence2: 17 12 21 12 8 10 13 79 31 44 9 23 0 ……

step5, mapping token to an embeddings:
sentence1:
[0.3410.1330.011...0.4350.0810.501...0.0130.9580.121...............]\begin{bmatrix} 0.341 & 0.133 & 0.011 & ... \\ 0.435 & 0.081 & 0.501 & ...\\ 0.013& 0.958 & 0.121 & ...\\ ...& ... & ... & ... \end{bmatrix}?????0.3410.4350.013...?0.1330.0810.958...?0.0110.5010.121...?............??????,每一列代表一個(gè)詞向量,詞向量維度自行確定;矩陣列數(shù)固定為time_step length。
sentence2:
……

step6, feed into RNNs as input: 假設(shè) 一個(gè)RNN的time_step 確定為 ,則padded sentence length(step5中矩陣列數(shù))固定為 。一次RNNs的run只處理一條sentence。每個(gè)sentence的每個(gè)token的embedding對應(yīng)了每個(gè)時(shí)序 的輸入 。一次RNNs的run,連續(xù)地將整個(gè)sentence處理完。

step7, get output:
看圖,每個(gè)time_step都是可以輸出當(dāng)前時(shí)序 t 的隱狀態(tài) h_{i}^{t} ;但整體RNN的輸出 o_{i}^{t} 是在最后一個(gè)time_step t=l 時(shí)獲取,才是完整的最終結(jié)果。

step8, further processing with the output:我們可以將output根據(jù)分類任務(wù)或回歸擬合任務(wù)的不同,分別進(jìn)一步處理。比如,傳給cross_entropy&softmax進(jìn)行分類……或者獲取每個(gè)time_step對應(yīng)的隱狀態(tài) ,做seq2seq 網(wǎng)絡(luò)……或者搞創(chuàng)新……

總結(jié)

以上是生活随笔為你收集整理的深度学习笔记2:关于LSTM神经网络输入输出的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。