{"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":"markdown","source":"# GLC2022 - KNN Baseline\n\nI was wondering about what we can learn from coordinates alone. Before going into much more complex models, I tought a knn might be a good baseline.\n","metadata":{}},{"cell_type":"code","source":"%pylab inline --no-import-all\n\nimport os\nfrom pathlib import Path\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom sklearn.neighbors import NearestNeighbors\n\n# Change this path to adapt to where you downloaded the data\nDATA_PATH = Path(\"../input/geolifeclef-2022-lifeclef-2022-fgvc9\")\n\n# Create the path to save submission files\nSUBMISSION_PATH = Path(\"submissions\")\nos.makedirs(SUBMISSION_PATH, exist_ok=True)\n\n# Clone the GitHub repository\n!rm -rf GLC\n!git clone https://github.com/maximiliense/GLC\n    \n#from GLC.metrics import top_30_error_rate, top_k_error_rate_from_sets, predict_top_30_set, generate_submission_file\n\nfrom GLC.metrics import top_30_error_rate, top_k_error_rate_from_sets, predict_top_30_set\nfrom GLC.submission import generate_submission_file","metadata":{"ExecuteTime":{"end_time":"2022-02-15T15:34:34.825855Z","start_time":"2022-02-15T15:34:33.902797Z"},"execution":{"iopub.status.busy":"2022-03-19T10:58:51.310481Z","iopub.execute_input":"2022-03-19T10:58:51.311113Z","iopub.status.idle":"2022-03-19T10:58:54.733833Z","shell.execute_reply.started":"2022-03-19T10:58:51.311046Z","shell.execute_reply":"2022-03-19T10:58:54.732661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Loading","metadata":{}},{"cell_type":"code","source":"df_obs_fr = pd.read_csv(DATA_PATH / \"observations\" / \"observations_fr_train.csv\", sep=\";\", index_col=\"observation_id\")\ndf_obs_us = pd.read_csv(DATA_PATH / \"observations\" / \"observations_us_train.csv\", sep=\";\", index_col=\"observation_id\")\ndf_obs = pd.concat((df_obs_fr, df_obs_us))\n\ndf_obs_fr_test = pd.read_csv(DATA_PATH / \"observations\" / \"observations_fr_test.csv\", sep=\";\", index_col=\"observation_id\")\ndf_obs_us_test = pd.read_csv(DATA_PATH / \"observations\" / \"observations_us_test.csv\", sep=\";\", index_col=\"observation_id\")\ndf_obs_test = pd.concat((df_obs_fr_test, df_obs_us_test))\n\nobs_id_train = df_obs.index[df_obs[\"subset\"] == \"train\"].values\nobs_id_val = df_obs.index[df_obs[\"subset\"] == \"val\"].values\nobs_id_test = df_obs_test.index.values\n\ny_train = df_obs.loc[obs_id_train][\"species_id\"].values\ny_val = df_obs.loc[obs_id_val][\"species_id\"].values\n\nn_obs = len(df_obs)\nn_train = len(obs_id_train)\nn_val = len(obs_id_val)\nn_test = len(obs_id_test)\n\nprint(f'Data set size: {n_obs} observations')\nprint(f'Train set size: {n_train} - {n_train / n_obs :.2%} of observations')\nprint(f'Validation set size: {n_val} - {n_val / n_obs :.2%} of observations')\nprint(f'Test set size: {n_test} - {n_test/n_train:.2%} of observations')","metadata":{"ExecuteTime":{"end_time":"2022-02-15T15:34:35.686811Z","start_time":"2022-02-15T15:34:34.851926Z"},"execution":{"iopub.status.busy":"2022-03-19T10:58:54.736330Z","iopub.execute_input":"2022-03-19T10:58:54.736644Z","iopub.status.idle":"2022-03-19T10:58:57.111389Z","shell.execute_reply.started":"2022-03-19T10:58:54.736609Z","shell.execute_reply":"2022-03-19T10:58:57.110099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nn_neighbors = 1200\n\nX_train = df_obs.loc[obs_id_train][['latitude','longitude']].values.copy()\nX_val = df_obs.loc[obs_id_val][['latitude','longitude']].values.copy()\nX_test = df_obs_test[['latitude','longitude']].values.copy()","metadata":{"execution":{"iopub.status.busy":"2022-03-19T10:58:57.112727Z","iopub.execute_input":"2022-03-19T10:58:57.112980Z","iopub.status.idle":"2022-03-19T10:58:57.334300Z","shell.execute_reply.started":"2022-03-19T10:58:57.112951Z","shell.execute_reply":"2022-03-19T10:58:57.333390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def pred_line(line, y, top_k = 30):\n    exta = line\n    arr = y[exta]\n    u, count = np.unique(arr, return_counts=True)\n    count_sort_ind = np.argsort(-count)\n    return u[count_sort_ind][:top_k]\n\n\ndef predict_NN(model, X_loc, y, top_k=30):\n    distances, indices = model.kneighbors(X_loc)\n    indices\n    preds = []\n    for i in range(len(indices)):\n        preds.append(pred_line(indices[i],y,top_k))\n    pred = np.array(preds)\n    return np.array(preds)\n\n\nX_train_loc = X_train.copy()\nX_val_loc = X_val.copy()\nX_test_loc = X_test.copy()\n\nnbrs = NearestNeighbors(n_neighbors=n_neighbors, algorithm='ball_tree').fit(X_train_loc)\n\ns_pred = predict_NN(nbrs, X_val_loc, y_train)\nscore = top_k_error_rate_from_sets(y_val, s_pred)\nprint(f'KNN {n_neighbors} - Top-30 error rate: {score:.2%}')","metadata":{"execution":{"iopub.status.busy":"2022-03-19T10:58:57.336776Z","iopub.execute_input":"2022-03-19T10:58:57.337158Z","iopub.status.idle":"2022-03-19T11:00:03.713147Z","shell.execute_reply.started":"2022-03-19T10:58:57.337111Z","shell.execute_reply":"2022-03-19T11:00:03.711747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# post processing\n\nWe only predict 5925 species. What if we remove those we are never predicting from training ? ","metadata":{}},{"cell_type":"code","source":"unique_preds = np.unique(predict_NN(nbrs, X_val_loc, y_train, 40))\n\nfilter_keep = np.isin(y_train, unique_preds)\n\ny_train_bis = y_train[filter_keep]\nX_train_loc_bis = X_train_loc[filter_keep]\n\nprint(f' propotion of target kept: {len(np.unique(y_train_bis))/len(np.unique(y_train)):.2%}')\nprint(f' propotion of instance kept: {len(y_train_bis)/len(y_train):.2%}')","metadata":{"execution":{"iopub.status.busy":"2022-03-19T11:10:29.710362Z","iopub.execute_input":"2022-03-19T11:10:29.711168Z","iopub.status.idle":"2022-03-19T11:10:30.280897Z","shell.execute_reply.started":"2022-03-19T11:10:29.711124Z","shell.execute_reply":"2022-03-19T11:10:30.279783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"nbrs = NearestNeighbors(n_neighbors=n_neighbors, algorithm='ball_tree').fit(X_train_loc_bis)\n\ns_pred_bis = predict_NN(nbrs, X_val_loc, y_train_bis)\nscore = top_k_error_rate_from_sets(y_val, s_pred_bis)\nprint(f'KNN {n_neighbors} - Top-30 error rate: {score:.2%}')","metadata":{"execution":{"iopub.status.busy":"2022-03-19T11:01:23.483733Z","iopub.execute_input":"2022-03-19T11:01:23.484105Z","iopub.status.idle":"2022-03-19T11:05:58.520471Z","shell.execute_reply.started":"2022-03-19T11:01:23.484056Z","shell.execute_reply":"2022-03-19T11:05:58.519170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# retrain on whole data set","metadata":{}},{"cell_type":"code","source":"# retrain on whole data set\n#nbrs = NearestNeighbors(n_neighbors=n_neighbors, algorithm='ball_tree').fit(df_obs[['latitude','longitude']].values)\n\n# Compute baseline on the test set\ns_pred = predict_NN(nbrs, X_test_loc, y_train_bis)\n\n# Generate the submission file\ngenerate_submission_file(SUBMISSION_PATH / \"lat_long_knn_1200.csv\", df_obs_test.index, s_pred)","metadata":{"ExecuteTime":{"end_time":"2022-02-15T15:38:44.086269Z","start_time":"2022-02-15T15:38:04.921407Z"},"execution":{"iopub.status.busy":"2022-03-19T11:00:20.455994Z","iopub.status.idle":"2022-03-19T11:00:20.456625Z","shell.execute_reply.started":"2022-03-19T11:00:20.456337Z","shell.execute_reply":"2022-03-19T11:00:20.456361Z"},"trusted":true},"execution_count":null,"outputs":[]}]}