-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreprocess_parallel.py
More file actions
163 lines (133 loc) · 5.4 KB
/
Copy pathpreprocess_parallel.py
File metadata and controls
163 lines (133 loc) · 5.4 KB
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import pickle
import numpy as np
import os
from multiprocessing import Pool, cpu_count
def write_vocab(id_word, word_id):
if not os.path.exists("./vocab"):
os.makedirs("./vocab")
with open("./vocab/WordID.pkl", "wb") as f:
pickle.dump(word_id, f)
with open("./vocab/IDWord.pkl", "wb") as f:
pickle.dump(id_word, f)
def load_vocab():
with open('./vocab/IDWord.pkl', 'rb') as IDWord_file:
id_word = pickle.load(IDWord_file)
with open('./vocab/WordID.pkl', 'rb') as WordID_file:
word_id = pickle.load(WordID_file)
return word_id, id_word
def processLines(line, line_len, known_words, word_id):
""" Parallel processing lines function"""
line = ['<bos>'] + line
line += ['<eos>']
line += ['<pad>']*(line_len-len(line))
# exchanges words with ids and replaces words that are not in vocab with the id of unk
for idx,word in enumerate(line):
if word not in known_words:
line[idx] = word_id['<unk>']
else:
line[idx] = word_id[word]
return list(line)
def preprocess_data(read_file, write_file="sentences.train.preprocess", vocab_size=20000, line_len=30):
# read lines and construct vocabulary
vocab = dict()
lines = []
read_file = open(read_file, 'r')
for line in read_file:
split_line = line[:-1].split(' ')
for word in split_line:
if word in vocab.keys():
vocab[word] += 1
else:
vocab[word] = 1
if len(split_line) <= line_len - 2:
lines += [split_line]
read_file.close()
# add most frequent words in vocabulary to known words
known_words = []
for word in sorted(vocab, key=vocab.get, reverse=True):
if len(known_words) < vocab_size - 4:
known_words += [word]
# build dictonary of word to ids
word_id = {word: i for i, word in enumerate(known_words, 4)}
word_id["<unk>"] = 0
word_id["<eos>"] = 1
word_id["<bos>"] = 2
word_id["<pad>"] = 3
id_word = dict(zip(word_id.values(), word_id.keys())) # reverse dict to get word from id
# write to pickle
write_vocab(id_word, word_id)
known_words.extend(["<eos>", "<bos>", "<pad>"])
processed_lines = []
if write_file is not None:
if not os.path.exists("./data"):
os.makedirs("./data")
write_file = open("./data/" + write_file, 'w')
# Try to parallelize everything to make it at least more doable for the 20k case
num_cores = cpu_count() if cpu_count() < 16 else 16
print('* Add tags, unks and pads. (In parallel using {} threads)'.format(num_cores))
print('...running (probably)', end='')
pool = Pool(num_cores)
processed_lines = pool.starmap(processLines, [(line, line_len, known_words, word_id) for line in lines]) #TODO There has to be a way to track this shit, I tried with TQDM but it's been impossibl
print(' DONE!')
if write_file is not None:
for line in processed_lines:
line_str1 = ' '.join(str(x) for x in line)
line_str1 += '\n'
write_file.write(line_str1)
write_file.close()
lines_np = np.array(processed_lines)
return lines_np,word_id,id_word
def preprocess_eval_data(vocab, read_file, write_file="sentences.eval.preprocess", line_len=30):
# read lines
lines = []
read_file = open(read_file, 'r')
for line in read_file:
split_line = line[:-1].split(' ')
if len(split_line) <= line_len - 2:
lines += [split_line]
read_file.close()
processed_lines = []
if write_file is not None: # To be consistent with a single format, lets put the folder out
write_file = open(write_file, 'w')
for line in lines:
line = ['<bos>'] + line
line += ['<eos>']
line += ['<pad>']*(line_len-len(line))
# exchanges words with ids and replaces words that are not in vocab with the id of unk
for idx, word in enumerate(line):
if word not in vocab.keys():
line[idx] = vocab['<unk>']
else:
line[idx] = vocab[word]
processed_lines.append(list(line))
if write_file is not None:
line_str1 = ' '.join(str(x) for x in line)
line_str1 += '\n'
write_file.write(line_str1)
if write_file is not None:
write_file.close()
lines_np = np.array(processed_lines)
return lines_np
def load_continuation_data(continuation_path='./data/sentences.continuation', sentence_lenght=20):
word_id, id_word = load_vocab()
vocab = list(word_id.keys())
continuation = []
with open(continuation_path, "r") as continuation_sentences:
for sentence in continuation_sentences:
words = sentence.strip().split(" ")
if len(words) < sentence_lenght:
for idx, word in enumerate(words):
if word not in vocab:
words[idx] = word_id['<unk>']
else:
words[idx] = word_id[word]
continuation.append(words)
return np.array(continuation)
# read data from preprocessed file written by preprocess_data
def load_preprocessed_data(read_file="./data/sentences.preprocess"):
lines = []
read_file = open(read_file, 'r')
for line in read_file:
lines += [[int(word) for word in line[:-1].split(' ')]]
read_file.close()
return lines