-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreader.py
107 lines (87 loc) · 4.22 KB
/
reader.py
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"""Utilities for parsing PTB text files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import collections
import os
import sys
import tensorflow as tf
Py3 = sys.version_info[0] == 3
def _read_words(filename):
"""
Replace /n with <eos>, then separate sentences into words with space.
:param filename: The path of the corpus
:return: A list of words
"""
with tf.gfile.GFile(filename, 'r') as f:
if Py3:
return f.read().replace('\n', '<eos>').split()
else:
return f.read().decode('utf-8').replace('\n', '<eos>').split()
def _build_vocab(filename):
# Get a list of words from file
data = _read_words(filename)
counter = collections.Counter(data) # Calculate the frequency
count_pairs = sorted(counter.items(), key=lambda x:(-x[1], x[0])) # Order words with frequency
words, _ = list(zip(*count_pairs))
word_to_id = dict(zip(words, range(len(words))))
return word_to_id
def _file_to_word_ids(filename, word_to_id):
data = _read_words(filename)
return [word_to_id[word] for word in data if word in word_to_id]
def ptb_raw_data(data_path=None):
"""Load PTB raw data from data directory "data_path".
Reads PTB text files, converts strings to integer ids,
and performs mini-batching of the inputs.
The PTB dataset comes from Tomas Mikolov's webpage:
http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
Args:
data_path: string path to the directory where simple-examples.tgz has
been extracted.
Returns:
tuple (train_data, valid_data, test_data, vocabulary)
where each of the data objects can be passed to PTBIterator.
"""
train_path = os.path.join(data_path, "ptb.train.txt")
valid_path = os.path.join(data_path, "ptb.valid.txt")
test_path = os.path.join(data_path, "ptb.test.txt")
word_to_id = _build_vocab(train_path) # Generate 10000 words vocabulary dict from training corpus
# Convert words to ids with corpus and word_to_id
train_data = _file_to_word_ids(train_path, word_to_id) # Convert words to ids with corpus and word_to_id
valid_data = _file_to_word_ids(valid_path, word_to_id)
test_data = _file_to_word_ids(test_path, word_to_id)
vocabulary = len(word_to_id)
return train_data, valid_data, test_data, vocabulary
def ptb_producer(raw_data, batch_size, num_steps, name=None):
"""Iterate on the raw PTB data.
This chunks up raw_data into batches of examples and returns Tensors that
are drawn from these batches.
Args:
raw_data: one of the raw data outputs from ptb_raw_data.
batch_size: int, the batch size.
num_steps: int, the number of unrolls.
name: the name of this operation (optional).
Returns:
A pair of Tensors, each shaped [batch_size, num_steps]. The second element
of the tuple is the same data time-shifted to the right by one.
Raises:
tf.errors.InvalidArgumentError: if batch_size or num_steps are too high.
"""
with tf.name_scope(name, "PTBProducer", [raw_data, batch_size, num_steps]):
raw_data = tf.convert_to_tensor(raw_data, name="raw_data", dtype=tf.int32)
data_len = tf.size(raw_data) # The length of corpus
batch_len = data_len // batch_size # How many batchs
# Reshape corpus from (1, data_len) to (batch_size, batch_len)
data = tf.reshape(raw_data[0:batch_size * batch_len], [batch_size, batch_len])
# Minus 1 makes sure sentences can be generated to x and y
# Divide num_steps makes sure batch_len large enough
epoch_size = (batch_len - 1) // num_steps
assertion = tf.assert_positive(epoch_size, message="epoch_size == 0, decrease batch")
with tf.control_dependencies([assertion]):
epoch_size = tf.identity(epoch_size, name='epoch_size')
i = tf.train.range_input_producer(epoch_size, shuffle=False).dequeue()
x = tf.strided_slice(data, [0, i * num_steps], [batch_size, (i + 1) * num_steps])
x.set_shape([batch_size, num_steps])
y = tf.strided_slice(data, [0, i * num_steps + 1], [batch_size, (i + 1) * num_steps + 1])
y.set_shape([batch_size, num_steps])
return x, y