{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Mixing PCA with \"raw\" data\n\nSince this competition has a lot of features which are meaningless for human eyes, I first decided to reduce them using PCA.  \nAfter that, why not concat some **temporal** data to this?  \nWhether this is makes sense is out of scope (yes I don't know an answer). My point is: since we do not know the meaning of *input_XXX* columns,\nwhy don't just reduce the dimensionaly since we actually lack the original meaning of the data?  \nThis could not be said about *date* columns however."},{"metadata":{},"cell_type":"markdown","source":"### PS: pleave upvote if it inspired you somehow!"},{"metadata":{"_uuid":"7ff8e885-2aac-47a1-8691-2decea1513e7","_cell_guid":"02ff9c3c-6a5f-4483-9221-fd0ed0f22678","trusted":true},"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)\nimport pickle\nfrom collections import Counter\n\nfrom sklearn.decomposition import PCA, TruncatedSVD\nfrom sklearn.manifold import TSNE\nimport os\nfrom sklearn.multioutput import MultiOutputRegressor\nfrom xgboost import XGBRegressor\nfrom sklearn.pipeline import Pipeline\nimport json\nfrom datetime import datetime\n# In[2]:\n\nINITIAL_DATE = str(datetime.now())\nDUMP_DIR = '_DUMP_' + INITIAL_DATE\n\ndef load_year(y):\n    dtypes = pickle.load(open(\n        f'../input/kdd2020-cpr/{y}_dtypes.pkl', 'rb'\n    ))\n    del dtypes['date']\n    df = pd.read_csv(\n        f'../input/kdd2020-cpr/{y}.csv',\n        dtype=dtypes, parse_dates=['date']\n    )\n    return df\n\ndef create_features(df):\n    df['input_month'] = df.date.dt.month\n    df['input_day'] = df.date.dt.day\n    df['input_dt_sin_quarter']     = np.sin(2*np.pi*df.date.dt.quarter/4)\n    df['input_dt_sin_day_of_week'] = np.sin(2*np.pi*df.date.dt.dayofweek/6)\n    df['input_dt_sin_day_of_year'] = np.sin(2*np.pi*df.date.dt.dayofyear/365)\n    df['input_dt_sin_day']         = np.sin(2*np.pi*df.date.dt.day/30)\n    df['input_dt_sin_month']       = np.sin(2*np.pi*df.date.dt.month/12)\n    return df\n\n\ndef date_expand(df, pipeline = True):\n    def is_weekend(num):\n        return num > 5\n    dt = df['date'].dt\n    df['input_week'] = dt.week\n    df['input_weekday'] = dt.weekday + 1\n    df['input_weekday_sin'] = np.sin(2*np.pi*df.date.dt.weekday/7)    \n    df['input_weekofyear'] = dt.weekofyear\n    df['input_weekofyear_sin'] = np.sin(2*np.pi*dt.weekofyear/52)\n    df['input_weekend'] = dt.weekday.apply(is_weekend)\n    return df if pipeline else None\n\nGLOBAL=\"\"\"\nYEAR = 2018\nCOMPONENTS = 100\nXGB_ESTIMATORS = 100\nMAGICIAN = 'PCA'\nINPUT_NA = 0\n\"\"\"\n# \nexec(GLOBAL)\ndf = load_year(YEAR)\ny_cols = df.columns[df.columns.str.contains('output')]\ny_train = df[y_cols]\ny_cols_flat = y_cols.ravel()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"COMPONENTS = 1000\nparams = {\n\t'n_estimators':XGB_ESTIMATORS,\n\t'random_state':0,\n\t'n_jobs':-1,\n\t'learning_rate':.2,\n\t'max_depth':13,\n\t'tree_method':'gpu_hist',\n}\n\ncp = df.copy()\ncp['day'] = cp.date.dt.day\ncp['month'] = cp.date.dt.month\ncp.drop(['date', 'id'] + y_cols.tolist(), axis=1, inplace=True)\ncp.fillna(INPUT_NA, inplace=True)\n\n\npca = PCA(n_components=COMPONENTS)\npca.fit(cp)\n\nclf = MultiOutputRegressor(XGBRegressor(**params))\n\n\ndef preprocess(df):\n\tcp = df.copy()\n\tids = df.id.copy()\n\tcp.drop(['id'] + y_cols.tolist(), axis=1, inplace=True, errors='ignore')\n\tcp.fillna(0, inplace=True)\n\tcp['day'] = cp.date.dt.day\n\tcp['month'] = cp.date.dt.month\n\tcomponentes_principais = pd.DataFrame(pca.transform(cp.drop('date', axis=1)))\n\tprint('componentes_principais.shape:', componentes_principais.shape)\n\tmixed_df = pd.concat([cp.date, componentes_principais], axis=1, ignore_index=True)\n\tprint(\"mixed_df.shape:\", mixed_df.shape)\n\tmixed_df.columns = ['date', *[f'c_{i}' for i in list(range(0, 100))]]\n\tcreate_features(mixed_df);\n\tdate_expand(mixed_df);\n\tmixed_df.drop('date', inplace=True, axis=1)\n\treturn mixed_df, ids\n\ndf_train, ids_train = preprocess(df)\nclf.fit( df_train, y_train.fillna(INPUT_NA))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.cumsum(pca.explained_variance_ratio_)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nd9 = load_year(2019)\nX, ids = preprocess(d9)\nID_COL = []\nfor i in ids:\n    ID_COL.extend(\n    \t[f'{i}_{sufix}' for sufix in y_cols_flat]\n    )\n\ny_pred = clf.predict(X)\ndf_sub = pd.DataFrame(\n    {'id':ID_COL , 'value':y_pred.ravel()}\n)\ndf_sub.set_index('id', inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def dump():\n\tos.makedirs(DUMP_DIR, exist_ok=True)\n\tglobal CSV_PATH\n\tCSV_PATH = '{}/submission.csv'.format(DUMP_DIR)\n\tdf_sub.to_csv(CSV_PATH, index='id')\n\tparams_dump_name = '{}/params.json'.format(DUMP_DIR)\n\tjson.dump(params, open(params_dump_name, 'w'))\n\twith open(f'{DUMP_DIR}/global.txt', 'w') as fp:\n\t\tfp.write(GLOBAL+'\\n')\n# Após treinar e criar o csv para submeter, salva os parâmetros.\ndump()\n\n\n# message = f\"\"\"\n# - {MAGICIAN}\n# - params: {str(params)}\n# \"\"\"\n\n# os.system(\n# \t'kaggle competitions submit -c kddbr-2020 -f {} -m \"{}\"'.format(CSV_PATH, message)\n# )","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}