下面我們看看抽象出來的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**:
首先我們定義x1require 'nngraph'
x1=nn.identity()()
x2=nn.identity()()
x3=nn.identity()()
l=nn.caddtable()()})
mlp=nn.gmodule(,)
,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是否正確:
首先我們定義三個輸入h1h1=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
,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模組,**如下:
其中xt和prev_h是輸入,prev_c是cell state,然後我們按照前文的公式一次計算,最後輸出ct(new cell state),ht(輸出)。**的計算順序與上文完全一致,所以這裡就不再一一解釋了。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
(,)
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...