<jupyter_start><jupyter_text><jupyter_code># Colab settings/mount
from google.colab import drive
drive.mount('/content/gdrive')
%cd gdrive/My\ Drive/CSE\ 245\ Project
!ls Data
!pip install transformers
dataset_name = "data_fixed_train_complement_analysis"
speaker_model_name = "model3"
listener_model_name = "model2"
model_type = "emotion" #pos_neg or emotion
import tensorflow as tf

# Get the GPU device name.
device_name = tf.test.gpu_device_name()

# The device name should look like the following:
if device_name == '/device:GPU:0':
    print('Found GPU at: {}'.format(device_name))
else:
    raise SystemError('GPU device not found')

import torch

# If there's a GPU available...
if torch.cuda.is_available():    

    # Tell PyTorch to use the GPU.    
    device = torch.device("cuda")

    print('There are %d GPU(s) available.' % torch.cuda.device_count())

    print('We will use the GPU:', torch.cuda.get_device_name(0))

# If not...
else:
    print('No GPU available, using the CPU instead.')
    device = torch.device("cpu")
import json
with open("Data/data_sample_10.json") as infile:
  data = json.load(infile)
print(data['1022'])
print(data.keys())
print(data['2103'])
with open("Data/data_fixed_train.json","r") as infile:
  data = json.load(infile)
  with open("Data/data_complement_analysis.csv","w") as outfile:
    outfile.write("emotion|speaker_utterance|listener_utterance\n")
    for key in data.keys():
      dialog = data[key]['dialog']
      emotion = data[key]['emotion']
      i = 0
      while i < len(dialog):
        speaker_utterance = str(dialog[i]['utterance']).replace("|","").replace("_comma_",",")
        listener_utterance = str(dialog[i+1]['utterance']).replace("|","").replace("_comma_",",") if i + 1 < len(dialog) else ""
        line = "%s|%s|%s\n" % (emotion, speaker_utterance, listener_utterance)
        outfile.write(line)
        #print(line)
        i += 2
import pandas as pd
import numpy as np
train_filename = "Data/" + dataset_name + ".csv"
train_df = pd.read_csv(train_filename, sep='|', error_bad_lines=False)
train_df = train_df.dropna()
train_df
category2index = {
    "invalid":0,
    "sentimental":1,
    "sad":2,
    "hopeful":3,
    "joyful":4,
    "impressed":5,
    "terrified":6,
    "proud":7,
    "afraid":8,
    "grateful":9,
    "lonely":10,
    "surprised":11,
    "anxious":12,
    "guilty":13,
    "trusting":14,
    "nostalgic":15,
    "excited":16,
    "disgusted":17,
    "caring":18,
    "furious":19,
    "angry":20,
    "prepared":21,
    "disappointed":22,
    "faithful":23,
    "confident":24,
    "apprehensive":25,
    "jealous":26,
    "embarrassed":27,
    "devastated":28,
    "annoyed":29,
    "ashamed":30,
    "content":31,
    "anticipating":32
}
index2category = {}
for key, value in category2index.items():
  index2category[value] = key

def category2label(category):
  for key in category2index.keys():
    if key == category:
      return category2index[key]
  return 0

def label2emotion(labels):
  emotion_list = []
  for label in labels:
    emotion_list.append(index2category[label])
  return emotion_list
print('Number of training sentences: {:,}\n'.format(train_df.shape[0]))
if model_type == "emotion":
  train_df['orignial_label'] = train_df['emotion'].apply(lambda x: int(category2label(x.lower())))

# Display 10 random rows from the data.
train_df.sample(10)
speaker_sentences_train = train_df.speaker_utterance.values
listener_sentences_train = train_df.listener_utterance.values
labels_train = train_df.orignial_label.values
from transformers import BertTokenizer

# Load the BERT tokenizer.
print('Loading BERT tokenizer...')
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', do_lower_case=True)

longer_list = []
for index, sent in enumerate(speaker_sentences_train):
  if len(tokenizer.encode(sent, add_special_tokens=True)) > 500:
    longer_list.append(index)
speaker_sentences_train = np.delete(speaker_sentences_train, longer_list)

longer_list = []
for index, sent in enumerate(listener_sentences_train):
  if len(tokenizer.encode(sent, add_special_tokens=True)) > 500:
    longer_list.append(index)
listener_sentences_train = np.delete(listener_sentences_train, longer_list)
from transformers import BertTokenizer

def tokenize(sentences, labels):
  # Tokenize all of the sentences and map the tokens to thier word IDs.
  input_ids = []
  attention_masks = []

  # For every sentence...
  for sent in sentences:
      # `encode_plus` will:
      #   (1) Tokenize the sentence.
      #   (2) Prepend the `[CLS]` token to the start.
      #   (3) Append the `[SEP]` token to the end.
      #   (4) Map tokens to their IDs.
      #   (5) Pad or truncate the sentence to `max_length`
      #   (6) Create attention masks for [PAD] tokens.

      encoded_dict = tokenizer.encode_plus(
                          sent,                      # Sentence to encode.
                          add_special_tokens = True, # Add '[CLS]' and '[SEP]'
                          max_length = 256,           # Pad & truncate all sentences.
                          pad_to_max_length = True,
                          return_attention_mask = True,   # Construct attn. masks.
                          return_tensors = 'pt',     # Return pytorch tensors.
                    )
      
      # Add the encoded sentence to the list.    
      input_ids.append(encoded_dict['input_ids'])
      
      # And its attention mask (simply differentiates padding from non-padding).
      attention_masks.append(encoded_dict['attention_mask'])

  # Convert the lists into tensors.
  input_ids = torch.cat(input_ids, dim=0)
  attention_masks = torch.cat(attention_masks, dim=0)
  labels = torch.from_numpy(labels)

  return(input_ids, attention_masks, labels)

speaker_input_ids_train, speaker_attention_masks_train, speaker_labels_train = tokenize(speaker_sentences_train, labels_train)
listener_input_ids_train, listener_attention_masks_train, listener_labels_train = tokenize(listener_sentences_train, labels_train)
from torch.utils.data import TensorDataset, random_split

# Combine the training inputs into a TensorDataset.
speaker_dataset_train = TensorDataset(speaker_input_ids_train, speaker_attention_masks_train, speaker_labels_train)
listener_dataset_train = TensorDataset(listener_input_ids_train, listener_attention_masks_train, listener_labels_train)

print('{:>5,} training samples'.format(len(speaker_dataset_train)))
from transformers import BertForSequenceClassification, BertTokenizer
output_dir = "./" + model_type + "_" + speaker_model_name + "_save/"

# Load a trained model and vocabulary that you have fine-tuned
model = BertForSequenceClassification.from_pretrained(output_dir)
tokenizer = BertTokenizer.from_pretrained(output_dir)

# Copy the model to the GPU.
model.to(device)

print(model_type + "_" + speaker_model_name + " loaded...")
from torch.utils.data import DataLoader, RandomSampler, SequentialSampler
batch_size = 32

def predict(dataset):

  # Create the DataLoader for  dataset.
  prediction_data = dataset
  prediction_sampler = SequentialSampler(prediction_data)
  prediction_dataloader = DataLoader(prediction_data, sampler=prediction_sampler, batch_size=batch_size)


  # Prediction on test set

  print('Predicting labels for {:,} sentences...'.format(len(dataset)))

  # Put model in evaluation mode
  model.eval()

  # Tracking variables 
  predictions , true_labels, speaker_utterance = [], [], []

  # Predict 
  for batch in prediction_dataloader:
    # Add batch to GPU
    batch = tuple(t.to(device) for t in batch)
    
    # Unpack the inputs from our dataloader
    b_input_ids, b_input_mask, b_labels = batch
    
    # Telling the model not to compute or store gradients, saving memory and 
    # speeding up prediction
    with torch.no_grad():
        # Forward pass, calculate logit predictions
        outputs = model(b_input_ids, token_type_ids=None, 
                        attention_mask=b_input_mask)

    logits = outputs[0]

    # Move logits and labels to CPU
    logits = logits.detach().cpu().numpy()
    label_ids = b_labels.to('cpu').numpy()
    
    # Store predictions and true labels
    predictions.append(logits)
    true_labels.append(label_ids)

  print('DONE.')
  return predictions, true_labels

speaker_train_predictions, speaker_train_true_labels = predict(speaker_dataset_train)
def predictions2labels(predictions):
  for i in range(len(predictions)):
    if i == 0:
      pred_flat = np.argmax(predictions[i], axis=1).flatten()
    else:
      pred_flat = np.append(pred_flat, np.argmax(predictions[i], axis=1).flatten())
  return label2emotion(pred_flat)
train_df['emotion_speaker'] = pd.DataFrame(predictions2labels(speaker_train_predictions), columns=['emotion_speaker'])
train_df.sample(10)
del model
torch.cuda.empty_cache()
from transformers import BertForSequenceClassification, BertTokenizer
output_dir = "./" + model_type + "_" + listener_model_name + "_save/"

# Load a trained model and vocabulary that you have fine-tuned
model = BertForSequenceClassification.from_pretrained(output_dir)
tokenizer = BertTokenizer.from_pretrained(output_dir)

# Copy the model to the GPU.
model.to(device)

print(model_type + "_" + listener_model_name + " loaded...")
from torch.utils.data import DataLoader, RandomSampler, SequentialSampler
batch_size = 32

def predict(dataset):

  # Create the DataLoader for  dataset.
  prediction_data = dataset
  prediction_sampler = SequentialSampler(prediction_data)
  prediction_dataloader = DataLoader(prediction_data, sampler=prediction_sampler, batch_size=batch_size)


  # Prediction on test set

  print('Predicting labels for {:,} sentences...'.format(len(dataset)))

  # Put model in evaluation mode
  model.eval()

  # Tracking variables 
  predictions , true_labels = [], []

  # Predict 
  for batch in prediction_dataloader:
    # Add batch to GPU
    batch = tuple(t.to(device) for t in batch)
    
    # Unpack the inputs from our dataloader
    b_input_ids, b_input_mask, b_labels = batch
    
    # Telling the model not to compute or store gradients, saving memory and 
    # speeding up prediction
    with torch.no_grad():
        # Forward pass, calculate logit predictions
        outputs = model(b_input_ids, token_type_ids=None, 
                        attention_mask=b_input_mask)

    logits = outputs[0]

    # Move logits and labels to CPU
    logits = logits.detach().cpu().numpy()
    label_ids = b_labels.to('cpu').numpy()
    
    # Store predictions and true labels
    predictions.append(logits)
    true_labels.append(label_ids)

  print('DONE.')
  return predictions, true_labels

listener_train_predictions, listener_train_true_labels = predict(listener_dataset_train)
train_df['emotion_listener'] = pd.DataFrame(predictions2labels(listener_train_predictions), columns=['emotion_listener'])
train_df.sample(10)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10974490732244449, 'fraction_numerical': 0.011745274362268306, 'mean_word_length': 4.011034482758621, 'pattern_counts': {'":': 34, '<': 7, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '356772', 'license': 'MIT', 'n_tokens_mistral': 3586, 'n_tokens_neox': 3465, 'n_words': 809, 'path': 'Complement_Emotion_analysis.ipynb', 'repo_name': 'omkarpat/EmpatheticDialoguesEmotionDetection', 'size': '10898'}