Files
Castor/utils/nce_neighbors.py
Victor Yang 51d8e29525 add NCE to MP-CNN (#84)
* update nce-sm

* refactor code, update torchtext

* use shared evaluation

* refactor code, use shared data loader

* refactor code

* refactor code

* refactor code according to Michael's great suggestions

* update readme and requirement

* update datasets and readme

* update data loader

* add space between +

* update refactor code

* add nce-mp

* remove duplicate files

* update readme, refactor code according to mp_cnn and delete duplicate code, follow PEP8 standard

* refactor code, add/delete comments

* import exit from sys
2018-01-03 18:12:57 -05:00

51 lines
1.8 KiB
Python

import random
import numpy as np
import heapq
import operator
import torch
from torchtext import data
# get the nearest negative samples to the positive sample by computing the feature difference
def get_nearest_neg_id(pos_feature, neg_dict, distance="cosine", k=1, weight=False):
dis_list = []
pos_feature = pos_feature.data.cpu().numpy()
pos_feature_norm = pos_feature / np.sqrt(sum(pos_feature ** 2))
neg_list = []
for key in neg_dict:
if distance == "l2":
dis = np.sqrt(np.sum((np.array(pos_feature) - neg_dict[key]["feature"]) ** 2))
elif distance == "cosine":
neg_feature = np.array(neg_dict[key]["feature"])
feat_norm = neg_feature / np.sqrt(sum(neg_feature ** 2))
dis = 1 - feat_norm.dot(pos_feature_norm)
dis_list.append(dis)
neg_list.append(key)
k = min(k, len(neg_dict))
min_list = heapq.nsmallest(k, enumerate(dis_list), key=operator.itemgetter(1))
# find the corresponding neg id
min_id_list = [neg_list[x[0]] for x in min_list]
if weight:
min_id_score = [1 - x[1] for x in min_list]
return min_id_list, min_id_score
else:
return min_id_list
# get the negative samples randomly
def get_random_neg_id(q2neg, qid_i, k=8):
# question 1734 in TrecQA has only one positive answer and no negative answer
if qid_i not in q2neg:
return []
k = min(k, len(q2neg[qid_i]))
ran = random.sample(q2neg[qid_i], k)
return ran
# pack the lists of question/answer/ext_feat into a torchtext batch
def get_batch(question, answer, ext_feat, size):
new_batch = data.Batch()
new_batch.batch_size = size
setattr(new_batch, "sentence_2", torch.stack(answer))
setattr(new_batch, "sentence_1", torch.stack(question))
setattr(new_batch, "ext_feats", torch.stack(ext_feat))
return new_batch