Skip to content
Permalink
Browse files

Add files via upload

  • Loading branch information...
hstm3105 committed Jun 8, 2018
1 parent 897d200 commit 536664ab95e27101b94e804e031d7bf04f20a0e1
Showing with 98 additions and 87 deletions.
  1. +28 −28 dmn_loader.py
  2. +11 −0 fetch_data.sh
  3. +21 −22 modelDMN.py
  4. +38 −37 train_test.py
@@ -7,15 +7,15 @@
from torch.utils.data.dataloader import default_collate

class adict(dict):
def __init__(self, *args, **kargs):
dict.__init__(self, *args, **kargs)
def __init__(self, *arg, **karg):
dict.__init__(self, *arg, **karg)
self.__dict__ = self

def pad_collate(batch):
max_len_ques = float('-inf')
max_sen_len_context = float('-inf')
max_len_context = float('-inf')

for item in batch:
contexts, ques, _ = item
if len(contexts) > max_len_context:
@@ -34,7 +34,7 @@ def pad_collate(batch):
context[i] = np.pad(sen, (0, max_sen_len_context-len(sen)), 'constant', constant_values=0)
question = np.pad(question, (0, max_len_ques-len(question)), 'constant', constant_values=0)
batch[idx] = (context, question, answer)

return default_collate(batch)

class BabiDataSet(Dataset):
@@ -44,36 +44,36 @@ def __init__(self, task_id, mode='train'):
train_data, test_data = get_train_test(task_id) # Get raw train_data and test_data from babi dataset
self.QA = adict()
self.QA.VOCAB = {'<PAD>': 0, '<EOS>':1}
self.QA.INV_VOCAB = {0:'<PAD>', 1:'<EOS>'}
self.QA.IVOCAB = {0:'<PAD>', 1:'<EOS>'}
self.train = self.get_processed_data(train_data)
self.val = [self.train[i][int(9*len(self.train[i])/10):] for i in range(3)] # splitting into 90/10 train/val dataset
self.valid = [self.train[i][-int(len(self.train[i])/10):] for i in range(3)] # splitting into 90/10 train/val dataset
self.train = [self.train[i][:int(9*len(self.train[i])/10)] for i in range(3)] # splitting into 90/10 train/val dataset
self.test = self.get_processed_data(test_data)

def set_mode(self, mode):
self.mode = mode #????
self.mode = mode

def __len__(self):
if self.mode == 'train':
return len(self.train[0])
elif self.mode == 'val':
return len(self.val[0])
elif self.mode == 'valid':
return len(self.valid[0])
elif self.mode == 'test':
return len(self.test[0])
else:
print ("Invalid Mode!")
return

def __getdata__(self, index):
if self.mode == 'train':
contexts, questions, answers = self.train
elif self.mode == 'val':
contexts, questions, answers = self.val
elif self.mode == 'valid':
contexts, questions, answers = self.valid
elif self.mode == 'test':
contexts, questions, answers = self.test

return contexts[index], questions[index], answers[index]

def get_processed_data(self, raw_data):
unindexed= get_unprocessed_data(raw_data)
questions=[]
@@ -91,7 +91,7 @@ def get_processed_data(self, raw_data):
for token in question:
self.build_vocab(token)
question= [self.QA.VOCAB[token] for token in question]

self.build_vocab(qa['A'].lower())
answer= self.QA.VOCAB[qa['A'].lower()]

@@ -102,24 +102,24 @@ def get_processed_data(self, raw_data):

def build_vocab(self, token):
if not token in self.QA.VOCAB:
next_index= len(self.QA.VOCAB)
self.QA.VOCAB[token]= next_index
self.QA.IVOCAB[next_index]= token
next_index= len(self.QA.VOCAB)
self.QA.VOCAB[token]= next_index
self.QA.IVOCAB[next_index]= token



def get_train_test(task_id):
paths = glob('data/en-10k/qa{}_*'.format(task_id))
for path in paths:
if 'train' in path;
if 'train' in path:
with open(path, 'r') as f:
train = f.read()
elif 'test' in path:
with open(path, 'r') as f:
test = f.read()

return train, test


def build_vocab(raw_data):
lowered= raw_data.lower()
@@ -165,8 +165,8 @@ def get_unprocessed_data(raw_data):


if __name__ == '__main__':
dataset_train= BabiDataset(20, mode='train') # Loading the dataset with task_id = 20
dataset_train= BabiDataSet(20, is_train= True) # Loading the dataset with task_id = 20
train_loader= DataLoader(dataset_train,batch_size=2, shuffle=True,collate_fn= pad_collate)
for batch_idx, data in enumerate(train_loader):
contexts, questions, answers= data
break
break
@@ -0,0 +1,11 @@
#!/bin/bash

url=http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz
fname=`basename $url`

curl -SLO $url
tar zxvf $fname
mkdir -p data
mv tasks_1-20_v1-2/* data/
rm -r tasks_1-20_v1-2
rm tasks_1-20_v1-2.tar.gz
@@ -3,8 +3,8 @@
import torch.nn as nn
import torch.nn.init as init
import torch.nn.functional as F
import torch.autograd as Variable
import torch.utils.data as DataLoader
from torch.autograd import Variable
from torch.utils.data import DataLoader

class QuestionModule(nn.Module):
def __init__(self, vocab_size, hidden_size):
@@ -35,7 +35,7 @@ def __init__(self, vocab_size, hidden_size):
init.xavier_normal(param)
self.dropout = nn.Dropout(0.1)

''' We will now define the encoding scheme which is positional encoding in the paper " Dynamic Memory Network for Textual and Visual
''' We will now define the encoding scheme which is positional encoding in the paper " Dynamic Memory Network for Textual and Visual
Question Answering '''
def positional_encoder(embedded_sentence):
# embedded_sentence.size() = (batch_size, num_sentences, num_tokens, embedding_length)
@@ -51,7 +51,7 @@ def positional_encoder(embedded_sentence):
for d in range(embedding_length):
x.append((1 - (j/(num_tokens-1))) - (d/(embedding_length-1)) * (1 - 2*j/(num_tokens-1)))
l.append(x)

l = torch.FloatTensor(l)
l = l.unsqueeze(0) # adding an extra dimension at first place for batch_size
l = l.unsqueeze(1) # adding an extra dimension at sencond place for num_sentences
@@ -126,7 +126,7 @@ def forward(self, facts, G):
for sen in range(facts.size()[1]):
fact = facts[:, sen, :]
g = G[:, sen]
if sen == 0: # Initialization for first sentence only
if sen == 0: # Initialization for first sentence only
hi_1 = h_0.unsqueeze(0).expand_as(fact)
hi_1 = self.AttnGRUCell(fact, hi_1, g)
C = hi_1 # Final hidden vector as the contextual vector used for updating memory
@@ -189,29 +189,29 @@ def __init__(self, vocab_size, hidden_size):
def forward(self, final_mem, questions):
final_mem = self.dropout(final_mem)
concat = torch.cat([final_mem, questions], dim=2).squeeze(1)
out = self.W(concat) # As per the paper, we are concatenating the final memory state m_T, and the question q and passing
out = self.W(concat) # As per the paper, we are concatenating the final memory state m_T, and the question q and passing
# this resultant vector to a linear layer

return out


''' We define the model for the network incorporating the input, question, answer and the episodic memory module. We use the Cross Entropy loss criterion for measuring loss'''
''' We define the model for the network incorporating the input, question, answer and the episodic memory module. We use the Cross Entropy loss criterion for measuring loss'''
class DMN(nn.Module):
def __init__(self, hidden_size, vocab_size, num_pass=3, qa=None):
super(DMN,self).__init__()
self.num_pass= num_pass
self.qa= qa
self.word_embedding= nn.Embedding(vocab_size, hidden_size, padding_index=0, sparse=True)
self.word_embedding= nn.Embedding(vocab_size, hidden_size, padding_idx=0, sparse=True)
init.uniform(self.word_embedding.state_dict()['weight'], a= -(3**0.5), b=3**0.5)
self.criterion= nn.CrossEntropyLoss(size_average=False)
self.input_module= input_module(vocab_size,hidden_size) ##Vocab size refers to the size of vocabulary used
self.question_module= question_module(vocab_size, hidden_size)
self.memory= episodic_memory(hidden_size)
self.answer_module= answer_module(vocab_size,hidden_size)

self.input_module= InputModule(vocab_size,hidden_size) ##Vocab size refers to the size of vocabulary used
self.question_module= QuestionModule(vocab_size, hidden_size)
self.memory= MemoryModule(hidden_size)
self.answer_module= AnswerModule(vocab_size,hidden_size)

def forward(self, context, questions):
#facts.size()= (batch_size, num_sentences, embedding_length= hidden.size())
#facts.size()= (batch_size, num_sentences, embedding_length= hidden.size())
#questions.size() = (batch_size, 1, embedding_length)
facts= self.input_module(context, self.word_embedding)
questions= self.question_module(questions, self.word_embedding)
@@ -220,9 +220,9 @@ def forward(self, context, questions):
X= self.memory(facts, questions, X)
pred= self.answer_module(X, questions)
return pred_id

'''Total loss to be calculated '''

def loss(self,context, questions, targets):
output= self.forward(context, questions)
loss= self.criterion(output, targets)
@@ -232,22 +232,21 @@ def loss(self,context, questions, targets):
pred= F.softmax(output)
_, pred_id= torch.max(pred, dim=1)
correct= (pred_id.data == answers.data)
acc= torch.mean(correct.float())
acc= torch.mean(correct.float())
return loss+para_loss, acc

def interpret_indexed_tensor(self,var):
if len(var.size()) == 3:
for n, sentences in enumerate(var):
s= ' '.join([self.qa.IVOCAB[elem.data[0]] for elem in sentence])
print (str(n)+'th batch, '+str(i)+'th sentence, '+str(s))

elif len(var.size()) == 2:
for n, sentence in enumerate(var):
s= ' '.join([self.qa.IVOCAB[elem.data[0]] for elem in sentence])
print (str(n)+'th batch, '+str(s))

elif len(var.size()) == 1:
for n, token in enumerate(var):
s= self.qa.IVOCAB[token.data[0]]
print (str(n)+'th of batch, '+str(s))

0 comments on commit 536664a

Please sign in to comment.
You can’t perform that action at this time.