{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"tpu1vmV38","dataSources":[{"sourceId":33579,"databundleVersionId":3073370,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-22T21:36:22.576754Z","iopub.execute_input":"2023-12-22T21:36:22.577101Z","iopub.status.idle":"2023-12-22T21:36:22.974772Z","shell.execute_reply.started":"2023-12-22T21:36:22.577069Z","shell.execute_reply":"2023-12-22T21:36:22.974080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install seaborn\n!pip install transformers\n!pip install imblearn","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:36:22.976128Z","iopub.execute_input":"2023-12-22T21:36:22.976407Z","iopub.status.idle":"2023-12-22T21:36:34.454629Z","shell.execute_reply.started":"2023-12-22T21:36:22.976382Z","shell.execute_reply":"2023-12-22T21:36:34.453741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:36:34.455856Z","iopub.execute_input":"2023-12-22T21:36:34.456115Z","iopub.status.idle":"2023-12-22T21:36:35.905385Z","shell.execute_reply.started":"2023-12-22T21:36:34.456089Z","shell.execute_reply":"2023-12-22T21:36:35.904404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 1. Download datasets","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv('/kaggle/input/goodreads-books-reviews-290312/goodreads_train.csv'\n                      , usecols = ['review_id', 'rating', 'review_text'])\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:36:35.907270Z","iopub.execute_input":"2023-12-22T21:36:35.907677Z","iopub.status.idle":"2023-12-22T21:36:54.994438Z","shell.execute_reply.started":"2023-12-22T21:36:35.907647Z","shell.execute_reply":"2023-12-22T21:36:54.993450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv('/kaggle/input/goodreads-books-reviews-290312/goodreads_test.csv'\n                     , usecols = ['review_id', 'review_text'])\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:36:54.995719Z","iopub.execute_input":"2023-12-22T21:36:54.996037Z","iopub.status.idle":"2023-12-22T21:37:05.227688Z","shell.execute_reply.started":"2023-12-22T21:36:54.996005Z","shell.execute_reply":"2023-12-22T21:37:05.226819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df_ids = test_df.review_id","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:05.228927Z","iopub.execute_input":"2023-12-22T21:37:05.229212Z","iopub.status.idle":"2023-12-22T21:37:05.233385Z","shell.execute_reply.started":"2023-12-22T21:37:05.229185Z","shell.execute_reply":"2023-12-22T21:37:05.232534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Investigate train dataset a bit","metadata":{}},{"cell_type":"markdown","source":"From Dataset description we know that:\n\n**user_id** - Id of user<br/>\n**book_id** - Id of Book<br/>\n**review_id** - Id of review<br/>\n**rating** - rating from 0 to 5<br/>\n**review_text** - review text<br/>\n**date_added** - date added<br/>\n**date_updated** - date updated<br/>\n**read_at** - read at<br/>\n**started_at** - started at<br/>\n**n_votes** - no. of votes<br/>\n**n_comments** - no. of comments<br/>","metadata":{}},{"cell_type":"code","source":"print(f'Len of train dataset: {len(train_df)}')\nprint(f'Len of test dataset: {len(test_df)}')","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:05.234607Z","iopub.execute_input":"2023-12-22T21:37:05.234855Z","iopub.status.idle":"2023-12-22T21:37:05.249528Z","shell.execute_reply.started":"2023-12-22T21:37:05.234829Z","shell.execute_reply":"2023-12-22T21:37:05.248780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.countplot(x = train_df.rating)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:05.250389Z","iopub.execute_input":"2023-12-22T21:37:05.250632Z","iopub.status.idle":"2023-12-22T21:37:07.026359Z","shell.execute_reply.started":"2023-12-22T21:37:05.250592Z","shell.execute_reply":"2023-12-22T21:37:07.025563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.027487Z","iopub.execute_input":"2023-12-22T21:37:07.027761Z","iopub.status.idle":"2023-12-22T21:37:07.187003Z","shell.execute_reply.started":"2023-12-22T21:37:07.027733Z","shell.execute_reply":"2023-12-22T21:37:07.186004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.190116Z","iopub.execute_input":"2023-12-22T21:37:07.190437Z","iopub.status.idle":"2023-12-22T21:37:07.278772Z","shell.execute_reply.started":"2023-12-22T21:37:07.190409Z","shell.execute_reply":"2023-12-22T21:37:07.277911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Clear the data","metadata":{}},{"cell_type":"code","source":"y = train_df.pop('rating')","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.280002Z","iopub.execute_input":"2023-12-22T21:37:07.280273Z","iopub.status.idle":"2023-12-22T21:37:07.286036Z","shell.execute_reply.started":"2023-12-22T21:37:07.280244Z","shell.execute_reply":"2023-12-22T21:37:07.285195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"common_df = pd.concat([train_df.review_text, test_df.review_text]).reset_index(drop = True)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.287080Z","iopub.execute_input":"2023-12-22T21:37:07.287349Z","iopub.status.idle":"2023-12-22T21:37:07.385461Z","shell.execute_reply.started":"2023-12-22T21:37:07.287322Z","shell.execute_reply":"2023-12-22T21:37:07.384352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# to lower\ndef to_lower(text):\n    return text.lower()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.387199Z","iopub.execute_input":"2023-12-22T21:37:07.387504Z","iopub.status.idle":"2023-12-22T21:37:07.391311Z","shell.execute_reply.started":"2023-12-22T21:37:07.387474Z","shell.execute_reply":"2023-12-22T21:37:07.390463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#remove stopwords\n#from nltk.corpus import stopwords\n#stop = set(stopwords.words('english'))\nstop = {'a', 'the', 'www', 'http', 'https', 'com'}\n\ndef remove_stopwords(text):\n    return ' '.join([word for word in text.split() if word not in stop])","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.392422Z","iopub.execute_input":"2023-12-22T21:37:07.392706Z","iopub.status.idle":"2023-12-22T21:37:07.408023Z","shell.execute_reply.started":"2023-12-22T21:37:07.392678Z","shell.execute_reply":"2023-12-22T21:37:07.407281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import re\nfrom urllib.parse import urlparse\n\ndef remove_url(text):\n    url = re.compile(r'https?://\\S+')\n    return url.sub(r'',text)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.408994Z","iopub.execute_input":"2023-12-22T21:37:07.409243Z","iopub.status.idle":"2023-12-22T21:37:07.418611Z","shell.execute_reply.started":"2023-12-22T21:37:07.409216Z","shell.execute_reply":"2023-12-22T21:37:07.417844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import string\nremove = string.punctuation\n\nperiod = '.'\nremove = remove.replace(period, '')\n\ndef remove_punctuation(text):\n    pattern = re.compile(r\"[{}]\".format(re.escape(remove)))\n    \n    res = []\n    for word in text.split():\n        \n        # remove all punctiations except periods\n        new_word = pattern.sub(r' ', word)\n        new_word = new_word.strip(period)\n        \n        try:\n            float(new_word)\n        except:\n            new_word = new_word.replace(period, ' ')\n            \n        res.append(new_word)\n    \n    return ' '.join(res)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.419523Z","iopub.execute_input":"2023-12-22T21:37:07.419817Z","iopub.status.idle":"2023-12-22T21:37:07.429494Z","shell.execute_reply.started":"2023-12-22T21:37:07.419790Z","shell.execute_reply":"2023-12-22T21:37:07.428688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# remove all non-alphabetic chars (punctuation, numbers, emojies ...)\ndef remove_non_alphabetic(text):\n    alpha = re.compile(r'[^a-zA-Z]') \n    return alpha.sub(r' ', text)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.430477Z","iopub.execute_input":"2023-12-22T21:37:07.430735Z","iopub.status.idle":"2023-12-22T21:37:07.443677Z","shell.execute_reply.started":"2023-12-22T21:37:07.430708Z","shell.execute_reply":"2023-12-22T21:37:07.442861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def remove_quotes(text):\n    alpha = re.compile(r'\"([^\"\\\\]|\\\\.)*\"') \n    return alpha.sub(r' ', text)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.444687Z","iopub.execute_input":"2023-12-22T21:37:07.444937Z","iopub.status.idle":"2023-12-22T21:37:07.454648Z","shell.execute_reply.started":"2023-12-22T21:37:07.444911Z","shell.execute_reply":"2023-12-22T21:37:07.453733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def remove_spoiler_alert(text):\n    spoiler = re.compile(r'(\\(view spoiler\\).*?\\(hide spoiler\\))') \n    return spoiler.sub(r' ', text)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.455596Z","iopub.execute_input":"2023-12-22T21:37:07.455849Z","iopub.status.idle":"2023-12-22T21:37:07.465744Z","shell.execute_reply.started":"2023-12-22T21:37:07.455823Z","shell.execute_reply":"2023-12-22T21:37:07.464892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def remove_small_words(text):\n    return ' '.join([word for word in text.split() if len(word) > 2])","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.466716Z","iopub.execute_input":"2023-12-22T21:37:07.466966Z","iopub.status.idle":"2023-12-22T21:37:07.477258Z","shell.execute_reply.started":"2023-12-22T21:37:07.466940Z","shell.execute_reply":"2023-12-22T21:37:07.476421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# after applying usual text preprocessing steps (list below)\n# I found ot that many reviews are empty! (because not all of them are meaningful 🤷)\n# so I commented almost all of these steps out to avoid empty reviews in both train and test sets\n\ndef process_text(text):\n    text = to_lower(text)\n    #text = remove_url(text)\n    text = remove_punctuation(text)\n    #text = remove_spoiler_alert(text)\n    #text = remove_quotes(text)\n    #text = remove_non_alphabetic(text)\n    text = remove_stopwords(text)\n    #text = remove_small_words(text)\n    return text","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.478264Z","iopub.execute_input":"2023-12-22T21:37:07.478506Z","iopub.status.idle":"2023-12-22T21:37:07.488656Z","shell.execute_reply.started":"2023-12-22T21:37:07.478480Z","shell.execute_reply":"2023-12-22T21:37:07.487855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"common_df = common_df.apply(process_text)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:37:07.489635Z","iopub.execute_input":"2023-12-22T21:37:07.489890Z","iopub.status.idle":"2023-12-22T21:43:40.598988Z","shell.execute_reply.started":"2023-12-22T21:37:07.489863Z","shell.execute_reply":"2023-12-22T21:43:40.597901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check min number of words\ncommon_df.apply(lambda x : len(x.split())).min()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:43:40.600259Z","iopub.execute_input":"2023-12-22T21:43:40.600542Z","iopub.status.idle":"2023-12-22T21:43:56.171755Z","shell.execute_reply.started":"2023-12-22T21:43:40.600513Z","shell.execute_reply":"2023-12-22T21:43:56.170901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"common_df[12]","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:43:56.172860Z","iopub.execute_input":"2023-12-22T21:43:56.173122Z","iopub.status.idle":"2023-12-22T21:43:56.178675Z","shell.execute_reply.started":"2023-12-22T21:43:56.173095Z","shell.execute_reply":"2023-12-22T21:43:56.177710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 5. TPU setup","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\n\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\nexcept ValueError:\n    tpu = None\n    gpus = tf.config.experimental.list_logical_devices(\"GPU\")\n    \nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\n    print('Running on TPU')\nelif len(gpus) > 1:\n    strategy = tf.distribute.MirroredStrategy([gpu.name for gpu in gpus])\n    print('Running on multiple GPUs ', [gpu.name for gpu in gpus])\nelif len(gpus) == 1:\n    strategy = tf.distribute.get_strategy() \n    print('Running on single GPU ', gpus[0].name)\nelse:\n    strategy = tf.distribute.get_strategy() \n    print('Running on CPU')\nprint(\"Number of accelerators: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:43:56.179720Z","iopub.execute_input":"2023-12-22T21:43:56.179975Z","iopub.status.idle":"2023-12-22T21:44:16.748832Z","shell.execute_reply.started":"2023-12-22T21:43:56.179951Z","shell.execute_reply":"2023-12-22T21:44:16.747913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 6. XLM_RoBERTa model","metadata":{}},{"cell_type":"code","source":"X_train = common_df.iloc[:len(y)]\nX_test = common_df.iloc[len(y):]","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:44:16.749998Z","iopub.execute_input":"2023-12-22T21:44:16.750272Z","iopub.status.idle":"2023-12-22T21:44:16.755033Z","shell.execute_reply.started":"2023-12-22T21:44:16.750242Z","shell.execute_reply":"2023-12-22T21:44:16.754271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.utils import to_categorical\n\ny_cat = to_categorical(y)\ny_cat.shape","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:44:16.756015Z","iopub.execute_input":"2023-12-22T21:44:16.756275Z","iopub.status.idle":"2023-12-22T21:44:16.848741Z","shell.execute_reply.started":"2023-12-22T21:44:16.756247Z","shell.execute_reply":"2023-12-22T21:44:16.847890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from transformers import TFAutoModel, AutoTokenizer\n\nMAX_LEN = 100 # use only first 100 words of review to predict the rating\nmodel_name = 'xlm-roberta-base'\n\n# tokenizing\ntokenizer = AutoTokenizer.from_pretrained(model_name)\ntrain_inputs = tokenizer(X_train.to_list(), \n                         max_length = MAX_LEN,\n                         padding = 'max_length', \n                         truncation = True,\n                         return_tensors = 'np')\n\ntest_inputs = tokenizer(X_test.to_list(), \n                        max_length = MAX_LEN,\n                        padding = 'max_length',\n                        truncation = True,\n                        return_tensors = 'np')","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:44:16.852678Z","iopub.execute_input":"2023-12-22T21:44:16.853006Z","iopub.status.idle":"2023-12-22T21:47:13.241476Z","shell.execute_reply.started":"2023-12-22T21:44:16.852974Z","shell.execute_reply":"2023-12-22T21:47:13.239953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fine-tune the model\n#from transformers import TFAutoModelForSequenceClassification\n#from tensorflow.keras.optimizers import Adam\n\n#with strategy.scope():\n#    model = TFAutoModelForSequenceClassification.from_pretrained(model_name, num_labels = y_cat.shape[-1])\n#    model.compile(Adam(learning_rate = 5e-5), \n#                  loss = 'categorical_crossentropy', \n#                  metrics=['accuracy'], steps_per_execution = 200)\n\n#model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:47:13.242517Z","iopub.execute_input":"2023-12-22T21:47:13.243078Z","iopub.status.idle":"2023-12-22T21:47:13.247442Z","shell.execute_reply.started":"2023-12-22T21:47:13.243047Z","shell.execute_reply":"2023-12-22T21:47:13.246752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras import Input, Model\nfrom tensorflow.keras.layers import Dense, Dropout\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras import regularizers\n\n# build the model\nwith strategy.scope():\n    encoder = TFAutoModel.from_pretrained(model_name)\n    \n    input_word_ids = Input(shape = (MAX_LEN, ), dtype = tf.int32, name = \"input_ids\")\n    input_mask = Input(shape = (MAX_LEN, ), dtype = tf.int32, name = \"attention_mask\") \n\n    embedding = encoder([input_word_ids, input_mask])[1] # pooled_output\n    x = Dropout(0.3)(embedding)\n    x = Dense(128, activation = 'relu', kernel_regularizer = regularizers.L2(0.1))(x)\n    x = Dropout(0.3)(x)\n    x = Dense(32, activation = 'relu', kernel_regularizer = regularizers.L2(0.1))(x)\n    x = Dropout(0.3)(x)\n    x = Dense(y_cat.shape[1], activation = 'softmax')(x)\n    \n    model = Model(inputs = [input_word_ids, input_mask], \n                  outputs = x)\n    \n    model.compile(Adam(learning_rate = 1e-5), \n                  loss = 'categorical_crossentropy', \n                  metrics=['accuracy'], steps_per_execution = 200)\n    \nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:47:13.248370Z","iopub.execute_input":"2023-12-22T21:47:13.248632Z","iopub.status.idle":"2023-12-22T21:47:54.410941Z","shell.execute_reply.started":"2023-12-22T21:47:13.248605Z","shell.execute_reply":"2023-12-22T21:47:54.409986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# callbacks\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\n\nearly_stop = EarlyStopping(patience = 5, restore_best_weights = True, verbose = 1) # val_loss\nreduce_lr = ReduceLROnPlateau(factor = 0.1, patience = 2, mode = 'min', verbose = 1) # val_loss","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:47:54.412069Z","iopub.execute_input":"2023-12-22T21:47:54.412379Z","iopub.status.idle":"2023-12-22T21:47:54.418331Z","shell.execute_reply.started":"2023-12-22T21:47:54.412347Z","shell.execute_reply":"2023-12-22T21:47:54.417510Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fine-tune the model\n\n# https://github.com/huggingface/transformers/issues/20709\n# The problem is that Keras recognizes dict objects \n# but not our BatchEncoding returned by the tokenizer, \n# even though BatchEncoding is a subclass of dict.\n# If you replace the last line with model.fit(dict(tokenized_data), labels) it should work.\n\nhistory = model.fit(dict(train_inputs), \n                    y_cat,\n                    epochs = 50,\n                    verbose = 1,\n                    validation_split = 0.1,\n                    batch_size = 64 * strategy.num_replicas_in_sync,\n                    callbacks = [reduce_lr, early_stop])","metadata":{"execution":{"iopub.status.busy":"2023-12-22T21:47:54.419334Z","iopub.execute_input":"2023-12-22T21:47:54.419624Z","iopub.status.idle":"2023-12-22T23:14:08.260808Z","shell.execute_reply.started":"2023-12-22T21:47:54.419595Z","shell.execute_reply":"2023-12-22T23:14:08.259539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss = history.history['loss']\nacc = history.history['accuracy']\nval_loss = history.history['val_loss']\nval_acc = history.history['val_accuracy'] \n\nepochs = range(1, len(loss) + 1)\n\nplt.figure(figsize=(16, 5))\n#accuracy\nplt.subplot(1,2,1)\nplt.plot(epochs, acc, 'bo', label = 'Training accuracy')\nplt.plot(epochs, val_acc, 'r', label = 'Validation accuracy')\nplt.legend()\n\n#loss\nplt.subplot(1,2,2)\nplt.plot(epochs, loss, 'bo', label = 'Trainig loss')\nplt.plot(epochs, val_loss, 'r', label = 'Validation loss')\nplt.legend()\n\nplt.show() ","metadata":{"execution":{"iopub.status.busy":"2023-12-22T23:14:08.262361Z","iopub.execute_input":"2023-12-22T23:14:08.262709Z","iopub.status.idle":"2023-12-22T23:14:08.585325Z","shell.execute_reply.started":"2023-12-22T23:14:08.262674Z","shell.execute_reply":"2023-12-22T23:14:08.584100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('model.keras')","metadata":{"execution":{"iopub.status.busy":"2023-12-22T23:14:08.586387Z","iopub.execute_input":"2023-12-22T23:14:08.586685Z","iopub.status.idle":"2023-12-22T23:14:20.621521Z","shell.execute_reply.started":"2023-12-22T23:14:08.586657Z","shell.execute_reply":"2023-12-22T23:14:20.620240Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 7. Submission","metadata":{}},{"cell_type":"code","source":"sub = pd.DataFrame()\nsub['review_id'] = test_df_ids\nsub['rating'] = [np.argmax(i) for i in model.predict(dict(test_inputs))]\nsub.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-22T23:14:20.622788Z","iopub.execute_input":"2023-12-22T23:14:20.623099Z","iopub.status.idle":"2023-12-22T23:17:33.414550Z","shell.execute_reply.started":"2023-12-22T23:14:20.623068Z","shell.execute_reply":"2023-12-22T23:17:33.413614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv(\"sub.csv\", index = False)","metadata":{"execution":{"iopub.status.busy":"2023-12-22T23:17:33.415386Z","iopub.execute_input":"2023-12-22T23:17:33.415653Z","iopub.status.idle":"2023-12-22T23:17:34.097022Z","shell.execute_reply.started":"2023-12-22T23:17:33.415627Z","shell.execute_reply":"2023-12-22T23:17:34.095987Z"},"trusted":true},"execution_count":null,"outputs":[]}]}