使用Torch nngraph實現LSTM

2021-07-09 17:37:55 字數 4543 閱讀 3032

下面我們看看抽象出來的rnn的公式: ht

=θϕ(

ht−1

)+θx

xt y

t=θy

ϕ(ht

) 可以發現每次rnn都要使用上一次中間層的輸出ht

傳統rnn的缺點—梯度消失問題(vanishing gradient problem)

我們定義loss function為

e ,那麼梯度公式如下: ∂e

∂θ=∑

st=1

∂et∂

θ∂et

∂θ=∑

tk=1

∂et∂

yt∂y

t∂ht

∂ht∂

hk∂h

k∂θ

∂ht∂

hk=∏

ti=k

+1∂h

i∂hi

−1=∏

ti=k

+1θt

diag

[ϕ′(

hi−1

)] |

|∂hi

∂hi−

1||≤

||θt

||||

diag

[ϕ′(

hi−1

)]||

≤γθγ

ϕ ∂h

t∂hk

≤(γθ

γϕ)t

−k不斷的乘以小於1的數,梯度會越來越小。為了解決這個問題,lstm應運而生。

定義:lstm(long-short term memory,lstm)
提到lstm,總會伴隨一張如下所示的圖:

從圖中可以看到除了輸入,還有三個部分:1)input gate;2)forget gate;3)output gate

根據上文提到的rnn,我們的輸入是xt

和ht−

1 ,而輸入是ht

和ct (cell state),其中cell state是lstm的關鍵所在,它使得lstm具有記憶功能。下面是關於lstm的公式:

1)input gate:it

=σ(w

xixt

+whi

ht−1

+bi)

=σ(l

inea

rxi(

xt)+

line

arhi

(ht−

1))

其中σ指的是sigmoid函式。

2)forget gate:決定是否刪除或者保留記憶(memory) ft

=σ(w

xfxt

+whf

ht−1

+bf)

3)output gate:ot

=σ(w

xoxt

+who

ht−1

+bo)

4)cell update:gt

=tan

h(wx

gxt+

whgh

t−1+

bg)

5)cell state update:ct

=ft⊙

ct−1

+it⊙

gt6)final output of lstm:ht

=ot⊙

tanh

(ct)

以上是lstm乙個cell涉及的公式,下面講解為什麼lstm可以解決在rnn中梯度消失的問題

對於任意

k<

t ,我們可以計算:

由於每乙個因子都非常接近1,所以梯度很難衰減,這樣就解決了梯度消失的問題。

在使用torch編寫lstm之前,我們需要學習torch中的乙個工具nngraph,安轉nngraph的命令如下:

luarocks install nngraph
nngraph的詳細介紹:

nngraph可以方便設計乙個神經網路模組。我們先使用nngraph建立乙個簡單的網路模組: z=

x1+x

2⊙li

near

(x3)

可以看出這個模組的輸入一共有三個,x1

,x2 和x3

,輸出是

z 。下面是實現這個模組的torch**:

require 'nngraph'

x1=nn.identity()()

x2=nn.identity()()

x3=nn.identity()()

l=nn.caddtable()()})

mlp=nn.gmodule(,)

首先我們定義x1

,x2 和x3

,使用nn.identity()();然後對於li

near

(x3)

,我們使用x4=nn.linear(20,10)(x3),定義了乙個輸入層有20個神經元,輸出層有10個神經元的線性神經網路;對於x2

⊙lin

ear(

x3) ,使用x5=nn.cmultable()(x2,x4);對於x1

+x2⊙

line

ar(x

3),我們使用nn.caddtable()(x1,x5)實現;最後使用nn.gmodule(,)來定義神經網路模組。

我們使用forward方法測試我們的module是否正確:

h1=torch.tensor

h2=torch.tensor(10):fill(1)

h3=torch.tensor(20):fill(2)

b=mlp:forward()

parameters=mlp:parameters()[1]

bias=mlp:parameters()[2]

result=torch.cmul(h2,(parameters*h3+bias))+h1

首先我們定義三個輸入h1

,h2 和 h3

,然後呼叫模組mpl的forward命令得到輸出b,然後我們獲取網路權重w和bias分別儲存在parameters和bias變數中,計算z=

h1+h

2⊙li

near

(h3)

的結果result=torch.cmul(h2,(parameters*h3+bias))+h1,最後比較result和b是否一致,我們發現計算的結果是一樣的,說明我們的模組是正確的。

現在我們使用nngraph寫前文所描述的lstm模組,**如下:

require

'nngraph'

function

lstm

(xt,prev_c,prev_h)

function

new_input_sum

()local

i2h=nn.linear

(400,400)

local

h2h=nn.linear

(400,400)

return

nn.caddtable

()()

endlocal

input_gate=nn.sigmoid

()(new_input_sum())

local

forget_gate=nn.sigmoid

()(new_input_sum())

local

output_gate=nn.sigmoid

()(new_input_sum())

local

gt=nn.tanh

()(new_input_sum())

local

ct=nn.caddtable

()(),nn.cmultable()

()})

local

ht=nn.cmultable

()()

return

ct,ht

endxt=nn.identity

()()

prev_c=nn.identity

()()

prev_h=nn.identity

()()

lstm=nn.gmodule

(,)

其中xtprev_h是輸入,prev_c是cell state,然後我們按照前文的公式一次計算,最後輸出ct(new cell state),ht(輸出)。**的計算順序與上文完全一致,所以這裡就不再一一解釋了。

Response AddHeader使用例項收集

response.addheader refresh 60 url newpath newpage.asp 這等同於客戶機端元素 頁面轉向 response.status 302 object moved response.addheader location newpath newpage.asp...

使用ServletFileUpload實現上傳

1.首先我們應該為上傳的檔案建乙個存放的位置,一般位置分為臨時和真是資料夾,那我們就需要獲取這倆個資料夾的絕對路徑,在servlet中我們可以這樣做 然後建立檔案工廠即倉庫乙個引數表示存放多大後flush,fileitemfactory factory new diskfileitemfactory...

使用ServletFileUpload實現上傳

1.首先我們應該為上傳的檔案建乙個存放的位置,一般位置分為暫時和真是目錄,那我們就須要獲取這倆個目錄的絕對路徑,在servlet中我們能夠這樣做 然後建立檔案工廠即倉庫乙個引數表示存放多大後flush,fileitemfactory factory new diskfileitemfactory c...