{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Disaster Watcher \n", "\n", "## Disaster Identification using Tweeter Data and Deep Learning" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The sole purpose of this notebook is to presents and outlines the steps that was taken to train the model.\n", "\n", "Due to the large run time, the model training section was not run in this notebook.The actual production jupyter notebook which was trained using google Colab can be found in the [github repo](https://github.com/khordoo/disaster-watch-classifier)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Introduction\n", "Social media is increasingly being used to broadcast useful information during local crisis situations(e.g. hurricanes, earthquakes, explosions, bombings,etc).Identifying disaster related information in social media is challenging due to the low signal-to-noise ratio.In this work we will use NLP to address this challenge. \n", "\n", "Some of the tweets sent from mobile devices can be geotagged containing the precise\n", "location coordinates. However, only about 1% to 3% of all tweets are geotagged.Identifying the disaster related tweets along with their is highly valuable to for the first responders in the disaster and crisis situations.\n", "In this project we fist. identify the disaster related tweets from a deep learning model and then use Named Entity Recognition library to identify and map the location of the data.\n", "\n", "## 2. Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The natural disaster events generally generate a massive and disperse reaction in social media channels.Users usually express their thoughts and actions taken before, during, and after the storm. We \n", "used the classified crisis related tweets collection from the CrisisLex.org which is a repository of crisis-related social media data. \n", "We used the CrisisLexT6 dataset which includes Tweets from 6 crises, labeled by relatedness.\n", "- Contents: ~60K tweets posted during 6 crisis events in 2012 and 2013.\n", "- Labels: ~60,000 tweets (10,000 in each collection) were labeled by crowdsourcing workers according to relatedness (as \"on-topic\", or \"off-topic\").\n", "\n", "The data from the following crisis events were used in this analysis : \n", " - Flood \n", " - Earthquake\n", " - Hurricane\n", " - Tornado\n", " - Explosion\n", " - Bombing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Preprocessing \n", "The preprocessing of the text data is an essential step in any NLP and text classification analysis and machine learning algorithms.[]The objective of this step is to clean noise those are less relevant to find the sentiment of tweets such as punctuation, special characters, numbers, and terms which don’t carry much weightage in context to the text.[]\n", "Lets first import the required packages." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "%%capture\n", "%matplotlib inline\n", "\n", "import os\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "import tensorflow as tf\n", "from sklearn.base import TransformerMixin ,BaseEstimator\n", "from sklearn.pipeline import Pipeline\n", "from sklearn.preprocessing import LabelEncoder\n", "from sklearn.model_selection import train_test_split\n", "from tensorflow.keras.utils import to_categorical\n", "from tensorflow.keras.preprocessing.sequence import pad_sequences\n", "from tensorflow.keras.models import Sequential ,model_from_json\n", "from tensorflow.keras.layers import Embedding,Dense,Dropout ,GlobalMaxPool1D\n", "\n", "from IPython.display import clear_output\n", "from tensorflow.keras.wrappers.scikit_learn import KerasClassifier\n", "from sklearn.model_selection import RandomizedSearchCV" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3.1 Loading\n", "The data are stored in 11 csv formated files.We first load this data and then save it into a single combined file for further analysis.The name of the file is the same as the name of the crisis.The Tweets in each files has been labeled as \"on-topic\" or \"off-topic\" and do not contains information about the type of the crisis.However, the the type of the crisis is represented in the file name.We will use these file name to assign proper labels to each category.\n", "First lets load the data and have quick look at it.\n", "\n", "We will be using the Pipeline from Sklean library to streamline the preprocessing routine. As a result the the classes in the analysis should be compatible with the pipeline arcitecture." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "COMBINDED_DATASET='combined.csv'\n", "DATA_DIRECTORY='../datasets'\n", "class DatasetExtractor(BaseEstimator,TransformerMixin):\n", " \"\"\"Extractor class that loads multiple Tweet files and creates a single unified file.\"\"\"\n", " \n", " def transform(self,X,y=None):\n", " return self.hot_load()\n", " \n", " def hot_load(self):\n", " \"\"\"Loads the pre-combined file if exists otherwise load all the files\"\"\"\n", " combined_file_path=f'{DATA_DIRECTORY}/{COMBINDED_DATASET}'\n", " if os.path.isfile(combined_file_path):\n", " print('File Exists.Reloaded.')\n", " return pd.read_csv(combined_file_path, index_col=0)\n", " print('Loading Files..')\n", " combined_dataset=self.load_data()\n", " combined_dataset.to_csv(combined_file_path)\n", " return combined_dataset\n", " \n", " def load_data(self):\n", " \"\"\"Loads multiple disaster related tweet file and returns a Single Pandas data frame\"\"\" \n", " combined_dataset=pd.DataFrame()\n", " for file_name in os.listdir(path=DATA_DIRECTORY):\n", " category=self.extract_category_name(file_name)\n", " df=pd.read_csv(f'{DATA_DIRECTORY}/{file_name}')\n", " df['category']= category \n", " combined_dataset=combined_dataset.append(df,ignore_index = True)\n", " return combined_dataset \n", " \n", " def extract_category_name(self,file_name):\n", " \"\"\"Helper method that extracts the Disaster Category from the file name\"\"\"\n", " category=file_name.split('.')[0]\n", " if '_' in category:\n", " category=category.split('_')[0]\n", " return category " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the purpose of demonstration We load each part of the pipeline to provide explanation and explanation about each part separately .Ultimately we chain all of these methods into a pipeline for the final modeling. \n", "Lets load the data and see how it looks like:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File Exists.Reloaded.\n" ] }, { "data": { "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", "
tweet idtweetlabelcategory
0'348351442404376578'@Jay1972Jay Nope. Mid 80's. It's off Metallica...off-topicfloods
1'348167215536803841'Nothing like a :16 second downpour to give us ...off-topicfloods
2'348644655786778624'@NelsonTagoona so glad that you missed the flo...on-topicfloods
3'350519668815036416'Party hard , suns down , still warm , lovin li...off-topicfloods
4'351446519733432320'@Exclusionzone if you compare yourself to wate...off-topicfloods
\n", "
" ], "text/plain": [ " tweet id tweet \\\n", "0 '348351442404376578' @Jay1972Jay Nope. Mid 80's. It's off Metallica... \n", "1 '348167215536803841' Nothing like a :16 second downpour to give us ... \n", "2 '348644655786778624' @NelsonTagoona so glad that you missed the flo... \n", "3 '350519668815036416' Party hard , suns down , still warm , lovin li... \n", "4 '351446519733432320' @Exclusionzone if you compare yourself to wate... \n", "\n", " label category \n", "0 off-topic floods \n", "1 off-topic floods \n", "2 on-topic floods \n", "3 off-topic floods \n", "4 off-topic floods " ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dataset=DatasetExtractor().transform(None)\n", "dataset.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As mentioned, the data consistes of the following features: \n", " - tweet id\n", " - tweet\n", " - label \n", " - category\n", " \n", " The category feature was inferred from the file name and added to the data during the loading. The labels were assigned using human labels for each crisis.We will only use the \"on-topic\" tweets from each category.All the \"off-topic\" tweets would be combined and would be classified as the \"unrelated\".\n", " \n", "## 3.2 Data Cleaning\n", "\n", "#### 3.3.1 Text cleaning\n", "Tweets can contain many different kind of noise that can negatively affect the performance of the machine learning algorithms . We need to carefully get rid of them. We will use the of regular expressions and replace functionality in Pandas to remove the unwanted noise in the data.\n", "\n", "#### 3.3.1 Re-Tweets:\n", "They add no real value to the data and can sometimes lead to overfitting \n", "\n", "#### 3.3.2 URL's\n", "They do not deliver any predictive power, The sentiment of a tweet can not be judged by reading an URL. In the worst case scenario they might lead to overfitting.\n", "\n", "`df['tweet']=df['tweet'].str.replace('http\\S+', '',regex=True)`\n", "#### 3.3.3 Symbols\n", "Hashtags, commas, points and and all kind of punctuation symbols are removed.\n", "\n", "`df['tweet']=df['tweet'].str.replace('[^a-zA-Z\\s]', '',regex=True)`\n", "\n", "#### 3.3.3 White Spaces\n", "We also get ride of any additional white spaces in the texts that might be created due to the previous steps.\n", "\n", "`df['tweet']=df['tweet'].str.strip()`\n", "\n", "`df['tweet']=df['tweet'].str.replace('\\s+', '',regex=True)`\n", "\n", "#### 3.3.4 Lower case\n", "All texts are transformed to lowercase.\n", "\n", "#### 3.3.4 Location Names\n", "The names of the location which disaster happened were repeated in so many tweets.We want to prevent the model from associating these location names with the crisis and as a result we remove the most frequent ones from the Tweets.\n", "The follwing list of words were removed from the Tweets:\n", "\n", "*[\"Boston\", \"Oklahoma\",\"Texas\",\"Nepal\",\"California\",\"Calgary\",\"Chile\",\"Alberta\",\"Pakistan\" ,\"WestTX\",\"Canada\",\"yycflood\",\"USA\",\"'S\",]*\n", " " ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "STOP_WORDS=[\"Boston\", \"Oklahoma\",\"Texas\",\"Nepal\",\"California\",\"Calgary\",\"Chile\",\"Alberta\",\"Pakistan\" ,\"WestTX\",\"Canada\",\"yycflood\",\"USA\",\"'S\",]\n", "class DatasetCleaner(BaseEstimator,TransformerMixin):\n", " \"\"\"Removes Redundent features and rows with missing values\"\"\"\n", " def transform(self,X,y=None):\n", " columns=X.columns.tolist()\n", " X.columns=[column.strip() for column in columns]\n", " X=X.drop('tweet id',axis=1)\n", " X=X.dropna()\n", " X['tweet']=X['tweet'].str.replace('@', '')\n", " X['tweet']=X['tweet'].str.replace('#', '')\n", " X['tweet']=X['tweet'].str.replace('.', '')\n", " X['tweet']=X['tweet'].str.replace(',', '')\n", " X['tweet']=X['tweet'].str.replace('http\\S+', '',regex=True)\n", " X['tweet']=X['tweet'].str.replace('@\\w+', '',regex=True)\n", " X['tweet']=X['tweet'].str.replace('\\s+', '',regex=True)\n", " X['tweet']=X['tweet'].str.strip()\n", " X['tweet']=X['tweet'].str.lower()\n", " for word in STOP_WORDS:\n", " word=word.lower()\n", " X['tweet']=X['tweet'].str.replace(word, '') \n", " return X" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "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", "
tweetlabelcategory
0jay1972jaynopemid80itoffmetallica2ndalbumridet...off-topicfloods
1nothinglikea:16seconddownpourtogiveussomemuchn...off-topicfloods
2nelsontagoonasogladthatyoumissedthefloodsandsa...on-topicfloods
3partyhardsunsdownstillwarmlovinlifesmileharddo...off-topicfloods
4exclusionzoneifyoucompareyourselftowaterdoesth...off-topicfloods
\n", "
" ], "text/plain": [ " tweet label category\n", "0 jay1972jaynopemid80itoffmetallica2ndalbumridet... off-topic floods\n", "1 nothinglikea:16seconddownpourtogiveussomemuchn... off-topic floods\n", "2 nelsontagoonasogladthatyoumissedthefloodsandsa... on-topic floods\n", "3 partyhardsunsdownstillwarmlovinlifesmileharddo... off-topic floods\n", "4 exclusionzoneifyoucompareyourselftowaterdoesth... off-topic floods" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dataset_cleaned=DatasetCleaner().transform(dataset)\n", "dataset_cleaned.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " ## 3.3 Re-Sampling\n", "Lets take a look to see how many Tweets do we have in each category regardless of being on or off topic.We want to make sure the number of tweets in each category are in the same order and we have a balanced dataset.We would also shuffle the tweets to make sure that the tweets have no particular order.\n", "Lets first see how many tweets we have in each category.This would be total number of tweets.Each file has **on-topic** and **off-topic** tweets which is the way they have been labeled by human labelers." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "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", "
CrisisTweet Count
0floods20064
1bombing10012
2hurricane10008
3explosion10006
4tornado9992
5earthquake9057
\n", "
" ], "text/plain": [ " Crisis Tweet Count\n", "0 floods 20064\n", "1 bombing 10012\n", "2 hurricane 10008\n", "3 explosion 10006\n", "4 tornado 9992\n", "5 earthquake 9057" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Crisis=pd.DataFrame(dataset['category'].value_counts())\n", "Crisis.reset_index(inplace=True)\n", "Crisis.rename(columns={'index':'Crisis',\"category\":'Tweet Count'} ,inplace=True)\n", "Crisis" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 0, ' ')" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "f,ax =plt.subplots(figsize=(15,7))\n", "sns.barplot(x='Crisis',y='Tweet Count',data=Crisis ,palette=sns.light_palette((210, 90, 60),10, input=\"husl\" ,reverse=True),ax=ax)\n", "ax.set_xlabel(' ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 3.3.1 All Tweets ( On-Topic and off-Topic ) for each category \n", "\n", "As you can see we have roughly about 10,000 tweets for each crisis, except floods.As a next step lets see how many related (on-topic) Tweets we have in each category.This is more important since we are only using the on-topic Tweets from each category during the classification." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "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", "
CrisisTweet Count
0on-topic_floods10603
1off-topic_floods9461
2on-topic_hurricane6138
3on-topic_bombing5648
4on-topic_explosion5246
5off-topic_tornado5165
6on-topic_tornado4827
7off-topic_explosion4760
8on-topic_earthquake4580
9Off-topic_earthquake4475
10off-topic_bombing4364
11off-topic_hurricane3870
\n", "
" ], "text/plain": [ " Crisis Tweet Count\n", "0 on-topic_floods 10603\n", "1 off-topic_floods 9461\n", "2 on-topic_hurricane 6138\n", "3 on-topic_bombing 5648\n", "4 on-topic_explosion 5246\n", "5 off-topic_tornado 5165\n", "6 on-topic_tornado 4827\n", "7 off-topic_explosion 4760\n", "8 on-topic_earthquake 4580\n", "9 Off-topic_earthquake 4475\n", "10 off-topic_bombing 4364\n", "11 off-topic_hurricane 3870" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dataset['label_full']=dataset['label']+'_'+dataset['category']\n", "Crisis_topics=pd.DataFrame(dataset['label_full'].value_counts())\n", "Crisis_topics.drop('On-topic_earthquake',axis=0,inplace=True)\n", "Crisis_topics.reset_index(inplace=True)\n", "Crisis_topics.rename(columns={'index':'Crisis',\"label_full\":'Tweet Count'} ,inplace=True)\n", "\n", "Crisis_topics" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'Numer of on-topic and off-topic Tweets in each crisis Category ')" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "f,ax =plt.subplots(figsize=(15,7))\n", "sns.barplot(y='Crisis',x='Tweet Count',data=Crisis_topics ,palette=sns.light_palette((210, 90, 60),20, input=\"husl\" ,reverse=True),ax=ax)\n", "ax.set_xlabel(' ')\n", "ax.set_title('Numer of on-topic and off-topic Tweets in each crisis Category ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 3.3.2 On-Topic Tweets\n", "\n", "Lets take a look at only the on topic Tweets in each Category:\n", "We can see that labels are balanced. We have about 5000 on-topic Tweets in each category(except flood)." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/adminn/.local/lib/python3.6/site-packages/ipykernel_launcher.py:2: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", " \n" ] }, { "data": { "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", "
CrisisTweet CountTweet_pct
0on-topic_floods1060328.624264
2on-topic_hurricane613816.570380
3on-topic_bombing564815.247557
4on-topic_explosion524614.162302
6on-topic_tornado482713.031154
8on-topic_earthquake458012.364343
\n", "
" ], "text/plain": [ " Crisis Tweet Count Tweet_pct\n", "0 on-topic_floods 10603 28.624264\n", "2 on-topic_hurricane 6138 16.570380\n", "3 on-topic_bombing 5648 15.247557\n", "4 on-topic_explosion 5246 14.162302\n", "6 on-topic_tornado 4827 13.031154\n", "8 on-topic_earthquake 4580 12.364343" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Crisis_topics_on_topic= Crisis_topics[Crisis_topics['Crisis'].str.contains(\"on-topic\")]\n", "Crisis_topics_on_topic['Tweet_pct']=Crisis_topics_on_topic['Tweet Count']*100/Crisis_topics_on_topic['Tweet Count'].sum()\n", "Crisis_topics_on_topic" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/plain": [ "Text(0, 0.5, 'Percentage of on-topic Tweets in Each Category')" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "f,ax =plt.subplots(figsize=(15,7))\n", "sns.barplot(x='Crisis',y='Tweet_pct',data=Crisis_topics_on_topic ,palette=sns.light_palette((216, 100, 40), input=\"husl\" ,reverse=True),ax=ax)\n", "ax.set_xlabel(' ')\n", "ax.set_ylabel('Percentage of on-topic Tweets in Each Category')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 3.3.3 Off-Topic Tweets\n", "To avoid overfitting we also use a random set of off-topic tweets from each of the categories.We label all these tweets as **unrelated**. Using these additional label would let the model learn to better distinguish between the related and unrelated tweets for each category.\n", "\n" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total Number of 'Off-Topic' Tweets 32095\n" ] }, { "data": { "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", "
CrisisTweet Count
1off-topic_floods9461
5off-topic_tornado5165
7off-topic_explosion4760
9Off-topic_earthquake4475
10off-topic_bombing4364
\n", "
" ], "text/plain": [ " Crisis Tweet Count\n", "1 off-topic_floods 9461\n", "5 off-topic_tornado 5165\n", "7 off-topic_explosion 4760\n", "9 Off-topic_earthquake 4475\n", "10 off-topic_bombing 4364" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Crisis_topics_off_topic= Crisis_topics[~Crisis_topics['Crisis'].str.contains(\"on-topic\")]\n", "total_off_topic_tweets=Crisis_topics_off_topic['Tweet Count'].sum()\n", "print(\"Total Number of 'Off-Topic' Tweets\",total_off_topic_tweets)\n", "Crisis_topics_off_topic.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### 3.3.3.1 Imbalanced Data\n", "Imbalanced data generally refers to an issue with classification problems where the classes are not represented equally.In our case, since each category has it own off-topic tweets, the total number of off-topic tweets from all of the categories would be way higher than the on-topic tweets in each category.This would make our database highly imbalanced.\n", "\n", "Lets plot the total number of off-topic tweets along with the on-topic tweets.Note that the \"off-topic\" would also be one of our prediction categories, as a result, this category should also have the same number of tweets (roughly) as the other categories. \n", "\n", "Lets label all of these tweets with an *unrelated* label." ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/adminn/.local/lib/python3.6/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", " \"\"\"Entry point for launching an IPython kernel.\n" ] }, { "data": { "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", "
CrisisTweet Count
0unrelated32095
0on-topic_floods10603
2on-topic_hurricane6138
3on-topic_bombing5648
4on-topic_explosion5246
6on-topic_tornado4827
8on-topic_earthquake4580
\n", "
" ], "text/plain": [ " Crisis Tweet Count\n", "0 unrelated 32095\n", "0 on-topic_floods 10603\n", "2 on-topic_hurricane 6138\n", "3 on-topic_bombing 5648\n", "4 on-topic_explosion 5246\n", "6 on-topic_tornado 4827\n", "8 on-topic_earthquake 4580" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Crisis_topics_off_topic['Crisis']='unrelated'\n", "Crisis_topics_off_topic_g=Crisis_topics_off_topic.groupby(by='Crisis').sum()\n", "Crisis_topics_off_topic_g.reset_index(inplace=True)\n", "all_topics =Crisis_topics_off_topic_g.append(Crisis_topics_on_topic[['Crisis','Tweet Count']])\n", "all_topics" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'Imbalanced Dataset: Total Number of Tweets in each category')" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "f,ax =plt.subplots(figsize=(15,7))\n", "blues=sns.light_palette((216, 100, 40),all_topics.shape[0], input=\"husl\" ,reverse=True)\n", "blues[0]=sns.color_palette(\"RdBu\", 10)[0]\n", "sns.barplot(x='Crisis',y='Tweet Count',data=all_topics ,palette=blues, ax=ax)\n", "ax.set_xlabel(' ')\n", "ax.set_ylabel('Number of Tweets')\n", "ax.set_title( 'Imbalanced Dataset: Total Number of Tweets in each category')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### 3.3.3.2 balancing the Data\n", "As we can see the number of *unrelated* tweets are way higher than the actual on topic tweets.To solve the problem, we resample a subset of these these unrelated Tweets.The total number that we re-sample from these unrelated tweets would be equal to the average number of all tweets in each dataset." ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [], "source": [ "class DistributionValidSampler(BaseEstimator,TransformerMixin):\n", " \"\"\"Samples the (related and random ) tweets with equal proportion\"\"\"\n", " def __init__(self,unrelated_size=None ,ignore_unrelated_proportion=True):\n", " self._unrelated_size=unrelated_size\n", " self._ignore_unrelated_proportion=ignore_unrelated_proportion\n", "\n", " \n", " def transform(self,X,y=None):\n", " #Shuffle tweets\n", " X_=X.sample(frac=1).reset_index(drop=True)\n", " X_=self._label_categories(X_) \n", " related,unrelated =self._equal_split(X_)\n", " X_=self._merge(related,unrelated)\n", " X_=X_.drop('category',axis=1) \n", " return X_\n", " \n", " def _label_categories(self,X):\n", " \"\"\"Assings the category name to on-topic tweets and unrelated to off-topic tweets in \n", " each category\n", " \"\"\" \n", " if self._ignore_unrelated_proportion:\n", " X['label']=X.apply(lambda row: row['category'] if 'on-topic' in row['label'] else 'unrelated',axis=1 ) \n", " else:\n", " X['label']=X.apply(lambda row: row['category'] if 'on-topic' in row['label'] else 'unrelated_'+row['category'],axis=1 ) \n", " return X\n", " \n", " def _equal_split(self,X):\n", " \"\"\"Splits the dataseta into related and unrelated tweets.\n", " This ensures that the number of unrelated tweets are not too high and \n", " is in reasonable range.\n", " \"\"\"\n", " related=X[X['label'].str.contains('unrelated')==False]\n", " unrelated=X[X['label'].str.contains('unrelated')]\n", " ave_tweets=self._average_tweet_per_category(X)\n", " unrelated=self._slice(unrelated,size=self._unrelated_size ,ave_size=ave_tweets)\n", " return related,unrelated\n", " \n", " def _merge(self,X1,X2):\n", " \"\"\"Merges the dataframes toghether\"\"\"\n", " X=pd.DataFrame()\n", " X=X.append(X1)\n", " X=X.append(X2)\n", " return X\n", " \n", " def _slice(self,X, size ,ave_size):\n", " \"\"\"Extracts a subset of rows from a dataframe\"\"\"\n", " if size is None:\n", " size =ave_size\n", " if size < X.shape[0]:\n", " return X[:size]\n", " return X \n", " \n", " def _average_tweet_per_category(self,X):\n", " \"\"\"Calculate the average number of tweets across all tweet categories\"\"\"\n", " category_values=pd.DataFrame(X['label'].value_counts())\n", " category_values=category_values.drop('unrelated',axis=0)\n", " return int(category_values['label'].mean())\n", " " ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "scrolled": false }, "outputs": [ { "data": { "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", "
label
floods10603
unrelated6173
hurricane6138
bombing5648
explosion5246
tornado4827
earthquake4580
\n", "
" ], "text/plain": [ " label\n", "floods 10603\n", "unrelated 6173\n", "hurricane 6138\n", "bombing 5648\n", "explosion 5246\n", "tornado 4827\n", "earthquake 4580" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "dataset_resampled=DistributionValidSampler().transform(dataset_cleaned)\n", "dataset_resampled_topics=pd.DataFrame(dataset_resampled['label'].value_counts())\n", "display(dataset_resampled_topics)\n", "dataset_resampled_topics.reset_index(inplace=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets see the number of tweets in each category in the re-sampled dataset:" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'Balanced Dataset: Total Number of Tweets in each category')" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "f,ax =plt.subplots(figsize=(15,7))\n", "blues=sns.light_palette((216, 100, 40),dataset_resampled_topics.shape[0], input=\"husl\" ,reverse=True)\n", "blues[1]=sns.color_palette(\"RdBu\", 10)[0]\n", "sns.barplot(x='index',y='label',data=dataset_resampled_topics ,palette=blues, ax=ax)\n", "ax.set_xlabel(' ')\n", "ax.set_ylabel('Number of Tweets')\n", "ax.set_title( 'Balanced Dataset: Total Number of Tweets in each category')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Data Transformation\n", "### 4.1 Tokenization\n", "One of the common preprocessing task in NLP (Natural Language Processing) is tokenization. Given a character sequence and a defined document unit, tokenization is the task of chopping it up into pieces, called tokens[[1]](https://nlp.stanford.edu/IR-book/html/htmledition/tokenization-1.html)\n", "We used the Tokenizer() class from the Keras Preprocessing to vectorize our text data. It will turn our sentences into sequences of integers.We use 10,000 words for this analysis. \n", "### 4.2 Padding\n", "We pad all the vectorized text sequences with zeros to make all the sequences of the same length. We use the maximum size to be 100." ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [], "source": [ "class TextTokenizer(BaseEstimator,TransformerMixin):\n", " \"\"\"This is a simple Wrapper class for Keras Tokenizer.\"\"\"\n", " def __init__(self,pad_sequences,num_words=10000,max_length=100,max_pad_length=100 ):\n", " self._num_words=num_words\n", " self.max_length=max_length\n", " self._tokenizer=None\n", " self._pad_sequences=pad_sequences\n", " self._max_pad_length=max_pad_length\n", " self.vocab_size=None\n", " self.tokenizer=None\n", " \n", " def transform(self,X,y=None):\n", " self.tokenizer,self.vocab_size=self._get_tokenizer(X['tweet'])\n", " X['tweet_encoded']=self.tokenizer.texts_to_sequences(X['tweet'])\n", " X['tweet_encoded']= X['tweet_encoded'].apply(lambda x: self._pad_sequences([x],maxlen=self._max_pad_length ,padding='post')[0])\n", " \n", " return X\n", " def _get_tokenizer(self,X):\n", " tokenizer=tf.keras.preprocessing.text.Tokenizer(num_words=self._num_words)\n", " tokenizer.fit_on_texts(X)\n", " vocab_size=len(tokenizer.word_index)+1\n", " return tokenizer,vocab_size" ] }, { "cell_type": "code", "execution_count": 118, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vocab Size: 65246\n" ] }, { "data": { "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", "
tweetlabeltweet_encodedlabel_encodedlabel_one_hot
1zooduringfloodmtnatstechysonstaffmemberspentwe...floods[7554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...3[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
4findthelatestlocalfloodinformation:assoutheast...floods[634, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...3[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
5floodvictimslookingtogovernmentforhelp-mostins...floods[2366, 7555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...3[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
7rt911buff::massiveexplosionu/d-localhospitalsn...explosion[41, 1743, 86, 2367, 0, 0, 0, 0, 0, 0, 0, 0, 0...2[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
8caughtoncamera:fertilizerplantexplosionnearwac...explosion[29, 27, 7556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...2[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
\n", "
" ], "text/plain": [ " tweet label \\\n", "1 zooduringfloodmtnatstechysonstaffmemberspentwe... floods \n", "4 findthelatestlocalfloodinformation:assoutheast... floods \n", "5 floodvictimslookingtogovernmentforhelp-mostins... floods \n", "7 rt911buff::massiveexplosionu/d-localhospitalsn... explosion \n", "8 caughtoncamera:fertilizerplantexplosionnearwac... explosion \n", "\n", " tweet_encoded label_encoded \\\n", "1 [7554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", "4 [634, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,... 3 \n", "5 [2366, 7555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", "7 [41, 1743, 86, 2367, 0, 0, 0, 0, 0, 0, 0, 0, 0... 2 \n", "8 [29, 27, 7556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0... 2 \n", "\n", " label_one_hot \n", "1 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] \n", "4 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] \n", "5 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] \n", "7 [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0] \n", "8 [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0] " ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tokenization=TextTokenizer(pad_sequences)\n", "dataset_tokenized=tokenization.transform(dataset_resampled)\n", "vocab_size=tokenization.vocab_size\n", "print('Vocab Size:',vocab_size)\n", "dataset_tokenized.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.3 Label Encoding\n", "In this step all the target labels are converted to integer values.We use the LabelEncoder class from the Sklean package.\n", "\n", "### 4.4 One Hot Encoding \n", "In the next step we use the integer values for labels and create a one hot vector to be used for the machine learning analysis." ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [], "source": [ "class LabelOneHotEncoder(BaseEstimator,TransformerMixin):\n", " \"\"\"Transfroms the Categorical data to One Hot vector\"\"\"\n", " def __init__(self):\n", " self.label_encoder=None\n", " self.one_hot_encoder=None\n", " \n", " def transform(self,X,y=None):\n", " self.label_encoder=LabelEncoder().fit(X['label'])\n", " self.one_hot_encoder=to_categorical\n", " num_classes=len(set(X['label']))\n", " X['label_encoded']= self.label_encoder.transform(X['label'].values)\n", " X['label_one_hot']= X['label_encoded'].apply(lambda x: self.one_hot_encoder([x],num_classes=num_classes)[0]) \n", " \n", " return X" ] }, { "cell_type": "code", "execution_count": 124, "metadata": {}, "outputs": [ { "data": { "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", "
tweetlabeltweet_encodedlabel_encodedlabel_one_hot
1zooduringfloodmtnatstechysonstaffmemberspentwe...floods[7554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...3[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
4findthelatestlocalfloodinformation:assoutheast...floods[634, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...3[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
5floodvictimslookingtogovernmentforhelp-mostins...floods[2366, 7555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...3[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
7rt911buff::massiveexplosionu/d-localhospitalsn...explosion[41, 1743, 86, 2367, 0, 0, 0, 0, 0, 0, 0, 0, 0...2[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
8caughtoncamera:fertilizerplantexplosionnearwac...explosion[29, 27, 7556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...2[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
\n", "
" ], "text/plain": [ " tweet label \\\n", "1 zooduringfloodmtnatstechysonstaffmemberspentwe... floods \n", "4 findthelatestlocalfloodinformation:assoutheast... floods \n", "5 floodvictimslookingtogovernmentforhelp-mostins... floods \n", "7 rt911buff::massiveexplosionu/d-localhospitalsn... explosion \n", "8 caughtoncamera:fertilizerplantexplosionnearwac... explosion \n", "\n", " tweet_encoded label_encoded \\\n", "1 [7554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", "4 [634, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,... 3 \n", "5 [2366, 7555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", "7 [41, 1743, 86, 2367, 0, 0, 0, 0, 0, 0, 0, 0, 0... 2 \n", "8 [29, 27, 7556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0... 2 \n", "\n", " label_one_hot \n", "1 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] \n", "4 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] \n", "5 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] \n", "7 [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0] \n", "8 [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0] " ] }, "execution_count": 124, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encoder=LabelOneHotEncoder()\n", "dataset_encoded=encoder.transform(dataset_resampled)\n", "dataset_encoded.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.3 Word embeddings\n", "\n", "Word Embedding is a representation of text where words that have the same meaning have a similar representation. In other words it represents words in a coordinate system where related words, based on a corpus of relationships, are placed closer together. In the deep learning frameworks such as TensorFlow, Keras, this part is usually handled by an embedding layer which stores a lookup table to map the words represented by numeric indexes to their dense vector representations.[[2]](https://towardsdatascience.com/machine-learning-word-embedding-sentiment-classification-using-keras-b83c28087456)\n", "\n", "Word embeddings can be generated using pre-trained word embeddings such as Glove and Word2Vec. Any one of them can be downloaded and used as transfer learning. In this work we use the Embedding Layer of Keras maps the pre-calculated integers to a dense vector of the embedding.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Train test Data set \n", "In this section we split our data into training and testing datasets.It is important to use a splitting strategy that preserve the percentage of samples for each class.We use the train_test_split tool from the sklean library to achieve this goal.\n", "\n" ] }, { "cell_type": "code", "execution_count": 115, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of Tweets in Training set: 30250\n", "Number of Tweets in Test set: 12965\n" ] } ], "source": [ "X_train,X_test,y_train,y_test =train_test_split(dataset_encoded['tweet_encoded'],dataset_encoded['label_one_hot'],test_size=0.3,stratify=dataset_encoded['label_encoded'])\n", "X_train=np.array(X_train.values.tolist())\n", "X_test=np.array(X_test.values.tolist())\n", "y_train=np.array(y_train.values.tolist())\n", "y_test=np.array(y_test.values.tolist())\n", "print('Number of Tweets in Training set: ',X_train.shape[0])\n", "print('Number of Tweets in Test set: ',X_test.shape[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Modeling \n", "\n", "### 5.1 Model Architecture\n", "For the modeling we will use the Keras's Sequential model API.The Sequential model is essentially a linear stack of layers.We can use different types of available Keras layers in this model.\n" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Model: \"sequential_1\"\n", "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", "embedding (Embedding) (None, 100, 50) 3262300 \n", "_________________________________________________________________\n", "global_max_pooling1d (Global (None, 50) 0 \n", "_________________________________________________________________\n", "dropout (Dropout) (None, 50) 0 \n", "_________________________________________________________________\n", "dense (Dense) (None, 10) 510 \n", "_________________________________________________________________\n", "dropout_1 (Dropout) (None, 10) 0 \n", "_________________________________________________________________\n", "dense_1 (Dense) (None, 7) 77 \n", "=================================================================\n", "Total params: 3,262,887\n", "Trainable params: 3,262,887\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "max_length=100\n", "embeding_dim=50\n", "num_classes=y_train[0].shape[0]\n", "model=Sequential()\n", "model.add(Embedding(input_dim=vocab_size,output_dim=embeding_dim,input_length=max_length))\n", "model.add(GlobalMaxPool1D())\n", "model.add(Dropout(0.3))\n", "model.add(Dense(10,activation='relu'))\n", "model.add(Dropout(0.3))\n", "model.add(Dense(num_classes,activation='softmax'))\n", "model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'] )\n", "model.summary()" ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [], "source": [ "class PlotLosses(tf.keras.callbacks.Callback):\n", " \"\"\"Simple utility function to plot the model losses during training\"\"\"\n", " def on_train_begin(self, logs={}):\n", " self.i = 0\n", " self.x = []\n", " self.losses = []\n", " self.val_losses = []\n", " \n", " self.fig = plt.figure()\n", " \n", " self.logs = []\n", "\n", " def on_epoch_end(self, epoch, logs={}):\n", " \n", " self.logs.append(logs)\n", " self.x.append(self.i)\n", " self.losses.append(logs.get('loss'))\n", " self.val_losses.append(logs.get('val_loss'))\n", " self.i += 1\n", " \n", " clear_output(wait=True)\n", " plt.plot(self.x, self.losses, label=\"loss\")\n", " plt.plot(self.x, self.val_losses, label=\"val_loss\")\n", " plt.legend()\n", " plt.show();\n", "plot_losses = PlotLosses() \n", "\n", "def save_model(model,save_name):\n", " with open(save_name,'w+') as f:\n", " f.write(model.to_json())\n", " model.save_weights(save_name+'.h5') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.2 Training " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "model.fit(X_train,y_train,epochs=2,batch_size=10,verbose=0,validation_data=(X_test,y_test),callbacks=[plot_losses])\n", "save_model(model,'model')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.3 Evaluation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# load json and create model\n", "json_file = open('model', 'r')\n", "loaded_model_json = json_file.read()\n", "json_file.close()\n", "loaded_model = model_from_json(loaded_model_json)\n", "# load weights into new model\n", "loaded_model.load_weights(\"model.h5\")\n", "print(\"Loaded model from disk\")\n", " \n", "# evaluate loaded model on test data\n", "loaded_model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n", "score = loaded_model.evaluate(X_test, y_test, verbose=0)\n", "print(\"%s: %.2f%%\" % (loaded_model.metrics_names[1], score[1]*100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.5 Hyperparameters Optimization" ] }, { "cell_type": "code", "execution_count": 126, "metadata": {}, "outputs": [], "source": [ "def create_model(dropout, dense_size, vocab_size, embedding_dim, maxlen):\n", " model=Sequential()\n", " model.add(Embedding(input_dim=vocab_size,output_dim=embeding_dim,input_length=max_length))\n", " model.add(GlobalMaxPool1D())\n", " model.add(Dropout(dropout))\n", " model.add(Dense(dense_size,activation='relu'))\n", " model.add(Dropout(dropout))\n", " model.add(Dense(num_classes,activation='softmax'))\n", " model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])\n", " return model" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Main settings\n", "epochs = 5\n", "embedding_dim = 50\n", "maxlen = 100\n", "vocab_size=10000\n", "output_file = 'output.txt'\n", "dense_size=[10, 50,100],\n", "# Parameter grid for grid search\n", "param_grid = dict(dropout=[0.1],\n", " dense_size=[10, 50,100],\n", " vocab_size=[vocab_size],\n", " embedding_dim=[embedding_dim],\n", " maxlen=[maxlen])\n", "model = KerasClassifier(build_fn=create_model,\n", " epochs=epochs, batch_size=10,\n", " verbose=False)\n", "grid = RandomizedSearchCV(estimator=model, param_distributions=param_grid,\n", " cv=4, verbose=1, n_iter=5 ,n_jobs=2)\n", "grid_result = grid.fit(X_train, y_train)\n", "\n", "# Evaluate testing set\n", "test_accuracy = grid.score(X_test, y_test)\n", "# Save and evaluate results\n", "with open(output_file, 'a') as f:\n", " s = ('Best Accuracy : '\n", " '{:.4f}\\n{}\\nTest Accuracy : {:.4f}\\n\\n')\n", " output_string = s.format(\n", " grid_result.best_score_,\n", " grid_result.best_params_,\n", " test_accuracy)\n", " print(output_string)\n", " f.write(output_string) \n", "print('Done')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.6.7" } }, "nbformat": 4, "nbformat_minor": 2 }