lc222


  • 首页

  • 分类

  • 归档

  • 标签

Tensorflow中使用TFRecords高效读取数据--结合NLP数据实践

发表于 2017-06-23 | 分类于 深度学习 , TensorFlow | 阅读次数

之前一篇博客在进行论文仿真的时候用到了TFRecords进行数据的读取操作,但是因为当时比较忙,所以没有进行深入学习。这两天看了一下,决定写篇博客专门结合该代码记录一下TFRecords的相关操作。
首先说一下为什么要使用TFRecords来进行文件的读写,在TF中数据的传入方式主要包含以下几种:

  1. 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据。
  2. 从文件读取数据: 在TensorFlow图的起始, 让一个输入管线从文件中读取数据。
  3. 预加载数据: 在TensorFlow图中定义常量或变量来保存所有数据(仅适用于数据量比较小的情况)。

之前都是使用1和3进行数据的操作,但是当我们遇到数据集比较大的情况时,这两种方法会及其占用内存,效率很差。那么为甚么使用TFRecords会比较快呢?因为其使用二进制存储文件,也就是将数据存储在一个内存块中,相比其它文件格式要快很多,特别是如果你使用hdd而不是ssd,因为它涉及移动磁盘阅读器头并且需要相当长的时间。总体而言,通过使用二进制文件,您可以更轻松地分发数据,使数据更好地对齐,以实现高效的读取。接下来我们看一下具体的操作。

个人感觉可以分成两部分,一是将文件保存成TFRecords格式的.tfrecords文件,这里主要涉及到使用tf.python_io.TFRecordWriter("train.tfrecords")和tf.train.Example以及tf.train.Features三个函数,第一个是生成需要对应格式的文件,后面两个函数主要是将我们要传入的数据按照一定的格式进行规范化。这里还要提到一点就是使用TFRecords可以避免多个文件的使用,比如说我们一般会将一次要传入的数据的不同部分分别存放在不同文件夹中,question一个,answer一个,query一个等等,但是使用TFRecords之后,我们可以将一批数据同时保存在一个文件之中,这样方便我们在后续程序中的使用。

另一部分就是在训练模型时将我们生成的.tfrecords文件读入并传到模型中进行使用。这部分主要涉及到使用tf.TFRecordReader("train.tfrecords")和tf.parse_single_example两个函数。第一个函数是将我们的二进制文件读入,第二个则是进行解析然后得到我们想要的数据。

接下来我们结合代码进行理解:

生成TFRecords文件

这里关于要使用的数据集的介绍可以参考我的上一篇博客,主要是QA任务的数据集。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def tokenize(index, word):
#index是每个单词对应词袋子之中的索引值,word是所有出现的单词
directories = ['cnn/questions/training/', 'cnn/questions/validation/', 'cnn/questions/test/']
for directory in directories:
#分别读取训练测试验证集的数据
out_name = directory.split('/')[-2] + '.tfrecords'
#生成对应.tfrecords文件
writer = tf.python_io.TFRecordWriter(out_name)
#每个文件夹下面都有若干文件,每个文件代表一个QA队,也就是一条训练数据
files = map(lambda file_name: directory + file_name, os.listdir(directory))
for file_name in files:
with open(file_name, 'r') as f:
lines = f.readlines()
#对每条数据分别获得文档,问题,答案三个值,并将相应单词转化为索引
document = [index[token] for token in lines[2].split()]
query = [index[token] for token in lines[4].split()]
answer = [index[token] for token in lines[6].split()]
#调用Example和Features函数将数据格式化保存起来。注意Features传入的参数应该是一个字典,方便后续读数据时的操作
example = tf.train.Example(
features = tf.train.Features(
feature = {
'document': tf.train.Feature(
int64_list=tf.train.Int64List(value=document)),
'query': tf.train.Feature(
int64_list=tf.train.Int64List(value=query)),
'answer': tf.train.Feature(
int64_list=tf.train.Int64List(value=answer))
}))
true #写数据
serialized = example.SerializeToString()
writer.write(serialized)

读取.tfrecords文件

因为在读取数据之后我们可能还会进行一些额外的操作,使我们的数据格式满足模型输入,所以这里会引入一些额外的函数来实现我们的目的。这里介绍几个个人感觉较重要常用的函数。不过还是推荐到官网API去查,或者有某种需求的时候到Stack Overflow上面搜一搜,一般都能找到满足自己需求的函数。
1,string_input_producer( string_tensor, num_epochs=None, shuffle=True, seed=None, capacity=32, shared_name=None, name=None, cancel_op=None )其输出是一个输入管道的队列

2,shuffle_batch( tensors, batch_size, capacity, min_after_dequeue, num_threads=1, seed=None, enqueue_many=False, shapes=None, allow_smaller_final_batch=False, shared_name=None, name=None )产生随机打乱之后的batch数据

3,sparse_ops.serialize_sparse(sp_input, name=None): 返回一个字符串的3-vector(1-D的tensor),分别表示索引、值、shape

4,deserialize_many_sparse(serialized_sparse, dtype, rank=None, name=None): 将多个稀疏的serialized_sparse合并成一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def read_records(index=0):
#生成读取数据的队列,要指定epoches
train_queue = tf.train.string_input_producer(['training.tfrecords'], num_epochs=FLAGS.epochs)
validation_queue = tf.train.string_input_producer(['validation.tfrecords'], num_epochs=FLAGS.epochs)
test_queue = tf.train.string_input_producer(['test.tfrecords'], num_epochs=FLAGS.epochs)
queue = tf.QueueBase.from_list(index, [train_queue, validation_queue, test_queue])
#定义一个recordreader对象,用于数据的读取
reader = tf.TFRecordReader()
#从之前的队列中读取数据到serialized_example
_, serialized_example = reader.read(queue)
#调用parse_single_example函数解析数据
features = tf.parse_single_example(
serialized_example,
features={
'document': tf.VarLenFeature(tf.int64),
'query': tf.VarLenFeature(tf.int64),
'answer': tf.FixedLenFeature([], tf.int64)
})
#返回索引、值、shape的三元组信息
document = sparse_ops.serialize_sparse(features['document'])
query = sparse_ops.serialize_sparse(features['query'])
answer = features['answer']
#生成batch切分数据
document_batch_serialized, query_batch_serialized, answer_batch = tf.train.shuffle_batch(
[document, query, answer], batch_size=FLAGS.batch_size,
capacity=2000,
min_after_dequeue=1000)
sparse_document_batch = sparse_ops.deserialize_many_sparse(document_batch_serialized, dtype=tf.int64)
sparse_query_batch = sparse_ops.deserialize_many_sparse(query_batch_serialized, dtype=tf.int64)
document_batch = tf.sparse_tensor_to_dense(sparse_document_batch)
document_weights = tf.sparse_to_dense(sparse_document_batch.indices, sparse_document_batch.shape, 1)
query_batch = tf.sparse_tensor_to_dense(sparse_query_batch)
query_weights = tf.sparse_to_dense(sparse_query_batch.indices, sparse_query_batch.shape, 1)
return document_batch, document_weights, query_batch, query_weights, answer_batch

至此,我们就可以
参考连接:
https://www.tensorflow.org/programmers_guide/reading_data

http://warmspringwinds.github.io/tensorflow/tf-slim/2016/12/21/tfrecords-guide/

http://ycszen.github.io/2016/08/17/TensorFlow%E9%AB%98%E6%95%88%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE/

Hierarchical Attention Network for Document Classification阅读笔记

发表于 2017-06-13 | 分类于 深度学习 , NLP | 阅读次数

最近看了”Hierarchical Attention Network for Document Classification”一篇文章,也在网上找了一些资料结合理解,发现在此之前有篇文章跟他提出的模型架构基本相似,只不过不包含attention机制:“Document Modeling with Gated Recurrent Neural Network
for Sentiment Classification”,也就是说本篇论文是基于这篇论文作了一些改进的。所以这里主要结合两篇论文进行介绍文档的分层架构模型。

Non-Attention

第一篇文章主要是使用两个神经网络分别建模句子和文档,采用一种自下向上的基于向量的文本表示模型。首先使用CNN/LSTM来建模句子表示,接下来使用双向GRU模型对句子表示进行编码得到文档表示,这里论文中提到在情感分类任务中,GRU往往比RNN效果要好。模型架构如下图所示:
这里写图片描述
再上图中,词向量是从语料库中使用Word2vec模型训练出来的,保存在词嵌入矩阵中。然后使用CNN/LSTM模型学习句子表示,这里会将变长的句子表示成相同维度的向量,以消除句子长度不同所带来的不便。也就是说之后的GRU模型的输入是长度相同的句子向量。
卷积模型如下图所示,filter的宽度分别取1,2,3来编码unigrams,bigrams和trigrams的语义信息。最后使用一个Average层捕获全局信息并转化为固定长度的输出向量。
这里写图片描述
接下来进行文本层面建模,使用GRU模型,输入是变长的句子向量,输出固定长度的文本向量,这里会对最后每个单元的输出向量进行取平均操作,虽然会忽略句子顺序的信息,但是相对来说较为简单方便,如下图所示,其中GNN代表GRU的一个基础计算单元:
这里写图片描述

With-Attention HAN模型

接下来我们介绍一下本篇文章的模型架构,其实主要的思想和上面的差不多,也是分层构建只不过加上了两个Attention层,用于分别对句子和文档中的单词、句子的重要性进行建模。其主要思想是,首先考虑文档的分层结构:单词构成句子,句子构成文档,所以建模时也分这两部分进行。其次,不同的单词和句子具有不同的信息量,不能单纯的统一对待所以引入Attention机制。而且引入Attention机制除了提高模型的精确度之外还可以进行单词、句子重要性的分析和可视化,让我们对文本分类的内部有一定了解。模型主要可以分为下面四个部分,如下图所示:

  1. a word sequence encoder,
  2. a word-level attention layer,
  3. a sentence encoder
  4. a sentence-level attention layer.

这里写图片描述、
这里对Attention机制进行一个补充介绍,可以参考论文“FEED-FORWARD NETWORKS WITH ATTENTION CAN SOLVE SOME LONG -TERM MEMORY PROBLEMS”里面的插图:
这里写图片描述
这里的word sequence encoder也是使用的双向GRU模型,与上篇文章不同。无聊的堆砌一下公式,四个部分分别对应下面四个:

  1. Word Encoder:这里写图片描述
  2. Word Attention:这里写图片描述
  3. Sentence Encoder:这里写图片描述
  4. Sentence Attention:这里写图片描述
    这里不进行过多的解释,主要针对Attention部分说一下,结合上图,我们会发现ui是使用一个简单的神经网络对hi的隐层表示,然后α是其softmax之后的结果,然后使用α对hi进行加权计算得到最终的输出向量即可。总结如下图:
    这里写图片描述
    最后是一个文本分类层,其实就是一个简单的softmax,然后目标函数使用负对数似然函数。

好了,介绍完模型架构,接下俩就是仿真实现了,争取下周搞出来~~

使用hexo+github创建属于自己的博客

发表于 2017-06-13 | 分类于 其他 | 阅读次数

之前一直使用CSDN写博客,记录自己的学习经验收获,但是最近一直想自己尝试着搭一个简洁、优雅的博客,在网上查了一些资料之后发现使用hexo+github的组合无疑是个人建站的最佳选择,所以昨天就搭建了自己的博客。因为网上有很多使用hexo+github搭建个人博客的文章,而内容也都基本相同,所以本篇博客不会再去重复造轮子,而是记录自己在搭建环境过程中遇到的一些问题和解决办法。

首先推荐几个搭建博客的链接,大家可以先按照上面的步骤搭建自己的博客:

  1. 史上最详细的Hexo博客搭建图文教程
  2. 安装next主题,也就是我博客使用的主题风格,这里包含了如何设置next主题、内部风格、语言、菜单栏、头像。
  3. 为NexT主题添加文章阅读量统计功能
  4. 主体内部配置包括菜单栏设计、代码风格、友情打赏、侧边栏社交链接、友情链接、公众号,以及特别炫酷的背景动画效果等等功能实现。
  5. 如果你想特别简单的,也可以看这个教程,写的比较全,但是有些模块比如打赏等可能是因为版本比较老,所以还是推荐按照上面那个连接设置。

基本上就是先安装hexo、在配置github pages页面,接下来更改自己喜欢的主题风格(next),最后自定义自己的博客细节(添加一些小的模块等)的步骤。

几个需要注意的地方就是要区分开hexo和next的_config.yml文件,另外就是注意自己头像、微信支付宝收款图片要放在F:\blog\themes\next\source\imagesnext目录下面的images文件夹中。每次部署博客之前最好先使用hexo clean清一下缓存,以免部署之后发现没有更新。

还有就是如果执行hexo g -d命令时如果报错:

ERROR Script load failed: themes\next\scripts\tags\exturl.js Error: Cannot find module 'hexo-util'

那么执行下面这条命令即可:npm install -- save-dev hexo-util

最后,当我们配置好环境之后,下一步就是要写博客发表,所以我们就需要使用markdown的编辑器,网上有很多推荐,有在线版也有软件。可以驱搜一搜,选择一款自己喜欢的就行。
对了,当我们没有发表博客或者发表的博客没有tags和category时,首页下面的菜单栏中相应选项也是没有任何信息的,只有当我们添加相应博客之后才会有。

好啦,接下来就可以开心写博客啦~~

Hello World

发表于 2017-06-12 | 阅读次数

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

lc222

lc222

4 日志
4 分类
6 标签
© 2017 lc222
由 Hexo 强力驱动
主题 - NexT.Mist