Source code for gatelfpytorchjson.ngrammodule

from . embeddingsmodule import EmbeddingsModule
import torch
import sys
import logging
from . LayerCNN import LayerCNN

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
streamhandler = logging.StreamHandler(stream=sys.stderr)
formatter = logging.Formatter(
                '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
streamhandler.setFormatter(formatter)
logger.addHandler(streamhandler)



[docs]class NgramModule(torch.nn.Module): def __init__(self, embeddingsmodule, method="lstm"): """Create a module for processing ngram sequences for the given EmbeddingsModule embeddingsmodule. How eventually will be one of lstm, gru, conv, mean, sum. """ super().__init__() # since we directly assign, this should get registered! self.embeddingsmodule = embeddingsmodule self.emb_dims = self.embeddingsmodule.emb_dims if method == "lstm": self.forward_method = self.forward_method_lstm self.init_method = self.init_method_lstm elif method == "cnn": self.forward_method = self.forward_method_cnn self.init_method = self.init_method_cnn # now use the configured init method self.init_method()
[docs] def init_method_lstm(self): # TODO: maybe use heuristics to find better values for # hidden_size # num_layers # dropout # bidirectional num_layers = 1 bidirectional = True hidden_size = self.embeddingsmodule.emb_dims self.lstm = torch.nn.LSTM(input_size=self.embeddingsmodule.emb_dims, hidden_size=hidden_size, num_layers=num_layers, dropout=0.4, bidirectional=bidirectional, batch_first=True) # TODO: create a better lstm initialisation vector here for repeated # use doring forward, if needed! if bidirectional: num_directions = 2 else: num_directions = 1 self.out_dim = hidden_size * num_layers * num_directions logger.info("Created LSTM with out_dim {}".format(self.out_dim))
[docs] def init_method_cnn(self): self.cnn = LayerCNN(self.emb_dims) self.out_dim = self.cnn.dim_outputs
[docs] def forward_method_lstm(self, batchofsequences): batchsize = len(batchofsequences) # NOTE: we already expect batchofsequences to be a variable with batch_first zero-padded sequences! # now run the data through the embeddings, then run the sequences of embeddings through the lstm # Note: the embeddingsmodule.forward method expects the original batchofsequences, we do not need to convert # to a tensor and variable here! tmp1 = self.embeddingsmodule.forward(batchofsequences) out, (h0, c0) = self.lstm(tmp1) # TODO: for now we use zero vectors for initialization # we only need the final hidden state # logger.info("out is of shape {}, batchsize={}".format(out.size(), batchsize)) ret = out[:, -1, :] # logger.info("ret is of shape {}".format(ret.size())) ret = ret.view(batchsize, -1) return ret
[docs] def forward_method_cnn(self, batchofsequences): tmp1 = self.embeddingsmodule.forward(batchofsequences) out = self.cnn(tmp1) return out
[docs] def forward(self, batchofsequences): # just delegate to the forward method for the method chosen return self.forward_method(batchofsequences)