diff --git a/Solutions.ipynb b/Solutions.ipynb
new file mode 100644
index 0000000..e045f47
--- /dev/null
+++ b/Solutions.ipynb
@@ -0,0 +1,744 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "5a37bb75",
+ "metadata": {},
+ "source": [
+ "1. ) Import the required libraries and modules that you would need."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "5d66768a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import seaborn as sns\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "from sklearn.linear_model import LinearRegression\n",
+ "from sklearn.linear_model import LogisticRegression\n",
+ "from sklearn.neural_network import MLPRegressor\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.preprocessing import StandardScaler\n",
+ "from sklearn.preprocessing import OneHotEncoder, Normalizer, LabelEncoder\n",
+ "from sklearn import metrics\n",
+ "import warnings\n",
+ "warnings.filterwarnings('ignore')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "73648fab",
+ "metadata": {},
+ "source": [
+ "2.) Read that data into Python and call the dataframe churnData."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "c25f693d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " gender | \n",
+ " SeniorCitizen | \n",
+ " Partner | \n",
+ " Dependents | \n",
+ " tenure | \n",
+ " PhoneService | \n",
+ " OnlineSecurity | \n",
+ " OnlineBackup | \n",
+ " DeviceProtection | \n",
+ " TechSupport | \n",
+ " StreamingTV | \n",
+ " StreamingMovies | \n",
+ " Contract | \n",
+ " MonthlyCharges | \n",
+ " TotalCharges | \n",
+ " Churn | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " Female | \n",
+ " 0 | \n",
+ " Yes | \n",
+ " No | \n",
+ " 1 | \n",
+ " No | \n",
+ " No | \n",
+ " Yes | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " Month-to-month | \n",
+ " 29.85 | \n",
+ " 29.85 | \n",
+ " No | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " Male | \n",
+ " 0 | \n",
+ " No | \n",
+ " No | \n",
+ " 34 | \n",
+ " Yes | \n",
+ " Yes | \n",
+ " No | \n",
+ " Yes | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " One year | \n",
+ " 56.95 | \n",
+ " 1889.5 | \n",
+ " No | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " Male | \n",
+ " 0 | \n",
+ " No | \n",
+ " No | \n",
+ " 2 | \n",
+ " Yes | \n",
+ " Yes | \n",
+ " Yes | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " Month-to-month | \n",
+ " 53.85 | \n",
+ " 108.15 | \n",
+ " Yes | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " Male | \n",
+ " 0 | \n",
+ " No | \n",
+ " No | \n",
+ " 45 | \n",
+ " No | \n",
+ " Yes | \n",
+ " No | \n",
+ " Yes | \n",
+ " Yes | \n",
+ " No | \n",
+ " No | \n",
+ " One year | \n",
+ " 42.30 | \n",
+ " 1840.75 | \n",
+ " No | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " Female | \n",
+ " 0 | \n",
+ " No | \n",
+ " No | \n",
+ " 2 | \n",
+ " Yes | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " No | \n",
+ " Month-to-month | \n",
+ " 70.70 | \n",
+ " 151.65 | \n",
+ " Yes | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " gender SeniorCitizen Partner Dependents tenure PhoneService \\\n",
+ "0 Female 0 Yes No 1 No \n",
+ "1 Male 0 No No 34 Yes \n",
+ "2 Male 0 No No 2 Yes \n",
+ "3 Male 0 No No 45 No \n",
+ "4 Female 0 No No 2 Yes \n",
+ "\n",
+ " OnlineSecurity OnlineBackup DeviceProtection TechSupport StreamingTV \\\n",
+ "0 No Yes No No No \n",
+ "1 Yes No Yes No No \n",
+ "2 Yes Yes No No No \n",
+ "3 Yes No Yes Yes No \n",
+ "4 No No No No No \n",
+ "\n",
+ " StreamingMovies Contract MonthlyCharges TotalCharges Churn \n",
+ "0 No Month-to-month 29.85 29.85 No \n",
+ "1 No One year 56.95 1889.5 No \n",
+ "2 No Month-to-month 53.85 108.15 Yes \n",
+ "3 No One year 42.30 1840.75 No \n",
+ "4 No Month-to-month 70.70 151.65 Yes "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "churnData = pd.read_csv('Customer-Churn.csv')\n",
+ "churnData.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58516276",
+ "metadata": {},
+ "source": [
+ "3.) Check the datatypes of all the columns in the data. You would see that the column TotalCharges is object type. Convert this column into numeric type using pd.to_numeric function."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "a293b997",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_started(data): \n",
+ " data.columns = [column.lower().replace(' ', '_').replace('#_','') for column in data.columns]\n",
+ " print(\"shape dataframe: \", data.shape, data.info())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "414bf65f",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "RangeIndex: 7043 entries, 0 to 7042\n",
+ "Data columns (total 16 columns):\n",
+ " # Column Non-Null Count Dtype \n",
+ "--- ------ -------------- ----- \n",
+ " 0 gender 7043 non-null object \n",
+ " 1 seniorcitizen 7043 non-null int64 \n",
+ " 2 partner 7043 non-null object \n",
+ " 3 dependents 7043 non-null object \n",
+ " 4 tenure 7043 non-null int64 \n",
+ " 5 phoneservice 7043 non-null object \n",
+ " 6 onlinesecurity 7043 non-null object \n",
+ " 7 onlinebackup 7043 non-null object \n",
+ " 8 deviceprotection 7043 non-null object \n",
+ " 9 techsupport 7043 non-null object \n",
+ " 10 streamingtv 7043 non-null object \n",
+ " 11 streamingmovies 7043 non-null object \n",
+ " 12 contract 7043 non-null object \n",
+ " 13 monthlycharges 7043 non-null float64\n",
+ " 14 totalcharges 7043 non-null object \n",
+ " 15 churn 7043 non-null object \n",
+ "dtypes: float64(1), int64(2), object(13)\n",
+ "memory usage: 880.5+ KB\n",
+ "shape dataframe: (7043, 16) None\n"
+ ]
+ }
+ ],
+ "source": [
+ "get_started(churnData)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "f79b152f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Index(['gender', 'seniorcitizen', 'partner', 'dependents', 'tenure',\n",
+ " 'phoneservice', 'onlinesecurity', 'onlinebackup', 'deviceprotection',\n",
+ " 'techsupport', 'streamingtv', 'streamingmovies', 'contract',\n",
+ " 'monthlycharges', 'totalcharges', 'churn'],\n",
+ " dtype='object')"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "churnData.columns"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "ae7f29eb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "churnData[\"totalcharges\"] = pd.to_numeric(churnData[\"totalcharges\"], errors='raise')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a6fb09bc",
+ "metadata": {},
+ "source": [
+ "4.) Check for null values in the dataframe. Replace the null values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "4705f339",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def percantage_null(data):\n",
+ " nulls = pd.DataFrame(data.isna().sum()*100/len(data), columns=['percentage'])\n",
+ " print(nulls.sort_values('percentage', ascending = False))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "76b89ae3",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " percentage\n",
+ "totalcharges 0.156183\n",
+ "gender 0.000000\n",
+ "seniorcitizen 0.000000\n",
+ "partner 0.000000\n",
+ "dependents 0.000000\n",
+ "tenure 0.000000\n",
+ "phoneservice 0.000000\n",
+ "onlinesecurity 0.000000\n",
+ "onlinebackup 0.000000\n",
+ "deviceprotection 0.000000\n",
+ "techsupport 0.000000\n",
+ "streamingtv 0.000000\n",
+ "streamingmovies 0.000000\n",
+ "contract 0.000000\n",
+ "monthlycharges 0.000000\n",
+ "churn 0.000000\n"
+ ]
+ }
+ ],
+ "source": [
+ "percantage_null(churnData)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "id": "88c91f54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def replace_by_mean(data, columns = []):\n",
+ " for i in columns:\n",
+ " data[i].fillna(data[i].mean(), inplace = True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "738fb927",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "replace_by_mean(churnData, columns = [\"totalcharges\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "id": "83a062a7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " percentage\n",
+ "gender 0.0\n",
+ "seniorcitizen 0.0\n",
+ "partner 0.0\n",
+ "dependents 0.0\n",
+ "tenure 0.0\n",
+ "phoneservice 0.0\n",
+ "onlinesecurity 0.0\n",
+ "onlinebackup 0.0\n",
+ "deviceprotection 0.0\n",
+ "techsupport 0.0\n",
+ "streamingtv 0.0\n",
+ "streamingmovies 0.0\n",
+ "contract 0.0\n",
+ "monthlycharges 0.0\n",
+ "totalcharges 0.0\n",
+ "churn 0.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "percantage_null(churnData)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3fbfaeb5",
+ "metadata": {},
+ "source": [
+ "5.) Use the following features: tenure, SeniorCitizen, MonthlyCharges and TotalCharges:\n",
+ "- Scale the features either by using normalizer or a standard scaler.\n",
+ "- Split the data into a training set and a test set.\n",
+ "- Fit a logistic regression model on the training data.\n",
+ "- Check the accuracy on the test data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "id": "00f31375",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X = churnData[['seniorcitizen', 'tenure', 'monthlycharges', 'totalcharges']]\n",
+ "y = churnData['churn']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "id": "3753e689",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(7043, 4)"
+ ]
+ },
+ "execution_count": 50,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "transformer = Normalizer() \n",
+ "transformer.fit(X)\n",
+ "x_normalized = transformer.transform(X)\n",
+ "x_normalized.shape"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "id": "9d262bc1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=100)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "id": "945e196c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " precision recall f1-score support\n",
+ "\n",
+ " No 0.82 0.90 0.86 1025\n",
+ " Yes 0.64 0.46 0.54 384\n",
+ "\n",
+ " accuracy 0.78 1409\n",
+ " macro avg 0.73 0.68 0.70 1409\n",
+ "weighted avg 0.77 0.78 0.77 1409\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "model = LogisticRegression()\n",
+ "model.fit(X_train,y_train)\n",
+ "preds = model.predict(X_test)\n",
+ "print(classification_report(y_test, preds))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8bab8c90",
+ "metadata": {},
+ "source": [
+ "## Managing imbalance in the dataset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19b512f1",
+ "metadata": {},
+ "source": [
+ "6.) Check for the imbalance."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "id": "fe04e1c1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "No 5174\n",
+ "Yes 1869\n",
+ "Name: churn, dtype: int64"
+ ]
+ },
+ "execution_count": 53,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "y.value_counts()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bd277168",
+ "metadata": {},
+ "source": [
+ "Targetcolumn is imbalanced. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1e32be72",
+ "metadata": {},
+ "source": [
+ "7.) Use the resampling strategies used in class for upsampling and downsampling to create a balance between the two classes.\n",
+ "Each time fit the model and see how the accuracy of the model is."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "id": "f73691a5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from imblearn.over_sampling import SMOTE\n",
+ "from imblearn.under_sampling import TomekLinks"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9f101815",
+ "metadata": {},
+ "source": [
+ "7.1.) Upsampling with smote"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "id": "73ce4f5a",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Yes 5174\n",
+ "No 5174\n",
+ "Name: churn, dtype: int64"
+ ]
+ },
+ "execution_count": 54,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "smote = SMOTE()\n",
+ "X_sm, y_sm = smote.fit_resample(X, y)\n",
+ "y_sm.value_counts()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 55,
+ "id": "517b6147",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " precision recall f1-score support\n",
+ "\n",
+ " No 0.74 0.73 0.73 1052\n",
+ " Yes 0.72 0.73 0.73 1018\n",
+ "\n",
+ " accuracy 0.73 2070\n",
+ " macro avg 0.73 0.73 0.73 2070\n",
+ "weighted avg 0.73 0.73 0.73 2070\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(X_sm, y_sm, test_size=0.2, random_state=100)\n",
+ "\n",
+ "model = LogisticRegression()\n",
+ "model.fit(X_train,y_train)\n",
+ "preds = model.predict(X_test)\n",
+ "print(classification_report(y_test, preds))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ba0d4f67",
+ "metadata": {},
+ "source": [
+ "Prediction on Yes much better than imbalanced data (recall before: 0.49)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4c0fc008",
+ "metadata": {},
+ "source": [
+ "7.2.) Downsampling with tomeklinks"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 58,
+ "id": "354cd206",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "No 4620\n",
+ "Yes 1869\n",
+ "Name: churn, dtype: int64"
+ ]
+ },
+ "execution_count": 58,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tomek = TomekLinks()\n",
+ "X_tl, y_tl = tomek.fit_resample(X, y)\n",
+ "y_tl.value_counts()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 59,
+ "id": "50766482",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " precision recall f1-score support\n",
+ "\n",
+ " No 0.83 0.90 0.86 891\n",
+ " Yes 0.73 0.59 0.65 407\n",
+ "\n",
+ " accuracy 0.80 1298\n",
+ " macro avg 0.78 0.74 0.76 1298\n",
+ "weighted avg 0.80 0.80 0.80 1298\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(X_tl, y_tl, test_size=0.2, random_state=100)\n",
+ "\n",
+ "model = LogisticRegression()\n",
+ "model.fit(X_train,y_train)\n",
+ "preds = model.predict(X_test)\n",
+ "print(classification_report(y_test, preds))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31c7adb8",
+ "metadata": {},
+ "source": [
+ "Prediction on Yes a little bit better than imbalanced data (recall before: 0.49)"
+ ]
+ }
+ ],
+ "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.8.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}