{"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 as pd \nimport matplotlib.pyplot as plt \nimport numpy as np \nimport seaborn as sns\nfrom tqdm.notebook import tqdm \n\nimport matplotlib\nfrom matplotlib import rc\n\nrc(\"font\", **{\"family\": \"sans-serif\", \"sans-serif\": \"DejaVu Sans\"})\nrc(\"figure\", **{\"dpi\": 200})\nrc(\n    \"axes\",\n    **{\"spines.right\": False, \"spines.top\": False, \"xmargin\": 0.0, \"ymargin\": 0.05}\n)","metadata":{"_uuid":"349a1362-e369-49ae-906d-1b5f8a48475d","_cell_guid":"994dad23-6226-4b87-a0be-56f9a378ac40","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-20T12:06:00.663391Z","iopub.execute_input":"2022-04-20T12:06:00.664683Z","iopub.status.idle":"2022-04-20T12:06:00.671665Z","shell.execute_reply.started":"2022-04-20T12:06:00.664634Z","shell.execute_reply":"2022-04-20T12:06:00.670824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('../input/eurecom-aml-2022-challenge-1/public/train.csv', low_memory=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T11:53:21.662828Z","iopub.execute_input":"2022-04-20T11:53:21.663111Z","iopub.status.idle":"2022-04-20T11:54:31.472034Z","shell.execute_reply.started":"2022-04-20T11:53:21.663072Z","shell.execute_reply":"2022-04-20T11:54:31.470628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = pd.read_csv('../input/eurecom-aml-2022-challenge-1/public/test_feat.csv', low_memory=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T11:54:31.474073Z","iopub.execute_input":"2022-04-20T11:54:31.474423Z","iopub.status.idle":"2022-04-20T11:54:48.565663Z","shell.execute_reply.started":"2022-04-20T11:54:31.474379Z","shell.execute_reply":"2022-04-20T11:54:48.564695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T11:56:03.406761Z","iopub.execute_input":"2022-04-20T11:56:03.407116Z","iopub.status.idle":"2022-04-20T11:56:03.416506Z","shell.execute_reply.started":"2022-04-20T11:56:03.407079Z","shell.execute_reply":"2022-04-20T11:56:03.415657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data analysis\n\nIn this challenge, you are free (and encouraged) to explore in depth the data you have, you can run simple queries on the data, perform exploration and compute statistics.\n\n**NOTE**: finding the right question to ask is difficult! Don't be afraid to complement your analysis with your own questions. This can give you extra points!\n\n**NOTE 2**: the presentation quality is critical in any business-oriented data analysis. Take time to create few but informative plots, rather than endless tables! ","metadata":{}},{"cell_type":"code","source":"tr_coordinates = df[['fact_latitude','fact_longitude']].drop_duplicates()\nte_coordinates = df_test[['fact_latitude','fact_longitude']].drop_duplicates()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:03:23.223225Z","iopub.execute_input":"2022-04-20T12:03:23.224049Z","iopub.status.idle":"2022-04-20T12:03:23.500428Z","shell.execute_reply.started":"2022-04-20T12:03:23.223975Z","shell.execute_reply":"2022-04-20T12:03:23.499273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged = te_coordinates.merge(tr_coordinates, how='left', indicator=True)\ntropic_coordinates = merged[merged['_merge']=='left_only']\ncommon_coordinates = merged[merged['_merge']=='both']","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:03:24.359089Z","iopub.execute_input":"2022-04-20T12:03:24.359441Z","iopub.status.idle":"2022-04-20T12:03:24.406464Z","shell.execute_reply.started":"2022-04-20T12:03:24.359402Z","shell.execute_reply":"2022-04-20T12:03:24.405299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, (ax0, ax1) = plt.subplots(1, 2, figsize=[10, 3], dpi=200, sharex=True, sharey=True)\nax0.scatter(tr_coordinates['fact_longitude'], tr_coordinates['fact_latitude'], \n            s=1, c='tab:green', label='Train data')\nax1.scatter(common_coordinates['fact_longitude'], common_coordinates['fact_latitude'], \n            s=1, c='tab:orange', label='In-domain test data')\nax1.scatter(tropic_coordinates['fact_longitude'], tropic_coordinates['fact_latitude'], \n            s=1, c='tab:red', label='Out-domain test data')\nax0.legend(), ax1.legend()\nfig.suptitle('Distribution of train and test points in the dataset', y=1.01, fontsize=14)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:13:07.842394Z","iopub.execute_input":"2022-04-20T12:13:07.842973Z","iopub.status.idle":"2022-04-20T12:13:08.666354Z","shell.execute_reply.started":"2022-04-20T12:13:07.842932Z","shell.execute_reply":"2022-04-20T12:13:08.665219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n# Data Pre-processing\n\nThe previous step should give you a better understanding of which pre-processing is required for the data. This may include:\n\n-    Normalising and standardising the given data;\n-    Removing outliers;\n-    Carrying out feature selection, possibly using metrics derived from information theory;\n-    Handling missing information in the dataset;\n-    Augmenting the dataset with external information;\n-    Combining existing features.\n\nBelow is a very basic example of pre-processing steps.\n","metadata":{}},{"cell_type":"code","source":"col_selection = [\n    'index', 'fact_time', 'fact_latitude', 'fact_longitude',\n    'topography_bathymetry', 'sun_elevation', 'cmc_precipitations', \n    'gfs_a_vorticity', 'gfs_cloudness', 'gfs_clouds_sea', 'gfs_humidity',\n    'fact_temperature'\n]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:08.770862Z","iopub.execute_input":"2022-04-20T12:14:08.77129Z","iopub.status.idle":"2022-04-20T12:14:08.776828Z","shell.execute_reply.started":"2022-04-20T12:14:08.771253Z","shell.execute_reply":"2022-04-20T12:14:08.775759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X = df[col_selection].dropna().iloc[:, 1:-1].values\ny = df[col_selection].dropna().iloc[:, -1].values","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:12.765727Z","iopub.execute_input":"2022-04-20T12:14:12.76649Z","iopub.status.idle":"2022-04-20T12:14:13.544204Z","shell.execute_reply.started":"2022-04-20T12:14:12.76643Z","shell.execute_reply":"2022-04-20T12:14:13.543073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Xmean, Xstd, ymean, ystd = X.mean(0), X.std(0), y.mean(), y.std()\nX = (X - Xmean) / Xstd\ny = (y - ymean) / ystd","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:13.545793Z","iopub.execute_input":"2022-04-20T12:14:13.546101Z","iopub.status.idle":"2022-04-20T12:14:13.833163Z","shell.execute_reply.started":"2022-04-20T12:14:13.546066Z","shell.execute_reply":"2022-04-20T12:14:13.832056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n# Model Selection\n\nPerhaps one of the most important segments of this challenge involves the selection of a model that can successfully handle the given data and yield sensible predictions. Instead of focusing exclusively on your final chosen model, it is also important to share your thought process in this notebook by additionally describing alternative candidate models. There is a wealth of models to choose from, such as decision trees, random forests, (Bayesian) neural networks, Gaussian processes, Lasso regression, and so on. There are several factors which may influence your decision:\n\n-    What is the model's complexity?\n-    Is the model interpretable?\n-    Is the model capable of handling different data-types?\n-    Does the model return uncertainty estimates along with predictions?\n\nIn this baseline solution, we use the Lasso regression model, which is a linear least-square model with L1 regularization on its parameters. There is a hyper-parameter that should be tuned which is the regularization strength α. Intuitively, this hyper-parameter controls the amount of shrinkage of the parameters of the model: the larger the value of α the greater the amount of shrinkage.\n\nSection 3.4.1 of the book The Elements of Statistical Learning: Data Mining, Inference, and Prediction from Trevor Hastie et al. (https://hastie.su.domains/Papers/ESLII.pdf) is a good reference for some classic regression models.","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nXtr, Xval, ytr, yval = train_test_split(X, y, random_state=1, test_size=10000)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:42.449107Z","iopub.execute_input":"2022-04-20T12:14:42.449522Z","iopub.status.idle":"2022-04-20T12:14:43.312937Z","shell.execute_reply.started":"2022-04-20T12:14:42.449476Z","shell.execute_reply":"2022-04-20T12:14:43.311986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.linear_model import Lasso\n\ndef compute_rmse(y, ypred, ystd=1.):\n    return np.mean((y - ypred)**2)**0.5 * ystd\n\nmodel = Lasso(alpha=1)\nmodel.fit(Xtr, ytr)\nypred_tr = model.predict(Xtr)\nypred_val = model.predict(Xval)\n\nprint(f'Train RMSE: {compute_rmse(ytr, ypred_tr, ystd):.3f}')\nprint(f'Valid RMSE: {compute_rmse(yval, ypred_val, ystd):.3f}')","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:49.518968Z","iopub.execute_input":"2022-04-20T12:14:49.519316Z","iopub.status.idle":"2022-04-20T12:14:50.164611Z","shell.execute_reply.started":"2022-04-20T12:14:49.519282Z","shell.execute_reply":"2022-04-20T12:14:50.163611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Parameter Optimisation\n\nIrrespective of your choice, it is highly likely that your model will have one or more parameters that require tuning. There are several techniques for carrying out such a procedure, including cross-validation, Bayesian optimisation, and several others. As before, an analysis into which parameter tuning technique best suits your model is expected before proceeding with the optimisation of your model.\n\nThe below cells demonstrate tuning the hyper-parameters α of the Ridge regression model by using cross-validation.","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import RandomizedSearchCV, GridSearchCV","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:55.071037Z","iopub.execute_input":"2022-04-20T12:14:55.071372Z","iopub.status.idle":"2022-04-20T12:14:55.07656Z","shell.execute_reply.started":"2022-04-20T12:14:55.07134Z","shell.execute_reply":"2022-04-20T12:14:55.07556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\n\ndef get_cv_idx(n, test_size=0.2, n_splits=2):\n    train_idx, test_idx = [], []\n    for _ in range(n_splits):\n        idx = np.random.permutation(n)\n        train_size = int(n * (1 - test_size)) if isinstance(test_size, float) else n - test_size\n        train_idx.append(idx[:train_size])\n        test_idx.append(idx[train_size:])\n    return train_idx, test_idx","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:14:59.071293Z","iopub.execute_input":"2022-04-20T12:14:59.071681Z","iopub.status.idle":"2022-04-20T12:14:59.079179Z","shell.execute_reply.started":"2022-04-20T12:14:59.071636Z","shell.execute_reply":"2022-04-20T12:14:59.078162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_idx, cv_idx = get_cv_idx(len(Xtr), test_size=10000, n_splits=10)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:15:19.292841Z","iopub.execute_input":"2022-04-20T12:15:19.293953Z","iopub.status.idle":"2022-04-20T12:15:20.297347Z","shell.execute_reply.started":"2022-04-20T12:15:19.293901Z","shell.execute_reply":"2022-04-20T12:15:20.296365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"param_grid = {\n    \"alpha\": [0.001, 0.01, 0.1, 1, 10]\n}\n\nsearch = GridSearchCV(model, \n                      param_grid,\n                      n_jobs=-1, \n                      verbose=1,\n                      cv=zip(train_idx, cv_idx), \n                      scoring='neg_root_mean_squared_error').fit(Xtr, ytr)\nprint('Done!')","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:15:20.299131Z","iopub.execute_input":"2022-04-20T12:15:20.299665Z","iopub.status.idle":"2022-04-20T12:15:44.215418Z","shell.execute_reply.started":"2022-04-20T12:15:20.29962Z","shell.execute_reply":"2022-04-20T12:15:44.214425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Best parameters set found on cv set:\")\nprint(search.best_params_)\nprint()\nprint(\"Grid scores on cv set:\")\nmeans = search.cv_results_[\"mean_test_score\"]\nstds = search.cv_results_[\"std_test_score\"]\nfor mean, std, params in zip(means, stds, search.cv_results_[\"params\"]):\n    print(\"%0.3f (+/-%0.03f) for %r\" % (-mean * ystd, (std * ystd) * 2, params))\nprint()\nprint(\"Error on the validation set\")\nypred_val = search.predict(Xval)\nprint(f'Valid RMSE: {compute_rmse(yval, ypred_val, ystd):.3f}')","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:15:44.220872Z","iopub.execute_input":"2022-04-20T12:15:44.223971Z","iopub.status.idle":"2022-04-20T12:15:44.252393Z","shell.execute_reply.started":"2022-04-20T12:15:44.2239Z","shell.execute_reply":"2022-04-20T12:15:44.251425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Evaluation\n\nSome form of pre-evaluation will inevitably be required in the preceding sections in order to both select an appropriate model and configure its parameters appropriately. In this final section, you may evaluate other aspects of the model such as:\n\n-    Assessing the running time of your model;\n-    Determining whether some aspects can be parallelised;\n-    Training the model with smaller subsets of the data.\n-    etc.\n\nRemember, the goal of this challenge is to construct a model for predicting the temperature around the globe.\n\n","metadata":{}},{"cell_type":"code","source":"df_test = pd.read_csv('../input/eurecom-aml-2022-challenge-1/public/test_feat.csv', low_memory=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T09:48:06.27814Z","iopub.execute_input":"2022-04-20T09:48:06.278404Z","iopub.status.idle":"2022-04-20T09:48:26.036221Z","shell.execute_reply.started":"2022-04-20T09:48:06.278379Z","shell.execute_reply":"2022-04-20T09:48:26.034719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"col_selection = [\n    'index', 'fact_time', 'fact_latitude', 'fact_longitude',\n    'topography_bathymetry', 'sun_elevation', 'cmc_precipitations',\n    'gfs_a_vorticity', 'gfs_cloudness', 'gfs_clouds_sea', 'gfs_humidity'\n]\n\nXte = df_test[col_selection].iloc[:, 1:].values\nXte = (Xte - Xmean) / Xstd","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:16:26.904866Z","iopub.execute_input":"2022-04-20T12:16:26.905234Z","iopub.status.idle":"2022-04-20T12:16:27.026594Z","shell.execute_reply.started":"2022-04-20T12:16:26.905198Z","shell.execute_reply":"2022-04-20T12:16:27.025664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ypred_te = search.predict(Xte) * ystd + ymean  # Remember to un-standardize the predictions","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:16:31.29766Z","iopub.execute_input":"2022-04-20T12:16:31.298063Z","iopub.status.idle":"2022-04-20T12:16:31.326329Z","shell.execute_reply.started":"2022-04-20T12:16:31.298019Z","shell.execute_reply":"2022-04-20T12:16:31.32505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n# Submission\nYour submission is a CSV file containing your final model's predictions on the given test data. This file should contain a header and have the following format:\n\n```\nindex,fact_temperature\n1993574,3.9865149124872303\n1993575,18.165092058370533\n1993576,16.53315442160854\n1993577,8.377598784006866\n...\n```\n\nA leaderboard for this challenge will be ranked using the root mean squared error between the predicted values and the observed arrival delays. However, you can use other metrics for regression tasks in your presentation notebook to evaluate many aspects of your model, including quantification of the uncertainty in the predictions.\n\nBelow is an example of creating a submission file.\n","metadata":{}},{"cell_type":"code","source":"submission_df = pd.DataFrame(data={'index': df_test['index'].values,\n                                   'fact_temperature': ypred_te.squeeze()})\n\n# Save the predictions into a csv file\n# Notice that this file should be saved under the directory `/kaggle/working` \n# so that you can download it later\nsubmission_df.to_csv(\"/kaggle/working/submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:17:06.770444Z","iopub.execute_input":"2022-04-20T12:17:06.770835Z","iopub.status.idle":"2022-04-20T12:17:08.111242Z","shell.execute_reply.started":"2022-04-20T12:17:06.770786Z","shell.execute_reply":"2022-04-20T12:17:08.110326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check the submission file\n! head -6 \"/kaggle/working/submission.csv\"","metadata":{"execution":{"iopub.status.busy":"2022-04-20T12:17:42.390138Z","iopub.execute_input":"2022-04-20T12:17:42.391091Z","iopub.status.idle":"2022-04-20T12:17:43.274662Z","shell.execute_reply.started":"2022-04-20T12:17:42.391019Z","shell.execute_reply":"2022-04-20T12:17:43.273299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}