<jupyter_start><jupyter_text>Import<jupyter_code>import numpy as np
import pandas as pd
from keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical
from keras.models import Model, Input
from keras.layers import LSTM, Embedding, Dense, TimeDistributed, Dropout, Bidirectional,Conv1D,concatenate
from tensorflow import keras

import torch
import torch.nn as nn
import torch.nn.functional as F
import pandas as pd 
import os
import pickle
import numpy as np
import xml.etree.ElementTree as ET
from torch.utils.data import Dataset

import os
import torch
import torch.nn as nn
import argparse
from sklearn import metrics
from torch.utils.data import DataLoader<jupyter_output><empty_output><jupyter_text>Load/Save<jupyter_code>import pickle
import joblib

#Load Save Pickle Utility
def save(filename, obj):
  with open(filename, 'wb') as handle:
      joblib.dump(obj, handle, protocol=pickle.HIGHEST_PROTOCOL)

def load(filename):
  with open(filename, 'rb') as handle:
      return joblib.load(filename)<jupyter_output><empty_output><jupyter_text>Required Model classes and code for ATC  Models<jupyter_code># Models 
class Squeezer(nn.Module):
    
    #Squeeze sequence embedding length to the longest one in the batch
    
    def __init__(self, batch_first=True):
        super(Squeezer, self).__init__()
        self.batch_first = batch_first
    
    def forward(self, x, x_len):
        # sequence , sort , pad and pack , unpack , unsort
        
        # sorting the given x lengths values 
        x_sort_idx = torch.sort(x_len, descending=True)[1].long()
        x_unsort_idx = torch.sort(x_sort_idx)[1].long()
        x_len = x_len[x_sort_idx]
        x_len = np.array(x_len.cpu())
        x = x[x_sort_idx]
        '''pack'''
        x_emb_p = torch.nn.utils.rnn.pack_padded_sequence(x, x_len, batch_first=self.batch_first)
        '''unpack'''
        out, _ = torch.nn.utils.rnn.pad_packed_sequence(x_emb_p, batch_first=self.batch_first)
        if self.batch_first:
            out = out[x_unsort_idx]
        else:
            out = out[:, x_unsort_idx]
        return out

class Recurrent_Models(nn.Module):
    '''
    LSTM which can hold variable length sequence, use like TensorFlow's RNN(input, lenght...).
    '''
    def __init__(self, input_size, hidden_size, num_layers=1, bias=True, batch_first=True, dropout=0,
                 bidirectional=False, only_use_last_hidden_state=False, rnn_type='LSTM'):
        super(Recurrent_Models, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.bias = bias
        self.batch_first = batch_first
        self.dropout = dropout
        self.bidirectional = bidirectional
        self.only_use_last_hidden_state = only_use_last_hidden_state
        self.rnn_type = rnn_type
        
        if self.rnn_type == 'LSTM':
            self.RNN = nn.LSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers,
                               bias=bias, batch_first=batch_first, dropout=dropout, bidirectional=bidirectional)
        elif self.rnn_type == 'GRU':
            self.RNN = nn.GRU(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers,
                              bias=bias, batch_first=batch_first, dropout=dropout, bidirectional=bidirectional)
        elif self.rnn_type == 'RNN':
            self.RNN = nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers,
                              bias=bias, batch_first=batch_first, dropout=dropout, bidirectional=bidirectional)
    
    def forward(self, x, x_len):
        
        '''
        sequence -> sort -> pad and pack -> process using RNN -> unpack -> unsort
        '''
        '''sort'''
        x_sort_idx = torch.sort(x_len, descending=True)[1].long()
        x_unsort_idx = torch.sort(x_sort_idx)[1].long()

        
        x_len = x_len[x_sort_idx]
        x_len = np.array(x_len.cpu())
        x = x[x_sort_idx]
        
        '''pack'''
        x_emb_p = torch.nn.utils.rnn.pack_padded_sequence(x, x_len, batch_first=self.batch_first)
        ''' process '''
        if self.rnn_type == 'LSTM':
            out_pack, (ht, ct) = self.RNN(x_emb_p, None)
        else:
            out_pack, ht = self.RNN(x_emb_p, None)
            ct = None
        '''unsort'''
        ht = ht[:, x_unsort_idx]
        if self.only_use_last_hidden_state:
            return ht
        else:
            out, _ = torch.nn.utils.rnn.pad_packed_sequence(out_pack, batch_first=self.batch_first)
            if self.batch_first:
                out = out[x_unsort_idx]
            else:
                out = out[:, x_unsort_idx]
            if self.rnn_type == 'LSTM':
                ct = ct[:, x_unsort_idx]
            return out, (ht, ct)

# PBAN Model 
class PBAN(nn.Module):
    # Position-aware bidirectional attention network 
    # paper https://aclanthology.org/C18-1066.pdf

    # if embedding matrix not one then glove or word to vec used else brt used for embeddings 
    # hyper_param is a dictionary containing all required hyperparameters 
    def __init__(self, embedding_matrix, hyper_param):

        super(PBAN, self).__init__()
        # embeddings of the text 
        
        self.embed = nn.Embedding.from_pretrained(torch.tensor(embedding_matrix, dtype=torch.float))
   
     
        # randomly intialised embedding for position with respect to aspect  
        self.pos_embed = nn.Embedding(hyper_param['max_length'], hyper_param['position_dim'])
        # Left GRU taking aspect 
        self.aspect_gru = Recurrent_Models(hyper_param['embed_dim'], hyper_param['hidden_dim'], num_layers=1, 
                                    batch_first=True, bidirectional=True, rnn_type='GRU')
        # Right GRU taking input as words and position embedding 
        self.sentence_position_gru = Recurrent_Models(hyper_param['embed_dim']+hyper_param['position_dim'], hyper_param['hidden_dim'], num_layers=1, 
                                     batch_first=True, bidirectional=True, rnn_type='GRU')
        

        self.weight_m = nn.Parameter(torch.Tensor(hyper_param['hidden_dim']*2, hyper_param['hidden_dim']*2))
        self.bias_m = nn.Parameter(torch.Tensor(1))
        self.weight_n = nn.Parameter(torch.Tensor( hyper_param['hidden_dim']*2, hyper_param['hidden_dim']*2))
        self.bias_n = nn.Parameter(torch.Tensor(1))
        self.w_r = nn.Linear( hyper_param['hidden_dim']*2,  hyper_param['hidden_dim'])
        self.w_s = nn.Linear( hyper_param['hidden_dim'], hyper_param['polarities_dim'])
    
    def forward(self, X):
        # getting text , aspect term and position indices 
        text, aspect_text, position_tag = X[0], X[1], X[2]
  
        x = self.embed(text)
          #Sentence representation from any glove or wrod to vec '''
          
        ''' Hidden Representation from Sentence and Position knowledge '''
        # getting position embedding 
        position_embedding = self.pos_embed(position_tag)
        # getting lengths of all batch sentences into a array x_len (removing padded 0)
        x_len = torch.sum(text != 0, dim=-1)
        # passing sentence and position embedding to gru 
        x = torch.cat((position_embedding, x), dim=-1)
        h_x, _ = self.sentence_position_gru(x, x_len)

        ''' Aspect term representation '''
        aspect_embedding = self.embed(aspect_text)
        aspect_len = torch.sum(aspect_text != 0, dim=-1)
        h_t, _ = self.aspect_gru(aspect_embedding, aspect_len)

        # Attention Calculation 
        ''' Aspect term to position-aware sentence attention '''
         
        alpha = F.softmax(torch.tanh(torch.add(torch.bmm(torch.matmul(h_t, self.weight_m), torch.transpose(h_x, 1, 2)), self.bias_m)), dim=1)
        s_x = torch.bmm(alpha, h_x)
        ''' Position-aware sentence attention to aspect term '''
        h_x_pool = torch.unsqueeze(torch.div(torch.sum(h_x, dim=1), x_len.float().view(x_len.size(0), 1)), dim=1)
        gamma = F.softmax(torch.tanh(torch.add(torch.bmm(torch.matmul(h_x_pool, self.weight_n), torch.transpose(h_t, 1, 2)), self.bias_n)), dim=1)
        h_r = torch.squeeze(torch.bmm(gamma, s_x), dim=1)
        ''' Output transform '''
        out = torch.tanh(self.w_r(h_r))
        out = self.w_s(out)
        return out

class LSTM(nn.Module):
    # standard LSTM output without any consideration of target  
    def __init__(self, embedding_matrix, hyper_param):
        super(LSTM, self).__init__()
        
        self.embedding = nn.Embedding.from_pretrained(torch.tensor(embedding_matrix, dtype=torch.float))
        self.lstm = Recurrent_Models(hyper_param['embed_dim'], hyper_param['hidden_dim'], num_layers=1, batch_first=True)
        self.out = nn.Linear(hyper_param['hidden_dim'], hyper_param['polarities_dim'])
    
    def forward(self, x):
        # extracting only text 
        
        text = x[0]
        # substituting words by embedding
        
        x = self.embedding(text)
        x_len = torch.sum(text != 0, dim=-1)
        
        _, (hidden, _) = self.lstm(x, x_len)
        out = self.out(hidden[0])
        return out


class AE_LSTM(nn.Module):
    ''' LSTM with Aspect Embedding '''
    def __init__(self, embedding_matrix, hyper_param):
        super(AE_LSTM, self).__init__()
        self.embedding = nn.Embedding.from_pretrained(torch.tensor(embedding_matrix, dtype=torch.float))
        self.squeeze_embedding = Squeezer()
        self.lstm = Recurrent_Models(hyper_param['embed_dim']*2, hyper_param['hidden_dim'], num_layers=1, batch_first=True)
        self.dense_layer = nn.Linear(hyper_param['hidden_dim'], hyper_param['polarities_dim'])
    
    def forward(self, x):
        # extracting text and aspect words from given batch of sentences
        text_words, aspect_text = x[0], x[1]
        
        # finding max length among all aspects and text  
        x_len = torch.sum(text_words != 0, dim=-1)
        x_len_max = torch.max(x_len)
        aspect_len = torch.sum(aspect_text != 0, dim=-1).float()
        
        # Geting embedding of aspects and words or texts 
        x = self.embedding(text_words)
        x = self.squeeze_embedding(x, x_len)
        aspect = self.embedding(aspect_text)
        # concatenating aspect and all the words respectively 
        aspect_pool = torch.div(torch.sum(aspect, dim=1), aspect_len.view(aspect_len.size(0), 1))
        aspect = torch.unsqueeze(aspect_pool, dim=1).expand(-1, x_len_max, -1)
        x = torch.cat((aspect, x), dim=-1)
        # sending input to lstm 
        _, (hidden, _) = self.lstm(x, x_len)
        out = self.dense_layer(hidden[0])
        return out<jupyter_output><empty_output><jupyter_text>Preprocessing and evaluate function<jupyter_code>def evaluate(model,test_dataloader):
    # switch model to evaluation mode
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.eval()
    test_correct, test_total = 0, 0
    y_complete, y_hat_complete = None, None
    
    with torch.no_grad():
        for idx,batch in enumerate(test_dataloader):
            
            x = [batch[col].to(device) for col in ['text', 'aspect', 'position']]
            y = batch['polarity'].to(device)
            outputs = model(x)
            
            test_correct += (torch.argmax(outputs, -1) == y).sum().item()
            test_total += len(outputs)
            # appending all y and y hats  
            if y_complete is not None:
              y_complete = torch.cat((y_complete, y), dim=0)
            else:
              y_complete = y
            if y_hat_complete is not None:
              y_hat_complete = torch.cat((y_hat_complete, outputs), dim=0)
            else:
              y_hat_complete = outputs

    test_acc = test_correct / test_total
    f1 = metrics.f1_score(y_complete.cpu(), torch.argmax(y_hat_complete, -1).cpu(), labels=[0, 1, 2], average='macro')
    return test_acc, f1

def create_vocab(arr):
  vocab = dict()
  idx = 0 
  # padding represented by 0 and on index 0 
  vocab[0] = 0
  idx = idx+1
  vocab['unk'] = 1
  
  for sen in arr:
    for w in sen:
      if w not in vocab.keys() and  w != 0:
        idx = idx+1
        vocab[w] = idx
  inv_vocab = {v: k for k, v in vocab.items()} 
  return vocab , inv_vocab

def word_to_id(vocab,w):
  if w not in vocab.keys():
    return 1
  else:
    return vocab[w]


def id_to_word(inv_vocab,id):
  return inv_vocab[id]
 

def getResults(data):
  rows = []
  # Iterate through every row
  for i in range(len(data.index)):
      # Collect all occurences of B
      indices_B = [k for k, x in enumerate(data.loc[i]["aspect_labels"]) if x == 'B']

      tempListA = data.loc[i]["terms"]

      # Iterate through every index
      for j in indices_B:
        tempListB = ['O'] * len(data.loc[i][0])
        tempListB[j] = "B"

        for k in range(j + 1, len(data.loc[i][0])):
          if data.loc[i]["aspect_labels"][k] == "I":
            if tempListB[k-1] == "B" or tempListB[k-1] == "I":
              tempListB[k] = "I"

        tempListC = ['NA'] * len(data.loc[i][0])
        senti = data.loc[i]["sentiments"][j]
      
      
        rows.append([tempListA, tempListB, senti])

  result = pd.DataFrame(rows, columns = ["terms", "aspect_labels", "sentiments"])

  return result

def prepare_dataset(vocab, df, max_length):

  number = df.shape[0]
  # returns all text element in data 
  text_data = np.zeros([number,max_length])
  aspect_data = np.zeros([number,max_length])
  position_data = np.zeros([number,max_length])
  sentiment = np.zeros([number])

  # flag to keep a track of how many aspect terms inserted 
  
  for idx, sen in enumerate(df['terms'].to_numpy()):
    flag = 0
    for wid , w in enumerate(sen):
      # text number pusshed 
      text_data[idx][wid] = word_to_id(vocab,w)

      # aspect number pushed 
      if df['aspect_labels'].iloc[idx][wid] == 'B' or df['aspect_labels'].iloc[idx][wid] == 'I':
        
        aspect_data[idx][flag] = word_to_id(vocab,w)
        flag = flag + 1
        
    # sentiment of sentence added 
    if df['sentiments'][idx] == 'NEU':
      sentiment[idx] = 2
    elif df['sentiments'][idx]  == 'POS':
      sentiment[idx] = 0 
    else:
      sentiment[idx] = 1

    # position embedding 
    x1 = np.array(df['aspect_labels'][idx])
    start = np.where(x1 == 'B')[0][0]
    if not len(np.where(x1 == 'I')[0]):
      end = start+1
    else:
      end = np.where(x1 == 'I')[0][-1]
      end = end+1
    # print(x1)
    # print("-----")
    # print(start,end)

    x = df['terms'][idx]
    text_left = list(x[:start])
    text_aspect = list(x[start:end])
    text_right = list(x[end:])
    tag_left = [len(text_left)-i for i in range(len(text_left))]
    tag_aspect = [0 for i in range(len(text_aspect))]
    tag_right = [i+1 for i in range(len(text_right))]
    position_tag = tag_left + tag_aspect + tag_right
    if len(position_tag) == 0:
        position_tag = [0]

    times = max_length - len(position_tag)
    r = [0]*times
    position_tag = position_tag+r
    position_data[idx] = np.array(position_tag)

  return text_data , aspect_data, position_data, sentiment 
      
def prepare_text_file_test(df,max_length,v):
  # max_length = 80

  my_df = getResults(df) 

  text_data , aspect_data, position_data, sentiment  = prepare_dataset(v, my_df, max_length)

  return text_data , aspect_data, position_data, sentiment<jupyter_output><empty_output><jupyter_text>Creating Dataloader<jupyter_code>class SentenceDataset(Dataset):
    
    def __init__(self, text_data , aspect_data, position_data, sentiment):
        data = list()
       
        for idx , text in enumerate(text_data):
          aspect_term = aspect_data[idx]
          position = position_data[idx]
          polarity = sentiment[idx]
          data.append({'text': torch.tensor(text,dtype=int), 'aspect': torch.tensor(aspect_term,dtype=int), 'position': torch.tensor(position,dtype=int), 'polarity':torch.tensor(polarity,dtype=int) })

        self._data = data
    
    def __getitem__(self, index):
        return self._data[index]
    
    def __len__(self):
        return len(self._data)<jupyter_output><empty_output><jupyter_text>Parameters used<jupyter_code>params = { 
'lstm': {
'data' :  ['text'],
'hyperparameters':  {'max_length' : 80,
'position_dim' : 100,
'embed_dim' : 300,
'hidden_dim' : 5,
'polarities_dim' : 3,
'epochs': 20 , 
'initializer': torch.nn.init.xavier_uniform_ , 
'optimizer':torch.optim.Adam, 
'lr': 1e-4 , 

  }  , 

},
'aelstm' : {
        'data' :  ['text', 'aspect'],
'hyperparameters': {'max_length' : 80,
'position_dim' : 100,
'embed_dim' : 300,
'hidden_dim' : 200,
'polarities_dim' : 3,
'epochs': 20 , 
'initializer': torch.nn.init.xavier_uniform_ , 
'optimizer': torch.optim.Adam, 
'lr': 1e-3 , 

  }  , 

},
'pban' : {
        'data' : ['text', 'aspect', 'position'] ,
'hyperparameters': {'max_length' : 80,
'position_dim' : 100,
'embed_dim' : 300,
'hidden_dim' : 200,
'polarities_dim' : 3,
  'epochs': 20 , 
'initializer': torch.nn.init.xavier_uniform_ , 
'optimizer':torch.optim.Adam, 
'lr': 1e-3 , 

  }  
}
}<jupyter_output><empty_output><jupyter_text>Parameters<jupyter_code># #baseline
# #Parameters
# model_type = 'lstm'         # 'lstm','cnn'
# embedding_type = 'double'  #  'triple' ,'double','bert'
# dataset_name = 'laptop'         # 'laptop', 'restaraunt'

# #Label Indices
# tag_indices = {'B':0, 'I':1, 'O':2}
# rev_tag_indices = {0:'B', 1:'I', 2:'O'}
#Parameters
model_type = 'cnn'         # 'lstm','cnn'
embedding_type = 'triple'  #  'triple' ,'double','bert'
dataset_name = 'restaraunt'         # 'laptop', 'restaraunt'

#Label Indices
tag_indices = {'B':0, 'I':1, 'O':2}
rev_tag_indices = {0:'B', 1:'I', 2:'O'}<jupyter_output><empty_output><jupyter_text>Load Dataset<jupyter_code>p = ""
laptop_train_set = load('/content/drive/MyDrive/NLP/Akanksha_files/data_pkl_files_laptop/train.pkl')
laptop_test_set = load('/content/drive/MyDrive/NLP/Akanksha_files/data_pkl_files_laptop/test.pkl')

restaraunt_train_set = load('/content/drive/MyDrive/NLP/Akanksha_files/data_pkl_files_restraunt/train.pkl')
restaraunt_test_set = load('/content/drive/MyDrive/NLP/Akanksha_files/data_pkl_files_restraunt/test.pkl')

if dataset_name == 'restaraunt':
  current_train_dataset = restaraunt_train_set
  current_test_dataset = restaraunt_test_set
else:
  current_train_dataset = laptop_train_set
  current_test_dataset = laptop_test_set

max_len = 0
for sample in current_train_dataset:
  if len(sample['terms']) > max_len:
    max_len = len(sample['terms'])<jupyter_output><empty_output><jupyter_text>Load Train Test Embedding<jupyter_code>p = "/content/drive/MyDrive/NLP"
X_train = load(p + '/Final/Embeddings/X_train_'+ embedding_type+'_'+dataset_name+'.pkl')
X_test = load(p + '/Final/Embeddings/X_test_'+ embedding_type +'_'+dataset_name+'.pkl')
y_train = load(p + '/Final/Embeddings/y_train_' + dataset_name +'.pkl')
y_test = load(p + '/Final/Embeddings/y_test_' + dataset_name +'.pkl')<jupyter_output><empty_output><jupyter_text>Load Model<jupyter_code>model = keras.models.load_model(p + '/Final/Models/ATE/'+dataset_name+'_'+embedding_type+'_'+model_type+'.pkl')<jupyter_output><empty_output><jupyter_text>Predictions<jupyter_code>train_pred = np.argmax(model.predict(X_train),axis = 2)
train_target = np.argmax(np.array(y_train),axis=2)
test_pred = np.argmax(model.predict(X_test),axis=2)
test_target = np.argmax(np.array(y_test),axis=2)

test_y_t = []
test_y_h = []
for i in range(test_pred.shape[0]):
  for j in range(test_pred.shape[1]):
    test_y_t.append(test_target[i,j])
    test_y_h.append(test_pred[i,j])
train_y_t = []
train_y_h = []
for i in range(train_pred.shape[0]):
  for j in range(train_pred.shape[1]):
    train_y_t.append(train_target[i,j])
    train_y_h.append(train_pred[i,j])<jupyter_output><empty_output><jupyter_text>Evaluation<jupyter_code>from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import classification_report
def tag_wise_metrics(y_true, y_pred, target_names):
  print(classification_report(y_true, y_pred, target_names=target_names))
print("=================================Train Dataset=================================")
tag_wise_metrics(train_y_t, train_y_h, ['B','I','O'])
print("=================================Test Dataset=================================")
tag_wise_metrics(test_y_t, test_y_h, ['B','I','O'])<jupyter_output>=================================Train Dataset=================================
              precision    recall  f1-score   support

           B       0.98      0.97      0.98      3269
           I       0.98      0.95      0.97      1231
           O       1.00      1.00      1.00    200700

    accuracy                           1.00    205200
   macro avg       0.99      0.98      0.98    205200
weighted avg       1.00      1.00      1.00    205200

=================================Test Dataset=================================
              precision    recall  f1-score   support

           B       0.84      0.73      0.78      1121
           I       0.84      0.57      0.68       502
           O       0.99      1.00      1.00     58377

    accuracy                           0.99     60000
   macro avg       0.89      0.77      0.82     60000
weighted avg       0.99      0.99      0.99     60000<jupyter_text>Output to Forward<jupyter_code>terms = [[t for t in sample['terms']] for sample in current_train_dataset]
pred_labels = [list(train_pred[i])[:len(terms[i])] for i in range(train_pred.shape[0])]
pred_labels = [[rev_tag_indices[t] for t in sample] for sample in pred_labels]
sentiments = [sample['sentiment'] for sample in current_train_dataset]
train_final = [[terms[i],pred_labels[i],sentiments[i]] for i in range(len(terms))]
train_final = pd.DataFrame(train_final,columns=["terms","aspect_labels","sentiments"])
train_final.head()
terms = [[t for t in sample['terms']] for sample in current_test_dataset]
pred_labels = [list(test_pred[i])[:len(terms[i])] for i in range(test_pred.shape[0])]
pred_labels = [[rev_tag_indices[t] for t in sample] for sample in pred_labels]
sentiments = [sample['sentiment'] for sample in current_test_dataset]
train_final2 = [[terms[i],pred_labels[i],sentiments[i]] for i in range(len(terms))]
train_final2 = pd.DataFrame(train_final2,columns=["terms","aspect_labels","sentiments"])
train_final2.head()
# train_final['aspect_labels'][0]
# train_final2<jupyter_output><empty_output><jupyter_text>ATC  Telling model and hyper param used later on<jupyter_code>max_length = 80

x = input("Name the model you want to input 'lstm, aelstm, pban : ")
model_name = x
model_data = params[model_name]['data'] 
model_hyper_param = params[model_name]['hyperparameters'] 

x = input("Enter dataset to be used 1. Restraunt 2.Laptop ")
base = '/content/drive/MyDrive/NLP'
if int(x) ==1:
  vocab = load( base + '/Akanksha_files/data_pkl_files_restraunt/vocab.pkl')
  embedding_matrix = load( base + '/Akanksha_files/data_pkl_files_restraunt/embedding_matrix.pkl')

else:

  vocab = load(base + '/Akanksha_files/data_pkl_files_laptop/vocab.pkl')
  embedding_matrix = load(base + '/Akanksha_files/data_pkl_files_laptop/embedding_matrix.pkl')<jupyter_output>Name the model you want to input 'lstm, aelstm, pban : pban
Enter dataset to be used 1. Restraunt 2.Laptop 1<jupyter_text>Processing further data<jupyter_code># training 
train_text_data , train_aspect_data, train_position_data, train_sentiment = prepare_text_file_test(train_final,max_length,vocab)
# testing 
test_text_data , test_aspect_data, test_position_data, test_sentiment = prepare_text_file_test(train_final2,max_length,vocab)
# create data loaders 
trainset = SentenceDataset(train_text_data , train_aspect_data, train_position_data, train_sentiment)
testset = SentenceDataset( test_text_data , test_aspect_data, test_position_data, test_sentiment)

train_dataloader = DataLoader(dataset=trainset, batch_size=64, shuffle=True)
test_dataloader = DataLoader(dataset=testset, batch_size=64, shuffle=False)
model_name , model_data , model_hyper_param 


device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 
if model_name == 'lstm':
  model = LSTM(embedding_matrix,model_hyper_param).to(device)
elif model_name == 'aelstm':
  model = AE_LSTM(embedding_matrix,model_hyper_param).to(device)
else:
  model = PBAN(embedding_matrix,model_hyper_param).to(device)


criterion = nn.CrossEntropyLoss()
_params = filter(lambda p: p.requires_grad, model.parameters())
optimizer = torch.optim.Adam(_params, lr=model_hyper_param['lr'], weight_decay=1e-5)

def replicate_results(path, model_name,test_dataloader,model_hyper_param):
# path of saved model 
  
  # model 
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 
  if model_name == 'lstm':
    model = LSTM(embedding_matrix,model_hyper_param).to(device)
  elif model_name == 'aelstm':
    model = AE_LSTM(embedding_matrix,model_hyper_param).to(device)
  else:
    model = PBAN(embedding_matrix,model_hyper_param).to(device)

  # load and evaluate 
  model.load_state_dict(torch.load(path))
  model.eval()
  test_acc, f1 = evaluate(model,test_dataloader)
  print("Accuracy , F1 score")
  print(test_acc, f1)
model_name = input("Enter the model name : lstm, aelstm, pban : ")
x = input("Enter dataset : 1.Restraunt 2.Laptop")

# best_path with respect to each model and dataset
# 1 is rest , 2 is laptop 
if model_name == 'lstm' and int(x) == 1:
  best_path = base + '/Akanksha_files/data_pkl_files_restraunt/models/lstm/state_dict/lstm_res_3f10.3224_19'
elif model_name == 'aelstm' and int(x) == 1:
  best_path = base + '/Akanksha_files/data_pkl_files_restraunt/models/aelstm/state_dict/lstm_res_3f10.5655_12'
elif model_name == 'pban' and int(x) == 1:
  best_path = base + '/Akanksha_files/data_pkl_files_restraunt/models/pban/state_dict/lstm_res_3f10.6684_17'
elif model_name == 'lstm' and int(x) == 2:
  best_path = base + '/Akanksha_files/data_pkl_files_laptop/models/lstm/state_dict/lstm_res_3f10.3946_19'
elif model_name == 'aelstm' and int(x) == 2:
  best_path = base + '/Akanksha_files/data_pkl_files_laptop/models/aelstm/state_dict/lstm_res_3f10.5260_10'
elif model_name == 'pban' and int(x) == 2:
  best_path = base + '/Akanksha_files/data_pkl_files_laptop/models/pban/state_dict/lstm_res_3f10.6111_9'

path = best_path 
print("Testing")
replicate_results(path, model_name,test_dataloader,model_hyper_param)
print("Training")
replicate_results(path, model_name,train_dataloader,model_hyper_param)
# embediing triple model type cnn 
# BASELINE 
# LSTM DOUBLE 
# LSTM CLASSIFICATION 

# restraunt 
# Enter the model name : lstm, aelstm, pban : lstm
# Enter dataset : 1.Restraunt 2.Laptop1
# Testing
# Accuracy , F1 score
# 0.6136125654450262 0.3129938405011427
# Training
# Accuracy , F1 score
# 0.5713324360699865 0.3534244748170867

# Laptop 
# Enter the model name : lstm, aelstm, pban : lstm
# Enter dataset : 1.Restraunt 2.Laptop2
# Testing
# Accuracy , F1 score
# 0.5515463917525774 0.4267538090911967
# Training
# Accuracy , F1 score
# 0.436498150431566 0.37061853059486594
# Final Model 
# CNN Triple 
# PBAN 

# restaurant 
# Enter the model name : lstm, aelstm, pban : pban
# Enter dataset : 1.Restraunt 2.Laptop1
# Testing
# Accuracy , F1 score
# 0.7267144319344934 0.6247275059590686
# Training
# Accuracy , F1 score
# 0.7838421214924453 0.7044096839861195



# # Laptop 
# Enter the model name : lstm, aelstm, pban : pban
# Enter dataset : 1.Restraunt 2.Laptop2
# Testing
# Accuracy , F1 score
# 0.6019736842105263 0.5543710516536603
# Training
# Accuracy , F1 score
# 0.82392667631452 0.8071314322140791<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13127274037249181, 'fraction_numerical': 0.025937533772830434, 'mean_word_length': 3.4580054600931427, 'pattern_counts': {'":': 2, '<': 59, '<?xml version=': 0, '>': 65, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 1}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '579685', 'license': 'MIT', 'n_tokens_mistral': 10302, 'n_tokens_neox': 9718, 'n_words': 1956, 'path': 'Code_files/ATE_APC_integration.ipynb', 'repo_name': 'AkankshaShrimal/Aspect-Based-Sentiment-Analysis', 'size': '27759'}