mirror of
https://github.com/wassname/Castor.git
synced 2026-09-25 13:10:11 +08:00
187 lines
6.2 KiB
Python
187 lines
6.2 KiB
Python
import sys
|
|
import re
|
|
import os
|
|
import numpy as np
|
|
|
|
import argparse
|
|
|
|
#from nltk.corpus import stopwords
|
|
from nltk.stem.porter import *
|
|
from collections import defaultdict
|
|
|
|
def load_data(dname):
|
|
stemmer = PorterStemmer()
|
|
qids, questions, answers, labels = [], [], [], []
|
|
print dname
|
|
with open(dname+'a.toks') as f:
|
|
for line in f:
|
|
line = unicode(line, errors='ignore')
|
|
question = line.strip().split()
|
|
question = [stemmer.stem(word) for word in question]
|
|
questions.append(question)
|
|
with open(dname+'b.toks') as f:
|
|
for line in f:
|
|
line = unicode(line, errors='ignore')
|
|
answer = line.decode('utf-8').strip().split()
|
|
answer = [stemmer.stem(word) for word in answer]
|
|
answers.append(answer)
|
|
with open(dname+'id.txt') as f:
|
|
for line in f:
|
|
qids.append(line.strip())
|
|
with open(dname+'sim.txt') as f:
|
|
for line in f:
|
|
labels.append(int(line.strip()))
|
|
return qids, questions, answers, labels
|
|
|
|
def compute_overlap_features(questions, answers, word2df=None, stoplist=None):
|
|
word2df = word2df if word2df else {}
|
|
stoplist = stoplist if stoplist else set()
|
|
feats_overlap = []
|
|
for question, answer in zip(questions, answers):
|
|
# q_set = set(question)
|
|
# a_set = set(answer)
|
|
q_set = set([q for q in question if q not in stoplist])
|
|
a_set = set([a for a in answer if a not in stoplist])
|
|
word_overlap = q_set.intersection(a_set)
|
|
# overlap = float(len(word_overlap)) / (len(q_set) * len(a_set) + 1e-8)
|
|
if len(q_set) == 0 and len(a_set) == 0:
|
|
overlap = 0
|
|
else:
|
|
overlap = float(len(word_overlap)) / (len(q_set) + len(a_set))
|
|
|
|
# q_set = set([q for q in question if q not in stoplist])
|
|
# a_set = set([a for a in answer if a not in stoplist])
|
|
word_overlap = q_set.intersection(a_set)
|
|
df_overlap = 0.0
|
|
for w in word_overlap:
|
|
df_overlap += word2df[w]
|
|
if len(q_set) == 0 and len(a_set) == 0:
|
|
df_overlap = 0
|
|
else:
|
|
df_overlap /= (len(q_set) + len(a_set))
|
|
|
|
feats_overlap.append(np.array([
|
|
overlap,
|
|
df_overlap,
|
|
]))
|
|
return np.array(feats_overlap)
|
|
|
|
def compute_overlap_idx(questions, answers, stoplist, q_max_sent_length, a_max_sent_length):
|
|
stoplist = stoplist if stoplist else []
|
|
feats_overlap = []
|
|
q_indices, a_indices = [], []
|
|
for question, answer in zip(questions, answers):
|
|
q_set = set([q for q in question if q not in stoplist])
|
|
a_set = set([a for a in answer if a not in stoplist])
|
|
word_overlap = q_set.intersection(a_set)
|
|
|
|
q_idx = np.ones(q_max_sent_length) * 2
|
|
for i, q in enumerate(question):
|
|
value = 0
|
|
if q in word_overlap:
|
|
value = 1
|
|
q_idx[i] = value
|
|
q_indices.append(q_idx)
|
|
|
|
#### ERROR
|
|
# a_idx = np.ones(a_max_sent_length) * 2
|
|
# for i, q in enumerate(question):
|
|
# value = 0
|
|
# if q in word_overlap:
|
|
|
|
a_idx = np.ones(a_max_sent_length) * 2
|
|
for i, a in enumerate(answer):
|
|
value = 0
|
|
if a in word_overlap:
|
|
value = 1
|
|
a_idx[i] = value
|
|
a_indices.append(a_idx)
|
|
|
|
q_indices = np.vstack(q_indices).astype('int32')
|
|
a_indices = np.vstack(a_indices).astype('int32')
|
|
|
|
return q_indices, a_indices
|
|
|
|
def compute_dfs(docs):
|
|
word2df = defaultdict(float)
|
|
for doc in docs:
|
|
for w in set(doc):
|
|
word2df[w] += 1.0
|
|
num_docs = len(docs)
|
|
for w, value in word2df.iteritems():
|
|
word2df[w] /= np.math.log(num_docs / value)
|
|
return word2df
|
|
|
|
if __name__ == '__main__':
|
|
ap = argparse.ArgumentParser(description="compute overlap features for SM model")
|
|
ap.add_argument("dataset", help="path/to/dataset-directory", default="../../data/TrecQA")
|
|
args = ap.parse_args()
|
|
|
|
stoplist = set([line.strip() for line in open('stopwords.txt')])
|
|
import string
|
|
punct = set(string.punctuation)
|
|
stoplist.update(punct)
|
|
#stoplist = None
|
|
|
|
all_questions, all_answers, all_qids = [], [], []
|
|
base_dir = args.dataset
|
|
# base_dir = '../../data/' + sys.argv[1] + '/'
|
|
# sub_dirs = ['train/', 'raw-dev/', 'test.minimal/','test.complete/']
|
|
# sub_dirs = ['train-all/', 'raw-dev/', 'raw-test/']
|
|
sub_dirs = ['train/', 'clean-dev/', 'clean-test/']
|
|
for sub in sub_dirs:
|
|
qids, questions, answers, labels = load_data(base_dir+sub)
|
|
all_questions.extend(questions)
|
|
all_answers.extend(answers)
|
|
all_qids.extend(qids)
|
|
|
|
seen = set()
|
|
unique_questions = []
|
|
for q, qid in zip(all_questions, all_qids):
|
|
if qid not in seen:
|
|
seen.add(qid)
|
|
unique_questions.append(q)
|
|
|
|
docs = all_answers + unique_questions
|
|
word2dfs = compute_dfs(docs)
|
|
print word2dfs.items()[:10]
|
|
|
|
q_max_sent_length = max(map(lambda x: len(x), all_questions))
|
|
a_max_sent_length = max(map(lambda x: len(x), all_answers))
|
|
print 'q_max_sent_length', q_max_sent_length
|
|
print 'a_max_sent_length', a_max_sent_length
|
|
|
|
for sub in sub_dirs:
|
|
print sub
|
|
qids, questions, answers, labels = load_data(base_dir+sub)
|
|
|
|
overlap_feats = compute_overlap_features(questions, answers, stoplist=None, word2df=word2dfs)
|
|
overlap_feats_stoplist = compute_overlap_features(questions, answers, stoplist=stoplist, word2df=word2dfs)
|
|
overlap_feats = np.hstack([overlap_feats, overlap_feats_stoplist])
|
|
print overlap_feats[:3]
|
|
print 'overlap_feats', overlap_feats.shape
|
|
|
|
from sklearn.preprocessing import StandardScaler
|
|
scaler = StandardScaler()
|
|
print "Scaling overlap features"
|
|
overlap_feats = scaler.fit_transform(overlap_feats)
|
|
print overlap_feats[:3]
|
|
|
|
'''q_overlap_indices, a_overlap_indices = compute_overlap_idx(questions, answers, stoplist, q_max_sent_length, a_max_sent_length)
|
|
print q_overlap_indices[:3], a_overlap_indices[:3]
|
|
print 'q_overlap_indices', q_overlap_indices.shape
|
|
print 'a_overlap_indices', a_overlap_indices.shape'''
|
|
|
|
with open(base_dir+sub+'overlap_feats.txt', 'w') as f:
|
|
for i in range(overlap_feats.shape[0]):
|
|
for j in range(4):
|
|
f.write(str(overlap_feats[i][j]) + ' ')
|
|
f.write('\n')
|
|
'''with open(base_dir+sub+'overlap_indices.txt', 'w') as f:
|
|
for i in range(q_overlap_indices.shape[0]):
|
|
for j in range(q_max_sent_length):
|
|
f.write(str(q_overlap_indices[i][j]) + ' ')
|
|
for j in range(a_max_sent_length):
|
|
f.write(str(a_overlap_indices[i][j]) + ' ')
|
|
f.write('\n')'''
|