# 学习笔记CB013: TensorFlow、TensorBoard、seq2seq

tensorflow基于图结构深度学习框架，内部通过session实现图和计算内核交互。

tensorflow基本数学运算用法。

`import tensorflow as tf`
`sess = tf.Session()`
`a = tf.placeholder("float")`
`b = tf.placeholder("float")`
`c = tf.constant(6.0)`
`d = tf.mul(a, b)`
`y = tf.mul(d, c)`
`print sess.run(y, feed_dict={a: 3, b: 3})`
`A = [[1.1,2.3],[3.4,4.1]]`
`Y = tf.matrix_inverse(A)`
`print sess.run(Y)`
`sess.close()`

`tf.add`
`tf.sub`
`tf.mul`
`tf.div`
`tf.mod`
`tf.abs`
`tf.neg`
`tf.sign`
`tf.inv`
`tf.square`
`tf.round`
`tf.sqrt`
`tf.pow`
`tf.exp`
`tf.log`
`tf.maximum`
`tf.minimum`
`tf.cos`
`tf.sin`

`tf.diag #生成对角阵`
`tf.transpose`
`tf.matmul`
`tf.matrix_determinant #计算行列式的值`
`tf.matrix_inverse #计算矩阵的逆`

tensorboard使用。tensorflow代码，先构建图，然后执行，对中间过程调试不方便，提供一个tensorboard工具调试。训练时提示写入事件文件到目录(/tmp/tflearn_logs/11U8M4/)。执行命令打开 http://192.168.1.101:6006 看到tensorboard的界面。

`tensorboard --logdir=/tmp/tflearn_logs/11U8M4/`

Graph和Session。

`import tensorflow as tf`
`with tf.Graph().as_default() as g:`
`    with g.name_scope("myscope") as scope: # 有了这个scope，下面的op的name都是类似myscope/Placeholder这样的前缀`
`        sess = tf.Session(target='', graph = g, config=None) # target表示要连接的tf执行引擎`
`        print "graph version:", g.version # 0`
`        a = tf.placeholder("float")`
`        print a.op # 输出整个operation信息，跟下面g.get_operations返回结果一样`
`        print "graph version:", g.version # 1`
`        b = tf.placeholder("float")`
`        print "graph version:", g.version # 2`
`        c = tf.placeholder("float")`
`        print "graph version:", g.version # 3`
`        y1 = tf.mul(a, b) # 也可以写成a * b`
`        print "graph version:", g.version # 4`
`        y2 = tf.mul(y1, c) # 也可以写成y1 * c`
`        print "graph version:", g.version # 5`
`        operations = g.get_operations()`
`       for (i, op) in enumerate(operations):`
`            print "============ operation", i+1, "==========="`
`            print op # 一个结构，包括：name、op、attr、input等,不同op不一样`
`        assert y1.graph is g`
`        assert sess.graph is g`
`        print "================ graph object address ================"`
`        print sess.graph`
`        print "================ graph define ================"`
`        print sess.graph_def`
`        print "================ sess str ================"`
`        print sess.sess_str`
`        print sess.run(y1, feed_dict={a: 3, b: 3}) # 9.0 feed_dictgraph中的元素和值的映射`
`        print sess.run(fetches=[b,y1], feed_dict={a: 3, b: 3}, options=None, run_metadata=None) # 传入的feches和返回值的shape相同`
`        print sess.run({'ret_name':y1}, feed_dict={a: 3, b: 3}) # {'ret_name': 9.0} 传入的feches和返回值的shape相同`
`        assert tf.get_default_session() is not sess`
`        with sess.as_default(): # 把sess作为默认的session，那么tf.get_default_session就是sess, 否则不是`
`            assert tf.get_default_session() is sess`
`        h = sess.partial_run_setup([y1, y2], [a, b, c]) # 分阶段运行，参数指明了feches和feed_dict列表`
`        res = sess.partial_run(h, y1, feed_dict={a: 3, b: 4}) # 12 运行第一阶段`
`        res = sess.partial_run(h, y2, feed_dict={c: res}) # 144.0 运行第二阶段，其中使用了第一阶段的执行结果`
`        print "partial_run res:", res`
`        sess.close()`

tensorflow Session是Graph和执行者媒介，Session.run()将graph、fetches、feed_dict序列化到字节数组，调用tf_session.TF_Run（参见/usr/local/lib/python2.7/site-packages/tensorflow/python/client/session.py）。tf_session.TF_Run调用动态链接库_pywrap_tensorflow.so实现_pywrap_tensorflow.TF_Run接口(参见/usr/local/lib/python2.7/site-packages/tensorflow/python/pywrap_tensorflow.py)。动态链接库是tensorflow多语言python接口。_pywrap_tensorflow.so和pywrap_tensorflow.py通过SWIG工具自动生成，tensorflow核心语言c语言，通过SWIG生成各种脚本语言接口。

10行关键代码实现线性回归。用梯度下降求解线性回归问题是tensorflow最简单入门例子（10行关键代码）。

`# -*- coding: utf-8 -*-`
`import numpy as np`
`import tensorflow as tf`
`# 随机生成1000个点，围绕在y=0.1x+0.3的直线周围`
`num_points = 1000`
`vectors_set = []`
`for i in xrange(num_points):`
`    x1 = np.random.normal(0.0, 0.55)`
`    y1 = x1 * 0.1 + 0.3 + np.random.normal(0.0, 0.03)`
`    vectors_set.append([x1, y1])`
`# 生成一些样本`
`x_data = [v[0] for v in vectors_set]`
`y_data = [v[1] for v in vectors_set]`
`# 生成1维的W矩阵，取值是[-1,1]之间的随机数`
`W = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='W')`
`# 生成1维的b矩阵，初始值是0`
`b = tf.Variable(tf.zeros([1]), name='b')`
`# 经过计算得出预估值y`
`y = W * x_data + b`
`# 以预估值y和实际值y_data之间的均方误差作为损失`
`loss = tf.reduce_mean(tf.square(y - y_data), name='loss')`
`# 采用梯度下降法来优化参数`
`optimizer = tf.train.GradientDescentOptimizer(0.5)`
`# 训练的过程就是最小化这个误差值`
`train = optimizer.minimize(loss, name='train')`
`sess = tf.Session()`
`# 输出图结构`
`#print sess.graph_def`
`init = tf.initialize_all_variables()`
`sess.run(init)`
`# 初始化的W和b是多少`
`print "W =", sess.run(W), "b =", sess.run(b), "loss =", sess.run(loss)`
`# 执行20次训练`
`for step in xrange(20):`
`    sess.run(train)`
`    # 输出训练好的W和b`
`    print "W =", sess.run(W), "b =", sess.run(b), "loss =", sess.run(loss)`
`# 生成summary文件，用于tensorboard使用`
`writer = tf.train.SummaryWriter("./tmp", sess.graph)`

`tensorboard --logdir=./tmp/`

`W = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='W')`

`y = W * x_data + b`

train对应梯度下降训练过程操作。

`loss = tf.reduce_mean(tf.square(y - y_data), name='loss')`

tensorflow自带seq2seq模型基于one-hot词嵌入，每个词用一个数字代替不足表示词与词之间关系，word2vec多维向量做词嵌入，能够表示出词之间关系。基于seq2seq思想，利用多维词向量实现模型，预期会有更高准确性。

seq2seq模型原理。参考《Sequence to Sequence Learning with Neural Networks》论文。核心思想，ABC是输入语句，WXYZ是输出语句，EOS是标识一句话结束，训练单元是lstm，lstm的特点是有长短时记忆，能够根据输入多个字确定后面多个字，lstm知识参考 http://deeplearning.net/tutorial/lstm.html 模型编码器和解码器共用同一个lstm层，共享参数，分开 https://github.com/farizrahman4u/seq2seq 绿色是编码器，黄色是解码器，橙色箭头传递lstm层状态信息(记忆信息)，编码器唯一传给解码器的状态信息。

`python word_segment.py ./corpus.raw ./corpus.segment`

`cat ./corpus.segment | awk '{if(last!="")print last"|"\$0;last=\$0}' | sed 's/| /|/g' > ./corpus.segment.pair`

`word2vec -train ./corpus.segment -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-5 -threads 20 -binary 1 -iter 15`

corpus.raw 原始语料数据，vectors.bin 生成的词向量二进制文件。

`# 首先我们为输入的样本数据申请变量空间，如下。其中self.max_seq_len是指一个切好词的句子最多包含多少个词，self.word_vec_dim是词向量的维度，这里面shape指定了输入数据是不确定数量的样本，每个样本最多包含max_seq_len*2个词，每个词用word_vec_dim维浮点数表示。这里面用2倍的max_seq_len是因为我们训练是输入的X既要包含question句子又要包含answer句子`
`input_data = tflearn.input_data(shape=[None, self.max_seq_len*2, self.word_vec_dim], dtype=tf.float32, name = "XY")`
`# 然后我们将输入的所有样本数据的词序列切出前max_seq_len个，也就是question句子部分，作为编码器的输入`
`encoder_inputs = tf.slice(input_data, [0, 0, 0], [-1, self.max_seq_len, self.word_vec_dim], name="enc_in")`
`# 再取出后max_seq_len-1个，也就是answer句子部分，作为解码器的输入。注意，这里只取了max_seq_len-1个，是因为还要在前面拼上一组GO标识来告诉解码器我们要开始解码了，也就是下面加上go_inputs拼成最终的go_inputs`
`decoder_inputs_tmp = tf.slice(input_data, [0, self.max_seq_len, 0], [-1, self.max_seq_len-1, self.word_vec_dim], name="dec_in_tmp")`
`go_inputs = tf.ones_like(decoder_inputs_tmp)`
`go_inputs = tf.slice(go_inputs, [0, 0, 0], [-1, 1, self.word_vec_dim])`
`decoder_inputs = tf.concat(1, [go_inputs, decoder_inputs_tmp], name="dec_in")`
`# 之后开始编码过程，返回的encoder_output_tensor展开成tflearn.regression回归可以识别的形如(?, 1, 200)的向量；返回的states后面传入给解码器`
`(encoder_output_tensor, states) = tflearn.lstm(encoder_inputs, self.word_vec_dim, return_state=True, scope='encoder_lstm')`
`encoder_output_sequence = tf.pack([encoder_output_tensor], axis=1)`
`# 取出decoder_inputs的第一个词，也就是GO`
`first_dec_input = tf.slice(decoder_inputs, [0, 0, 0], [-1, 1, self.word_vec_dim])`
`# 将其输入到解码器中，如下，解码器的初始化状态为编码器生成的states，注意：这里的scope='decoder_lstm'是为了下面重用同一个解码器`
`decoder_output_tensor = tflearn.lstm(first_dec_input, self.word_vec_dim, initial_state=states, return_seq=False, reuse=False, scope='decoder_lstm')`
`# 暂时先将解码器的第一个输出存到decoder_output_sequence_list中供最后一起输出`
`decoder_output_sequence_single = tf.pack([decoder_output_tensor], axis=1)`
`decoder_output_sequence_list = [decoder_output_tensor]`
`# 接下来我们循环max_seq_len-1次，不断取decoder_inputs的一个个词向量作为下一轮解码器输入，并将结果添加到decoder_output_sequence_list中，这里面的reuse=True, scope='decoder_lstm'说明和上面第一次解码用的是同一个lstm层`
`for i in range(self.max_seq_len-1):`
`   next_dec_input = tf.slice(decoder_inputs, [0, i+1, 0], [-1, 1, self.word_vec_dim])`
`   decoder_output_tensor = tflearn.lstm(next_dec_input, self.word_vec_dim, return_seq=False, reuse=True, scope='decoder_lstm')`
`   decoder_output_sequence_single = tf.pack([decoder_output_tensor], axis=1)`
`   decoder_output_sequence_list.append(decoder_output_tensor)`
`# 下面我们把编码器第一个输出和解码器所有输出拼接起来，作为tflearn.regression回归的输入`
`decoder_output_sequence = tf.pack(decoder_output_sequence_list, axis=1)`
`real_output_sequence = tf.concat(1, [encoder_output_sequence, decoder_output_sequence])`
`net = tflearn.regression(real_output_sequence, optimizer='sgd', learning_rate=0.1, loss='mean_square')`
`model = tflearn.DNN(net)`

`1）训练输入X、Y分别是编码器解码器输入和预测输出；`
`2）X切分两半，前一半是编码器输入，后一半是解码器输入；`
`3）编码解码器输出预测值用Y做回归训练`
`4）训练通过样本真实值作解码器输入，实际预测不会有WXYZ部分，上一时序输出将作下一时序输入`

`model = self.model()`
`model.fit(trainXY, trainY, n_epoch=1000, snapshot_epoch=False, batch_size=1)`
`model.load('./model/model')`

trainXY和trainY通过加载语料赋值。

`def init_seq(input_file):`
`    """读取切好词的文本文件，加载全部词序列`
`    """`
`    file_object = open(input_file, 'r')`
`    vocab_dict = {}`
`    while True:`
`        question_seq = []`
`        answer_seq = []`
`        line = file_object.readline()`
`        if line:`
`            line_pair = line.split('|')`
`            line_question = line_pair[0]`
`            line_answer = line_pair[1]`
`            for word in line_question.decode('utf-8').split(' '):`
`                if word_vector_dict.has_key(word):`
`                    question_seq.append(word_vector_dict[word])`
`            for word in line_answer.decode('utf-8').split(' '):`
`                if word_vector_dict.has_key(word):`
`                    answer_seq.append(word_vector_dict[word])`
`        else:`
`            break`
`        question_seqs.append(question_seq)`
`        answer_seqs.append(answer_seq)`
`    file_object.close()`

`    def generate_trainig_data(self):`
`        xy_data = []`
`        y_data = []`
`        for i in range(len(question_seqs)):`
`            question_seq = question_seqs[i]`
`            answer_seq = answer_seqs[i]`
`            if len(question_seq) < self.max_seq_len and len(answer_seq) < self.max_seq_len:`
`                sequence_xy = [np.zeros(self.word_vec_dim)] * (self.max_seq_len-len(question_seq)) + list(reversed(question_seq))`
`                sequence_y = answer_seq + [np.zeros(self.word_vec_dim)] * (self.max_seq_len-len(answer_seq))`
`                sequence_xy = sequence_xy + sequence_y`
`                sequence_y = [np.ones(self.word_vec_dim)] + sequence_y`
`                xy_data.append(sequence_xy)`
`                y_data.append(sequence_y)`
`        return np.array(xy_data), np.array(y_data)`

`python my_seq2seq_v2.py train`

`predict = model.predict(testXY)`

`for i in range(self.max_seq_len-1):`
`   # next_dec_input = tf.slice(decoder_inputs, [0, i+1, 0], [-1, 1, self.word_vec_dim])这里改成下面这句`
`   next_dec_input = decoder_output_sequence_single`
`   decoder_output_tensor = tflearn.lstm(next_dec_input, self.word_vec_dim, return_seq=False, reuse=True, scope='decoder_lstm')`
`   decoder_output_sequence_single = tf.pack([decoder_output_tensor], axis=1)`
`   decoder_output_sequence_list.append(decoder_output_tensor)`

`def vector2word(vector):`
`    max_cos = -10000`
`    match_word = ''`
`    for word in word_vector_dict:`
`        v = word_vector_dict[word]`
`        cosine = vector_cosine(vector, v)`
`        if cosine > max_cos:`
`            max_cos = cosine`
`            match_word = word`
`    return (match_word, max_cos)`

`def vector_cosine(v1, v2):`
`    if len(v1) != len(v2):`
`        sys.exit(1)`
`    sqrtlen1 = vector_sqrtlen(v1)`
`    sqrtlen2 = vector_sqrtlen(v2)`
`    value = 0`
`    for item1, item2 in zip(v1, v2):`
`        value += item1 * item2`
`    return value / (sqrtlen1*sqrtlen2)`
`def vector_sqrtlen(vector):`
`    len = 0`
`    for item in vector:`
`        len += item * item`
`    len = math.sqrt(len)`
`    return len`

`python my_seq2seq_v2.py test test.data`

max_seq_len定长8，输出序列最后会多余一些字，根据余弦相似度或者其他指标设定一个阈值截断。

《Python 自然语言处理》

《NLTK基础教程 用NLTK和Python库构建机器学习应用》

http://www.shareditor.com/blogshow?blogId=119

http://www.shareditor.com/blogshow?blogId=120

http://www.shareditor.com/blogshow?blogId=121

0 条评论

• ### 学习笔记TF063:TensorFlow Debugger

TensorFlow Debugger(tfdbg)，TensorFlow专用调试器。用断点、计算机图形化展现实时数据流，可视化运行TensorFlow图形内部...

• ### 学习笔记TF060:图像语音结合，看图说话

实现人工智能3要素：语法(syntax)、语义(semantics)、推理(inference)。语言、视觉。通过语法(语言语法解析、视觉三维结构解析)和语义(...

• ### 学习笔记CB009:人工神经网络模型、手写数字识别、多层卷积网络、词向量、word2vec

由n个输入特征得出与输入特征几乎相同的n个结果，训练隐藏层得到意想不到信息。信息检索领域，模型训练合理排序模型，输入特征，文档质量、文档点击历史、文档前链数目、...

• ### tensorflow编程: Running Graphs

A class for running TensorFlow operations.   这是一个类，执行 tensorflow 中的 op 。它里面定...

• ### 深度学习|费解的tensorflow

学过Python的小伙伴都会觉得，python的语法简单，逻辑清晰。虽然tensorflow是python的一个库（并不是标准库），但是使用并不简单，你可能会被...

• ### TensorFlow tfjs 0.10.3 发布

TensorFlow tfjs 0.10.3 近日正式发布，新版本主要有以下改进内容，AI科技大本营对其编译如下。 ▌资源

• ### TensorFlow练习2: 对评论进行分类

1、 使用大数据，了解怎么处理数据不能一次全部加载到内存的情况。如果你内存充足，当我没说

• ### TensorFlow入门 原

本文将初步向码农和程序媛们介绍如何使用TensorFlow进行编程。在阅读之前请先 安装TensorFlow，此外为了能够更好的理解本文的内容，阅读之前需要了解...

• ### 基于Serverless的验证码识别API

之前和大家分享了很多的CV相关的例子，被很多小伙伴吐槽说我是调包侠，还连累了Serverless被很多人误以为也仅仅能"调包玩一玩"，其实在Serverless...