{"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":"Credit to @columbia2131 - I started with his notebook and then added an external data set with descriptive statistics of the targets for each player and also added unique params for each target model","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"## About Dataset","metadata":{}},{"cell_type":"markdown","source":"Train.csv is stored as a csv file with each column as follows.  \n\ntrain.csvを以下のようにして各カラムをcsvファイルとして保管しています。","metadata":{}},{"cell_type":"code","source":"%%capture\n\"\"\"\n!pip install pandarallel \n\nimport gc\n\nimport numpy as np\nimport pandas as pd\nfrom pathlib import Path\n\nfrom pandarallel import pandarallel\npandarallel.initialize()\n\nBASE_DIR = Path('../input/mlb-player-digital-engagement-forecasting')\ntrain = pd.read_csv(BASE_DIR / 'train.csv')\n\nnull = np.nan\ntrue = True\nfalse = False\n\nfor col in train.columns:\n\n    if col == 'date': continue\n\n    _index = train[col].notnull()\n    train.loc[_index, col] = train.loc[_index, col].parallel_apply(lambda x: eval(x))\n\n    outputs = []\n    for index, date, record in train.loc[_index, ['date', col]].itertuples():\n        _df = pd.DataFrame(record)\n        _df['index'] = index\n        _df['date'] = date\n        outputs.append(_df)\n\n    outputs = pd.concat(outputs).reset_index(drop=True)\n\n    outputs.to_csv(f'{col}_train.csv', index=False)\n    outputs.to_pickle(f'{col}_train.pkl')\n\n    del outputs\n    del train[col]\n    gc.collect()\n\"\"\"","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:28.104321Z","iopub.execute_input":"2021-06-18T21:49:28.105205Z","iopub.status.idle":"2021-06-18T21:49:28.121665Z","shell.execute_reply.started":"2021-06-18T21:49:28.105052Z","shell.execute_reply":"2021-06-18T21:49:28.120501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{"execution":{"iopub.status.busy":"2021-06-16T09:14:33.869464Z","iopub.execute_input":"2021-06-16T09:14:33.869905Z","iopub.status.idle":"2021-06-16T09:14:33.874766Z","shell.execute_reply.started":"2021-06-16T09:14:33.869879Z","shell.execute_reply":"2021-06-16T09:14:33.873097Z"}}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom pathlib import Path\nfrom sklearn.metrics import mean_absolute_error\nfrom datetime import timedelta\nfrom functools import reduce\nfrom tqdm import tqdm\nimport lightgbm as lgbm\nimport mlb","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:28.123263Z","iopub.execute_input":"2021-06-18T21:49:28.12359Z","iopub.status.idle":"2021-06-18T21:49:30.575622Z","shell.execute_reply.started":"2021-06-18T21:49:28.12356Z","shell.execute_reply":"2021-06-18T21:49:30.574163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_DIR = Path('../input/mlb-player-digital-engagement-forecasting')\nTRAIN_DIR = Path('../input/mlb-pdef-train-dataset')","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:30.578512Z","iopub.execute_input":"2021-06-18T21:49:30.578979Z","iopub.status.idle":"2021-06-18T21:49:30.584799Z","shell.execute_reply.started":"2021-06-18T21:49:30.578934Z","shell.execute_reply":"2021-06-18T21:49:30.582945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players = pd.read_csv(BASE_DIR / 'players.csv')\n\nrosters = pd.read_pickle(TRAIN_DIR / 'rosters_train.pkl')\ntargets = pd.read_pickle(TRAIN_DIR / 'nextDayPlayerEngagement_train.pkl')\nfollowers = pd.read_pickle(TRAIN_DIR / 'playerTwitterFollowers_train.pkl')\nteam_followers = pd.read_pickle(TRAIN_DIR / 'teamTwitterFollowers_train.pkl')\nteam_followers = team_followers.rename(columns={'numberOfFollowers': 'teamFollowers'})\nscores = pd.read_pickle(TRAIN_DIR / 'playerBoxScores_train.pkl')\nscores = scores.groupby(['playerId', 'date']).sum().reset_index()","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:30.587361Z","iopub.execute_input":"2021-06-18T21:49:30.587806Z","iopub.status.idle":"2021-06-18T21:49:35.308441Z","shell.execute_reply.started":"2021-06-18T21:49:30.587762Z","shell.execute_reply":"2021-06-18T21:49:35.307246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"targets_cols = ['playerId', 'target1', 'target2', 'target3', 'target4', 'date']\nplayers_cols = ['playerId', 'primaryPositionName']\nrosters_cols = ['playerId', 'teamId', 'status', 'date']\nfollowers_cols = ['playerId', 'numberOfFollowers', 'date']\nteamfollowers_cols = ['teamId', 'teamFollowers', 'date']\nscores_cols = ['playerId', 'battingOrder', 'gamesPlayedBatting', 'flyOuts',\n       'groundOuts', 'runsScored', 'doubles', 'triples', 'homeRuns',\n       'strikeOuts', 'baseOnBalls', 'intentionalWalks', 'hits', 'hitByPitch',\n       'atBats', 'caughtStealing', 'stolenBases', 'groundIntoDoublePlay',\n       'groundIntoTriplePlay', 'plateAppearances', 'totalBases', 'rbi',\n       'leftOnBase', 'sacBunts', 'sacFlies', 'catchersInterference',\n       'pickoffs', 'gamesPlayedPitching', 'gamesStartedPitching',\n       'completeGamesPitching', 'shutoutsPitching', 'winsPitching',\n       'lossesPitching', 'flyOutsPitching', 'airOutsPitching',\n       'groundOutsPitching', 'runsPitching', 'doublesPitching',\n       'triplesPitching', 'homeRunsPitching', 'strikeOutsPitching',\n       'baseOnBallsPitching', 'intentionalWalksPitching', 'hitsPitching',\n       'hitByPitchPitching', 'atBatsPitching', 'caughtStealingPitching',\n       'stolenBasesPitching', 'inningsPitched', 'saveOpportunities',\n       'earnedRuns', 'battersFaced', 'outsPitching', 'pitchesThrown', 'balls',\n       'strikes', 'hitBatsmen', 'balks', 'wildPitches', 'pickoffsPitching',\n       'rbiPitching', 'gamesFinishedPitching', 'inheritedRunners',\n       'inheritedRunnersScored', 'catchersInterferencePitching',\n       'sacBuntsPitching', 'sacFliesPitching', 'saves', 'holds', 'blownSaves',\n       'assists', 'putOuts', 'errors', 'chances', 'date']\n\nfeature_cols = ['label_playerId', 'label_primaryPositionName', 'label_teamId',\n       'label_status', 'battingOrder', 'gamesPlayedBatting', 'flyOuts',\n       'groundOuts', 'runsScored', 'doubles', 'triples', 'homeRuns',\n       'strikeOuts', 'baseOnBalls', 'intentionalWalks', 'hits', 'hitByPitch',\n       'atBats', 'caughtStealing', 'stolenBases', 'groundIntoDoublePlay',\n       'groundIntoTriplePlay', 'plateAppearances', 'totalBases', 'rbi',\n       'leftOnBase', 'sacBunts', 'sacFlies', 'catchersInterference',\n       'pickoffs', 'gamesPlayedPitching', 'gamesStartedPitching',\n       'completeGamesPitching', 'shutoutsPitching', 'winsPitching',\n       'lossesPitching', 'flyOutsPitching', 'airOutsPitching',\n       'groundOutsPitching', 'runsPitching', 'doublesPitching',\n       'triplesPitching', 'homeRunsPitching', 'strikeOutsPitching',\n       'baseOnBallsPitching', 'intentionalWalksPitching', 'hitsPitching',\n       'hitByPitchPitching', 'atBatsPitching', 'caughtStealingPitching',\n       'stolenBasesPitching', 'inningsPitched', 'saveOpportunities',\n       'earnedRuns', 'battersFaced', 'outsPitching', 'pitchesThrown', 'balls',\n       'strikes', 'hitBatsmen', 'balks', 'wildPitches', 'pickoffsPitching',\n       'rbiPitching', 'gamesFinishedPitching', 'inheritedRunners',\n       'inheritedRunnersScored', 'catchersInterferencePitching',\n       'sacBuntsPitching', 'sacFliesPitching', 'saves', 'holds', 'blownSaves',\n       'assists', 'putOuts', 'errors', 'chances','target1_mean',\n 'target1_median',\n 'target1_std',\n 'target1_min',\n 'target1_max',\n 'target1_prob','target2_mean',\n 'target2_median',\n 'target2_std',\n 'target2_min',\n 'target2_max',\n 'target2_prob','target3_mean',\n 'target3_median',\n 'target3_std',\n 'target3_min',\n 'target3_max',\n 'target3_prob','target4_mean',\n 'target4_median',\n 'target4_std',\n 'target4_min',\n 'target4_max',\n 'target4_prob']#'numberOfFollowers','teamFollowers'","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:35.310119Z","iopub.execute_input":"2021-06-18T21:49:35.310733Z","iopub.status.idle":"2021-06-18T21:49:35.327351Z","shell.execute_reply.started":"2021-06-18T21:49:35.310681Z","shell.execute_reply":"2021-06-18T21:49:35.326441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"player_target_stats = pd.read_csv(\"../input/player-target-stats/player_target_stats.csv\")\ndata_names=player_target_stats.columns.values.tolist()\ndata_names","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:35.328826Z","iopub.execute_input":"2021-06-18T21:49:35.329529Z","iopub.status.idle":"2021-06-18T21:49:35.373003Z","shell.execute_reply.started":"2021-06-18T21:49:35.329474Z","shell.execute_reply":"2021-06-18T21:49:35.37176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# creat dataset\ntrain = targets[targets_cols].merge(players[players_cols], on=['playerId'], how='left')\ntrain = train.merge(rosters[rosters_cols], on=['playerId', 'date'], how='left')\ntrain = train.merge(scores[scores_cols], on=['playerId', 'date'], how='left')\ntrain = train.merge(followers[followers_cols], on=['playerId', 'date'], how='left')\ntrain = train.merge(team_followers[teamfollowers_cols], on=['teamId', 'date'], how='left')\ntrain = train.merge(player_target_stats, how='inner', left_on=[\"playerId\"],right_on=[\"playerId\"])\n\n# label encoding\nplayer2num = {c: i for i, c in enumerate(train['playerId'].unique())}\nposition2num = {c: i for i, c in enumerate(train['primaryPositionName'].unique())}\nteamid2num = {c: i for i, c in enumerate(train['teamId'].unique())}\nstatus2num = {c: i for i, c in enumerate(train['status'].unique())}\ntrain['label_playerId'] = train['playerId'].map(player2num)\ntrain['label_primaryPositionName'] = train['primaryPositionName'].map(position2num)\ntrain['label_teamId'] = train['teamId'].map(teamid2num)\ntrain['label_status'] = train['status'].map(status2num)","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:35.374424Z","iopub.execute_input":"2021-06-18T21:49:35.374775Z","iopub.status.idle":"2021-06-18T21:49:47.348919Z","shell.execute_reply.started":"2021-06-18T21:49:35.374731Z","shell.execute_reply":"2021-06-18T21:49:47.347842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_X = train[feature_cols]\ntrain_y = train[['target1', 'target2', 'target3', 'target4']]\n\n_index = (train['date'] < 20210401)\nx_train = train_X.loc[_index].reset_index(drop=True)\ny_train = train_y.loc[_index].reset_index(drop=True)\nx_valid = train_X.loc[~_index].reset_index(drop=True)\ny_valid = train_y.loc[~_index].reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:47.351187Z","iopub.execute_input":"2021-06-18T21:49:47.351505Z","iopub.status.idle":"2021-06-18T21:49:51.409274Z","shell.execute_reply.started":"2021-06-18T21:49:47.351475Z","shell.execute_reply":"2021-06-18T21:49:51.408226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def fit_lgbm(x_train, y_train, x_valid, y_valid, params: dict=None, verbose=100):\n    oof_pred = np.zeros(len(y_valid), dtype=np.float32)\n    model = lgbm.LGBMRegressor(**params)\n    model.fit(x_train, y_train, \n        eval_set=[(x_valid, y_valid)],  \n        early_stopping_rounds=verbose, \n        verbose=verbose)\n    oof_pred = model.predict(x_valid)\n    score = mean_absolute_error(oof_pred, y_valid)\n    print('mae:', score)\n    return oof_pred, model, score\n\n\n# training lightgbm\nparams1 = {\n 'objective':'mae',\n 'reg_alpha': 0.1,\n 'reg_lambda': 0.1, \n 'n_estimators': 10000,\n 'learning_rate': 0.1,\n 'random_state': 42,\n \"num_leaves\": 100\n}\n\nparams2 = {\n 'objective':'mae',\n 'reg_alpha': 0.1,\n 'reg_lambda': 0.1, \n 'n_estimators': 80,\n 'learning_rate': 0.1,\n 'random_state': 42,\n \"num_leaves\": 22\n}\n\nparams4 = {\n 'objective':'mae',\n 'reg_alpha': 0.1,\n 'reg_lambda': 0.1, \n 'n_estimators': 10000,\n 'learning_rate': 0.1,\n 'random_state': 42,\n \"num_leaves\": 100\n}\n\n\nparams = {\n 'objective':'mae',\n 'reg_alpha': 0.1,\n 'reg_lambda': 0.1, \n 'n_estimators': 10000,\n 'learning_rate': 0.1,\n 'random_state': 42,\n \"num_leaves\": 100\n}\n\n\noof1, model1, score1 = fit_lgbm(\n    x_train, y_train['target1'],\n    x_valid, y_valid['target1'],\n    params1\n)\n\noof2, model2, score2 = fit_lgbm(\n    x_train, y_train['target2'],\n    x_valid, y_valid['target2'],\n    params2\n)\n\noof3, model3, score3 = fit_lgbm(\n    x_train, y_train['target3'],\n    x_valid, y_valid['target3'],\n    params\n)\n\noof4, model4, score4 = fit_lgbm(\n    x_train, y_train['target4'],\n    x_valid, y_valid['target4'],\n    params4\n)\n\nscore = (score1+score2+score3+score4) / 4\nprint(f'score: {score}')","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:49:51.411052Z","iopub.execute_input":"2021-06-18T21:49:51.411483Z","iopub.status.idle":"2021-06-18T21:54:04.866575Z","shell.execute_reply.started":"2021-06-18T21:49:51.411437Z","shell.execute_reply":"2021-06-18T21:54:04.865476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\nfeature_imp = pd.DataFrame(sorted(zip(model1.feature_importances_,x_train[feature_cols])), columns=['Value','Feature'])\n\nplt.figure(figsize=(15, 10))\nsns.barplot(x=\"Value\", y=\"Feature\", data=feature_imp.sort_values(by=\"Value\", ascending=False))\nplt.title('LightGBM Features (avg over folds)')\nplt.tight_layout()\nplt.show()\n#plt.savefig('lgbm_importances-01.png')\n\nprint (feature_imp['Feature'].tolist())\n\nfeature_imp.tail(20)","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:54:04.870774Z","iopub.execute_input":"2021-06-18T21:54:04.872922Z","iopub.status.idle":"2021-06-18T21:54:07.87298Z","shell.execute_reply.started":"2021-06-18T21:54:04.872869Z","shell.execute_reply":"2021-06-18T21:54:07.871349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{}},{"cell_type":"code","source":"players_cols = ['playerId', 'primaryPositionName']\nrosters_cols = ['playerId', 'teamId', 'status']\nscores_cols = ['playerId', 'battingOrder', 'gamesPlayedBatting', 'flyOuts',\n       'groundOuts', 'runsScored', 'doubles', 'triples', 'homeRuns',\n       'strikeOuts', 'baseOnBalls', 'intentionalWalks', 'hits', 'hitByPitch',\n       'atBats', 'caughtStealing', 'stolenBases', 'groundIntoDoublePlay',\n       'groundIntoTriplePlay', 'plateAppearances', 'totalBases', 'rbi',\n       'leftOnBase', 'sacBunts', 'sacFlies', 'catchersInterference',\n       'pickoffs', 'gamesPlayedPitching', 'gamesStartedPitching',\n       'completeGamesPitching', 'shutoutsPitching', 'winsPitching',\n       'lossesPitching', 'flyOutsPitching', 'airOutsPitching',\n       'groundOutsPitching', 'runsPitching', 'doublesPitching',\n       'triplesPitching', 'homeRunsPitching', 'strikeOutsPitching',\n       'baseOnBallsPitching', 'intentionalWalksPitching', 'hitsPitching',\n       'hitByPitchPitching', 'atBatsPitching', 'caughtStealingPitching',\n       'stolenBasesPitching', 'inningsPitched', 'saveOpportunities',\n       'earnedRuns', 'battersFaced', 'outsPitching', 'pitchesThrown', 'balls',\n       'strikes', 'hitBatsmen', 'balks', 'wildPitches', 'pickoffsPitching',\n       'rbiPitching', 'gamesFinishedPitching', 'inheritedRunners',\n       'inheritedRunnersScored', 'catchersInterferencePitching',\n       'sacBuntsPitching', 'sacFliesPitching', 'saves', 'holds', 'blownSaves',\n       'assists', 'putOuts', 'errors', 'chances']\n\nnull = np.nan\ntrue = True\nfalse = False\n\nenv = mlb.make_env() # initialize the environment\niter_test = env.iter_test() # iterator which loops over each date in test set\n\nfor (test_df, sample_prediction_df) in iter_test: # make predictions here\n    \n    sample_prediction_df = sample_prediction_df.reset_index(drop=True)\n    \n    # creat dataset\n    sample_prediction_df['playerId'] = sample_prediction_df['date_playerId']\\\n                                        .map(lambda x: int(x.split('_')[1]))\n    # Dealing with missing values\n    if test_df['rosters'].iloc[0] == test_df['rosters'].iloc[0]:\n        test_rosters = pd.DataFrame(eval(test_df['rosters'].iloc[0]))\n    else:\n        test_rosters = pd.DataFrame({'playerId': sample_prediction_df['playerId']})\n        for col in rosters.columns:\n            if col == 'playerId': continue\n            test_rosters[col] = np.nan\n            \n    if test_df['playerBoxScores'].iloc[0] == test_df['playerBoxScores'].iloc[0]:\n        test_scores = pd.DataFrame(eval(test_df['playerBoxScores'].iloc[0]))\n    else:\n        test_scores = pd.DataFrame({'playerId': sample_prediction_df['playerId']})\n        for col in scores.columns:\n            if col == 'playerId': continue\n            test_scores[col] = np.nan\n    test_scores = test_scores.groupby('playerId').sum().reset_index()\n    test = sample_prediction_df[['playerId']].copy()\n    test = test.merge(players[players_cols], on='playerId', how='left')\n    test = test.merge(test_rosters[rosters_cols], on='playerId', how='left')\n    test = test.merge(test_scores[scores_cols], on='playerId', how='left')\n    test = test.merge(player_target_stats, how='inner', left_on=[\"playerId\"],right_on=[\"playerId\"])\n    \n\n    test['label_playerId'] = test['playerId'].map(player2num)\n    test['label_primaryPositionName'] = test['primaryPositionName'].map(position2num)\n    test['label_teamId'] = test['teamId'].map(teamid2num)\n    test['label_status'] = test['status'].map(status2num)\n    \n    test_X = test[feature_cols]\n    \n    # predict\n    pred1 = model1.predict(test_X)\n    pred2 = model2.predict(test_X)\n    pred3 = model3.predict(test_X)\n    pred4 = model4.predict(test_X)\n    \n    # merge submission\n    sample_prediction_df['target1'] = np.clip(pred1, 0, 100)\n    sample_prediction_df['target2'] = np.clip(pred2, 0, 100)\n    sample_prediction_df['target3'] = np.clip(pred3, 0, 100)\n    sample_prediction_df['target4'] = np.clip(pred4, 0, 100)\n    sample_prediction_df = sample_prediction_df.fillna(0.)\n    del sample_prediction_df['playerId']\n    \n    env.predict(sample_prediction_df)","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:54:07.87481Z","iopub.execute_input":"2021-06-18T21:54:07.875255Z","iopub.status.idle":"2021-06-18T21:54:10.933038Z","shell.execute_reply.started":"2021-06-18T21:54:07.875207Z","shell.execute_reply":"2021-06-18T21:54:10.932058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_prediction_df","metadata":{"execution":{"iopub.status.busy":"2021-06-18T21:54:10.934514Z","iopub.execute_input":"2021-06-18T21:54:10.935172Z","iopub.status.idle":"2021-06-18T21:54:10.954915Z","shell.execute_reply.started":"2021-06-18T21:54:10.935119Z","shell.execute_reply":"2021-06-18T21:54:10.953661Z"},"trusted":true},"execution_count":null,"outputs":[]}]}