# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     name: python3
# ---

# + [markdown] id="pyPei1w4ptMB"
# # Assignment-8
#
# Author: <NAME> (201011057)

# + id="gKsTi1lvrW7F"
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Dropout, Embedding, LSTM, Bidirectional
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

# + colab={"base_uri": "https://localhost:8080/"} id="edoiBo0FqVoF" outputId="e6310e8c-a7f5-44f1-a207-c2107f32d345"
# downloading the dataset 
# !gdown https://drive.google.com/uc?id=18l6IwSqavnqtLQpVnrRqOugZf9XkhEAN

# + colab={"base_uri": "https://localhost:8080/"} id="9ATcJ49uqzGF" outputId="6889e126-d798-4e3c-9983-71d0430356ec"
# unzipping
# !unzip /content/jigsaw-toxic-comment-classification-challenge.zip
# !unzip /content/train.csv.zip

# + id="fdhLsfERtExn"
# train data 
df = pd.read_csv("/content/train.csv")

# + colab={"base_uri": "https://localhost:8080/", "height": 255} id="9gMJmhBrtMEv" outputId="6abc4136-b097-48cd-cca4-395e8d47d8b2"
df.head()

# + colab={"base_uri": "https://localhost:8080/", "height": 289} id="N5syG1EPtPlx" outputId="712870b2-e1f8-40bf-f4a5-6efa25367f72"
labels = ['toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate']

# adding 'none' label for a scenario where record is classified in neither of the given classes 
df['none'] = 1 - df[labels].max(axis=1)
df.head()

# + id="2P422quIZfQg"
df['none'] = 1 - df[labels].max(axis=1)

# filling null with <unknown> token 
df['comment_text'].fillna('<unknown>',inplace=True)

# + id="QqgCXYFwaEKx"
# updated labels
labels = ['toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate', 'none']

# + id="r9fdDdlfaJcC"
# maximum sequence length of input (i.e. every sequence will be padded upto this length)
max_sequence_length = 128

# tokenizer - to split text sequence into tokens 
tokenizer = Tokenizer()
tokenizer.fit_on_texts(df['comment_text'])
sequences = tokenizer.texts_to_sequences(df['comment_text'])

# to pad the sequences upto max length 
pad_sequences = pad_sequences(sequences, maxlen=max_sequence_length)


# + id="IP_CnGdLbKcn"
def build_model(vocab_size, max_sequence_length, n_class):
    input = Input(shape=(max_sequence_length,))

    # step-1: calculating embedding of input sequenes
    # transforms: (batch_size x max_seq_len) -> (batch size x max_seq_len x embedding_dim)
    
    # step-2: applying bidirectional lstm
    # transforms: (batch_size x 2*16)
    x = Bidirectional(LSTM(16))(Embedding(input_dim=vocab_size, output_dim=64, input_length=max_sequence_length, embeddings_initializer='random_normal')(input))
    x = Dropout(0.5)(x)

    # step-3: dense layer: 32 -> 16
    x = Dense(16, activation='relu')(x)

    # step-4: dense layer: 16 -> 7
    output = Dense(n_class, activation='sigmoid')(x)
    
    model = tf.keras.Model(inputs=input, outputs=output)

    # loss:  binary cross entropy
    # optimizer: Adam  
    model.compile (optimizer='adam', 
                   loss="binary_crossentropy", 
                   metrics=['accuracy', 'Precision', 'Recall'])
    
    return model


# + colab={"base_uri": "https://localhost:8080/"} id="JrjgTZdTb_qL" outputId="50b2f102-ced4-4d44-af27-b295b317fa88"
vocab_size = len(tokenizer.word_index) + 1
n_class = len(labels)
model = build_model(vocab_size, max_sequence_length, n_class)
model.summary()

# + colab={"base_uri": "https://localhost:8080/"} id="MIUWgSLScEX6" outputId="4eda0464-e127-4cd0-ecce-13d99bdb85ab"
batch_size = 1024
epochs = 20

# fitting the model 
history = model.fit(pad_sequences, 
                    y=df[labels],
                    batch_size=batch_size,
                    epochs=epochs, 
                    validation_split=0.1,
                    shuffle = True
                    )

# + colab={"base_uri": "https://localhost:8080/", "height": 295} id="Z17qdhCqf8w9" outputId="9998b38e-d29b-4ffe-9a8d-f267a6fc5d31"
# plotting training and validation accuracy 
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Metric Value')
plt.legend()
plt.show()

# + colab={"base_uri": "https://localhost:8080/", "height": 295} id="tA9uXW8cgR9S" outputId="4802ed36-8420-44c8-e0b3-6b708ff68465"
# plotting training and validation precision 
plt.plot(history.history['precision'], label='Training Precision')
plt.plot(history.history['val_precision'], label='Validation Precision')
plt.title('Training and Validation Precision')
plt.xlabel('Epoch')
plt.ylabel('Metric Value')
plt.legend()
plt.show()

# + colab={"base_uri": "https://localhost:8080/", "height": 295} id="qKuwMZiQhPGx" outputId="97065b0b-9eaf-4f30-a4a6-6f990e4de326"
# plotting training and validation recall 
plt.plot(history.history['recall'], label='Training Recall')
plt.plot(history.history['val_recall'], label='Validation Recall')
plt.title('Training and Validation Recall')
plt.xlabel('Epoch')
plt.ylabel('Metric Value')
plt.legend()
plt.show()


# + id="nxdpbTrHipQ4"
# defining f1 score 
def f1(prec, recall):
    return (2 * prec * recall) / (prec + recall)


# + colab={"base_uri": "https://localhost:8080/", "height": 111} id="x6gDmyPvEjd1" outputId="8f500c5b-c902-4240-b0ec-455855b9dbec"
# final scores 
pd.DataFrame(dict({
    'precision': [history.history["precision"][-1], history.history["val_precision"][-1]], 
    'recall': [history.history["recall"][-1], history.history["val_recall"][-1]], 
    'f1': [f1(history.history["precision"][-1],history.history["recall"][-1]), f1(history.history["val_precision"][-1],history.history["val_recall"][-1])], 
}), index = ['train', 'validation'])

StarcoderdataJupyterScriptsDedupFiltered