在TensorFlow中基于lstm構(gòu)建分詞系統(tǒng)筆記(一)

前言

我打算基于lstm構(gòu)建一個分詞系統(tǒng),通過這個例子來學(xué)習(xí)下TensorFlow中如何訓(xùn)練循環(huán)遞歸神經(jīng)網(wǎng)絡(luò)。我們將從最粗糙的版本開始搭建這個小系統(tǒng),然后一步步優(yōu)化其中的每一部分,包括網(wǎng)絡(luò)架構(gòu)的優(yōu)化,數(shù)據(jù)處理的優(yōu)化,甚至整個代碼架構(gòu)的優(yōu)化。希望想我一樣的入門選手看到其中的每一步實現(xiàn)以及如何去優(yōu)化。
關(guān)于LSTM網(wǎng)絡(luò)的介紹,可以看官網(wǎng)推薦的一篇博客,寫的實在是太棒了http://colah.github.io/posts/2015-08-Understanding-LSTMs
另外這篇翻譯也很贊啊http://www.itdecent.cn/p/9dc9f41f0b29,這里不在詳述。
我們第一個版本的模型來自官網(wǎng)的tutorials中Recurrent Neural Networks部分內(nèi)容,官網(wǎng)的數(shù)據(jù)并不利于我們?nèi)ブ苯痈惺苣P陀?xùn)練的帶來的結(jié)果,所以后來我想了下用它來實現(xiàn)一個中文分詞,可能更有利于初學(xué)者去直觀的感受。第一個版本會我寫的很粗糙,主要是為了理解在TensorFlow中如何搭建LSTM網(wǎng)絡(luò)。

模型搭建

我對官網(wǎng)中的例子用我自己更喜歡的結(jié)構(gòu)重寫了下。 首先我們來看下如何搭建這個模型。開始我把模型部分代碼主要由inference(),loss()和training()三部分構(gòu)成,inference()部分負(fù)責(zé)模型搭建,loss()負(fù)責(zé)計算損失,為優(yōu)化做準(zhǔn)備,training()負(fù)責(zé)優(yōu)化部分,主要是對損失函數(shù)應(yīng)用梯度下降,更新參數(shù)。我把上面三部分寫封裝一個類里面。后來發(fā)現(xiàn)這樣實現(xiàn)會存在些問題,然后又把inference()的實現(xiàn)直接放在了類的init()函數(shù)里面。下面先看下模型的整體實現(xiàn),

class ptb_lstm():

    def __init__(self,config):
        ...
    def loss(self):
        ....
    def train(self):
        ....

這里,我們在init()中傳了一個config類,這個config主要是一些模型參數(shù),大致形式是下面這樣,這篇筆記就不詳講了

class config():
    '''參數(shù)配置類'''
    init_scale = 0.1
    learning_rate = 1.0
    max_grad_norm = 5
    num_layers = 2
    hidden_size = 200
    keep_prob = 1.0
    lr_decay = 0.5
    batch_size = 50
    num_steps = 50
    vocab_size = 3000
    output_size = 3
    learningrate = 0.5

好了,接下來我們先看init()部分

class lstm_model():
    def __init__(self, config):
        '''
        :param config:config類,一些訓(xùn)練參數(shù)設(shè)置
        '''
        self.config = config
        self.x = tf.placeholder(tf.int32, shape=(config.batch_size, config.num_steps))
        self.y = tf.placeholder(tf.int32, shape=(config.batch_size, config.num_steps))

        def lstm_cell():
        #構(gòu)建lstm基本單元
            return tf.contrib.rnn.BasicLSTMCell(
                    self.config.hidden_size, forget_bias=0.0, state_is_tuple=True)
        
        attn_cell = lstm_cell
        if config.keep_prob < 1:
        #如果config.keep_prob參數(shù)小于1,對lstm單元進行dropout,防止過擬合
            def attn_cell():
                return tf.contrib.rnn.DropoutWrapper(
                    lstm_cell(), output_keep_prob=config.keep_prob)
                    
        cell = tf.contrib.rnn.MultiRNNCell(
            [attn_cell() for _ in range(config.num_layers)], state_is_tuple=True)
        #構(gòu)建多層的lstm,config.num_layers是層數(shù)參數(shù)

        self._initial_state = cell.zero_state(self.config.batch_size, tf.float32)
        #初始化lstm的state

        with tf.device("/cpu:0"):
            embedding = tf.get_variable(
                "embedding", [self.config.vocab_size, self.config.hidden_size], dtype=tf.float32)
            inputs = tf.nn.embedding_lookup(embedding,self.x)
            #詞嵌入

        outputs = []
        state = self._initial_state
        with tf.variable_scope("RNN"):
            for time_step in range(self.config.num_steps):
                if time_step > 0: tf.get_variable_scope().reuse_variables()
                (cell_output, state) = cell(inputs[:, time_step, :], state)
                outputs.append(cell_output)
                #前向傳播,計算每個單元的cell_output和state,把cell_output添加到outputs,把state傳遞到下個單元,最終outputs的為(config.num_steps,config.batch_size,config.hidden_size)

        output = tf.reshape(tf.concat(axis=1, values=outputs), [-1, self.config.hidden_size])
        #output的形狀為(config.num_steps*config.batch_size,config.hedden_size)
        
        softmax_w = tf.get_variable(
            "softmax_w", [self.config.hidden_size, self.config.output_size], dtype=tf.float32)
        softmax_b = tf.get_variable("softmax_b", [self.config.output_size], dtype=tf.float32)
        self.logits = tf.matmul(output, softmax_w) + softmax_b
        #得到最終的網(wǎng)絡(luò)輸出logits形狀為(config.num_steps*config.batch_size,config.output_size)

接著是loss(self,logits)

    def loss(self):

        logits = self.logits
        loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example(
            [logits],
            [tf.reshape(self.y, [-1])],
            [tf.ones([self.config.batch_size * self.config.num_steps], dtype=tf.float32)])
        # 交叉熵?fù)p失函數(shù),下一篇專門講下tensorflow中的幾個損失函數(shù)的實現(xiàn)
        cost = tf.reduce_sum(loss) / self.config.batch_size

最后是后向傳播參數(shù)更新部分training(self)

def training(self):
        loss = self.loss()

        tvars = tf.trainable_variables()
        grads, _ = tf.clip_by_global_norm(tf.gradients(loss, tvars),
                                          self.config.max_grad_norm)
        optimizer = tf.train.GradientDescentOptimizer(self.config.learningrate)
        #優(yōu)化器
        
        train_op = optimizer.apply_gradients(
            zip(grads, tvars),
            global_step=tf.contrib.framework.get_or_create_global_step())
        #梯度下降
        return train_op

模型部分就搭建完畢了,下一節(jié)我們來講下數(shù)據(jù)的預(yù)處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 文章作者:Tyan博客:noahsnail.com | CSDN | 簡書 聲明:作者翻譯論文僅為學(xué)習(xí),如有侵權(quán)請...
    SnailTyan閱讀 5,484評論 0 8
  • 神經(jīng)結(jié)構(gòu)進步、GPU深度學(xué)習(xí)訓(xùn)練效率突破。RNN,時間序列數(shù)據(jù)有效,每個神經(jīng)元通過內(nèi)部組件保存輸入信息。 卷積神經(jīng)...
    利炳根閱讀 4,896評論 0 7
  • 歲月在煮梅弄酒間悄悄老去,華發(fā)在青絲間不經(jīng)意的閃現(xiàn),身邊至親至愛的人越來越少,無數(shù)次送別的背影漸行漸遠消失在內(nèi)心深...
    飛流三千閱讀 178評論 0 2
  • 生活中的過客 你可曾記得 那些年我們經(jīng)歷的坎坷、有過的快樂 世界的誘惑太多 我們?nèi)狈π叛龅膱远ㄖ皇强諝?那些擁有過...
    風(fēng)吹梧桐閱讀 309評論 0 2
  • 序言 目前形勢,參加到iOS隊伍的人是越來越多,甚至已經(jīng)到供過于求了。今年,找過工作人可能會更深刻地體會到今年的就...
    iYeso閱讀 1,469評論 2 50

友情鏈接更多精彩內(nèi)容