{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"84cd48c15523e567b7e9e3cf272da50446c9b504"},"cell_type":"markdown","source":"**Libraries Loads**"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# Library Loads\nimport pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport calendar\nfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder\nfrom scipy.stats import norm\nfrom sklearn.model_selection import train_test_split\nfrom scipy import stats\nimport warnings\nwarnings.filterwarnings('ignore')\nimport keras\nfrom keras.models import Sequential\nfrom keras.layers import Dense\nfrom sklearn.preprocessing import StandardScaler\nfrom keras import backend\nfrom sklearn.metrics import mean_squared_error\nimport xgboost as xgb\nfrom sklearn.metrics import accuracy_score\nfrom keras.layers import Dense,Embedding,Flatten,Dropout\nfrom keras.losses import categorical_crossentropy\nfrom keras.losses import sparse_categorical_crossentropy\nfrom keras.optimizers import RMSprop\nimport re\nfrom numpy import argmax","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5133f7bf0da3343dc8f9f43701faaf42e48ee785"},"cell_type":"markdown","source":"**Dataset Load**"},{"metadata":{"trusted":true,"_uuid":"f459712bfae10b4e1fddefbde6559559fb514446"},"cell_type":"code","source":"raw_training = pd.read_json(\"../input/train.json\")\nraw_test = pd.read_json(\"../input/test.json\")\n\ntraining_set = raw_training.copy()\ntest_set = raw_test.copy()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8d3dd8ca58c5e2ff587b066349019a8abe10a0b8"},"cell_type":"markdown","source":"**Data Exploration**"},{"metadata":{"trusted":true,"_uuid":"e62a3b44fd41eecc575456d987832cac6acfd076"},"cell_type":"code","source":"# lets look the at the first 5 rows\ntraining_set.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ae94abc89571e39d920ec5051523a57445d6cdb0"},"cell_type":"code","source":"test_set.head()\n# missing the cuisine column - the variable we are trying to predict (classification problem)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b44e1f140fa5b1c303949085af78177745be220a"},"cell_type":"code","source":"# change the order of the columns to how I like it!\ntraining_set = training_set[[\"id\",\"cuisine\",\"ingredients\"]]\ntraining_set.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bf98129c4ed9906d5bcd440b6c89f7dbb0b285f2"},"cell_type":"code","source":"training_set.info()\n# we have no missing values - Good!","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d12531ab590c54753ad956bc3d0d82122cad8e11"},"cell_type":"code","source":"# countplot of cuisine\nf, ax = plt.subplots(figsize = (18, 4))\nsns.countplot(training_set[\"cuisine\"])\nplt.show()\n\n# we have 20 different cuisines","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a4482dbeee4b6596ad2749c5382a9aff2ea16c45"},"cell_type":"markdown","source":"**Dataset Manipulation**"},{"metadata":{"trusted":true,"_uuid":"83ab3b0c5550af7d8f5462b7dffa01c1dd68eb93"},"cell_type":"code","source":"# lets combine training_set & test_set, so all data manipulations don't have to be repeated\ntraining_set[\"training\"] = 1\ntest_set[\"training\"] = 0\ntest_set[\"cuisine\"] = \"test\"\ntest_set = test_set[[\"id\", \"training\", \"cuisine\", \"ingredients\"]]\ntraining_set = training_set[[\"id\", \"training\", \"cuisine\", \"ingredients\"]]\ntraining_set = pd.concat([training_set, test_set], axis=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6f5fb48084596d85f2ac02a67e1790178bbbcac6"},"cell_type":"code","source":"# de-list the ingredients column and have each ingredient as it's own column in a helper dataframe called ingredients\ningredients = training_set[\"ingredients\"].apply(pd.Series)\ningredients.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"94ea5a2e5193ddad672d94486b98e789c3185b54"},"cell_type":"code","source":"# now merge with original & delete old ingredients column\ntraining_set = pd.concat([training_set, ingredients], axis=1)\ntraining_set = training_set.drop(columns = [\"ingredients\"])\ntraining_set.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8178439ab3da7ed74ca6811d7a9bdb8e0b5feab1"},"cell_type":"code","source":"# now transform all the ingredients into one row each by each id and cuisine its attached to\ntraining_set = training_set.melt(id_vars = [\"id\", \"training\", \"cuisine\"], value_name = \"ingredient\")\ntraining_set = training_set.drop(columns = [\"variable\"])\ntraining_set.dropna(subset=[\"ingredient\"], inplace = True)\ntraining_set.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b0e7fc153c5a6eaf6251d5a8900783a1410fd776"},"cell_type":"code","source":"# lets do some modifications to the ingredients column\n# Clean the ingreidents columns\n# make all words lowers case\n# remove non alphabetic symbols (e.g numbers and symbols like '-')\n# remove unit measurements of ingreidients\ntraining_set[\"ingredient\"] = training_set[\"ingredient\"].astype(str).str.lower()\ntraining_set[\"ingredient\"] = training_set[\"ingredient\"].apply(lambda x: re.sub(\"[^a-zA-Z]\",\" \",x))\ntraining_set[\"ingredient\"] = training_set[\"ingredient\"].apply(lambda x: \\\n                                            re.sub((r'\\b(oz|ounc|ounce|pound|lb|inch|inches|kg|to)\\b'),\" \",x))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"10d1c128a271c1967e5ad00bce15280f33e584ef"},"cell_type":"code","source":"# remove cuisine column to make pivot of ingredients with count\ntraining_set = training_set.drop(columns = [\"cuisine\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5aff4c4d594228b4294f5faa2b91bd4c883f72f7"},"cell_type":"code","source":"# make training_set into pivot table\n# one column for each ingredient (1 if the reciepe has the ingredient, 0 if it did not)\ntraining_set[\"count\"] = 1\ntraining_set = pd.pivot_table(training_set, index = [\"id\",\"training\"], columns = [\"ingredient\"], values = \"count\", \\\n                           aggfunc = np.sum, fill_value = 0).reset_index().rename_axis(None, axis=1);\ntraining_set.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7b500db494056f0090da28759645dc6616754a0f"},"cell_type":"code","source":"# split out into test & training sets again\ntest_set = training_set[training_set[\"training\"] == 0].drop(columns = [\"training\"])\ntraining_set = training_set[training_set[\"training\"] == 1].drop(columns = [\"training\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ae7216e432c3d70d73702480a13f5d596218cb52"},"cell_type":"code","source":"# merge with raw datasets to ensure ids index remain same and add on cuisine column\ntraining_set = pd.merge(raw_training[[\"id\", \"cuisine\"]], training_set, how=\"left\",on=\"id\")\ntest_set = pd.merge(raw_test, test_set, how=\"left\", on=\"id\")\ntest_set = test_set.drop(columns = [\"ingredients\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"97164a8b45473851632f7bbf64762fce66f0c974"},"cell_type":"code","source":"# one hot encode the cusine column\nle = LabelEncoder()\ntraining_set[\"cuisine\"] = le.fit_transform(training_set[\"cuisine\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"95df6a78aad0f4d9a45399f6e0936185e341b4be"},"cell_type":"code","source":"training_set.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a965b5630aaadb004530490a6c1c58ef24b820d3"},"cell_type":"code","source":"test_set.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5cb66d7c0172ffe6d6b44a0316d997dd74d1c157"},"cell_type":"markdown","source":"**Split into Training & Test Sets**"},{"metadata":{"trusted":true,"_uuid":"17eda854021665eb1e8e983a4fde579784c86df7"},"cell_type":"code","source":"training_set.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"35de711a0232e581f1b8bb38839f34f898abf361"},"cell_type":"code","source":"test_set.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b968ed9c5b452638936bedbbe19af61901f861e7"},"cell_type":"code","source":"test_set = test_set.drop(columns = [\"id\"]).values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"668d1b93ad60185ef2ad7ad65ddce096a6576be9"},"cell_type":"code","source":"X = training_set.drop(columns = [\"id\", \"cuisine\"]).values\ny = training_set[[\"cuisine\"]].values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d607855c01a3e6c41e5cb83b26ec301bde5e1f6b"},"cell_type":"code","source":"# one hot encode y\nonehot_encoder = OneHotEncoder(sparse=False)\ny = y.reshape(len(y), 1)\ny = onehot_encoder.fit_transform(y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4b9ffc8d7429309e105e2fc7b60f0be676dde8e7"},"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, \n                                                    random_state = 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f7f8473e884f5641fb17794e39ba711413dba562"},"cell_type":"code","source":"X.shape","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"28110410044e007ef2b0f6def3ac813aa82c2cfb"},"cell_type":"markdown","source":"**Make our ANN model**"},{"metadata":{"_uuid":"f0bc8c23419738c7f232dd2c8ae3ba45610afa08"},"cell_type":"markdown","source":"*Testing Model on X_train*"},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"3d181d413a7cd104b5eaa02155c4827609be1872"},"cell_type":"code","source":"# Let's test our model on our training set first\n\n# Initialing the ANN\nclassifier = Sequential()\n\n# Adding the input layer and the first hidden layer\nclassifier.add(Dense(units = 2000, kernel_initializer = \"uniform\",\n                     activation = \"relu\", input_dim = 7120))\n\n# Adding the second hidden layer\nclassifier.add(Dense(units = 500, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Add drop out to reduce overfitting\nclassifier.add(Dropout(0.3))\n\n# Adding the third hidden layer\nclassifier.add(Dense(units = 250, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Adding the fourth hidden layer\nclassifier.add(Dense(units = 125, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Add drop out to reduce overfitting\nclassifier.add(Dropout(0.3))\n\n# Adding the fifth hidden layer\nclassifier.add(Dense(units = 50, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Adding the output layer\nclassifier.add(Dense(units = 20, kernel_initializer = \"uniform\",\n                     activation = \"softmax\"))\n\n# Compiling the ANN\nclassifier.compile(optimizer = RMSprop(lr=0.0005), loss = \"categorical_crossentropy\",\n                   metrics = [\"accuracy\"])\n\n# Fitting the ANN to the Training set\nclassifier.fit(X_train, y_train, batch_size = 50, epochs = 10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"61b8e0b2f22a1fec064f41091581d2ed8a3ed11a"},"cell_type":"code","source":"# let's see how are model fares against our training test set\n\n#predict on training test set\ny_pred = classifier.predict(X_test)\ny_pred = [np.argmax(i) for i in y_pred]\n\ny_test = [np.argmax(i) for i in y_test]\n\n# evaluate predictions\naccuracy = accuracy_score(y_test, y_pred)\nprint(\"Accuracy: %.2f%%\" % (accuracy * 100.0))\n\n# accuracy of 74% - we should improve our data manipulations in the ingredients column before feeding it into our model","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a65bf2f6304081dfdbea0fe2c2f7f47efd6cd1ff"},"cell_type":"markdown","source":"*Create model on full Training set for Kaggle Predictions*"},{"metadata":{"trusted":true,"_uuid":"d5b7f2deffee178b391f982cb110cd724e7a0731"},"cell_type":"code","source":"# Let's fit model on our full training set \n\n# Initialing the ANN\nclassifier = Sequential()\n\n# Adding the input layer and the first hidden layer\nclassifier.add(Dense(units = 2000, kernel_initializer = \"uniform\",\n                     activation = \"relu\", input_dim = 7120))\n\n# Adding the second hidden layer\nclassifier.add(Dense(units = 500, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Add drop out to reduce overfitting\nclassifier.add(Dropout(0.3))\n\n# Adding the third hidden layer\nclassifier.add(Dense(units = 250, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Adding the fourth hidden layer\nclassifier.add(Dense(units = 125, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Add drop out to reduce overfitting\nclassifier.add(Dropout(0.3))\n\n# Adding the fifth hidden layer\nclassifier.add(Dense(units = 50, kernel_initializer = \"uniform\",\n                     activation = \"relu\"))\n\n# Adding the output layer\nclassifier.add(Dense(units = 20, kernel_initializer = \"uniform\",\n                     activation = \"softmax\"))\n\n# Compiling the ANN\nclassifier.compile(optimizer = RMSprop(lr=0.0005), loss = \"categorical_crossentropy\",\n                   metrics = [\"accuracy\"])\n\n# Fitting the ANN to the Training set\nclassifier.fit(X, y, batch_size = 50, epochs = 10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"01f05a0b41d3190f36c04372ec093c47945ed6b0"},"cell_type":"code","source":"# fit model to training set\n\n#predict on training test set\ny_pred = classifier.predict(test_set)\ny_pred = le.inverse_transform([np.argmax(i) for i in y_pred])\n\nids = raw_test.iloc[:, 0:1].values\nids = ids.flatten()\n\nsubmission = pd.DataFrame(\n        {\"id\": ids,\n         \"cuisine\": y_pred})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6ce9796ea9b2750cba372f3e436a7c1ce23d0534"},"cell_type":"code","source":"submission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e50bbc26e972027565577c9fe671bd8a43ca3262"},"cell_type":"code","source":"submission.to_csv(\"submission.csv\", index = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dc5075de91de992a39d48ec9e5fd367b61b7d625"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}