aboutsummaryrefslogtreecommitdiffstats
path: root/sentence_emb_retrieval.py
diff options
context:
space:
mode:
authorYigit Sever2019-09-19 00:22:25 +0300
committerYigit Sever2019-09-19 00:22:25 +0300
commit1890976ed1eee59eda92ceabdcb1c966d6707269 (patch)
treef7bb7de36d158ee970aaf4f0f5a6b682ac359825 /sentence_emb_retrieval.py
parent68b6c55d0e3217362d6e17ea8458dfa7e5242e17 (diff)
downloadEvaluating-Dictionary-Alignment-1890976ed1eee59eda92ceabdcb1c966d6707269.tar.gz
Evaluating-Dictionary-Alignment-1890976ed1eee59eda92ceabdcb1c966d6707269.tar.bz2
Evaluating-Dictionary-Alignment-1890976ed1eee59eda92ceabdcb1c966d6707269.zip
Add experiment scripts
Diffstat (limited to 'sentence_emb_retrieval.py')
-rw-r--r--sentence_emb_retrieval.py151
1 files changed, 151 insertions, 0 deletions
diff --git a/sentence_emb_retrieval.py b/sentence_emb_retrieval.py
new file mode 100644
index 0000000..63ebcdc
--- /dev/null
+++ b/sentence_emb_retrieval.py
@@ -0,0 +1,151 @@
1import argparse
2
3parser = argparse.ArgumentParser(description='Run Retrieval using Sentence Embedding + Cosine')
4parser.add_argument('source_lang', help='source language short name')
5parser.add_argument('target_lang', help='target language short name')
6parser.add_argument('source_vector', help='path of the source vector')
7parser.add_argument('target_vector', help='path of the target vector')
8parser.add_argument('source_defs', help='path of the source definitions')
9parser.add_argument('target_defs', help='path of the target definitions')
10parser.add_argument('-n', '--instances', help='number of instances in each language to retrieve', default=1000, type=int)
11args = parser.parse_args()
12
13source_lang = args.source_lang
14target_lang = args.target_lang
15
16def load_embeddings(path, dimension = 300):
17 """
18 Loads the embeddings from a word2vec formatted file.
19 The first line may or may not include the word count and dimension
20 """
21 vectors = {}
22 with open(path, mode='r', encoding='utf8') as fp:
23 first_line = fp.readline().rstrip('\n')
24 if first_line.count(' ') == 1: # includes the "word_count dimension" information
25 (word_count, dimension) = map(int, first_line.split())
26 else: # assume the file only contains vectors
27 fp.seek(0)
28 for line in fp:
29 elems = line.split()
30 vectors[" ".join(elems[:-dimension])] = " ".join(elems[-dimension:])
31 return vectors
32
33lang_source = args.source_lang
34lang_target = args.target_lang
35
36vectors_filename_source = args.source_vector
37vectors_filename_target = args.target_vector
38
39vectors_source = load_embeddings(vectors_filename_source)
40vectors_target = load_embeddings(vectors_filename_target)
41
42defs_filename_source = args.source_defs
43defs_filename_target = args.target_defs
44defs_source = [line.rstrip('\n') for line in open(defs_filename_source, encoding='utf8')]
45defs_target = [line.rstrip('\n') for line in open(defs_filename_target, encoding='utf8')]
46
47print('Read {} {} documents and {} {} documents'.format(len(defs_source), lang_source, len(defs_target), lang_target))
48
49import numpy as np
50from mosestokenizer import *
51
52def clean_corpus_using_embeddings_vocabulary(
53 embeddings_dictionary,
54 corpus,
55 vectors,
56 language,
57 ):
58 '''
59 Cleans corpus using the dictionary of embeddings.
60 Any word without an associated embedding in the dictionary is ignored.
61 Adds '__target-language' and '__source-language' at the end of the words according to their language.
62 '''
63 clean_corpus, clean_vectors, keys = [], {}, []
64 words_we_want = set(embeddings_dictionary)
65 tokenize = MosesTokenizer(language)
66 for key, doc in enumerate(corpus):
67 clean_doc = []
68 words = tokenize(doc)
69 for word in words:
70 if word in words_we_want:
71 clean_doc.append(word + '__%s' % language)
72 clean_vectors[word + '__%s' % language] = np.array(vectors[word].split()).astype(np.float)
73 if len(clean_doc) > 3 and len(clean_doc) < 25:
74 keys.append(key)
75 clean_corpus.append(' '.join(clean_doc))
76 tokenize.close()
77 return np.array(clean_corpus), clean_vectors, keys
78
79clean_corpus_source, clean_vectors_source, keys_source = clean_corpus_using_embeddings_vocabulary(
80 set(vectors_source.keys()),
81 defs_source,
82 vectors_source,
83 lang_source,
84 )
85
86clean_corpus_target, clean_vectors_target, keys_target = clean_corpus_using_embeddings_vocabulary(
87 set(vectors_target.keys()),
88 defs_target,
89 vectors_target,
90 lang_target,
91 )
92
93import random
94take = args.instances
95
96common_keys = set(keys_source).intersection(set(keys_target)) # definitions that fit the above requirements
97take = min(len(common_keys), take) # you can't sample more than length
98experiment_keys = random.sample(common_keys, take)
99
100instances = len(experiment_keys)
101
102clean_corpus_source = list(clean_corpus_source[experiment_keys])
103clean_corpus_target = list(clean_corpus_target[experiment_keys])
104print(f'{source_lang} - {target_lang} : document sizes: {len(clean_corpus_source)}, {len(clean_corpus_target)}')
105
106del vectors_source, vectors_target, defs_source, defs_target
107
108from sklearn.feature_extraction.text import CountVectorizer
109from sklearn.feature_extraction.text import TfidfVectorizer
110
111vocab_counter = CountVectorizer().fit(clean_corpus_source + clean_corpus_target)
112common = [w for w in vocab_counter.get_feature_names() if w in clean_vectors_source or w in clean_vectors_target]
113
114W_common = []
115for w in common:
116 if w in clean_vectors_source:
117 W_common.append(np.array(clean_vectors_source[w]))
118 else:
119 W_common.append(np.array(clean_vectors_target[w]))
120
121print('The vocabulary size is %d' % (len(W_common)))
122
123from sklearn.preprocessing import normalize
124W_common = np.array(W_common)
125W_common = normalize(W_common) # default is l2
126
127vect_tfidf = TfidfVectorizer(vocabulary=common, dtype=np.double, norm='l2')
128vect_tfidf.fit(clean_corpus_source + clean_corpus_target)
129X_idf_source = vect_tfidf.transform(clean_corpus_source)
130X_idf_target = vect_tfidf.transform(clean_corpus_target)
131
132print(f'Matrices are {X_idf_source.shape} and {W_common.shape}')
133print(f'The dimensions are {X_idf_source.ndim} and {W_common.ndim}')
134
135X_idf_source_array = X_idf_source.toarray()
136X_idf_target_array = X_idf_target.toarray()
137S_emb_source = np.matmul(X_idf_source_array, W_common)
138S_emb_target = np.matmul(X_idf_target_array, W_common)
139
140S_emb_target_transpose = np.transpose(S_emb_target)
141
142cost_matrix = np.matmul(S_emb_source, S_emb_target_transpose)
143
144hit_at_one = len([x for x,y in enumerate(cost_matrix.argmax(axis=1)) if x == y])
145
146import csv
147percentage = hit_at_one / instances * 100
148fields = [f'{source_lang}', f'{target_lang}', f'{instances}', f'{hit_at_one}', f'{percentage}']
149with open('/home/syigit/multilang_results/sentence_emb_retrieval_axis_1.csv', 'a') as f:
150 writer = csv.writer(f)
151 writer.writerow(fields)