{"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":"from sklearn.preprocessing import LabelEncoder, StandardScaler, MinMaxScaler, QuantileTransformer\nfrom sklearn.metrics import mean_absolute_error\nfrom scipy.stats import norm, mode\nfrom tqdm import tqdm\nfrom functools import reduce, partial\n\nimport pandas as pd\npd.set_option('display.max_columns', 500)\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport optuna\nimport datetime as dt\nimport gc\nimport joblib\n\nfrom pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping\nfrom pytorch_lightning.loggers import TensorBoardLogger\nfrom torch.utils.data import DataLoader\n\nimport pytorch_lightning as pl\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nimport math","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:27:10.784024Z","iopub.execute_input":"2021-07-30T23:27:10.784503Z","iopub.status.idle":"2021-07-30T23:27:12.628958Z","shell.execute_reply.started":"2021-07-30T23:27:10.784392Z","shell.execute_reply":"2021-07-30T23:27:12.627563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = '../input/mlb-player-digital-engagement-forecasting'","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:27:12.631116Z","iopub.execute_input":"2021-07-30T23:27:12.631479Z","iopub.status.idle":"2021-07-30T23:27:12.636614Z","shell.execute_reply.started":"2021-07-30T23:27:12.63144Z","shell.execute_reply":"2021-07-30T23:27:12.635895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"awards = pd.read_csv(f'{data_dir}/awards.csv')\nplayers = pd.read_csv(f'{data_dir}/players.csv')\nseasons = pd.read_csv(f'{data_dir}/seasons.csv')\nteams = pd.read_csv(f'{data_dir}/teams.csv')\ntrain = pd.read_csv(f'{data_dir}/train_updated.csv')","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:27:12.638029Z","iopub.execute_input":"2021-07-30T23:27:12.638459Z","iopub.status.idle":"2021-07-30T23:28:10.329985Z","shell.execute_reply.started":"2021-07-30T23:27:12.638425Z","shell.execute_reply":"2021-07-30T23:28:10.328893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LAGS = list(range(1,15))\ntargets = ['target1', 'target2', 'target3', 'target4']\nid_cols = ['playerId']\nstandings_cols = [\n    'wins', 'losses', 'pct', 'xWinLossPct', \n    'divisionRank', 'lastTenWins', 'lastTenLosses'\n]\nplayers_cols = ['playerId', 'primaryPositionName']\nrosters_cols = ['playerId', 'teamId', 'status', 'gameDate']\ngames_cols = [\n    'gameDate', 'gameTimeUTC', 'homeId', 'awayId', 'gameType', \n    'homeWins', 'homeLosses', 'homeScore', 'awayWins', 'awayLosses', 'awayScore'\n]\nlong_games_cols = [\n    'gameDate', 'gameTimeUTC', 'teamId', 'oppId', 'gameType', \n    'teamWins', 'teamLosses', 'teamScore', 'oppWins', 'oppLosses', \n    'oppScore', 'isHome', 'teamWon', 'scoreDiff'\n]\nlong_games_features = [\n    'gameTimeUTC', 'wasSigned', 'wasTraded',\n    'teamWins', 'teamLosses', 'teamScore', 'isHome', 'teamWon', 'scoreDiff'\n]\nawards_cols = [\n    'awardName'\n]\n\nhitter_cols = [\n    'gamesPlayedBatting', 'hits', 'doubles', 'triples', 'runsScored',\n    'homeRuns', 'hitByPitch', 'totalBases', 'rbi', 'stolenBases', 'assists'\n]\npitcher_cols = [\n    'gamesPlayedPitching', 'completeGamesPitching', 'shutoutsPitching', 'earnedRuns', 'winsPitching', \n    'strikeOutsPitching', 'hitsPitching', 'saveOpportunities', 'saves', 'holds', 'inningsPitched'\n]\nscores_cols = hitter_cols + pitcher_cols\nday_of_cols = ['month', 'day']\ncategorical_cols = ['label_playerId', 'label_teamId', 'label_status', 'label_primaryPositionName']  \n\nplayers_cols = ['playerId', 'primaryPositionName']\n\ndef preprocess_data(raw_data):\n    data = raw_data.copy()\n    data['date'] = pd.to_datetime(data['date'], format='%Y%m%d')\n    data['year'] = data['date'].dt.year\n    data['month'] = data['date'].dt.month\n    data['day'] = data['date'].dt.day\n    data['day_of_week'] = data['date'].dt.day_name()\n\n    data = data.loc[data['date'] > dt.datetime(2020,12,1), :]\n\n    return data\n\ndef preprocess_sub_dfs(\n    rosters, player_box_scores, team_box_scores, transactions, games,\n    standings, awards, events, player_followers, team_followers, \n    next_day_player_engagement=None\n):\n    if rosters is not None:\n        rosters['gameDate'] = pd.to_datetime(rosters['gameDate'])\n\n    if player_box_scores is not None:\n        player_box_scores['gameDate'] = pd.to_datetime(player_box_scores['gameDate'])\n\n    if transactions is not None:\n        transactions['gameDate'] = pd.to_datetime(transactions['date'])\n        transactions['wasTraded'] = np.where(transactions['typeDesc'] == 'Trade', 1, 0)\n        transactions['wasSigned'] = np.where(transactions['typeDesc'].isin(['Signed', 'Signed as Free Agent']), 1, 0)\n        transactions = transactions[transactions['playerId'].notnull()]\n\n    if standings is not None:\n        standings['leagueGamesBack'] = np.where(standings['leagueGamesBack'] == '-', '0.0', standings['leagueGamesBack'])\n        standings['leagueGamesBack'] = pd.to_numeric(standings['leagueGamesBack'])\n    \n    if player_followers is not None:\n        player_followers['year'] = player_followers['date'].dt.year\n        player_followers['month'] = player_followers['date'].dt.month\n    \n    if awards is not None:\n        awards['awardDate'] = pd.to_datetime(awards['awardDate'])\n        awards.rename(columns={'awardDate': 'gameDate'}, inplace=True)\n    \n    if team_followers is not None:\n        team_followers['year'] = team_followers['date'].dt.year\n        team_followers['month'] = team_followers['date'].dt.month\n\n    if next_day_player_engagement is not None:\n        next_day_player_engagement['engagementMetricsDate'] = pd.to_datetime(next_day_player_engagement['engagementMetricsDate'])\n    \n        return (\n            rosters, player_box_scores, team_box_scores, transactions, games,\n            standings, awards, events, player_followers, team_followers, \n            next_day_player_engagement\n        )\n    return (\n        rosters, player_box_scores, team_box_scores, transactions, games,\n        standings, awards, events, player_followers, team_followers\n    )\n\ndef load_inner_dfs(data, is_test=False):\n    rosters, player_box_scores, team_box_scores, transactions, games, standings, awards, events, player_followers, team_followers = [], [], [], [], [], [], [], [], [], []\n    if not is_test:\n        next_day_player_engagement = []\n        all_dfs = [rosters, player_box_scores, team_box_scores, transactions, games, standings, awards, events, player_followers, team_followers, next_day_player_engagement]\n    else:\n        all_dfs = [rosters, player_box_scores, team_box_scores, transactions, games, standings, awards, events, player_followers, team_followers]\n\n    for row in data.itertuples():\n        if isinstance(row.rosters, str):\n            rosters.append(pd.read_json(row.rosters))\n        if isinstance(row.playerBoxScores, str):\n            player_box_scores.append(pd.read_json(row.playerBoxScores))\n        if isinstance(row.teamBoxScores, str):\n            team_box_scores.append(pd.read_json(row.teamBoxScores))\n        if isinstance(row.transactions, str):\n            transactions.append(pd.read_json(row.transactions))\n        if isinstance(row.games, str):\n            games.append(pd.read_json(row.games))\n        if isinstance(row.standings, str):\n            standings.append(pd.read_json(row.standings))\n        if isinstance(row.awards, str):\n            awards.append(pd.read_json(row.awards))\n        if isinstance(row.events, str):\n            events.append(pd.read_json(row.events))\n        if isinstance(row.playerTwitterFollowers, str):\n            player_followers.append(pd.read_json(row.playerTwitterFollowers))\n        if isinstance(row.teamTwitterFollowers, str):\n            team_followers.append(pd.read_json(row.teamTwitterFollowers))\n        if not is_test and isinstance(row.nextDayPlayerEngagement, str):\n            next_day_player_engagement.append(pd.read_json(row.nextDayPlayerEngagement))\n    \n    if not is_test:\n        return tuple([pd.concat(df, ignore_index=True) for df in all_dfs])\n    else:\n        return tuple([df[0] if len(df) > 0 else None for df in all_dfs])\n\ndef reduce_mem_usage(df, verbose=True):\n    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']\n    start_mem = df.memory_usage().sum() / 1024**2\n    for col in df.columns:\n        col_type = df[col].dtypes\n        if col_type in numerics:\n            c_min = df[col].min()\n            c_max = df[col].max()\n            if str(col_type)[:3] == 'int':\n                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                    df[col] = df[col].astype(np.int8)\n                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                    df[col] = df[col].astype(np.int16)\n                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                    df[col] = df[col].astype(np.int32)\n                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                    df[col] = df[col].astype(np.int64)\n            else:\n                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                    df[col] = df[col].astype(np.float16)\n                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                    df[col] = df[col].astype(np.float32)\n                else:\n                    df[col] = df[col].astype(np.float64)\n    end_mem = df.memory_usage().sum() / 1024**2\n    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))\n    return df\n\ndef process_games(games):\n    home_games = games.loc[:, games_cols].rename(columns={\n        'homeId': 'teamId',\n        'awayId': 'oppId',\n        'homeWins': 'teamWins',\n        'homeLosses': 'teamLosses',\n        'homeScore': 'teamScore',\n        'awayWins': 'oppWins',\n        'awayLosses': 'oppLosses',\n        'awayScore': 'oppScore',\n    })\n    home_games['isHome'] = 1\n    home_games['teamWon'] = np.where(home_games['teamScore'] > home_games['oppScore'], 1, 0)\n    home_games['scoreDiff'] = home_games['teamScore'] - home_games['oppScore']\n    home_games = home_games.loc[:, long_games_cols]\n\n    away_games = games.loc[:, games_cols].rename(columns={\n        'awayId': 'teamId',\n        'homeId': 'oppId',\n        'awayWins': 'teamWins',\n        'awayLosses': 'teamLosses',\n        'awayScore': 'teamScore',\n        'homeWins': 'oppWins',\n        'homeLosses': 'oppLosses',\n        'homeScore': 'oppScore',\n    })\n    away_games['isHome'] = 0\n    away_games['teamWon'] = np.where(away_games['teamScore'] > away_games['oppScore'], 1, 0)\n    away_games['scoreDiff'] = away_games['teamScore'] - away_games['oppScore']\n    away_games = away_games.loc[:, long_games_cols]\n\n    long_games = pd.concat([home_games, away_games], ignore_index=True)\n    long_games['gameDate'] = pd.to_datetime(long_games['gameDate'])\n    long_games['gameTimeUTC'] = pd.to_datetime(long_games['gameTimeUTC']).dt.hour\n\n    long_games = long_games.groupby(['teamId', 'gameDate']).agg({\n        c: 'sum' if c not in ['gameTimeUTC', 'gameType', 'oppId'] else 'last' for c in long_games_features if c not in ['wasSigned', 'wasTraded']\n    })\n\n    return long_games.reset_index()\n\ndef feature_engineering(next_day_player_engagement, player_box_scores, rosters, awards, games, standings, player_followers, team_followers, transactions):\n    scores = player_box_scores.drop(columns='teamId').groupby(['playerId', 'gameDate']).sum().reset_index()\n    scores = scores.sort_values(by=['gameDate', 'playerId'])\n    scores['days_since_last_game'] = scores.groupby(['playerId']).agg({'gameDate': 'diff'})\n    in_sample_players_df = players.loc[players['playerForTestSetAndFuturePreds'] == True, players_cols]\n    # in_sample_players_df = players\n    long_games = process_games(games)\n    standings['gameDate'] = pd.to_datetime(standings['gameDate'])\n    transactions = transactions[['gameDate', 'playerId', 'wasSigned', 'wasTraded']].drop_duplicates(subset=['gameDate', 'playerId'])\n    awards = awards.groupby(['gameDate', 'playerId']).agg({'awardName': 'last'}).reset_index()\n    df = next_day_player_engagement.merge(\n            rosters, on=['playerId', 'gameDate'], how='left',\n        ).merge(scores, on=['gameDate', 'playerId'], how='left').merge(\n            player_followers[['playerId', 'year', 'month', 'numberOfFollowers']],\n            on=['playerId', 'year', 'month'],\n            how='left'\n        ).rename(columns={'numberOfFollowers': 'player_followers'}).merge(\n            in_sample_players_df[players_cols], on='playerId', how='inner'\n        ).merge(\n            team_followers[['teamId', 'year', 'month', 'numberOfFollowers']], on=['teamId', 'year', 'month'], how='left'\n        ).rename(columns={'numberOfFollowers': 'team_followers'}).merge(\n            long_games[['teamId', 'gameDate'] + [c for c in long_games_features if c not in ['wasSigned', 'wasTraded']]], on=['teamId', 'gameDate'], how='left'\n        ).merge(\n            standings[['teamId', 'gameDate'] + standings_cols], on=['teamId', 'gameDate'], how='left'\n        ).merge(\n            transactions, on=['gameDate', 'playerId'], how='left'\n        )\n    \n    return df\n\n#=======================#\ndef flatten(df, col):\n    du = (df.pivot(index=\"playerId\", columns=\"gameDate\", \n               values=col).add_prefix(f\"{col}_\").\n      rename_axis(None, axis=1).reset_index())\n    return du\n#============================#\ndef reducer(left, right):\n    return left.merge(right, on=\"playerId\")\n#========================\n\nTGTCOLS = [\"target1\",\"target2\",\"target3\",\"target4\"]\ndef train_lag(df, lag=1):\n    dp = df[[\"playerId\",\"gameDate\"]+scores_cols+long_games_features+standings_cols+season_stats_cols].copy()\n    dp[\"gameDate\"]  =dp[\"gameDate\"] + dt.timedelta(days=lag) \n    df = df.merge(dp, on=[\"playerId\", \"gameDate\"], suffixes=[\"\",f\"_{lag}\"], how=\"left\")\n    return df\n#=================================\ndef test_lag(sub):\n    sub[\"playerId\"] = sub[\"date_playerId\"].apply(lambda s: int(  s.split(\"_\")[1]  ) )\n    assert sub.date.nunique() == 1\n    dte = sub[\"date\"].unique()[0]\n    \n    eval_dt = pd.to_datetime(dte, format=\"%Y%m%d\")\n    dtes = [eval_dt + dt.timedelta(days=-k) for k in LAGS]\n    mp_dtes = {eval_dt + dt.timedelta(days=-k):k for k in LAGS}\n    #     sl = LAST.loc[LAST.gameDate.between(dtes[-1], dtes[0]), [\"gameDate\",\"playerId\"]+TGTCOLS].copy()\n    sl = LAST.loc[LAST.gameDate.isin([d for d in dtes]), [\"gameDate\",\"playerId\"]+scores_cols+long_games_features+standings_cols+season_stats_cols].copy()\n    sl[\"gameDate\"] = sl[\"gameDate\"].map(mp_dtes)\n    du = [flatten(sl, col) for col in scores_cols+long_games_features+standings_cols+season_stats_cols]\n    du = reduce(reducer, du)\n    return du, eval_dt","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:28:10.331956Z","iopub.execute_input":"2021-07-30T23:28:10.33233Z","iopub.status.idle":"2021-07-30T23:28:10.405373Z","shell.execute_reply.started":"2021-07-30T23:28:10.332269Z","shell.execute_reply":"2021-07-30T23:28:10.404381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = preprocess_data(train)\n\nrosters, player_box_scores, team_box_scores, transactions, games, standings, awards, events, player_followers, team_followers, next_day_player_engagement = load_inner_dfs(train, is_test=False)\n\nrosters, player_box_scores, team_box_scores, transactions, games, standings, awards, events, player_followers, team_followers, next_day_player_engagement = preprocess_sub_dfs(\n    rosters, player_box_scores, team_box_scores, transactions, games,\n    standings, awards, events, player_followers, team_followers, \n    next_day_player_engagement\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:28:10.406653Z","iopub.execute_input":"2021-07-30T23:28:10.406962Z","iopub.status.idle":"2021-07-30T23:29:04.300912Z","shell.execute_reply.started":"2021-07-30T23:28:10.40693Z","shell.execute_reply":"2021-07-30T23:29:04.299773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"next_day_player_engagement['gameDate'] = next_day_player_engagement['engagementMetricsDate'] - dt.timedelta(days=1)\nnext_day_player_engagement['year'] = next_day_player_engagement['gameDate'].dt.year\nnext_day_player_engagement['month'] = next_day_player_engagement['gameDate'].dt.month\nnext_day_player_engagement['day'] = next_day_player_engagement['gameDate'].dt.day\nnext_day_player_engagement['day_of_week'] = next_day_player_engagement['gameDate'].dt.day_name()\ndata = feature_engineering(next_day_player_engagement, player_box_scores, rosters, awards, games, standings, player_followers, team_followers, transactions)","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:29:04.302306Z","iopub.execute_input":"2021-07-30T23:29:04.302641Z","iopub.status.idle":"2021-07-30T23:29:07.856627Z","shell.execute_reply.started":"2021-07-30T23:29:04.302608Z","shell.execute_reply":"2021-07-30T23:29:07.855468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del rosters, player_box_scores, team_box_scores, transactions, games, standings, awards, events, player_followers, team_followers, train\ngc.collect();","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:29:07.858317Z","iopub.execute_input":"2021-07-30T23:29:07.858696Z","iopub.status.idle":"2021-07-30T23:29:08.41606Z","shell.execute_reply.started":"2021-07-30T23:29:07.85866Z","shell.execute_reply":"2021-07-30T23:29:08.414726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = data.loc[data['gameDate'] >= dt.datetime(2020,12,31), :]","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:29:08.428381Z","iopub.execute_input":"2021-07-30T23:29:08.428897Z","iopub.status.idle":"2021-07-30T23:29:08.772673Z","shell.execute_reply.started":"2021-07-30T23:29:08.428843Z","shell.execute_reply":"2021-07-30T23:29:08.771619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def agg_targets(df, agg_func):\n    if agg_func == 'std':\n        target_agg = df.groupby(['playerId', 'lag_year', 'lag_month']).agg({t: lambda x: np.std(x) for t in targets}).reset_index()\n    else:\n        target_agg = df.groupby(['playerId', 'lag_year', 'lag_month']).agg({t: agg_func for t in targets}).reset_index()\n    agg_cols = [f'{t}_{agg_func}' for t in targets]\n    target_agg.columns = ['playerId', 'lag_year', 'lag_month'] + agg_cols\n    return target_agg, agg_cols\n\n\n# %%\ndata['lag_month'] = (data['gameDate'] + dt.timedelta(days=31)).dt.month\ndata['lag_year'] = (data['gameDate'] + dt.timedelta(days=31)).dt.year\nnext_day_player_engagement['lag_month'] = (next_day_player_engagement['gameDate'] + dt.timedelta(days=31)).dt.month\nnext_day_player_engagement['lag_year'] = (next_day_player_engagement['gameDate'] + dt.timedelta(days=31)).dt.year\n\ntarget_means, mean_cols = agg_targets(next_day_player_engagement, 'mean')\ntarget_medians, median_cols = agg_targets(next_day_player_engagement, 'median')\ntarget_stds, std_cols = agg_targets(next_day_player_engagement, 'std')\ntarget_mins, min_cols = agg_targets(next_day_player_engagement, 'min')\ntarget_maxs, max_cols = agg_targets(next_day_player_engagement, 'max')\n\ndel next_day_player_engagement\ngc.collect();\n\nagg_cols = mean_cols + median_cols + std_cols + min_cols + max_cols\n\nplayer_target_stats = target_means.merge(\n    target_medians, on=['playerId', 'lag_year', 'lag_month']\n).merge(\n    target_stds, on=['playerId', 'lag_year', 'lag_month']\n).merge(\n    target_mins, on=['playerId', 'lag_year', 'lag_month']\n).merge(\n    target_maxs, on=['playerId', 'lag_year', 'lag_month']\n)\n\ncum_stats = data[['playerId', 'year', 'gameDate'] + scores_cols].fillna(0).groupby(['playerId', 'year']).rolling(\n    365, min_periods=0, on='gameDate'\n)[scores_cols].sum().reset_index().rename(columns={\n    c: f'{c}_season' for c in scores_cols\n}).drop(columns='year')\nseason_stats_cols = [f'{c}_season' for c in scores_cols]\n\ndata = data.merge(cum_stats, on=['playerId', 'gameDate'], how='left')\nprint(data.shape)\ndata = data.merge(player_target_stats, left_on=['playerId', 'year', 'month'], right_on=['playerId', 'lag_year', 'lag_month'])\nprint(data.shape)\n\nfor lag in tqdm(LAGS):\n    data = train_lag(data, lag=lag)\n    gc.collect()\n\nlag_cols = [f'{t}_{l}' for l in LAGS for t in targets]\nscores_lag_cols = scores_cols + [f'{c}_{l}' for l in LAGS for c in scores_cols]\nlong_games_lag_cols = long_games_features + [f'{c}_{l}' for l in LAGS for c in long_games_features]\nstandings_lag_cols = standings_cols + [f'{c}_{l}' for l in LAGS for c in standings_cols]\nseason_stats_lag_cols = season_stats_cols + [f'{c}_{l}' for l in LAGS for c in season_stats_cols]","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:29:08.776759Z","iopub.execute_input":"2021-07-30T23:29:08.777108Z","iopub.status.idle":"2021-07-30T23:30:33.648056Z","shell.execute_reply.started":"2021-07-30T23:29:08.777074Z","shell.execute_reply":"2021-07-30T23:30:33.647301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"features = categorical_cols + agg_cols + scores_lag_cols + standings_lag_cols + long_games_lag_cols\nfeatures += season_stats_lag_cols + ['player_followers', 'team_followers']","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:30:33.649199Z","iopub.execute_input":"2021-07-30T23:30:33.649619Z","iopub.status.idle":"2021-07-30T23:30:33.653324Z","shell.execute_reply.started":"2021-07-30T23:30:33.649588Z","shell.execute_reply":"2021-07-30T23:30:33.652535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del target_means\ndel target_medians\ndel target_stds\ndel target_mins\ndel target_maxs\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:30:33.654362Z","iopub.execute_input":"2021-07-30T23:30:33.654669Z","iopub.status.idle":"2021-07-30T23:30:33.822956Z","shell.execute_reply.started":"2021-07-30T23:30:33.654632Z","shell.execute_reply":"2021-07-30T23:30:33.821825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"player2num = joblib.load('../input/mlbplfinalmodels/player2num.pkl')\nposition2num = joblib.load('../input/mlbplfinalmodels/position2num.pkl')\nteamid2num = joblib.load('../input/mlbplfinalmodels/teamid2num.pkl')\nstatus2num = joblib.load('../input/mlbplfinalmodels/status2num.pkl')","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:30:33.824376Z","iopub.execute_input":"2021-07-30T23:30:33.824765Z","iopub.status.idle":"2021-07-30T23:30:33.865608Z","shell.execute_reply.started":"2021-07-30T23:30:33.824732Z","shell.execute_reply":"2021-07-30T23:30:33.864589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset:\n    def __init__(self, X, y=None):\n        self.X = X[features]\n        self.cont_feats = [self.X.columns.get_loc(c) for c in agg_cols+['player_followers', 'team_followers'] if c in self.X]\n        self.cat_feats = [self.X.columns.get_loc(c) for c in categorical_cols if c in self.X]\n        self.scores_lags = [self.X.columns.get_loc(c) for c in scores_lag_cols if c in self.X]\n        self.games_lags = [self.X.columns.get_loc(c) for c in long_games_lag_cols if c in self.X]\n        self.standings_lags = [self.X.columns.get_loc(c) for c in standings_lag_cols if c in self.X]\n        self.season_stats_lags = [self.X.columns.get_loc(c) for c in season_stats_lag_cols if c in self.X]\n        self.X = self.X.values\n        if y is not None:\n            self.y = y.values\n        else:\n            self.y = y\n\n    def __len__(self):\n        return self.X.shape[0]\n\n    def __getitem__(self, idx):\n        row = self.X[idx, :]\n        d = {\n            'cont_feats': torch.as_tensor(row[self.cont_feats], dtype=torch.float32),\n            'cat_feats': torch.as_tensor(row[self.cat_feats], dtype=torch.long),\n            'scores_lags': torch.as_tensor(row[self.scores_lags], dtype=torch.float32),\n            'games_lags': torch.as_tensor(row[self.games_lags], dtype=torch.float32),\n            'standings_lags': torch.as_tensor(row[self.standings_lags], dtype=torch.float32),\n            'season_stats_lags': torch.as_tensor(row[self.season_stats_lags], dtype=torch.float32),\n        }\n        if self.y is not None:\n            d['y'] = torch.as_tensor(self.y[idx], dtype=torch.float32)\n            return d\n        else:\n            return d\n\nclass MLBDataModule(pl.LightningDataModule):\n    def __init__(self, X_train, y_train=None, X_val=None, y_val=None, batch_size=2048):\n        super().__init__()\n        self.X_train = X_train\n        self.y_train = y_train\n        self.X_val = X_val\n        self.y_val = y_val\n        self.batch_size = batch_size\n\n    def train_dataloader(self):\n        train_dataset = Dataset(self.X_train, self.y_train)\n        return DataLoader(\n            train_dataset, batch_size=self.batch_size,\n            shuffle=True, num_workers=4, pin_memory=True, drop_last=False\n        )\n\n    def val_dataloader(self):\n        val_dataset = Dataset(self.X_val, self.y_val)\n        return DataLoader(\n            val_dataset, batch_size=self.batch_size,\n            shuffle=False, num_workers=4, pin_memory=True, drop_last=False\n        )\n\n    def predict_dataloader(self):\n        pred_dataset = Dataset(self.X_train)\n        return DataLoader(\n            pred_dataset, batch_size=self.batch_size,\n            shuffle=False, num_workers=4, pin_memory=True\n        )\n\n    def test_dataloader(self):\n        pass","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:30:33.867142Z","iopub.execute_input":"2021-07-30T23:30:33.867661Z","iopub.status.idle":"2021-07-30T23:30:33.888616Z","shell.execute_reply.started":"2021-07-30T23:30:33.867615Z","shell.execute_reply":"2021-07-30T23:30:33.88721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_emb_params(d):\n    unq = len(d)\n    return unq+1, min(32, int((1.6 * unq)**0.56))\n\ndef conv_layer(conv_p, n_layers):\n    layers = [nn.Sequential(\n        nn.Conv1d(\n            in_channels=len(LAGS)+1,\n            out_channels=len(LAGS)+1,\n            kernel_size=4\n        ),\n        nn.BatchNorm1d(len(LAGS)+1),\n        nn.ReLU(),\n        nn.Dropout(conv_p)\n    ) for _ in range(n_layers)]\n    return nn.Sequential(*layers)\n\ndef create_gru_head(ff_layer_sizes, ff_drop_ps, cont_len, cat_len, hidden_dim):\n    ff_layers = nn.ModuleList([])\n    for i, sz in enumerate(range(len(ff_layer_sizes))):\n        in_dim = cat_len + cont_len + (hidden_dim*3 - 9) if i == 0 else ff_layer_sizes[i-1]\n        if i == 0:\n            ff_layers.append(nn.BatchNorm1d(in_dim))\n            ff_layers.append(nn.ReLU())\n        ff_layers.append(nn.Linear(in_dim, ff_layer_sizes[i]))\n        ff_layers.append(nn.BatchNorm1d(ff_layer_sizes[i]))\n        ff_layers.append(nn.ReLU())\n        ff_layers.append(nn.Dropout(ff_drop_ps[i]))\n\n    return nn.Sequential(*ff_layers, nn.Linear(ff_layer_sizes[-1], 1))\n\ndef create_transformer_head(ff_layer_sizes, ff_drop_ps, hidden_dim):\n    ff_layers = nn.ModuleList([])\n    for i, sz in enumerate(range(len(ff_layer_sizes))):\n        in_dim = hidden_dim-9 if i == 0 else ff_layer_sizes[i-1]\n        ff_layers.append(nn.Linear(in_dim, ff_layer_sizes[i]))\n        ff_layers.append(nn.BatchNorm1d(ff_layer_sizes[i]))\n        ff_layers.append(nn.ReLU())\n        ff_layers.append(nn.Dropout(ff_drop_ps[i]))\n\n    return nn.Sequential(*ff_layers, nn.Linear(ff_layer_sizes[-1], 1))\n\ndef future_mask(seq_length):\n    future_mask = (np.triu(np.ones([seq_length, seq_length]), k = 1)).astype('bool')\n    return torch.from_numpy(future_mask)\n\nclass MLBGRU(pl.LightningModule):\n    def __init__(self, batch_size, lr, wd, hidden_dim, n_rnn_layers, rnn_drop, emb_drop_ps, ff_layer_sizes, ff_drop_ps, conv_p):\n        super().__init__()\n        self.save_hyperparameters()\n\n        unique_players, player_emb_sz = get_emb_params(player2num)\n        self.player_emb = nn.Sequential(\n            nn.Embedding(1188, 32),\n            nn.Dropout(emb_drop_ps[0])\n        )\n        unique_teams, team_emb_sz = get_emb_params(teamid2num)\n        self.team_emb = nn.Sequential(\n            nn.Embedding(32, 8),\n            nn.Dropout(emb_drop_ps[1])\n        )\n        unique_status, status_emb_sz = get_emb_params(status2num)\n        self.status_emb = nn.Sequential(\n            nn.Embedding(17, 6),\n            nn.Dropout(emb_drop_ps[2])\n        )\n        unique_position, position_emb_sz = get_emb_params(position2num)\n        self.position_emb = nn.Sequential(\n            nn.Embedding(10, 4),\n            nn.Dropout(emb_drop_ps[3])\n        )\n\n        cont_len = len([f for f in agg_cols]) + 2\n        cat_len = 32 + 8 + 6 + 4\n        self.cont_bn_in = nn.BatchNorm1d(cont_len)\n\n        rnn_inp_len = len(scores_cols+long_games_features+standings_cols+season_stats_cols)\n        self.rnn_emb = nn.Linear(rnn_inp_len, hidden_dim)\n        self.rnn = nn.GRU(\n            input_size=hidden_dim,\n            num_layers=n_rnn_layers,\n            hidden_size=hidden_dim,\n            batch_first=True,\n            dropout=rnn_drop,\n        )\n\n        self.conv1 = conv_layer(conv_p, 3)\n        \n        self.ff_layers1 = create_gru_head(ff_layer_sizes, ff_drop_ps, cont_len, cat_len, hidden_dim)\n        self.ff_layers2 = create_gru_head(ff_layer_sizes, ff_drop_ps, cont_len, cat_len, hidden_dim)\n        self.ff_layers3 = create_gru_head(ff_layer_sizes, ff_drop_ps, cont_len, cat_len, hidden_dim)\n        self.ff_layers4 = create_gru_head(ff_layer_sizes, ff_drop_ps, cont_len, cat_len, hidden_dim)\n\n        self.train_loss_fn = nn.L1Loss()\n        self.val_loss_fn = nn.L1Loss()\n\n    def forward(self, cont_feats, cat_feats, scores_lags, games_lags, standings_lags, season_stats_lags):\n        x_player = self.player_emb(cat_feats[:, 0].long())\n        x_team = self.team_emb(cat_feats[:, 1].long())\n        x_status = self.status_emb(cat_feats[:, 2].long())\n        x_position = self.position_emb(cat_feats[:, 3].long())\n\n        bs = cont_feats.size(0)\n\n        x_cont = self.cont_bn_in(cont_feats)\n        x_static = torch.cat(\n            (x_cont, x_player, x_team, x_status, x_position),\n            dim=-1\n        )\n\n        x_scores = scores_lags.reshape(bs, len(LAGS)+1, len(scores_cols))\n        x_scores = torch.flip(x_scores, dims=(1,))\n\n        x_games = games_lags.reshape(bs, len(LAGS)+1, len(long_games_features))\n        x_games = torch.flip(x_games, dims=(1,))\n\n        x_standings = standings_lags.reshape(bs, len(LAGS)+1, len(standings_cols))\n        x_standings = torch.flip(x_standings, dims=(1,))\n\n        x_season_stats = season_stats_lags.reshape(bs, len(LAGS)+1, len(season_stats_cols))\n        x_season_stats = torch.flip(x_season_stats, dims=(1,))\n\n        x_lags = torch.cat((\n            x_scores, \n            x_games,\n            x_standings, \n            x_season_stats\n        ), dim=-1)\n        x_rnn = self.rnn_emb(x_lags)\n\n        rnn_out, h_n = self.rnn(x_rnn)\n        x = torch.cat((x_static, torch.mean(rnn_out, dim=1)), dim=-1)\n        \n        ar_out_cnn = self.conv1(rnn_out)\n\n        ar_out = torch.cat((\n            rnn_out[:, -1, :],\n            torch.mean(rnn_out, dim=1),\n            torch.mean(ar_out_cnn, dim=1),\n        ), dim=-1)\n        \n        x = torch.cat((x_static, ar_out), dim=-1)\n        return torch.cat((\n            self.ff_layers1(x),\n            self.ff_layers2(x),\n            self.ff_layers3(x),\n            self.ff_layers4(x),\n        ), dim=-1)\n\n        \n    def configure_optimizers(self):\n        optimizer = torch.optim.AdamW(self.parameters(), lr=self.hparams.lr, weight_decay=self.hparams.wd)\n        return {\n            'optimizer': optimizer,\n            'lr_scheduler': {\n                'scheduler': torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=3, factor=0.5),\n                'monitor': 'val_loss'\n            }\n        }\n\n    def training_step(self, batch, batch_idx):\n        cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n        games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n        y = batch['y']\n\n        logits = self(\n            cont_feats, cat_feats, scores_lags, \n            games_lags, standings_lags, season_stats_lags\n        )\n        loss = self.train_loss_fn(torch.clip(logits, min=0., max=100.), y)\n\n        self.log('train_loss', loss, on_step=True, on_epoch=True, prog_bar=True, logger=True)\n        return loss\n\n    def validation_step(self, batch, batch_idx):\n        cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n        games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n        y = batch['y']\n\n        logits = self(\n            cont_feats, cat_feats, scores_lags, \n            games_lags, standings_lags, season_stats_lags\n        )\n        logits = torch.clip(logits, min=0., max=100.)\n        loss_1 = self.val_loss_fn(logits[:, 0], y[:, 0])\n        loss_2 = self.val_loss_fn(logits[:, 1], y[:, 1])\n        loss_3 = self.val_loss_fn(logits[:, 2], y[:, 2])\n        loss_4 = self.val_loss_fn(logits[:, 3], y[:, 3])\n        loss = (loss_1 + loss_2 + loss_3 + loss_4) / 4\n\n        self.log('target_1', loss_1, on_epoch=True, logger=True)\n        self.log('target_2', loss_2, on_epoch=True, logger=True)\n        self.log('target_3', loss_3, on_epoch=True, logger=True)\n        self.log('target_4', loss_4, on_epoch=True, logger=True)\n        self.log('val_loss', loss, on_epoch=True, prog_bar=True, logger=True)\n\n    def predict_step(self, batch, batch_idx, dataloader_idx):\n        cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n        games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n\n        logits = self(\n            cont_feats, cat_feats, scores_lags, \n            games_lags, standings_lags, season_stats_lags\n        )\n        logits = torch.clip(logits, min=0., max=100.)\n\n        return logits\n\nclass PositionalEncoding(nn.Module):\n    def __init__(self, d_model, dropout=0.1, max_len=len(LAGS)+1):\n        super(PositionalEncoding, self).__init__()\n        self.dropout = nn.Dropout(p=dropout)\n\n        pe = torch.zeros(max_len, d_model)\n        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)\n        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))\n        pe[:, 0::2] = torch.sin(position * div_term)\n        pe[:, 1::2] = torch.cos(position * div_term)\n        pe = pe.unsqueeze(0).transpose(0, 1)\n        self.register_buffer('pe', pe)\n\n    def forward(self, x):\n        x = x + self.pe[:x.size(0), :]\n        return self.dropout(x)\n\nclass MLBTransformer(pl.LightningModule):\n    def __init__(\n        self, max_epochs, batch_size, lr, wd, hidden_dim, \n        dim_feedforward, nhead, encoder_drop, emb_drop_ps,\n        num_layers, conv_drop_p, ff_layer_sizes, ff_drop\n    ):\n        super().__init__()\n        self.save_hyperparameters()\n\n        unique_players, player_emb_sz = get_emb_params(player2num)\n        self.player_emb = nn.Sequential(\n            nn.Embedding(1188, 32),\n            nn.Dropout(emb_drop_ps[0])\n        )\n        unique_teams, team_emb_sz = get_emb_params(teamid2num)\n        self.team_emb = nn.Sequential(\n            nn.Embedding(32, 8),\n            nn.Dropout(emb_drop_ps[1])\n        )\n        unique_status, status_emb_sz = get_emb_params(status2num)\n        self.status_emb = nn.Sequential(\n            nn.Embedding(17, 6),\n            nn.Dropout(emb_drop_ps[2])\n        )\n        unique_position, position_emb_sz = get_emb_params(position2num)\n        self.position_emb = nn.Sequential(\n            nn.Embedding(10, 4),\n            nn.Dropout(emb_drop_ps[3])\n        )\n\n        cont_len = len([f for f in agg_cols]) + 2\n        cat_len = 32 + 8 + 6 + 4\n\n        ts_len = len(scores_cols)\n        self.enc_emb = nn.Linear(132, hidden_dim)\n        self.mask = future_mask(len(LAGS)+1).to(self.device)\n\n        self.pe = PositionalEncoding(hidden_dim).to(self.device)\n        encoder_layer = nn.TransformerEncoderLayer(\n            d_model=hidden_dim,\n            nhead=nhead,\n            dim_feedforward=dim_feedforward,\n            dropout=encoder_drop\n        )\n        self.transformer = nn.TransformerEncoder(\n            encoder_layer=encoder_layer,\n            num_layers=num_layers\n        )\n\n        self.conv = conv_layer(0.1, 3)\n\n        self.ff_layers1 = create_transformer_head(ff_layer_sizes, ff_drop, hidden_dim)\n        self.ff_layers2 = create_transformer_head(ff_layer_sizes, ff_drop, hidden_dim)\n        self.ff_layers3 = create_transformer_head(ff_layer_sizes, ff_drop, hidden_dim)\n        self.ff_layers4 = create_transformer_head(ff_layer_sizes, ff_drop, hidden_dim)\n\n        self.train_loss_fn = nn.L1Loss()\n        self.val_loss_fn = nn.L1Loss()\n\n    def forward(\n        self, cont_feats, cat_feats, scores_lags, games_lags, standings_lags, season_stats_lags\n    ):\n        x_player = self.player_emb(cat_feats[:, 0].long())\n        x_team = self.team_emb(cat_feats[:, 1].long())\n        x_status = self.status_emb(cat_feats[:, 2].long())\n        x_position = self.position_emb(cat_feats[:, 3].long())\n        \n        bs = cont_feats.size(0)\n\n        x_scores = scores_lags.reshape(bs, len(LAGS)+1, len(scores_cols))\n        x_scores = torch.flip(x_scores, dims=(1,))\n        x_scores_lags = x_scores\n\n        x_games = games_lags.reshape(bs, len(LAGS)+1, len(long_games_features))\n        x_games = torch.flip(x_games, dims=(1,))\n        x_games_lags = x_games\n\n        x_standings = standings_lags.reshape(bs, len(LAGS)+1, len(standings_cols))\n        x_standings = torch.flip(x_standings, dims=(1,))\n        x_standings_lags = x_standings\n\n        x_season_stats = season_stats_lags.reshape(bs, len(LAGS)+1, len(season_stats_cols))\n        x_season_stats = torch.flip(x_season_stats, dims=(1,))\n        x_season_stats_lags = x_season_stats\n\n        inputs = self.enc_emb(torch.cat((\n            torch.cat((x_player, x_team, x_status, x_position), dim=-1).unsqueeze(1).expand(-1, len(LAGS)+1, -1),\n            cont_feats.unsqueeze(1).expand(-1, len(LAGS)+1, -1),\n            x_scores_lags,\n            x_games_lags,\n            x_standings_lags,\n            x_season_stats_lags\n        ), dim=-1))\n\n        inputs = self.pe(inputs.permute(1, 0, 2))\n        x = self.transformer(src=inputs, mask=self.mask).permute(1,0,2)\n        x = self.conv(x)\n        x = torch.mean(x, dim=1)\n        \n        return torch.cat((\n            self.ff_layers1(x),\n            self.ff_layers2(x),\n            self.ff_layers3(x),\n            self.ff_layers4(x),\n        ), dim=-1)\n        \n        \n    def configure_optimizers(self):\n        optimizer = torch.optim.AdamW(self.parameters(), lr=self.hparams.lr, weight_decay=self.hparams.wd)\n        return {\n            'optimizer': optimizer,\n            'lr_scheduler': {\n                'scheduler': torch.optim.lr_scheduler.CosineAnnealingLR(\n                    optimizer, \n                    self.hparams.max_epochs,\n                    eta_min=1e-5\n                ),\n                'interval': 'epoch',\n                'monitor': 'val_loss'\n            }\n        }\n\n    def training_step(self, batch, batch_idx):\n        cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n        games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n        y = batch['y']\n\n        logits = self(\n            cont_feats, cat_feats, scores_lags, \n            games_lags, standings_lags, season_stats_lags\n        )\n        loss = self.train_loss_fn(torch.clip(logits, min=0., max=100.), y)\n\n        self.log('train_loss', loss, on_step=True, on_epoch=True, prog_bar=True, logger=True)\n        return loss\n\n    def validation_step(self, batch, batch_idx):\n        cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n        games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n        y = batch['y']\n\n        logits = self(\n            cont_feats, cat_feats, scores_lags, \n            games_lags, standings_lags, season_stats_lags\n        )\n        logits = torch.clip(logits, min=0., max=100.)\n        loss_1 = self.val_loss_fn(logits[:, 0], y[:, 0])\n        loss_2 = self.val_loss_fn(logits[:, 1], y[:, 1])\n        loss_3 = self.val_loss_fn(logits[:, 2], y[:, 2])\n        loss_4 = self.val_loss_fn(logits[:, 3], y[:, 3])\n        loss = (loss_1 + loss_2 + loss_3 + loss_4) / 4\n\n        self.log('target_1', loss_1, on_epoch=True, logger=True)\n        self.log('target_2', loss_2, on_epoch=True, logger=True)\n        self.log('target_3', loss_3, on_epoch=True, logger=True)\n        self.log('target_4', loss_4, on_epoch=True, logger=True)\n        self.log('val_loss', loss, on_epoch=True, prog_bar=True, logger=True)\n\n    def predict_step(self, batch, batch_idx, dataloader_idx):\n        cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n        games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n\n        logits = self(\n            cont_feats, cat_feats, scores_lags, \n            games_lags, standings_lags, season_stats_lags\n        )\n        logits = torch.clip(logits, min=0., max=100.)\n\n        return logits","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:30:33.891617Z","iopub.execute_input":"2021-07-30T23:30:33.892287Z","iopub.status.idle":"2021-07-30T23:30:33.987043Z","shell.execute_reply.started":"2021-07-30T23:30:33.892226Z","shell.execute_reply":"2021-07-30T23:30:33.985402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seeds = list(range(1, 11))\nrnn_steps = [1499 + 200*h for h in range(0, 16)]\ntransformer_steps = [1499 + 200*h for h in range(0, 16)]\ngru_models = [MLBGRU.load_from_checkpoint(f'../input/mlbplfinalmodels/final-ckpts/final-ckpts/rnn/rnn-model-seed{seed}-step_{step}.ckpt') for seed in seeds for step in rnn_steps]\ntransformer_models = [MLBTransformer.load_from_checkpoint(f'../input/mlbplfinalmodels/final-ckpts/final-ckpts/transformer/transformer-model-seed{seed}-step_{step}.ckpt') for seed in seeds for step in transformer_steps]\nmodels = gru_models + transformer_models\nscalers = joblib.load('../input/mlbplfinalmodels/rnn_scalers.pkl')","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:30:42.330798Z","iopub.execute_input":"2021-07-30T23:30:42.331436Z","iopub.status.idle":"2021-07-30T23:31:28.557562Z","shell.execute_reply.started":"2021-07-30T23:30:42.331384Z","shell.execute_reply":"2021-07-30T23:31:28.556299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"numerical_cols = [c for c in features if c not in categorical_cols]","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:31:28.559159Z","iopub.execute_input":"2021-07-30T23:31:28.559526Z","iopub.status.idle":"2021-07-30T23:31:28.565176Z","shell.execute_reply.started":"2021-07-30T23:31:28.559494Z","shell.execute_reply":"2021-07-30T23:31:28.564044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import copy\nimport mlb\n\nFE = []; SUB = [];\nLAST = data.loc[data['gameDate'] > pd.to_datetime('2020-12-31'), :].copy()\nlast_cumul_df = cum_stats[cum_stats['gameDate'] == cum_stats['gameDate'].max()].copy()\n\nnull = np.nan\ntrue = True\nfalse = False\n\nlast_player_followers = pd.read_csv('../input/mlb-preprocessed-data/last_player_twitter_followers.csv').rename(columns={\n    'numberOfFollowers': 'player_followers'\n}).drop(columns='date')\nlast_team_followers = pd.read_csv('../input/mlb-preprocessed-data/last_team_twitter_followers.csv').rename(columns={\n    'numberOfFollowers': 'team_followers'\n}).drop(columns='date')\nlast_rosters = None\nlast_player_box_scores = None\n\nplayer_target_stats = player_target_stats[\n    (player_target_stats['lag_year'] == 2021) & (player_target_stats['lag_month'] == 8)\n]\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    sub = copy.deepcopy(sample_prediction_df.reset_index())\n    test, eval_dt = test_lag(sub)\n    \n    test['gameDate'] = eval_dt\n    test['was_2020'] = 0\n    test['year'] = test['gameDate'].dt.year\n    test['month'] = test['gameDate'].dt.month\n    test['day'] = test['gameDate'].dt.day\n    \n    # Dealing with missing values\n    if isinstance(test_df['rosters'].iloc[0], str):\n        test_rosters = pd.DataFrame(eval(test_df['rosters'].iloc[0]))\n        last_rosters = test_rosters\n    else:\n        test_rosters = pd.read_csv('../input/mlb-preprocessed-data/example_rosters.csv')\n        for col in test_rosters.columns:\n            if col == 'playerId': continue\n            test_rosters[col] = np.nan\n        \n    if test_df['games'].iloc[0] == test_df['games'].iloc[0]:\n        test_games = pd.DataFrame(eval(test_df['games'].iloc[0]))\n        test_games = process_games(test_games)\n    else:\n        test_games = pd.read_csv('../input/mlb-preprocessed-data/example_games.csv')\n        test_games = process_games(test_games)\n        for col in test_games.columns:\n            if col == 'teamId': continue\n            test_games[col] = np.nan\n            \n    if test_df['standings'].iloc[0] == test_df['standings'].iloc[0]:\n        test_standings = pd.DataFrame(eval(test_df['standings'].iloc[0]))\n    else:\n        test_standings = pd.read_csv('../input/mlb-preprocessed-data/example_standings.csv')\n        for col in test_standings.columns:\n            if col == 'teamId': continue\n            test_standings[col] = np.nan\n\n    if test_df['transactions'].iloc[0] == test_df['transactions'].iloc[0]:\n        test_transactions = pd.DataFrame(eval(test_df['transactions'].iloc[0]))\n        test_transactions['gameDate'] = pd.to_datetime(test_transactions['date'])\n        test_transactions['wasTraded'] = np.where(test_transactions['typeDesc'] == 'Trade', 1, 0)\n        test_transactions['wasSigned'] = np.where(test_transactions['typeDesc'].isin(['Signed', 'Signed as Free Agent']), 1, 0)\n        test_transactions = test_transactions[test_transactions['playerId'].notnull()]\n    else:\n        test_transactions = pd.read_csv('../input/mlb-preprocessed-data/example_transactions.csv')\n        test_transactions['gameDate'] = pd.to_datetime(test_transactions['date'])\n        test_transactions['wasTraded'] = np.where(test_transactions['typeDesc'] == 'Trade', 1, 0)\n        test_transactions['wasSigned'] = np.where(test_transactions['typeDesc'].isin(['Signed', 'Signed as Free Agent']), 1, 0)\n        test_transactions = test_transactions[test_transactions['playerId'].notnull()]\n        for col in test_transactions.columns:\n            if col == 'playerId': continue\n            test_transactions[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        test_scores = pd.read_csv('../input/mlb-preprocessed-data/example_player_box_scores.csv')\n        for col in test_scores.columns:\n            if col == 'playerId': continue\n            test_scores[col] = np.nan\n            \n    if test_df['playerTwitterFollowers'].iloc[0] == test_df['playerTwitterFollowers'].iloc[0]:\n        test_player_followers = pd.DataFrame(eval(test_df['playerTwitterFollowers'].iloc[0])).drop(columns='date')\n        test_player_followers.rename(columns={\n            'numberOfFollowers': 'player_followers'\n        }, inplace=True)\n        last_player_followers = test_player_followers\n    else:\n        test_player_followers = last_player_followers\n\n    if test_df['teamTwitterFollowers'].iloc[0] == test_df['teamTwitterFollowers'].iloc[0]:\n        test_team_followers = pd.DataFrame(eval(test_df['teamTwitterFollowers'].iloc[0])).drop(columns='date')\n        test_team_followers.rename(columns={\n            'numberOfFollowers': 'team_followers'\n        }, inplace=True)\n        last_team_followers = test_team_followers\n    else:\n        test_team_followers = last_team_followers\n            \n    test_scores = test_scores.groupby('playerId').sum().reset_index()\n    #test_scores = test_scores.merge(test_player_followers, how='left', on='playerId')\n    \n    test = test.merge(players[players_cols], on='playerId', how='left')\n    test = test.merge(test_rosters[rosters_cols].drop(columns='gameDate'), on='playerId', how='left')\n    test = test.merge(test_scores[['playerId'] + scores_cols], on='playerId', how='left')\n    test = test.merge(test_games.drop(columns='gameDate'), on='teamId', how='left')\n    test = test.merge(test_standings[['teamId'] + standings_cols], on='teamId', how='left')\n    test = test.merge(test_transactions[['playerId', 'wasSigned', 'wasTraded']].drop_duplicates(subset=['playerId']), on='playerId', how='left')\n    test = test.merge(player_target_stats, how='left', on='playerId')\n    test = test.merge(test_player_followers, how='left', on='playerId')\n    test = test.merge(test_team_followers, how='left', on='teamId')\n    test.drop(columns=['lag_year', 'lag_month'], inplace=True)\n    \n    test_cum_stats = last_cumul_df.merge(test_scores[['playerId'] + scores_cols], on='playerId', how='left').fillna(0)\n    for c in scores_cols:\n        test_cum_stats[f'{c}_season'] = test_cum_stats[f'{c}_season'] + test_cum_stats[c]\n    test_cum_stats = test_cum_stats[['playerId'] + season_stats_cols]\n    last_cumul_df = test_cum_stats.copy()\n    test = test.merge(test_cum_stats, on='playerId', how='left')\n    \n    test['label_playerId'] = test['playerId'].fillna(-999).map(player2num)\n    test['label_primaryPositionName'] = test['primaryPositionName'].fillna(-999).map(position2num)\n    test['label_teamId'] = test['teamId'].fillna(-999).map(teamid2num).fillna(teamid2num[-999])\n    test['label_status'] = test['status'].fillna(-999).map(status2num).fillna(status2num[-999])\n    \n    X_test = test.loc[:, features]\n    \n    X_test = X_test.fillna(0)\n    for i, scaler in enumerate(scalers):\n        X_test[numerical_cols[i]] = scaler.transform(X_test[numerical_cols[i]].values.reshape(-1,1))\n    dm = MLBDataModule(X_test)\n    #model.freeze();\n    with torch.no_grad():\n        preds = []\n        for batch in dm.predict_dataloader():\n            cont_feats, cat_feats, scores_lags = batch['cont_feats'], batch['cat_feats'], batch['scores_lags']\n            games_lags, standings_lags, season_stats_lags = batch['games_lags'], batch['standings_lags'], batch['season_stats_lags']\n            model_preds = 0.\n            for m in models:\n                m.freeze();\n                model_preds += m(\n                    cont_feats, cat_feats, scores_lags, \n                    games_lags, standings_lags, season_stats_lags\n                ).detach().cpu() / len(models)\n            preds.append(model_preds)\n        \n        if len(preds) > 1:\n            preds = torch.cat(*preds, dim=0).numpy()\n        else:\n            preds = preds[0].numpy()\n        \n    test[targets] = np.clip(preds, 0, 100)\n    \n    sub.drop([\"date\"]+TGTCOLS, axis=1, inplace=True)\n    sub = sub.merge(test[['playerId']+targets], on=\"playerId\", how=\"left\")\n    sub.drop(\"playerId\", axis=1, inplace=True)\n    sub = sub.fillna(0.)\n\n    env.predict(sub)\n    \n    LAST = LAST.append(test.fillna(0))\n    LAST = LAST.drop_duplicates(subset=[\"gameDate\",\"playerId\"], keep=\"last\")","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:31:28.567581Z","iopub.execute_input":"2021-07-30T23:31:28.567907Z","iopub.status.idle":"2021-07-30T23:40:52.717505Z","shell.execute_reply.started":"2021-07-30T23:31:28.567868Z","shell.execute_reply":"2021-07-30T23:40:52.716088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_cum_stats","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:40:52.719889Z","iopub.execute_input":"2021-07-30T23:40:52.720237Z","iopub.status.idle":"2021-07-30T23:40:52.779766Z","shell.execute_reply.started":"2021-07-30T23:40:52.720198Z","shell.execute_reply":"2021-07-30T23:40:52.778391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:40:52.781177Z","iopub.execute_input":"2021-07-30T23:40:52.781543Z","iopub.status.idle":"2021-07-30T23:40:53.378834Z","shell.execute_reply.started":"2021-07-30T23:40:52.781508Z","shell.execute_reply":"2021-07-30T23:40:53.37758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LAST","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:40:53.380153Z","iopub.execute_input":"2021-07-30T23:40:53.380474Z","iopub.status.idle":"2021-07-30T23:40:55.742334Z","shell.execute_reply.started":"2021-07-30T23:40:53.380444Z","shell.execute_reply":"2021-07-30T23:40:55.741089Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:40:55.744087Z","iopub.execute_input":"2021-07-30T23:40:55.744556Z","iopub.status.idle":"2021-07-30T23:40:55.761844Z","shell.execute_reply.started":"2021-07-30T23:40:55.744508Z","shell.execute_reply":"2021-07-30T23:40:55.760667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LAST.tail()","metadata":{"execution":{"iopub.status.busy":"2021-07-30T23:40:55.76441Z","iopub.execute_input":"2021-07-30T23:40:55.765062Z","iopub.status.idle":"2021-07-30T23:40:56.331792Z","shell.execute_reply.started":"2021-07-30T23:40:55.765011Z","shell.execute_reply":"2021-07-30T23:40:56.330724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}