溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM

發(fā)布時(shí)間:2022-05-05 10:24:18 來源:億速云 閱讀:174 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM”吧!

LSTM簡(jiǎn)介

1、RNN的梯度消失問題

在過去的時(shí)間里我們學(xué)習(xí)了RNN循環(huán)神經(jīng)網(wǎng)絡(luò),其結(jié)構(gòu)示意圖是這樣的:

python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM

其存在的最大問題是,當(dāng)w1、w2、w3這些值小于0時(shí),如果一句話夠長(zhǎng),那么其在神經(jīng)網(wǎng)絡(luò)進(jìn)行反向傳播與前向傳播時(shí),存在梯度消失的問題。

0.925=0.07,如果一句話有20到30個(gè)字,那么第一個(gè)字的隱含層輸出傳遞到最后,將會(huì)變?yōu)樵瓉淼?.07倍,相比于最后一個(gè)字的影響,大大降低。

其具體情況是這樣的:

python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM

長(zhǎng)短時(shí)記憶網(wǎng)絡(luò)就是為了解決梯度消失的問題出現(xiàn)的。

2、LSTM的結(jié)構(gòu)

原始RNN的隱藏層只有一個(gè)狀態(tài)h,從頭傳遞到尾,它對(duì)于短期的輸入非常敏感。

如果我們?cè)僭黾右粋€(gè)狀態(tài)c,讓它來保存長(zhǎng)期的狀態(tài),問題就可以解決了。

對(duì)于RNN和LSTM而言,其兩個(gè)step單元的對(duì)比如下。

python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM

我們把LSTM的結(jié)構(gòu)按照時(shí)間維度展開:

python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM

我們可以看出,在n時(shí)刻,LSTM的輸入有三個(gè):
 

1、當(dāng)前時(shí)刻網(wǎng)絡(luò)的輸入值;
 

2、上一時(shí)刻LSTM的輸出值;
 

3、上一時(shí)刻的單元狀態(tài)。

LSTM的輸出有兩個(gè):
 

1、當(dāng)前時(shí)刻LSTM輸出值;
 

2、當(dāng)前時(shí)刻的單元狀態(tài)。

3、LSTM獨(dú)特的門結(jié)構(gòu)

LSTM用兩個(gè)門來控制單元狀態(tài)cn的內(nèi)容:
 

1、遺忘門(forget gate),它決定了上一時(shí)刻的單元狀態(tài)cn-1有多少保留到當(dāng)前時(shí)刻;
 

2、輸入門(input gate),它決定了當(dāng)前時(shí)刻網(wǎng)絡(luò)的輸入c’n有多少保存到單元狀態(tài)。

LSTM用一個(gè)門來控制當(dāng)前輸出值hn的內(nèi)容:
 

輸出門(output gate),它決定了當(dāng)前時(shí)刻單元狀態(tài)cn有多少輸出。

python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM

tensorflow中LSTM的相關(guān)函數(shù)

tf.contrib.rnn.BasicLSTMCell

tf.contrib.rnn.BasicLSTMCell(
    num_units,
    forget_bias=1.0,
    state_is_tuple=True,
    activation=None,
    reuse=None,
    name=None,
    dtype=None
)

num_units:RNN單元中的神經(jīng)元數(shù)量,即輸出神經(jīng)元數(shù)量。

forget_bias:偏置增加了忘記門。從CudnnLSTM訓(xùn)練的檢查點(diǎn)(checkpoin)恢復(fù)時(shí),必須手動(dòng)設(shè)置為0.0。

state_is_tuple:如果為True,則接受和返回的狀態(tài)是c_state和m_state的2-tuple;如果為False,則他們沿著列軸連接。False即將棄用。

activation:激活函數(shù)。

reuse:描述是否在現(xiàn)有范圍中重用變量。如果不為True,并且現(xiàn)有范圍已經(jīng)具有給定變量,則會(huì)引發(fā)錯(cuò)誤。

name:層的名稱。

dtype:該層的數(shù)據(jù)類型。

在使用時(shí),可以定義為:

lstm_cell = tf.contrib.rnn.BasicLSTMCell(self.cell_size, forget_bias=1.0, state_is_tuple=True)

在定義完成后,可以進(jìn)行狀態(tài)初始化:

self.cell_init_state = lstm_cell.zero_state(self.batch_size, dtype=tf.float32)

tf.nn.dynamic_rnn

tf.nn.dynamic_rnn(
    cell,
    inputs,
    sequence_length=None,
    initial_state=None,
    dtype=None,
    parallel_iterations=None,
    swap_memory=False,
    time_major=False,
    scope=None
)
  • cell:上文所定義的lstm_cell。

  • inputs:RNN輸入。如果time_major==false(默認(rèn)),則必須是如下shape的tensor:[batch_size,max_time,…]或此類元素的嵌套元組。如果time_major==true,則必須是如下形狀的tensor:[max_time,batch_size,…]或此類元素的嵌套元組。

  • sequence_length:Int32/Int64矢量大小。用于在超過批處理元素的序列長(zhǎng)度時(shí)復(fù)制通過狀態(tài)和零輸出。因此,它更多的是為了性能而不是正確性。

  • initial_state:上文所定義的_init_state。

  • dtype:數(shù)據(jù)類型。

  • parallel_iterations:并行運(yùn)行的迭代次數(shù)。那些不具有任何時(shí)間依賴性并且可以并行運(yùn)行的操作將是。這個(gè)參數(shù)用時(shí)間來交換空間。值>>1使用更多的內(nèi)存,但花費(fèi)的時(shí)間更少,而較小的值使用更少的內(nèi)存,但計(jì)算需要更長(zhǎng)的時(shí)間。

  • time_major:輸入和輸出tensor的形狀格式。如果為真,這些張量的形狀必須是[max_time,batch_size,depth]。如果為假,這些張量的形狀必須是[batch_size,max_time,depth]。使用time_major=true會(huì)更有效率,因?yàn)樗梢员苊庠赗NN計(jì)算的開始和結(jié)束時(shí)進(jìn)行換位。但是,大多數(shù)TensorFlow數(shù)據(jù)都是批處理主數(shù)據(jù),因此默認(rèn)情況下,此函數(shù)為False。

  • scope:創(chuàng)建的子圖的可變作用域;默認(rèn)為“RNN”。

在LSTM的最后,需要用該函數(shù)得出結(jié)果。

self.cell_outputs, self.cell_final_state = tf.nn.dynamic_rnn(
	lstm_cell, self.l_in_y, initial_state=self.cell_init_state, time_major=False)

返回的是一個(gè)元組 (outputs, state):

outputs:LSTM的最后一層的輸出,是一個(gè)tensor。如果為time_major== False,則它的shape為[batch_size,max_time,cell.output_size]。如果為time_major== True,則它的shape為[max_time,batch_size,cell.output_size]。

states:states是一個(gè)tensor。state是最終的狀態(tài),也就是序列中最后一個(gè)cell輸出的狀態(tài)。一般情況下states的形狀為 [batch_size, cell.output_size],但當(dāng)輸入的cell為BasicLSTMCell時(shí),states的形狀為[2,batch_size, cell.output_size ],其中2也對(duì)應(yīng)著LSTM中的cell state和hidden state。

整個(gè)LSTM的定義過程為:

    def add_input_layer(self,):
        #X最開始的形狀為(256 batch,28 steps,28 inputs)
        #轉(zhuǎn)化為(256 batch*28 steps,128 hidden)
        l_in_x = tf.reshape(self.xs, [-1, self.input_size], name='to_2D') 

        #獲取Ws和Bs
        Ws_in = self._weight_variable([self.input_size, self.cell_size])
        bs_in = self._bias_variable([self.cell_size])

        #轉(zhuǎn)化為(256 batch*28 steps,256 hidden) 
        with tf.name_scope('Wx_plus_b'):
            l_in_y = tf.matmul(l_in_x, Ws_in) + bs_in
        
        # (batch * n_steps, cell_size) ==> (batch, n_steps, cell_size)
        # (256*28,256)->(256,28,256)
        self.l_in_y = tf.reshape(l_in_y, [-1, self.n_steps, self.cell_size], name='to_3D')

    def add_cell(self):
        #神經(jīng)元個(gè)數(shù)
        lstm_cell = tf.contrib.rnn.BasicLSTMCell(self.cell_size, forget_bias=1.0, state_is_tuple=True)

        #每一次傳入的batch的大小
        with tf.name_scope('initial_state'):
            self.cell_init_state = lstm_cell.zero_state(self.batch_size, dtype=tf.float32)

        #不是主列
        self.cell_outputs, self.cell_final_state = tf.nn.dynamic_rnn(
            lstm_cell, self.l_in_y, initial_state=self.cell_init_state, time_major=False)
    
    def add_output_layer(self):
        #設(shè)置Ws,Bs
        Ws_out = self._weight_variable([self.cell_size, self.output_size])
        bs_out = self._bias_variable([self.output_size])
        # shape = (batch,output_size)
        # (256,10)
        with tf.name_scope('Wx_plus_b'):
            self.pred = tf.matmul(self.cell_final_state[-1], Ws_out) + bs_out

全部代碼

該例子為手寫體識(shí)別例子,將手寫體的28行分別作為每一個(gè)step的輸入,輸入維度均為28列。

import tensorflow as tf 
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np

mnist = input_data.read_data_sets("MNIST_data",one_hot = "true")

BATCH_SIZE = 256     # 每一個(gè)batch的數(shù)據(jù)數(shù)量
TIME_STEPS = 28      # 圖像共28行,分為28個(gè)step進(jìn)行傳輸
INPUT_SIZE = 28      # 圖像共28列
OUTPUT_SIZE = 10     # 共10個(gè)輸出
CELL_SIZE = 256      # RNN 的 hidden unit size,隱含層神經(jīng)元的個(gè)數(shù)
LR = 1e-3            # learning rate,學(xué)習(xí)率

def get_batch():    #獲取訓(xùn)練的batch
    batch_xs,batch_ys = mnist.train.next_batch(BATCH_SIZE)      
    batch_xs = batch_xs.reshape([BATCH_SIZE,TIME_STEPS,INPUT_SIZE])
    return [batch_xs,batch_ys]

class LSTMRNN(object):  #構(gòu)建LSTM的類
    def __init__(self, n_steps, input_size, output_size, cell_size, batch_size):
        self.n_steps = n_steps 
        self.input_size = input_size
        self.output_size = output_size
        self.cell_size = cell_size
        self.batch_size = batch_size

        #輸入輸出
        with tf.name_scope('inputs'):
            self.xs = tf.placeholder(tf.float32, [None, n_steps, input_size], name='xs')
            self.ys = tf.placeholder(tf.float32, [None, output_size], name='ys')
        #直接加層
        with tf.variable_scope('in_hidden'):
            self.add_input_layer()
        #增加LSTM的cell
        with tf.variable_scope('LSTM_cell'):
            self.add_cell()
        #直接加層
        with tf.variable_scope('out_hidden'):
            self.add_output_layer()
        #計(jì)算損失值
        with tf.name_scope('cost'):
            self.compute_cost()
        #訓(xùn)練
        with tf.name_scope('train'):
            self.train_op = tf.train.AdamOptimizer(LR).minimize(self.cost)
        #正確率計(jì)算
        self.correct_pre = tf.equal(tf.argmax(self.ys,1),tf.argmax(self.pred,1))
        self.accuracy = tf.reduce_mean(tf.cast(self.correct_pre,tf.float32))

    def add_input_layer(self,):
        #X最開始的形狀為(256 batch,28 steps,28 inputs)
        #轉(zhuǎn)化為(256 batch*28 steps,128 hidden)
        l_in_x = tf.reshape(self.xs, [-1, self.input_size], name='to_2D') 

        #獲取Ws和Bs
        Ws_in = self._weight_variable([self.input_size, self.cell_size])
        bs_in = self._bias_variable([self.cell_size])

        #轉(zhuǎn)化為(256 batch*28 steps,256 hidden) 
        with tf.name_scope('Wx_plus_b'):
            l_in_y = tf.matmul(l_in_x, Ws_in) + bs_in
        
        # (batch * n_steps, cell_size) ==> (batch, n_steps, cell_size)
        # (256*28,256)->(256,28,256)
        self.l_in_y = tf.reshape(l_in_y, [-1, self.n_steps, self.cell_size], name='to_3D')

    def add_cell(self):
        #神經(jīng)元個(gè)數(shù)
        lstm_cell = tf.contrib.rnn.BasicLSTMCell(self.cell_size, forget_bias=1.0, state_is_tuple=True)

        #每一次傳入的batch的大小
        with tf.name_scope('initial_state'):
            self.cell_init_state = lstm_cell.zero_state(self.batch_size, dtype=tf.float32)

        #不是主列
        self.cell_outputs, self.cell_final_state = tf.nn.dynamic_rnn(
            lstm_cell, self.l_in_y, initial_state=self.cell_init_state, time_major=False)
    
    def add_output_layer(self):
        #設(shè)置Ws,Bs
        Ws_out = self._weight_variable([self.cell_size, self.output_size])
        bs_out = self._bias_variable([self.output_size])
        # shape = (batch,output_size)
        # (256,10)
        with tf.name_scope('Wx_plus_b'):
            self.pred = tf.matmul(self.cell_final_state[-1], Ws_out) + bs_out

    def compute_cost(self):
        self.cost =  tf.reduce_mean(
            tf.nn.softmax_cross_entropy_with_logits(logits = self.pred,labels = self.ys)
            )

    def _weight_variable(self, shape, name='weights'):
        initializer = np.random.normal(0.0,1.0 ,size=shape)
        return tf.Variable(initializer, name=name,dtype = tf.float32)

    def _bias_variable(self, shape, name='biases'):
        initializer = np.ones(shape=shape)*0.1
        return tf.Variable(initializer, name=name,dtype = tf.float32)


if __name__ == '__main__':
    #搭建 LSTMRNN 模型
    model = LSTMRNN(TIME_STEPS, INPUT_SIZE, OUTPUT_SIZE, CELL_SIZE, BATCH_SIZE)
    sess = tf.Session()

    sess.run(tf.global_variables_initializer())
    
    #訓(xùn)練10000次
    for i in range(10000):
        xs, ys = get_batch()  #提取 batch data
        if i == 0:
        #初始化data
            feed_dict = {
                    model.xs: xs,
                    model.ys: ys,
            }
        else:
            feed_dict = {
                model.xs: xs,
                model.ys: ys,
                model.cell_init_state: state    #保持 state 的連續(xù)性
            }
        
        #訓(xùn)練
        _, cost, state, pred = sess.run(
            [model.train_op, model.cost, model.cell_final_state, model.pred],
            feed_dict=feed_dict)
        
        #打印精確度結(jié)果
        if i % 20 == 0:
            print(sess.run(model.accuracy,feed_dict = {
                    model.xs: xs,
                    model.ys: ys,
                    model.cell_init_state: state    #保持 state 的連續(xù)性
            }))

感謝各位的閱讀,以上就是“python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)python中怎么使用tensorflow構(gòu)建長(zhǎng)短時(shí)記憶LSTM這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI