def __init__(self, config): super(AspectSent, self).__init__() self.config = config self.cat_layer = SimpleCat(config) self.lstm = MLSTM(config) self.feat2tri = nn.Linear(config.l_hidden_size, 2) self.inter_crf = LinearCRF(config) self.feat2label = nn.Linear(config.l_hidden_size, 3) self.cri = nn.CrossEntropyLoss() self.cat_layer.load_vector() if not config.if_update_embed: self.cat_layer.word_embed.weight.requires_grad = False
def __init__(self, config): ''' Elmo+LSTM+Aspect ''' super(AspectSent, self).__init__() self.config = config #self.cat_layer = SimpleCat(config) self.lstm = MLSTM(config) self.feat2tri = nn.Linear(config.l_hidden_size, 2) self.inter_crf = LinearCRF(config) self.feat2label = nn.Linear(config.l_hidden_size, 3) self.cri = nn.CrossEntropyLoss()
class AspectSent(nn.Module): def __init__(self, config): super(AspectSent, self).__init__() self.config = config self.cat_layer = SimpleCat(config) self.lstm = MLSTM(config) self.feat2tri = nn.Linear(config.l_hidden_size, 2) self.inter_crf = LinearCRF(config) self.feat2label = nn.Linear(config.l_hidden_size, 3) self.cri = nn.CrossEntropyLoss() self.cat_layer.load_vector() if not config.if_update_embed: self.cat_layer.word_embed.weight.requires_grad = False def compute_scores(self, sent, mask): if self.config.if_reset: self.cat_layer.reset_binary() # self.inter_crf.reset_transition() sent = torch.LongTensor(sent) mask = torch.LongTensor(mask) sent_vec = self.cat_layer(sent, mask) context = self.lstm(sent_vec) # feat_context = torch.cat([context, asp_v], 1) # sent_len * dim_sum feat_context = context # sent_len * dim_sum tri_scores = self.feat2tri(feat_context) marginals = self.inter_crf(tri_scores) select_polarity = marginals[:,1] marginals = marginals.transpose(0,1) # 2 * sent_len sent_v = torch.mm(select_polarity.unsqueeze(0), context) # 1 * feat_dim label_scores = self.feat2label(sent_v).squeeze(0) return label_scores, select_polarity, marginals def compute_predict_scores(self, sent, mask): if self.config.if_reset: self.cat_layer.reset_binary() # self.inter_crf.reset_transition() sent = torch.LongTensor(sent) mask = torch.LongTensor(mask) sent_vec = self.cat_layer(sent, mask) context = self.lstm(sent_vec) # feat_context = torch.cat([context, asp_v], 1) # sent_len * dim_sum feat_context = context # sent_len * dim_sum tri_scores = self.feat2tri(feat_context) marginals = self.inter_crf(tri_scores) select_polarity = marginals[:,1] best_seqs = self.inter_crf.predict(tri_scores) sent_v = torch.mm(select_polarity.unsqueeze(0), context) # 1 * feat_dim label_scores = self.feat2label(sent_v).squeeze(0) return label_scores, select_polarity, best_seqs def forward(self, sent, mask, label): ''' inputs are list of list for the convenince of top CRF ''' # scores = self.compute_scores(sents, ents, asps, labels) scores, s_prob, marginal_prob = self.compute_scores(sent, mask) pena = F.relu( self.inter_crf.transitions[1,0] - self.inter_crf.transitions[0,0]) + \ F.relu(self.inter_crf.transitions[0,1] - self.inter_crf.transitions[1,1]) norm_pen = ( self.config.C1 * pena + self.config.C2 * s_prob.norm(1) ) / self.config.batch_size scores = F.softmax(scores) cls_loss = -1 * torch.log(scores[label]) print "cls loss {0} with penalty {1}".format(cls_loss.data[0], norm_pen.data[0]) return cls_loss + norm_pen def predict(self, sent, mask): scores, s_probs, best_seqs = self.compute_predict_scores(sent, mask) _, pred_label = scores.max(0) return pred_label.data[0], best_seqs
class AspectSent(nn.Module): def __init__(self, config): ''' Elmo+LSTM+Aspect ''' super(AspectSent, self).__init__() self.config = config #self.cat_layer = SimpleCat(config) self.lstm = MLSTM(config) self.feat2tri = nn.Linear(config.l_hidden_size, 2) self.inter_crf = LinearCRF(config) self.feat2label = nn.Linear(config.l_hidden_size, 3) self.cri = nn.CrossEntropyLoss() #Modified by Richard Sun #If we use Elmo, don't load GloVec #self.cat_layer.load_vector() #if not config.if_update_embed: self.cat_layer.word_embed.weight.requires_grad = False def compute_scores(self, sent, mask, lens): #if self.config.if_reset: self.cat_layer.reset_binary() # self.inter_crf.reset_transition() #sent = torch.LongTensor(sent) #sent = sent #Batch_size #sent_vec = self.cat_layer(sent, mask) #print('After concatenation:', sent_vec.size()) sent_vec = sent context = self.lstm(sent_vec, lens) #Batch_size*sent_len*hidden_dim #print('After lstm:', context.size()) # feat_context = torch.cat([context, asp_v], 1) # sent_len * dim_sum feat_context = context # batch_size*sent_len * hidden_dim tri_scores = self.feat2tri(feat_context) #Batch_size*sent_len*2 marginals = self.inter_crf(tri_scores) #Batch_size*sent_len*2 #Get only the positive latent factor select_polarity = marginals[:, :, 1] #batch_size*sent_len, select only positive ones marginals = marginals.transpose(1, 2) # batch_size*2 * sent_len sent_v = torch.bmm(select_polarity.unsqueeze(1), context) # batch_size * 1*feat_dim label_scores = self.feat2label(sent_v).squeeze(1) #print('Label Score', label_scores.size()) return label_scores, select_polarity, marginals def compute_predict_scores(self, sent, mask, lens): #if self.config.if_reset: self.cat_layer.reset_binary() # self.inter_crf.reset_transition() #sent = torch.LongTensor(sent) #mask = torch.LongTensor(mask) #1*word_len*emb_dim #sent_vec = self.cat_layer(sent, mask) sent_vec = sent context = self.lstm(sent_vec, lens) #Modified by Richard Sun # feat_context = torch.cat([context, asp_v], 1) # sent_len * dim_sum feat_context = context # batch_size*sent_len * hidden_dim tri_scores = self.feat2tri(feat_context) #Batch_size*sent_len*2 #print('model: tri_scores', tri_scores.size()) marginals = self.inter_crf(tri_scores) #Batch_size*sent_len*2 #Get only the positive latent factor select_polarity = marginals[:, :, 1] #batch_size*sent_len, select only positive ones marginals = marginals.transpose(1, 2) # batch_size*2 * sent_len sent_v = torch.bmm(select_polarity.unsqueeze(1), context) # batch_size * 1*feat_dim label_scores = self.feat2label(sent_v).squeeze(1) # # feat_context = torch.cat([context, asp_v], 1) # sent_len * dim_sum # feat_context = context # sent_len * dim_sum # tri_scores = self.feat2tri(feat_context) # marginals = self.inter_crf(tri_scores) # select_polarity = marginals[:,1] # sent_v = torch.mm(select_polarity.unsqueeze(0), context) # 1 * feat_dim # label_scores = self.feat2label(sent_v).squeeze(0) best_seqs = self.inter_crf.predict(tri_scores) return label_scores, select_polarity, best_seqs def forward(self, sent, mask, label, lens): ''' inputs are list of list for the convenince of top CRF Args: sent: a list of sentences, batch_size*len*emb_dim mask: a list of mask for each sentence, batch_size*len label: a list labels ''' # scores = self.compute_scores(sents, ents, asps, labels) #scores: batch_size*label_size #s_prob:batch_size*sent_len #marginal_prob:batch_size*2 * sent_len scores, s_prob, marginal_prob = self.compute_scores(sent, mask, lens) pena = F.relu( self.inter_crf.transitions[1,0] - self.inter_crf.transitions[0,0]) + \ F.relu(self.inter_crf.transitions[0,1] - self.inter_crf.transitions[1,1]) norm_pen = (self.config.C1 * pena + self.config.C2 * s_prob.norm(1)) / self.config.batch_size scores = F.log_softmax(scores, dim=1) #Batch_size*label_size loss = nn.NLLLoss() #cls_loss = -1 * torch.log(scores[label]) cls_loss = loss(scores, label) #print('Transition', pena) print("cls loss {0} with penalty {1}".format(cls_loss.item(), norm_pen.item())) return cls_loss + norm_pen def predict(self, sent, mask, sent_len): scores, s_probs, best_seqs = self.compute_predict_scores( sent, mask, sent_len) _, pred_label = scores.max(1) #Modified by Richard Sun return pred_label, best_seqs