-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmeta_data_prep.py
More file actions
284 lines (267 loc) · 13 KB
/
Copy pathmeta_data_prep.py
File metadata and controls
284 lines (267 loc) · 13 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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
import os
import random
import pathlib
import logging
import datetime
import argparse
import sys
import simplejson as json
import pandas as pd
import sentencepiece as spm
import pickle
from collections import namedtuple
# logging.basicConfig(format='%(levelname)s: %(message)s',
# level=logging.DEBUG)
MetaData = namedtuple('MetaData',['support','query'])
SEED = 7
def init_logger(log_path, name="meta-data-prep"):
root = logging.getLogger()
root.setLevel(logging.DEBUG)
logfile = os.path.join(log_path, "%s-%s.log" % (name, datetime.datetime.today()))
fileHandler = logging.FileHandler(logfile)
fileHandler.setLevel(logging.INFO)
root.addHandler(fileHandler)
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)
root.addHandler(consoleHandler)
logging.debug("Logging to %s" % logfile)
def sents_reader(file):
f = open(file, encoding='utf8')
lines = f.readlines()
f.close()
return [i.strip() for i in lines]
def read_para_data(domain, seen_status, data_dir):
path_prefix = os.path.join(data_dir, domain, 'split', 'clean_tok', domain + '.de-en.')
source_lang = sents_reader(path_prefix + 'en')
target_lang = sents_reader(path_prefix + 'de')
score_df = None
if seen_status == 'seen':
score_df = pd.read_csv(os.path.join(data_dir, domain, 'split', 'clean_tok', 'grading_info.csv'))
assert len(score_df) == len(source_lang)
assert len(source_lang) == len(target_lang) # check data integrity
para_data = list(zip(source_lang, target_lang))
return para_data, score_df
def build_corpus_info(para_data, score_df):
src_tokens = []
tgt_tokens = []
for idx, para_sent in enumerate(para_data):
en_sent, de_sent = para_sent
src_tokens.append(len(en_sent.split()))
tgt_tokens.append(len(de_sent.split()))
if score_df is not None: # exclude unseen cases
assert len(src_tokens) == len(score_df['diff_score'])
diff_score = score_df['diff_score']
domain_info_df = pd.DataFrame({
'src_tokens': src_tokens,
'tgt_tokens': tgt_tokens,
'diff_score': diff_score
}, index=list(range(0, len(para_data))))
else:
domain_info_df = pd.DataFrame({
'src_tokens': src_tokens,
'tgt_tokens': tgt_tokens,
}, index=list(range(0, len(para_data))))
return domain_info_df
def split_task_by_tokens(info_df, sample_tokens, used_index=[]):
shuffle_df = info_df.sample(frac=1, random_state=SEED)
cur_tokens = 0
sampled_index = []
for idx, row in shuffle_df.iterrows():
if cur_tokens >= sample_tokens:
break
if idx not in used_index:
sampled_index.append(idx)
cur_tokens += row['src_tokens']
# logging tokens
logging.info('sampled_len: {}, sampled_toknes: {}, target_tokens: {}'.format(
len(sampled_index), cur_tokens, sample_tokens
))
return sampled_index
def split_dev_data(all_indices, used_indices):
remain_indices = list(set(all_indices).difference(used_indices))
logging.info('[Remaining Sentences] All: {} | Meta-Used: {} | Dev: {}'.format(
len(all_indices),
len(used_indices),
len(remain_indices),
))
return remain_indices
def dump_dict_to_file(name_emb, emb_filename):
json.dump(name_emb, open(os.path.join(emb_filename, 'meta_split_info.json'), "w"))
pickle.dump(name_emb, open(os.path.join(emb_filename, 'meta_split_info.pkl'), "wb"))
def write_sents(para_list, meta_split_dir, set_type, source_lang='en', target_lang='de', scores=None):
src_writer = open(os.path.join(meta_split_dir, set_type + '.' + source_lang), 'w', encoding='utf8')
tgt_writer = open(os.path.join(meta_split_dir, set_type + '.' + target_lang), 'w', encoding='utf8')
score_writer = open(os.path.join(meta_split_dir, set_type + '.' + 'score'), 'w', encoding='utf8')
if scores is not None:
assert len(scores) == len(para_list)
for idx, para_tuple in enumerate(para_list):
src_sent, tgt_sent = para_tuple
src_writer.write(src_sent + '\n')
tgt_writer.write(tgt_sent + '\n')
if scores is not None:
score_writer.write(str(scores[idx]) + '\n')
def write_dev_data(para_data, domain_sample_info, split_dir, split_type, spm_model, is_spm=False):
dev_sents = [para_data[i] for i in domain_sample_info['meta-dev']]
meta_split_dir = os.path.join(split_dir, split_type)
pathlib.Path(meta_split_dir).mkdir(parents=True, exist_ok=True)
write_sents(dev_sents, meta_split_dir, 'dev', 'en', 'de')
if is_spm:
spm_dir = meta_split_dir + '-spm'
pathlib.Path(spm_dir).mkdir(parents=True, exist_ok=True)
sp = spm.SentencePieceProcessor()
sp.Load(spm_model)
spm_dev = []
for _, para_tuple in enumerate(dev_sents):
en, de = para_tuple
en_spm = ' '.join(sp.EncodeAsPieces(en))
de_spm = ' '.join(sp.EncodeAsPieces(de))
spm_dev.append((en_spm, de_spm))
write_sents(spm_dev, spm_dir, 'dev', 'en', 'de')
def write_split_data(para_data, domain_sample_info, split_dir, split_type, spm_model, is_spm=False):
if split_type not in ['meta-train', 'meta-test', 'meta-dev']:
raise 'Not supported meta split type'
meta_split_dir = os.path.join(split_dir, split_type)
pathlib.Path(meta_split_dir).mkdir(parents=True, exist_ok=True)
split_indices = domain_sample_info[split_type]
support_sents = [para_data[i] for i in split_indices.support]
query_sents = [para_data[i] for i in split_indices.query]
if domain_sample_info['status'] == 'seen':
scores = domain_sample_info[split_type + '-score']
write_sents(support_sents, meta_split_dir, 'support', 'en', 'de', scores=scores.support)
write_sents(query_sents, meta_split_dir, 'query', 'en', 'de', scores=scores.query)
else:
write_sents(support_sents, meta_split_dir, 'support', 'en', 'de')
write_sents(query_sents, meta_split_dir, 'query', 'en', 'de')
if is_spm:
spm_dir = meta_split_dir + '-spm'
pathlib.Path(spm_dir).mkdir(parents=True, exist_ok=True)
sp = spm.SentencePieceProcessor()
sp.Load(spm_model)
spm_support = []
spm_query = []
for _, para_tuple in enumerate(support_sents):
en, de = para_tuple
en_spm = ' '.join(sp.EncodeAsPieces(en))
de_spm = ' '.join(sp.EncodeAsPieces(de))
spm_support.append((en_spm, de_spm))
for _, para_tuple in enumerate(query_sents):
en, de = para_tuple
en_spm = ' '.join(sp.EncodeAsPieces(en))
de_spm = ' '.join(sp.EncodeAsPieces(de))
spm_query.append((en_spm, de_spm))
if domain_sample_info['status'] == 'seen':
scores = domain_sample_info[split_type + '-score']
write_sents(spm_support, spm_dir, 'support', 'en', 'de', scores=scores.support)
write_sents(spm_query, spm_dir, 'query', 'en', 'de', scores=scores.query)
else:
write_sents(spm_support, spm_dir, 'support', 'en', 'de')
write_sents(spm_query, spm_dir, 'query', 'en', 'de')
# Split the domain data into D_meta-train & D_meta-test
def meta_dataset_split(meta_train_task_N, meta_test_task_N, domains, support_tokens, query_tokens, split_dir, spm_model, data_dir):
domain_type = []
for key in domains.keys():
domain_type += [(i,key) for i in domains[key]]
for domain,seen_status in domain_type:
used_data_indices = []
logging.info("[Domain]:" + domain + "| [Type] " + seen_status + "| Start creating split...")
split_dir = os.path.join(split_dir, domain, 'meta_split')
domain_sample_info = {
'status': seen_status,
'support': str(support_tokens),
'query': str(query_tokens),
'meta-train-task': meta_train_task_N,
'meta-train': None,
'meta-train-score': None,
'meta-test-task': meta_test_task_N,
'meta-test': None,
'meta-test-score': None,
'meta-dev': None
}
para_data, score_df = read_para_data(domain, seen_status, data_dir)
domain_info_df = build_corpus_info(para_data, score_df)
# Must keep same for meta-test dataset
logging.info("[Meta Test Support]")
mtest_support = split_task_by_tokens(domain_info_df, meta_test_task_N * support_tokens)
logging.info("[Meta Test Query]")
used_data_indices += mtest_support
mtest_query = split_task_by_tokens(
info_df=domain_info_df,
sample_tokens=meta_test_task_N * query_tokens,
used_index=used_data_indices
)
used_data_indices += mtest_query
domain_sample_info['meta-test'] = MetaData(support=mtest_support, query=mtest_query)
# Rest ~ Meta-Train
if seen_status == 'seen': # Only seen domains need D_meta-train
domain_sample_info['meta-test-score'] = MetaData(
support=[domain_info_df.loc[i].diff_score for i in mtest_support],
query=[domain_info_df.loc[i].diff_score for i in mtest_query]
)
logging.info("[Meta Train Support]")
mtrain_support = split_task_by_tokens(
info_df=domain_info_df,
sample_tokens=meta_train_task_N * support_tokens,
used_index=used_data_indices
)
used_data_indices += mtrain_support
logging.info("[Meta Train Query]")
mtrain_query = split_task_by_tokens(
info_df=domain_info_df,
sample_tokens=meta_train_task_N * query_tokens,
used_index=used_data_indices
)
used_data_indices += mtrain_query
domain_sample_info['meta-train'] = MetaData(support=mtrain_support, query=mtrain_query)
domain_sample_info['meta-train-score'] = MetaData(
support=[domain_info_df.loc[i].diff_score for i in mtrain_support],
query=[domain_info_df.loc[i].diff_score for i in mtrain_query]
)
write_split_data(para_data, domain_sample_info, split_dir, 'meta-train', spm_model,is_spm=True)
# Save sampling info
logging.info("Check unused data for meta-dev")
mdev = split_dev_data(all_indices=list(range(0, len(para_data))), used_indices=used_data_indices)
domain_sample_info['meta-dev'] = mdev
logging.info("Save domain info csv & dataset info json")
pathlib.Path(split_dir).mkdir(parents=True, exist_ok=True)
domain_info_df.to_csv(os.path.join(split_dir, 'domain_info_all.csv'))
dump_dict_to_file(domain_sample_info, split_dir)
# Write sampled tok file & SPM file
logging.info("Write static files to {}".format(split_dir))
write_split_data(para_data, domain_sample_info, split_dir, 'meta-test', spm_model, is_spm=True)
write_dev_data(para_data, domain_sample_info, split_dir, 'meta-dev', spm_model, is_spm=True)
logging.info("========Done Current Domain========")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Adaptation distance scoring.')
parser.add_argument('--data-path', help='domain corpus', required=True)
parser.add_argument('--split-dir', help='path to save meta data split', required=True)
parser.add_argument('--spm-model', help='sentencepiece model path', required=True)
parser.add_argument('--k-support', metavar='N', type=int, help='support set tokens (K)', required=True)
parser.add_argument('--k-query', metavar='N', type=int, help='query set tokens (K)', required=True)
parser.add_argument('--meta_train_task', metavar='N', type=int, help='number of meta-train tasks', required=True)
parser.add_argument('--meta_test_task', metavar='N', type=int, help='number of meta-test tasks', required=True)
parser.add_argument('--unseen-domains', nargs="+", default=["bible"], help='unseen domains',required=True)
parser.add_argument('--seen-domains', nargs="+", default=["emea"], help='unseen domains',required=True)
args = parser.parse_args()
DATA_DIR = args.data_path
SPLIT_DIR = args.split_dir
SPM_MODEL_PATH = args.spm_model
init_logger(SPLIT_DIR)
domains = {
'unseen': args.unseen_domains,
'seen': args.seen_domains
}
k_support = args.k_support
k_query = args.k_query
meta_train_task_N = args.meta_train_task
meta_test_task_N = args.meta_test_task
logging.info("[Domains]: {}".format(domains['unseen'] + domains['seen']))
logging.info("[Toknes]: support-{}k, query-{}k".format(k_support, k_query))
meta_dataset_split(meta_train_task_N=meta_train_task_N,
meta_test_task_N=meta_test_task_N,
domains=domains,
support_tokens=k_support * 1000,
query_tokens=k_query * 1000,
split_dir=SPLIT_DIR,
spm_model=SPM_MODEL_PATH,
data_dir=DATA_DIR
)