在TensorFlow中基于lstm构建分词系统笔记(一)

前言

我打算基于lstm构建一个分词系统,通过这个例子来学习下TensorFlow中如何训练循环递归神经网络。我们将从最粗糙的版本开始搭建这个小系统,然后一步步优化其中的每一部分,包括网络架构的优化,数据处理的优化,甚至整个代码架构的优化。希望想我一样的入门选手看到其中的每一步实现以及如何去优化。
关于LSTM网络的介绍,可以看官网推荐的一篇博客,写的实在是太棒了http://colah.github.io/posts/2015-08-Understanding-LSTMs
另外这篇翻译也很赞啊http://www.jianshu.com/p/9dc9f41f0b29,这里不在详述。
我们第一个版本的模型来自官网的tutorials中Recurrent Neural Networks部分内容,官网的数据并不利于我们去直接感受模型训练的带来的结果,所以后来我想了下用它来实现一个中文分词,可能更有利于初学者去直观的感受。第一个版本会我写的很粗糙,主要是为了理解在TensorFlow中如何搭建LSTM网络。

模型搭建

我对官网中的例子用我自己更喜欢的结构重写了下。 首先我们来看下如何搭建这个模型。开始我把模型部分代码主要由inference(),loss()和training()三部分构成,inference()部分负责模型搭建,loss()负责计算损失,为优化做准备,training()负责优化部分,主要是对损失函数应用梯度下降,更新参数。我把上面三部分写封装一个类里面。后来发现这样实现会存在些问题,然后又把inference()的实现直接放在了类的init()函数里面。下面先看下模型的整体实现,

class ptb_lstm():

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

这里,我们在init()中传了一个config类,这个config主要是一些模型参数,大致形式是下面这样,这篇笔记就不详讲了

class config():
    '''参数配置类'''
    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类,一些训练参数设置
        '''
        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():
        #构建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参数小于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)
        #构建多层的lstm,config.num_layers是层数参数

        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
        #得到最终的网络输出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)])
        # 交叉熵损失函数,下一篇专门讲下tensorflow中的几个损失函数的实现
        cost = tf.reduce_sum(loss) / self.config.batch_size

最后是后向传播参数更新部分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)
        #优化器
        
        train_op = optimizer.apply_gradients(
            zip(grads, tvars),
            global_step=tf.contrib.framework.get_or_create_global_step())
        #梯度下降
        return train_op

模型部分就搭建完毕了,下一节我们来讲下数据的预处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • 文章作者:Tyan博客:noahsnail.com | CSDN | 简书 声明:作者翻译论文仅为学习,如有侵权请...
    SnailTyan阅读 5,059评论 0 8
  • 神经结构进步、GPU深度学习训练效率突破。RNN,时间序列数据有效,每个神经元通过内部组件保存输入信息。 卷积神经...
    利炳根阅读 4,728评论 0 7
  • 岁月在煮梅弄酒间悄悄老去,华发在青丝间不经意的闪现,身边至亲至爱的人越来越少,无数次送别的背影渐行渐远消失在内心深...
    飞流三千阅读 149评论 0 2
  • 生活中的过客 你可曾记得 那些年我们经历的坎坷、有过的快乐 世界的诱惑太多 我们缺乏信仰的坚定只是空壳 那些拥有过...
    风吹梧桐阅读 286评论 0 2
  • 序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了。今年,找过工作人可能会更深刻地体会到今年的就...
    iYeso阅读 1,438评论 2 50