{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Import pandas\nimport pandas as pd\n\n# Import training data\ndf_train = pd.read_csv('/kaggle/input/goodreads-books-reviews-290312/goodreads_train.csv')\n","metadata":{"execution":{"iopub.status.busy":"2023-03-27T19:56:26.343600Z","iopub.execute_input":"2023-03-27T19:56:26.344020Z","iopub.status.idle":"2023-03-27T19:56:55.740380Z","shell.execute_reply.started":"2023-03-27T19:56:26.343984Z","shell.execute_reply":"2023-03-27T19:56:55.738666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T19:57:42.172594Z","iopub.execute_input":"2023-03-27T19:57:42.173045Z","iopub.status.idle":"2023-03-27T19:57:42.202420Z","shell.execute_reply.started":"2023-03-27T19:57:42.172991Z","shell.execute_reply":"2023-03-27T19:57:42.201183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check null values and data type of each column\ndf_train.info()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T19:58:12.344368Z","iopub.execute_input":"2023-03-27T19:58:12.345860Z","iopub.status.idle":"2023-03-27T19:58:12.819769Z","shell.execute_reply.started":"2023-03-27T19:58:12.345797Z","shell.execute_reply":"2023-03-27T19:58:12.817753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n%matplotlib inline\n%config InlineBackend.figure_format = 'retina' \n\n# Check target balance\ndf_train['rating'].value_counts().sort_index().plot.bar(figsize=(10,5))\nplt.title('Rating distribution in the training set', fontweight=\"bold\")\nplt.xlabel('Target')\nplt.ylabel('Number of reviews')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:00:17.682730Z","iopub.execute_input":"2023-03-27T20:00:17.683582Z","iopub.status.idle":"2023-03-27T20:00:18.032809Z","shell.execute_reply.started":"2023-03-27T20:00:17.683537Z","shell.execute_reply":"2023-03-27T20:00:18.031655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Drop few columns\ndf_train = df_train.drop(columns=['user_id','book_id','date_added','date_updated',\n                                  'read_at','started_at','n_votes','n_comments'])","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:00:40.839214Z","iopub.execute_input":"2023-03-27T20:00:40.839657Z","iopub.status.idle":"2023-03-27T20:00:40.890173Z","shell.execute_reply.started":"2023-03-27T20:00:40.839614Z","shell.execute_reply":"2023-03-27T20:00:40.888847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import re\nfrom nltk.corpus import stopwords\n\n# Create a stopwords set adding some personal 'words'\nstopwords_english = set(stopwords.words('english'))\nmy_stopwords = set([\"http\", \"'s\", \"n't\", \"'m\", \"'re\", \"'ve\"])\nstopwords_english.update(my_stopwords)\n\ndef preprocess_review(text):\n    # Convert to lower case\n    text = text.lower()\n\n    # Remove numbers\n    text = re.sub(r'\\d+', '', text)\n\n    # Remove punctuation\n    text = re.sub(r'[^\\w\\s]', '', text)\n\n    # Split text into tokens\n    tokens = text.split()\n\n    # Filter tokens\n    clean_tokens = [tok for tok in tokens if tok not in stopwords_english and len(tok) > 1]\n\n    # Join tokens into a string\n    clean_text = ' '.join(clean_tokens)\n\n    return clean_text","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:09:13.718149Z","iopub.execute_input":"2023-03-27T20:09:13.718557Z","iopub.status.idle":"2023-03-27T20:09:14.712060Z","shell.execute_reply.started":"2023-03-27T20:09:13.718520Z","shell.execute_reply":"2023-03-27T20:09:14.710785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get one review as sample\nsample = df_train['review_text'][89999]\n\nprint('ORIGINAL REVIEW:   ' + sample + '\\n')\nprint('---------------------------------------------------------------------------- \\n')\nprint('WITH PROCESSING:    ' + preprocess_review(sample))","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:10:12.903076Z","iopub.execute_input":"2023-03-27T20:10:12.903487Z","iopub.status.idle":"2023-03-27T20:10:12.911183Z","shell.execute_reply.started":"2023-03-27T20:10:12.903452Z","shell.execute_reply":"2023-03-27T20:10:12.909838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Preprocess training data adding new column\ndf_train[\"clean_text\"] = df_train[\"review_text\"].apply(preprocess_review)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:11:15.407509Z","iopub.execute_input":"2023-03-27T20:11:15.407929Z","iopub.status.idle":"2023-03-27T20:12:37.641504Z","shell.execute_reply.started":"2023-03-27T20:11:15.407884Z","shell.execute_reply":"2023-03-27T20:12:37.640385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get 50 most frequent words in the training set\nfrequent_words = pd.Series(' '.join(df_train.clean_text).split()).value_counts()[:50]\nfrequent_words.plot.bar(figsize=(15,4))\nplt.title('50 most frequent terms in the training set', fontweight=\"bold\")\nplt.xlabel('Tokens')\nplt.ylabel('Frequency')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:19:23.838375Z","iopub.execute_input":"2023-03-27T20:19:23.838785Z","iopub.status.idle":"2023-03-27T20:19:58.996229Z","shell.execute_reply.started":"2023-03-27T20:19:23.838747Z","shell.execute_reply":"2023-03-27T20:19:58.994949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Filter rows with less than 250 tokens\nless_than_250 = df_train['clean_text'].apply(lambda x: len(x.split())) < 250  # Check by getting True and False values\n\n# Print percentage\nprint(f\"{(sum(less_than_250) / len(df_train) * 100):.2f}% of rows have less than 250 tokens.\")","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:20:12.669110Z","iopub.execute_input":"2023-03-27T20:20:12.669541Z","iopub.status.idle":"2023-03-27T20:20:18.166061Z","shell.execute_reply.started":"2023-03-27T20:20:12.669500Z","shell.execute_reply":"2023-03-27T20:20:18.164793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Remove original text column\ndf_train = df_train.drop(columns=['review_text'])\n\n# Get few entries to check operation\ndf_train.head()\n","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:20:40.628460Z","iopub.execute_input":"2023-03-27T20:20:40.629266Z","iopub.status.idle":"2023-03-27T20:20:40.864939Z","shell.execute_reply.started":"2023-03-27T20:20:40.629214Z","shell.execute_reply":"2023-03-27T20:20:40.863597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import training data\ndf_test = pd.read_csv('/kaggle/input/goodreads-books-reviews-290312/goodreads_test.csv')\n\n# Print a random row\ndf_test.sample()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:21:09.619077Z","iopub.execute_input":"2023-03-27T20:21:09.619502Z","iopub.status.idle":"2023-03-27T20:21:24.203194Z","shell.execute_reply.started":"2023-03-27T20:21:09.619465Z","shell.execute_reply":"2023-03-27T20:21:24.201894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\n# Remove unceccessary columns\ndf_test = df_test.drop(columns=['user_id','book_id','date_added','date_updated',\n                                  'read_at','started_at','n_votes','n_comments'])\n\n# Preprocess training data adding new column\ndf_test[\"clean_text\"] = df_test[\"review_text\"].apply(preprocess_review)\n\n# Remove original text column\ndf_test = df_test.drop(columns=['review_text'])\n\n# Get few entries to check cleaning operation\ndf_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:21:39.098859Z","iopub.execute_input":"2023-03-27T20:21:39.099305Z","iopub.status.idle":"2023-03-27T20:22:23.278756Z","shell.execute_reply.started":"2023-03-27T20:21:39.099266Z","shell.execute_reply":"2023-03-27T20:22:23.277451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create X, y arrays\nfrom sklearn.model_selection import train_test_split\n\n# Training data\nX_train = df_train[\"clean_text\"].values\ny_train = df_train[\"rating\"].values\n\n# Split into train/test sets\nX_tr, X_va, y_tr, y_va = train_test_split(X_train, y_train, test_size=0.2, random_state=0)\n\n# Test data\nX_te = df_test[\"clean_text\"].values\n\nprint(\"Training data:\", X_tr.shape, y_tr.shape)\nprint(\"Validation data:\", X_va.shape, y_va.shape)\nprint(\"Test data:\", X_te.shape)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:22:50.256875Z","iopub.execute_input":"2023-03-27T20:22:50.258143Z","iopub.status.idle":"2023-03-27T20:22:50.401872Z","shell.execute_reply.started":"2023-03-27T20:22:50.258090Z","shell.execute_reply":"2023-03-27T20:22:50.400646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer\n# Convert the text data into numerical features using TF-IDF\nvectorizer = TfidfVectorizer()\nX_train_features = vectorizer.fit_transform(X_tr)\nX_test_features = vectorizer.transform(X_va)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:28:42.728897Z","iopub.execute_input":"2023-03-27T20:28:42.729321Z","iopub.status.idle":"2023-03-27T20:30:11.605892Z","shell.execute_reply.started":"2023-03-27T20:28:42.729283Z","shell.execute_reply":"2023-03-27T20:30:11.604432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\n# Train a logistic regression model on the training data\n#model = LogisticRegression()\nmodel = LogisticRegression()\nmodel.fit(X_train_features, y_tr)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:35:48.918519Z","iopub.execute_input":"2023-03-27T20:35:48.918932Z","iopub.status.idle":"2023-03-27T20:39:40.412736Z","shell.execute_reply.started":"2023-03-27T20:35:48.918897Z","shell.execute_reply":"2023-03-27T20:39:40.411169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the test data\ny_pred = model.predict(X_test_features)\nfrom sklearn.metrics import accuracy_score, confusion_matrix\n# Evaluate the model's accuracy\naccuracy = accuracy_score(y_va, y_pred)\nprint(\"Accuracy:\", accuracy)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:42:24.663187Z","iopub.execute_input":"2023-03-27T20:42:24.663615Z","iopub.status.idle":"2023-03-27T20:42:24.857768Z","shell.execute_reply.started":"2023-03-27T20:42:24.663566Z","shell.execute_reply":"2023-03-27T20:42:24.856282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unseen_features = vectorizer.transform(df_test['clean_text'])","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:42:30.113530Z","iopub.execute_input":"2023-03-27T20:42:30.113996Z","iopub.status.idle":"2023-03-27T20:43:17.653917Z","shell.execute_reply.started":"2023-03-27T20:42:30.113951Z","shell.execute_reply":"2023-03-27T20:43:17.652696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use the model to make predictions on the new data\nunseen_predictions = model.predict(unseen_features)\n\nprint(\"Predictions:\", unseen_predictions)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:43:28.284442Z","iopub.execute_input":"2023-03-27T20:43:28.284860Z","iopub.status.idle":"2023-03-27T20:43:28.811516Z","shell.execute_reply.started":"2023-03-27T20:43:28.284823Z","shell.execute_reply":"2023-03-27T20:43:28.809941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create submission dataframe\nsubmission = pd.DataFrame({'review_id': df_test['review_id'],\n                           'rating': unseen_predictions})","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:43:59.213561Z","iopub.execute_input":"2023-03-27T20:43:59.213980Z","iopub.status.idle":"2023-03-27T20:43:59.231531Z","shell.execute_reply.started":"2023-03-27T20:43:59.213940Z","shell.execute_reply":"2023-03-27T20:43:59.230558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Export submission file for submit to competition\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T20:44:10.689460Z","iopub.execute_input":"2023-03-27T20:44:10.689947Z","iopub.status.idle":"2023-03-27T20:44:11.454326Z","shell.execute_reply.started":"2023-03-27T20:44:10.689904Z","shell.execute_reply":"2023-03-27T20:44:11.452950Z"},"trusted":true},"execution_count":null,"outputs":[]}]}