{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "8DfEKlbt_TMI", "outputId": "79666846-0691-490a-88b0-5f56f4769772" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Mounted at /content/drive/\n" ] } ], "source": [ "from google.colab import drive\n", "drive.mount('/content/drive/')" ], "id": "8DfEKlbt_TMI" }, { "cell_type": "markdown", "metadata": { "id": "8c25705b" }, "source": [ "# 1. Import libraries and load data" ], "id": "8c25705b" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "5b07ecd3" }, "outputs": [], "source": [ "import os\n", "import pandas as pd\n", "import tensorflow as tf\n", "import numpy as np" ], "id": "5b07ecd3" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "91d7e1f0" }, "outputs": [], "source": [ "df = pd.read_csv(os.path.join(\"/content/drive/MyDrive/ColabNotebooks/data\", \"train.csv\"))" ], "id": "91d7e1f0" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 815 }, "id": "1be479a4", "outputId": "88d487c7-8f13-43fe-e866-3c472a6f03d9" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " id comment_text \\\n", "0 0000997932d777bf Explanation\\nWhy the edits made under my usern... \n", "1 000103f0d9cfb60f D'aww! He matches this background colour I'm s... \n", "2 000113f07ec002fd Hey man, I'm really not trying to edit war. It... \n", "3 0001b41b1c6bb37e \"\\nMore\\nI can't make any real suggestions on ... \n", "4 0001d958c54c6e35 You, sir, are my hero. Any chance you remember... \n", "... ... ... \n", "159566 ffe987279560d7ff \":::::And for the second time of asking, when ... \n", "159567 ffea4adeee384e90 You should be ashamed of yourself \\n\\nThat is ... \n", "159568 ffee36eab5c267c9 Spitzer \\n\\nUmm, theres no actual article for ... \n", "159569 fff125370e4aaaf3 And it looks like it was actually you who put ... \n", "159570 fff46fc426af1f9a \"\\nAnd ... I really don't think you understand... \n", "\n", " toxic severe_toxic obscene threat insult identity_hate \n", "0 0 0 0 0 0 0 \n", "1 0 0 0 0 0 0 \n", "2 0 0 0 0 0 0 \n", "3 0 0 0 0 0 0 \n", "4 0 0 0 0 0 0 \n", "... ... ... ... ... ... ... \n", "159566 0 0 0 0 0 0 \n", "159567 0 0 0 0 0 0 \n", "159568 0 0 0 0 0 0 \n", "159569 0 0 0 0 0 0 \n", "159570 0 0 0 0 0 0 \n", "\n", "[159571 rows x 8 columns]" ], "text/html": [ "\n", "
\n", "
\n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idcomment_texttoxicsevere_toxicobscenethreatinsultidentity_hate
00000997932d777bfExplanation\\nWhy the edits made under my usern...000000
1000103f0d9cfb60fD'aww! He matches this background colour I'm s...000000
2000113f07ec002fdHey man, I'm really not trying to edit war. It...000000
30001b41b1c6bb37e\"\\nMore\\nI can't make any real suggestions on ...000000
40001d958c54c6e35You, sir, are my hero. Any chance you remember...000000
...........................
159566ffe987279560d7ff\":::::And for the second time of asking, when ...000000
159567ffea4adeee384e90You should be ashamed of yourself \\n\\nThat is ...000000
159568ffee36eab5c267c9Spitzer \\n\\nUmm, theres no actual article for ...000000
159569fff125370e4aaaf3And it looks like it was actually you who put ...000000
159570fff46fc426af1f9a\"\\nAnd ... I really don't think you understand...000000
\n", "

159571 rows × 8 columns

\n", "
\n", " \n", " \n", " \n", "\n", " \n", "
\n", "
\n", " " ] }, "metadata": {}, "execution_count": 4 } ], "source": [ "df" ], "id": "1be479a4" }, { "cell_type": "markdown", "metadata": { "id": "e352d92f" }, "source": [ "# 2. Preprocessing" ], "id": "e352d92f" }, { "cell_type": "markdown", "metadata": { "id": "dc5fe893" }, "source": [ "## 2.1. Data overview" ], "id": "dc5fe893" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "ea6fd11e", "outputId": "adb8a890-565d-4e5b-da14-d7f11db89735" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " toxic severe_toxic obscene threat insult identity_hate\n", "0 0 0 0 0 0 0\n", "1 0 0 0 0 0 0\n", "2 0 0 0 0 0 0\n", "3 0 0 0 0 0 0\n", "4 0 0 0 0 0 0\n", "... ... ... ... ... ... ...\n", "159566 0 0 0 0 0 0\n", "159567 0 0 0 0 0 0\n", "159568 0 0 0 0 0 0\n", "159569 0 0 0 0 0 0\n", "159570 0 0 0 0 0 0\n", "\n", "[159571 rows x 6 columns]" ], "text/html": [ "\n", "
\n", "
\n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
toxicsevere_toxicobscenethreatinsultidentity_hate
0000000
1000000
2000000
3000000
4000000
.....................
159566000000
159567000000
159568000000
159569000000
159570000000
\n", "

159571 rows × 6 columns

\n", "
\n", " \n", " \n", " \n", "\n", " \n", "
\n", "
\n", " " ] }, "metadata": {}, "execution_count": 5 } ], "source": [ "df[df.columns[2:]]" ], "id": "ea6fd11e" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 389 }, "id": "7eb94a81", "outputId": "c765800b-02a7-4e91-fe92-ae13b8d943ba" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " id comment_text \\\n", "6 0002bcb3da6cb337 COCKSUCKER BEFORE YOU PISS AROUND ON MY WORK \n", "12 0005c987bdfc9d4b Hey... what is it..\\n@ | talk .\\nWhat is it...... \n", "16 0007e25b2121310b Bye! \\n\\nDon't look, come or think of comming ... \n", "42 001810bf8c45bf5f You are gay or antisemmitian? \\n\\nArchangel WH... \n", "43 00190820581d90ce FUCK YOUR FILTHY MOTHER IN THE ASS, DRY! \n", "\n", " toxic severe_toxic obscene threat insult identity_hate \n", "6 1 1 1 0 1 0 \n", "12 1 0 0 0 0 0 \n", "16 1 0 0 0 0 0 \n", "42 1 0 1 0 1 1 \n", "43 1 0 1 0 1 0 " ], "text/html": [ "\n", "
\n", "
\n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idcomment_texttoxicsevere_toxicobscenethreatinsultidentity_hate
60002bcb3da6cb337COCKSUCKER BEFORE YOU PISS AROUND ON MY WORK111010
120005c987bdfc9d4bHey... what is it..\\n@ | talk .\\nWhat is it......100000
160007e25b2121310bBye! \\n\\nDon't look, come or think of comming ...100000
42001810bf8c45bf5fYou are gay or antisemmitian? \\n\\nArchangel WH...101011
4300190820581d90ceFUCK YOUR FILTHY MOTHER IN THE ASS, DRY!101010
\n", "
\n", " \n", " \n", " \n", "\n", " \n", "
\n", "
\n", " " ] }, "metadata": {}, "execution_count": 6 } ], "source": [ "df.loc[df.iloc[:, 2]==1].head()" ], "id": "7eb94a81" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 87 }, "id": "2bb35d57", "outputId": "c9531968-a5f4-4348-a833-4a366ee59010" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "'Hey... what is it..\\n@ | talk .\\nWhat is it... an exclusive group of some WP TALIBANS...who are good at destroying, self-appointed purist who GANG UP any one who asks them questions abt their ANTI-SOCIAL and DESTRUCTIVE (non)-contribution at WP?\\n\\nAsk Sityush to clean up his behavior than issue me nonsensical warnings...'" ], "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" } }, "metadata": {}, "execution_count": 7 } ], "source": [ "df.iloc[12].comment_text" ], "id": "2bb35d57" }, { "cell_type": "markdown", "metadata": { "id": "1fdd25c4" }, "source": [ "## 2.2. Data preprocessing" ], "id": "1fdd25c4" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "c8bd9d59" }, "outputs": [], "source": [ "from tensorflow.keras.layers import TextVectorization" ], "id": "c8bd9d59" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "b8c03840", "outputId": "d16ec2c2-b1d1-4956-a11b-6f8e1960a5b8" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "Index(['id', 'comment_text', 'toxic', 'severe_toxic', 'obscene', 'threat',\n", " 'insult', 'identity_hate'],\n", " dtype='object')" ] }, "metadata": {}, "execution_count": 9 } ], "source": [ "df.columns" ], "id": "b8c03840" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2e64c456" }, "outputs": [], "source": [ "X = df.comment_text\n", "y = df.iloc[:,2:].values" ], "id": "2e64c456" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "c924ed65" }, "outputs": [], "source": [ "# number of words in vocab\n", "MAX_VOCAB = 200000" ], "id": "c924ed65" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "d9e74b26" }, "outputs": [], "source": [ "vectorizer = TextVectorization(max_tokens=MAX_VOCAB, \n", " output_sequence_length=1800, \n", " output_mode='int')" ], "id": "d9e74b26" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "b89a019a" }, "outputs": [], "source": [ "vectorizer.adapt(X.values)" ], "id": "b89a019a" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "832c78b5", "outputId": "c5d8489f-1b6e-4bcc-e4e8-42359d85c4ce" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": {}, "execution_count": 14 } ], "source": [ "vectorizer('Hello world, welcome to this project')[:6]" ], "id": "832c78b5" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "d90fea8a" }, "outputs": [], "source": [ "processed_text = vectorizer(X.values)" ], "id": "d90fea8a" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "9891f1b3", "outputId": "16715f82-cc03-4bc9-bc4c-0d964111d0d3" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": {}, "execution_count": 16 } ], "source": [ "processed_text" ], "id": "9891f1b3" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9176a3c0" }, "outputs": [], "source": [ "# MCSHBAP - map, cache, shuffle, batch, prefetch\n", "# from_tensor_slices OR list_file\n", "data = tf.data.Dataset.from_tensor_slices((processed_text, y))\n", "data = data.cache()\n", "data = data.shuffle(160000)\n", "data = data.batch(16)\n", "data = data.prefetch(8) # prevent bottleneck" ], "id": "9176a3c0" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "042126d5" }, "outputs": [], "source": [ "batch_X, batch_y = data.as_numpy_iterator().next()" ], "id": "042126d5" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "5b73aea2", "outputId": "be6a586c-2d6e-459a-8748-ae4b4ec03125" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(16, 1800)" ] }, "metadata": {}, "execution_count": 19 } ], "source": [ "batch_X.shape" ], "id": "5b73aea2" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "8286ce71" }, "outputs": [], "source": [ "train = data.take(int(len(data) * .7))\n", "val = data.skip(int(len(data) * .7)).take(int(len(data)*.2))\n", "test = data.take(int(len(data) * .9)).take(int(len(data)*.1))" ], "id": "8286ce71" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "f06e8067", "outputId": "8dadd560-5bfb-4d58-8301-d9f56f30a0b0" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "6981" ] }, "metadata": {}, "execution_count": 21 } ], "source": [ "len(train)" ], "id": "f06e8067" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "74d5fb4e", "outputId": "7ddc0d55-360e-4283-a955-ce3dab49fc07" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(array([[ 5495, 51, 29, ..., 0, 0, 0],\n", " [ 33, 7, 69, ..., 0, 0, 0],\n", " [ 24, 1805, 2256, ..., 0, 0, 0],\n", " ...,\n", " [ 46, 1377, 31, ..., 0, 0, 0],\n", " [ 4354, 41514, 8, ..., 0, 0, 0],\n", " [ 215, 8, 477, ..., 0, 0, 0]]),\n", " array([[0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0]]))" ] }, "metadata": {}, "execution_count": 22 } ], "source": [ "train.as_numpy_iterator().next()" ], "id": "74d5fb4e" }, { "cell_type": "markdown", "metadata": { "id": "-8f_Bi-OAc03" }, "source": [ "# 3. Buiding model" ], "id": "-8f_Bi-OAc03" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ItiVy4-S1pK5" }, "outputs": [], "source": [ "from tensorflow.keras.models import Sequential\n", "from tensorflow.keras.layers import LSTM, Dropout, Bidirectional, Dense, Embedding" ], "id": "ItiVy4-S1pK5" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "8U9TmSbxAvEw" }, "outputs": [], "source": [ "model = Sequential()\n", "model.add(Embedding(MAX_VOCAB + 1, 32))\n", "model.add(Bidirectional(LSTM(32, activation='tanh')))\n", "model.add(Dense(128, activation='relu'))\n", "model.add(Dense(256, activation='relu'))\n", "model.add(Dense(128, activation='relu'))\n", "model.add(Dense(64, activation='relu'))\n", "model.add(Dense(32, activation='relu'))\n", "model.add(Dense(6, activation='sigmoid'))" ], "id": "8U9TmSbxAvEw" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pF_pooL4CY91" }, "outputs": [], "source": [ "model.compile(loss='BinaryCrossentropy', optimizer='Adam')" ], "id": "pF_pooL4CY91" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "ZtPm1Gp2GJza", "outputId": "222a35f6-4ad4-4c16-a240-3a18c0392525" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Model: \"sequential_2\"\n", "_________________________________________________________________\n", " Layer (type) Output Shape Param # \n", "=================================================================\n", " embedding_2 (Embedding) (None, None, 32) 6400032 \n", " \n", " bidirectional_2 (Bidirectio (None, 64) 16640 \n", " nal) \n", " \n", " dense_12 (Dense) (None, 128) 8320 \n", " \n", " dense_13 (Dense) (None, 256) 33024 \n", " \n", " dense_14 (Dense) (None, 128) 32896 \n", " \n", " dense_15 (Dense) (None, 64) 8256 \n", " \n", " dense_16 (Dense) (None, 32) 2080 \n", " \n", " dense_17 (Dense) (None, 6) 198 \n", " \n", "=================================================================\n", "Total params: 6,501,446\n", "Trainable params: 6,501,446\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "model.summary()" ], "id": "ZtPm1Gp2GJza" }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Cu-uCQaEJpjK", "outputId": "dd00becf-d085-47d2-ad04-fc121471ebef" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Epoch 1/10\n", "6981/6981 [==============================] - 642s 92ms/step - loss: 0.0645 - val_loss: 0.0441\n", "Epoch 2/10\n", "6981/6981 [==============================] - 639s 91ms/step - loss: 0.0458 - val_loss: 0.0398\n", "Epoch 3/10\n", "6981/6981 [==============================] - 660s 94ms/step - loss: 0.0412 - val_loss: 0.0366\n", "Epoch 4/10\n", "6981/6981 [==============================] - 639s 91ms/step - loss: 0.0371 - val_loss: 0.0335\n", "Epoch 5/10\n", "6981/6981 [==============================] - 648s 93ms/step - loss: 0.0335 - val_loss: 0.0297\n", "Epoch 6/10\n", "6981/6981 [==============================] - 634s 91ms/step - loss: 0.0307 - val_loss: 0.0261\n", "Epoch 7/10\n", "6981/6981 [==============================] - 634s 91ms/step - loss: 0.0278 - val_loss: 0.0254\n", "Epoch 8/10\n", "6981/6981 [==============================] - 634s 91ms/step - loss: 0.0252 - val_loss: 0.0231\n", "Epoch 9/10\n", "6981/6981 [==============================] - 623s 89ms/step - loss: 0.0234 - val_loss: 0.0193\n", "Epoch 10/10\n", "6981/6981 [==============================] - 627s 90ms/step - loss: 0.0214 - val_loss: 0.0197\n" ] } ], "source": [ "history = model.fit(train, epochs=10, validation_data=val)" ], "id": "Cu-uCQaEJpjK" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Ylqg0nwFGPBL" }, "outputs": [], "source": [ "import matplotlib.pyplot as plt" ], "id": "Ylqg0nwFGPBL" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "cD_u8JR4OYFL", "colab": { "base_uri": "https://localhost:8080/", "height": 282 }, "outputId": "61bab891-c2a2-44f4-afa4-c17e7aa37f05" }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": [ "
" ] }, "metadata": {} }, { "output_type": "display_data", "data": { "text/plain": [ "
" ], "image/png": "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\n" }, "metadata": { "needs_background": "light" } } ], "source": [ "plt.figure(figsize=(8, 5))\n", "pd.DataFrame(history.history).plot()\n", "plt.show()" ], "id": "cD_u8JR4OYFL" }, { "cell_type": "markdown", "metadata": { "id": "OJxNheOEVGoD" }, "source": [ "# 4. Make predictions" ], "id": "OJxNheOEVGoD" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qAlM31wVVFIx", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "86d60e93-348e-478b-991c-d5e86693157a" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": {}, "execution_count": 64 } ], "source": [ "text = vectorizer(\"you shit\")\n", "text" ], "id": "qAlM31wVVFIx" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "5Nlk_v_Da-Pi", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "ad328b76-840f-44e9-d048-23d6d5443cd9" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "array([[ 7, 318, 0, ..., 0, 0, 0]])" ] }, "metadata": {}, "execution_count": 65 } ], "source": [ "np.expand_dims(text, 0)" ], "id": "5Nlk_v_Da-Pi" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ReideBKOVhAY", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "5e6e9aab-332b-4de0-a590-f55d2dc6bfdf" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "array([[0.9876286 , 0.15251058, 0.9701179 , 0.0023339 , 0.33286613,\n", " 0.00344882]], dtype=float32)" ] }, "metadata": {}, "execution_count": 66 } ], "source": [ "res = model.predict(np.expand_dims(text, 0))\n", "res" ], "id": "ReideBKOVhAY" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "-uAI_l6XVvMC", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "76562f4d-0884-4e9b-96e9-351bc933a66e" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "Index(['toxic', 'severe_toxic', 'obscene', 'threat', 'insult',\n", " 'identity_hate'],\n", " dtype='object')" ] }, "metadata": {}, "execution_count": 67 } ], "source": [ "df.columns[2:]" ], "id": "-uAI_l6XVvMC" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ROi-r6MGVT1T" }, "outputs": [], "source": [ "batch_X, batch_y = test.as_numpy_iterator().next()" ], "id": "ROi-r6MGVT1T" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "vcTgLwQjYehR", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "8b25d0d8-bbe4-49ac-e67f-e8a929524bae" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "array([[0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [1, 0, 1, 0, 1, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0],\n", " [0, 0, 0, 0, 0, 0]])" ] }, "metadata": {}, "execution_count": 69 } ], "source": [ "pred = (model.predict(batch_X) > 0.5).astype(int)\n", "pred" ], "id": "vcTgLwQjYehR" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "kVWGgNWxc1LY", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "8be7ac60-e9d2-4007-9c06-358f1a58ab89" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0])" ] }, "metadata": {}, "execution_count": 70 } ], "source": [ "pred = pred.flatten()\n", "pred" ], "id": "kVWGgNWxc1LY" }, { "cell_type": "markdown", "metadata": { "id": "INW-U2pcaXHV" }, "source": [ "# 5. Evaluate model" ], "id": "INW-U2pcaXHV" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "6UfuO4WBaWre" }, "outputs": [], "source": [ "from tensorflow.keras.metrics import Precision, Recall, CategoricalAccuracy" ], "id": "6UfuO4WBaWre" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "zJ-1rJDuaJCp" }, "outputs": [], "source": [ "pre = Precision()\n", "re = Recall()\n", "acc = CategoricalAccuracy()" ], "id": "zJ-1rJDuaJCp" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "sQFmLI5JbQJZ" }, "outputs": [], "source": [ "for batch in test.as_numpy_iterator():\n", " X_true, y_true = batch\n", " pred = model.predict(X_true)\n", "\n", " y_true = y_true.flatten()\n", " pred = pred.flatten()\n", "\n", " pre.update_state(y_true, pred)\n", " re.update_state(y_true, pred)\n", " acc.update_state(y_true, pred)" ], "id": "sQFmLI5JbQJZ" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TRs7GXOddNAw", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "95910681-d680-4272-94bd-c6a94b4bfcc0" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Precision: 0.9102380275726318, Recall: 0.9139072895050049, Accuracy: 0.49949848651885986\n" ] } ], "source": [ "print(f\"Precision: {pre.result().numpy()}, Recall: {re.result().numpy()}, Accuracy: {acc.result().numpy()}\")" ], "id": "TRs7GXOddNAw" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "1oEUJDL5eymH" }, "outputs": [], "source": [ "model.save('toxic-detect.h5')" ], "id": "1oEUJDL5eymH" }, { "cell_type": "markdown", "metadata": { "id": "jFglatzteIXT" }, "source": [ "# 5. Test and Gradio" ], "id": "jFglatzteIXT" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Tg_jFNCOdC3V" }, "outputs": [], "source": [ "!pip install gradio jinja2" ], "id": "Tg_jFNCOdC3V" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "dKH2Er6Eenim" }, "outputs": [], "source": [ "import gradio as gr" ], "id": "dKH2Er6Eenim" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "JES3zWnRfHKt" }, "outputs": [], "source": [ "model = tf.keras.models.load_model('toxic-detect.h5')" ], "id": "JES3zWnRfHKt" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "q_zuX1vVfYHq" }, "outputs": [], "source": [ "def evaluate_comment(Comment):\n", " processed_Comment = vectorizer([Comment])\n", " res = model.predict(processed_Comment)\n", "\n", " text = ''\n", " for i, col in enumerate(df.columns[2:]):\n", " text += '{}: {}\\n'.format(col, 'Violate' if res[0][i] > 0.5 else 'None')\n", " \n", " return text" ], "id": "q_zuX1vVfYHq" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TpJeqs__gsCh" }, "outputs": [], "source": [ "interface = gr.Interface(fn = evaluate_comment, \n", " inputs = gr.inputs.Textbox(lines = 4, placeholder='Comment to evaluate'), \n", " outputs = 'text')" ], "id": "TpJeqs__gsCh" }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "a3DOdPazhGuW" }, "outputs": [], "source": [ "interface.launch(share=True)" ], "id": "a3DOdPazhGuW" } ], "metadata": { "accelerator": "GPU", "colab": { "collapsed_sections": [], "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" } }, "nbformat": 4, "nbformat_minor": 5 }