diff --git a/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.ipynb b/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.ipynb index 7246258..929f798 100644 --- a/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.ipynb +++ b/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.ipynb @@ -29,8 +29,8 @@ "execution_count": 1, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:02.257143Z", - "start_time": "2020-10-19T05:40:01.849614Z" + "end_time": "2020-10-19T09:44:37.619727Z", + "start_time": "2020-10-19T09:44:37.200497Z" } }, "outputs": [], @@ -52,8 +52,8 @@ "execution_count": 2, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:03.340735Z", - "start_time": "2020-10-19T05:40:02.261077Z" + "end_time": "2020-10-19T09:44:38.709728Z", + "start_time": "2020-10-19T09:44:37.625401Z" } }, "outputs": [], @@ -83,26 +83,59 @@ "execution_count": 3, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:03.942301Z", - "start_time": "2020-10-19T05:40:03.345778Z" + "end_time": "2020-10-19T09:44:38.741179Z", + "start_time": "2020-10-19T09:44:38.714268Z" } }, "outputs": [], "source": [ - "from seq2seq_time.data.dataset import Seq2SeqDataSet, Seq2SeqDataSets\n", - "from seq2seq_time.predict import predict" + "import warnings\n", + "warnings.simplefilter('once')" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 78, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:03.994750Z", - "start_time": "2020-10-19T05:40:03.949146Z" + "end_time": "2020-10-19T12:34:06.047830Z", + "start_time": "2020-10-19T12:34:05.980011Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + } + ], + "source": [ + "from seq2seq_time.data.dataset import Seq2SeqDataSet, Seq2SeqDataSets\n", + "from seq2seq_time.predict import predict, predict_multi" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T09:44:39.357695Z", + "start_time": "2020-10-19T09:44:39.306658Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + } + ], "source": [ "import logging, sys\n", "# logging.basicConfig(stream=sys.stdout, level=logging.INFO)" @@ -122,11 +155,11 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:04.076823Z", - "start_time": "2020-10-19T05:40:04.000002Z" + "end_time": "2020-10-19T09:44:39.442584Z", + "start_time": "2020-10-19T09:44:39.362549Z" } }, "outputs": [ @@ -148,7 +181,7 @@ "batch_size = 256\n", "num_workers = 5\n", "freq = '30T'\n", - "max_rows = 2e5" + "max_rows = 5e5" ] }, { @@ -160,18 +193,18 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:04.144289Z", - "start_time": "2020-10-19T05:40:04.082254Z" + "end_time": "2020-10-19T09:44:39.507875Z", + "start_time": "2020-10-19T09:44:39.446523Z" }, "lines_to_next_cell": 0 }, "outputs": [], "source": [ "\n", - "def get_smartmeter_df(indir=Path('../data/raw/smart-meters-in-london'), max_files=1):\n", + "def get_smartmeter_df(indir=Path('../data/raw/smart-meters-in-london'), max_files=8):\n", " \"\"\"\n", " Data loading and cleanding is always messy, so understand this code is optional.\n", " \"\"\"\n", @@ -179,59 +212,72 @@ " # Load csv files\n", " csv_files = sorted((indir/'halfhourly_dataset').glob('*.csv'))[:max_files]\n", " \n", - " # concatendate them\n", - " df = pd.concat([pd.read_csv(f, parse_dates=[1], na_values=['Null']) for f in csv_files])\n", + " dfs = []\n", + " for f in csv_files:\n", + " df = (pd.read_csv(f, parse_dates=[1], na_values=['Null'])\n", + " .groupby('tstp')\n", + " .sum()\n", + " .sort_index()\n", + " )\n", + " df['block'] = f.stem\n", + "\n", + " # Drop nan and 0's\n", + " df = df[df['energy(kWh/hh)']!=0]\n", + " df = df.dropna()\n", + " \n", + " # Add time features \n", + " time = df.index.to_series()\n", + " df[\"month\"] = time.dt.month\n", + " df['day'] = time.dt.day\n", + " df['week'] = time.dt.week\n", + " df['hour'] = time.dt.hour\n", + " df['minute'] = time.dt.minute\n", + " df['dayofweek'] = time.dt.dayofweek\n", + "\n", + " # Load weather data\n", + " df_weather = pd.read_csv(indir/'weather_hourly_darksky.csv', parse_dates=[3])\n", + " use_cols = ['visibility', 'windBearing', 'temperature', 'time', 'dewPoint',\n", + " 'pressure', 'apparentTemperature', 'windSpeed', \n", + " 'humidity']\n", + " df_weather = df_weather[use_cols].set_index('time')\n", + " \n", + " # Resample to match energy data \n", + " # Use first, since we have bearing, and you can't take mean\n", + " df_weather = df_weather.resample(freq).first().ffill() \n", + "\n", + " # Join weather and energy data\n", + " df = pd.merge(df, df_weather, how='inner', left_index=True, right_index=True, sort=True)\n", + "\n", + " # Holidays\n", + " df_hols = pd.read_csv(indir/'uk_bank_holidays.csv', parse_dates=[0])\n", + " holidays = set(df_hols['Bank holidays'].dt.round('D')) \n", + " def is_holiday(dt):\n", + " return dt in holidays\n", + " days = df.index.floor('D')\n", + " holiday_mapping = days.unique().to_series().apply(is_holiday).astype(int).to_dict()\n", + " df['holiday'] = days.to_series().map(holiday_mapping).values\n", + "\n", + " # sort\n", + " df.index.name = 'Date'\n", + " df = df.loc['2012-09':] # Weird value before this\n", " \n", - " # Add ACORN categories\n", - " df_households = pd.read_csv(indir/'informations_households.csv')\n", - " df_households = df_households[['LCLid', 'stdorToU', 'Acorn_grouped']]\n", - " df = pd.merge(df, df_households, on='LCLid')\n", + " dfs.append(df)\n", " \n", - " \n", - " df = df.sort_values(['tstp', 'LCLid'])\n", - " \n", - " df = df.set_index('tstp')\n", - " \n", - " # Drop nan and 0's\n", - " df = df[df['energy(kWh/hh)']!=0]\n", - " df = df.dropna()\n", - " \n", - " # Add time features \n", - " time = df.index.to_series()\n", - " df[\"month\"] = time.dt.month\n", - " df['day'] = time.dt.day\n", - " df['week'] = time.dt.week\n", - " df['hour'] = time.dt.hour\n", - " df['minute'] = time.dt.minute\n", - " df['dayofweek'] = time.dt.dayofweek\n", - " \n", - " # Load weather data\n", - " df_weather = pd.read_csv(indir/'weather_hourly_darksky.csv', parse_dates=[3])\n", - " use_cols = ['visibility', 'windBearing', 'temperature', 'time', 'dewPoint',\n", - " 'pressure', 'apparentTemperature', 'windSpeed', \n", - " 'humidity']\n", - " df_weather = df_weather[use_cols].set_index('time')\n", - " df_weather = df_weather.resample(freq).first().ffill() # Resample to match energy data \n", - " \n", - " # Join weather and energy data\n", - " df = pd.merge(df, df_weather, how='inner', left_index=True, right_index=True, sort=True)\n", - " \n", - " # Holidays\n", - " df_hols = pd.read_csv(indir/'uk_bank_holidays.csv', parse_dates=[0])\n", - " holidays = set(df_hols['Bank holidays'].dt.round('D')) \n", - " def is_holiday(dt):\n", - " return dt in holidays\n", - " days = df.index.floor('D')\n", - " holiday_mapping = days.unique().to_series().apply(is_holiday).astype(int).to_dict()\n", - " df['holiday'] = days.to_series().map(holiday_mapping).values\n", - " \n", - " # sort\n", - " df = df.reset_index().sort_values(['LCLid', 'index']).set_index('index')\n", - " df.index.name = 'Date'\n", - " \n", - " return df" + " return pd.concat(dfs)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T06:24:38.318999Z", + "start_time": "2020-10-19T06:24:35.452722Z" + } + }, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -241,11 +287,11 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:09.431159Z", - "start_time": "2020-10-19T05:40:04.149479Z" + "end_time": "2020-10-19T09:44:57.542614Z", + "start_time": "2020-10-19T09:44:39.513851Z" }, "lines_to_next_cell": 0, "scrolled": true @@ -255,70 +301,39 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:30: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n" + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel_launcher.py:26: FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead.\n" ] }, { - "data": { - "text/plain": [ - "MAC004387 34239\n", - "MAC004431 33999\n", - "MAC004179 31083\n", - "MAC004319 30893\n", - "MAC004247 30831\n", - "MAC005492 26479\n", - "MAC004034 12476\n", - "Name: LCLid, dtype: int64" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = get_smartmeter_df()\n", - "\n", - "# # Just get the first one for now\n", - "# dfs = list(dfs)\n", - "\n", - "# # df = df.resample(freq).first().dropna() # Where empty we will backfill, this will respect causality, and mostly maintain the mean\n", - "\n", - "df = df.tail(int(max_rows)).copy() # Just use last X rows\n", - "# df = pd.concat(dfs[:6], 0)\n", - "# # df = dfs[0]\n", - "df.LCLid.value_counts()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "start_time": "2020-10-19T01:00:04.600Z" + "name": "stdout", + "output_type": "stream", + "text": [ + "block_104 26161\n", + "block_1 26161\n", + "block_102 26161\n", + "block_107 26161\n", + "block_105 26161\n", + "block_0 26161\n", + "block_106 26161\n", + "block_100 26161\n", + "block_10 26161\n", + "block_108 26161\n", + "block_103 26161\n", + "block_101 26161\n", + "Name: block, dtype: int64\n" + ] }, - "lines_to_next_cell": 2 - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plot/explore" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2020-10-19T05:40:09.530210Z", - "start_time": "2020-10-19T05:40:09.438555Z" - } - }, - "outputs": [ { "data": { "text/html": [ @@ -340,10 +355,8 @@ " \n", " \n", " \n", - " LCLid\n", " energy(kWh/hh)\n", - " stdorToU\n", - " Acorn_grouped\n", + " block\n", " month\n", " day\n", " week\n", @@ -379,120 +392,108 @@ " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", " \n", - " 2013-01-01 12:30:00\n", - " MAC004034\n", - " 0.167\n", - " Std\n", - " Affluent\n", + " 2012-09-01 00:00:00\n", + " 5.013\n", + " block_0\n", + " 9\n", " 1\n", - " 1\n", - " 1\n", - " 12\n", - " 30\n", - " 1\n", - " 13.23\n", - " 256.0\n", - " 4.01\n", - " 2.08\n", - " 1017.77\n", - " 0.55\n", - " 4.15\n", - " 0.87\n", - " 1\n", - " \n", - " \n", - " 2013-01-01 13:00:00\n", - " MAC004034\n", - " 0.185\n", - " Std\n", - " Affluent\n", - " 1\n", - " 1\n", - " 1\n", - " 13\n", + " 35\n", " 0\n", - " 1\n", - " 13.16\n", - " 251.0\n", - " 3.94\n", - " 2.13\n", - " 1018.37\n", - " 0.68\n", - " 3.80\n", - " 0.88\n", - " 1\n", - " \n", - " \n", - " 2013-01-01 13:30:00\n", - " MAC004034\n", - " 0.180\n", - " Std\n", - " Affluent\n", - " 1\n", - " 1\n", - " 1\n", - " 13\n", - " 30\n", - " 1\n", - " 13.16\n", - " 251.0\n", - " 3.94\n", - " 2.13\n", - " 1018.37\n", - " 0.68\n", - " 3.80\n", - " 0.88\n", - " 1\n", - " \n", - " \n", - " 2013-01-01 14:00:00\n", - " MAC004034\n", - " 0.158\n", - " Std\n", - " Affluent\n", - " 1\n", - " 1\n", - " 1\n", - " 14\n", " 0\n", - " 1\n", - " 13.23\n", - " 246.0\n", - " 3.37\n", - " 2.03\n", - " 1019.14\n", - " 0.36\n", - " 3.25\n", - " 0.91\n", - " 1\n", + " 5\n", + " 13.36\n", + " 302.0\n", + " 14.08\n", + " 9.74\n", + " 1028.27\n", + " 14.08\n", + " 1.89\n", + " 0.75\n", + " 0\n", " \n", " \n", - " 2013-01-01 14:30:00\n", - " MAC004034\n", - " 0.200\n", - " Std\n", - " Affluent\n", + " 2012-09-01 00:30:00\n", + " 5.157\n", + " block_0\n", + " 9\n", " 1\n", - " 1\n", - " 1\n", - " 14\n", + " 35\n", + " 0\n", " 30\n", + " 5\n", + " 13.36\n", + " 302.0\n", + " 14.08\n", + " 9.74\n", + " 1028.27\n", + " 14.08\n", + " 1.89\n", + " 0.75\n", + " 0\n", + " \n", + " \n", + " 2012-09-01 01:00:00\n", + " 6.360\n", + " block_0\n", + " 9\n", " 1\n", - " 13.23\n", - " 246.0\n", - " 3.37\n", - " 2.03\n", - " 1019.14\n", - " 0.36\n", - " 3.25\n", - " 0.91\n", + " 35\n", " 1\n", + " 0\n", + " 5\n", + " 13.50\n", + " 298.0\n", + " 13.93\n", + " 9.81\n", + " 1027.96\n", + " 13.93\n", + " 1.59\n", + " 0.76\n", + " 0\n", + " \n", + " \n", + " 2012-09-01 01:30:00\n", + " 5.511\n", + " block_0\n", + " 9\n", + " 1\n", + " 35\n", + " 1\n", + " 30\n", + " 5\n", + " 13.50\n", + " 298.0\n", + " 13.93\n", + " 9.81\n", + " 1027.96\n", + " 13.93\n", + " 1.59\n", + " 0.76\n", + " 0\n", + " \n", + " \n", + " 2012-09-01 02:00:00\n", + " 4.922\n", + " block_0\n", + " 9\n", + " 1\n", + " 35\n", + " 2\n", + " 0\n", + " 5\n", + " 13.21\n", + " 274.0\n", + " 13.52\n", + " 9.94\n", + " 1028.04\n", + " 13.52\n", + " 0.82\n", + " 0.79\n", + " 0\n", " \n", " \n", " ...\n", @@ -513,15 +514,11 @@ " ...\n", " ...\n", " ...\n", - " ...\n", - " ...\n", " \n", " \n", " 2014-02-27 22:00:00\n", - " MAC005492\n", - " 0.182\n", - " ToU\n", - " ACORN-\n", + " 9.819\n", + " block_108\n", " 2\n", " 27\n", " 9\n", @@ -540,10 +537,8 @@ " \n", " \n", " 2014-02-27 22:30:00\n", - " MAC005492\n", - " 0.122\n", - " ToU\n", - " ACORN-\n", + " 8.792\n", + " block_108\n", " 2\n", " 27\n", " 9\n", @@ -562,10 +557,8 @@ " \n", " \n", " 2014-02-27 23:00:00\n", - " MAC005492\n", - " 0.140\n", - " ToU\n", - " ACORN-\n", + " 8.087\n", + " block_108\n", " 2\n", " 27\n", " 9\n", @@ -584,10 +577,8 @@ " \n", " \n", " 2014-02-27 23:30:00\n", - " MAC005492\n", - " 0.192\n", - " ToU\n", - " ACORN-\n", + " 7.114\n", + " block_108\n", " 2\n", " 27\n", " 9\n", @@ -606,10 +597,8 @@ " \n", " \n", " 2014-02-28 00:00:00\n", - " MAC005492\n", - " 0.088\n", - " ToU\n", - " ACORN-\n", + " 7.287\n", + " block_108\n", " 2\n", " 28\n", " 9\n", @@ -628,67 +617,67 @@ " \n", " \n", "\n", - "

200000 rows × 19 columns

\n", + "

313932 rows × 17 columns

\n", "" ], "text/plain": [ - " LCLid energy(kWh/hh) stdorToU Acorn_grouped month \\\n", + " energy(kWh/hh) block month day week hour \\\n", + "Date \n", + "2012-09-01 00:00:00 5.013 block_0 9 1 35 0 \n", + "2012-09-01 00:30:00 5.157 block_0 9 1 35 0 \n", + "2012-09-01 01:00:00 6.360 block_0 9 1 35 1 \n", + "2012-09-01 01:30:00 5.511 block_0 9 1 35 1 \n", + "2012-09-01 02:00:00 4.922 block_0 9 1 35 2 \n", + "... ... ... ... ... ... ... \n", + "2014-02-27 22:00:00 9.819 block_108 2 27 9 22 \n", + "2014-02-27 22:30:00 8.792 block_108 2 27 9 22 \n", + "2014-02-27 23:00:00 8.087 block_108 2 27 9 23 \n", + "2014-02-27 23:30:00 7.114 block_108 2 27 9 23 \n", + "2014-02-28 00:00:00 7.287 block_108 2 28 9 0 \n", + "\n", + " minute dayofweek visibility windBearing temperature \\\n", "Date \n", - "2013-01-01 12:30:00 MAC004034 0.167 Std Affluent 1 \n", - "2013-01-01 13:00:00 MAC004034 0.185 Std Affluent 1 \n", - "2013-01-01 13:30:00 MAC004034 0.180 Std Affluent 1 \n", - "2013-01-01 14:00:00 MAC004034 0.158 Std Affluent 1 \n", - "2013-01-01 14:30:00 MAC004034 0.200 Std Affluent 1 \n", - "... ... ... ... ... ... \n", - "2014-02-27 22:00:00 MAC005492 0.182 ToU ACORN- 2 \n", - "2014-02-27 22:30:00 MAC005492 0.122 ToU ACORN- 2 \n", - "2014-02-27 23:00:00 MAC005492 0.140 ToU ACORN- 2 \n", - "2014-02-27 23:30:00 MAC005492 0.192 ToU ACORN- 2 \n", - "2014-02-28 00:00:00 MAC005492 0.088 ToU ACORN- 2 \n", + "2012-09-01 00:00:00 0 5 13.36 302.0 14.08 \n", + "2012-09-01 00:30:00 30 5 13.36 302.0 14.08 \n", + "2012-09-01 01:00:00 0 5 13.50 298.0 13.93 \n", + "2012-09-01 01:30:00 30 5 13.50 298.0 13.93 \n", + "2012-09-01 02:00:00 0 5 13.21 274.0 13.52 \n", + "... ... ... ... ... ... \n", + "2014-02-27 22:00:00 0 3 14.00 216.0 4.10 \n", + "2014-02-27 22:30:00 30 3 14.00 216.0 4.10 \n", + "2014-02-27 23:00:00 0 3 14.03 200.0 3.93 \n", + "2014-02-27 23:30:00 30 3 14.03 200.0 3.93 \n", + "2014-02-28 00:00:00 0 4 12.63 190.0 3.81 \n", "\n", - " day week hour minute dayofweek visibility \\\n", - "Date \n", - "2013-01-01 12:30:00 1 1 12 30 1 13.23 \n", - "2013-01-01 13:00:00 1 1 13 0 1 13.16 \n", - "2013-01-01 13:30:00 1 1 13 30 1 13.16 \n", - "2013-01-01 14:00:00 1 1 14 0 1 13.23 \n", - "2013-01-01 14:30:00 1 1 14 30 1 13.23 \n", - "... ... ... ... ... ... ... \n", - "2014-02-27 22:00:00 27 9 22 0 3 14.00 \n", - "2014-02-27 22:30:00 27 9 22 30 3 14.00 \n", - "2014-02-27 23:00:00 27 9 23 0 3 14.03 \n", - "2014-02-27 23:30:00 27 9 23 30 3 14.03 \n", - "2014-02-28 00:00:00 28 9 0 0 4 12.63 \n", + " dewPoint pressure apparentTemperature windSpeed \\\n", + "Date \n", + "2012-09-01 00:00:00 9.74 1028.27 14.08 1.89 \n", + "2012-09-01 00:30:00 9.74 1028.27 14.08 1.89 \n", + "2012-09-01 01:00:00 9.81 1027.96 13.93 1.59 \n", + "2012-09-01 01:30:00 9.81 1027.96 13.93 1.59 \n", + "2012-09-01 02:00:00 9.94 1028.04 13.52 0.82 \n", + "... ... ... ... ... \n", + "2014-02-27 22:00:00 1.64 1005.67 1.41 3.02 \n", + "2014-02-27 22:30:00 1.64 1005.67 1.41 3.02 \n", + "2014-02-27 23:00:00 1.61 1004.62 1.42 2.75 \n", + "2014-02-27 23:30:00 1.61 1004.62 1.42 2.75 \n", + "2014-02-28 00:00:00 1.53 1003.57 1.47 2.53 \n", "\n", - " windBearing temperature dewPoint pressure \\\n", - "Date \n", - "2013-01-01 12:30:00 256.0 4.01 2.08 1017.77 \n", - "2013-01-01 13:00:00 251.0 3.94 2.13 1018.37 \n", - "2013-01-01 13:30:00 251.0 3.94 2.13 1018.37 \n", - "2013-01-01 14:00:00 246.0 3.37 2.03 1019.14 \n", - "2013-01-01 14:30:00 246.0 3.37 2.03 1019.14 \n", - "... ... ... ... ... \n", - "2014-02-27 22:00:00 216.0 4.10 1.64 1005.67 \n", - "2014-02-27 22:30:00 216.0 4.10 1.64 1005.67 \n", - "2014-02-27 23:00:00 200.0 3.93 1.61 1004.62 \n", - "2014-02-27 23:30:00 200.0 3.93 1.61 1004.62 \n", - "2014-02-28 00:00:00 190.0 3.81 1.53 1003.57 \n", + " humidity holiday \n", + "Date \n", + "2012-09-01 00:00:00 0.75 0 \n", + "2012-09-01 00:30:00 0.75 0 \n", + "2012-09-01 01:00:00 0.76 0 \n", + "2012-09-01 01:30:00 0.76 0 \n", + "2012-09-01 02:00:00 0.79 0 \n", + "... ... ... \n", + "2014-02-27 22:00:00 0.84 0 \n", + "2014-02-27 22:30:00 0.84 0 \n", + "2014-02-27 23:00:00 0.85 0 \n", + "2014-02-27 23:30:00 0.85 0 \n", + "2014-02-28 00:00:00 0.85 0 \n", "\n", - " apparentTemperature windSpeed humidity holiday \n", - "Date \n", - "2013-01-01 12:30:00 0.55 4.15 0.87 1 \n", - "2013-01-01 13:00:00 0.68 3.80 0.88 1 \n", - "2013-01-01 13:30:00 0.68 3.80 0.88 1 \n", - "2013-01-01 14:00:00 0.36 3.25 0.91 1 \n", - "2013-01-01 14:30:00 0.36 3.25 0.91 1 \n", - "... ... ... ... ... \n", - "2014-02-27 22:00:00 1.41 3.02 0.84 0 \n", - "2014-02-27 22:30:00 1.41 3.02 0.84 0 \n", - "2014-02-27 23:00:00 1.42 2.75 0.85 0 \n", - "2014-02-27 23:30:00 1.42 2.75 0.85 0 \n", - "2014-02-28 00:00:00 1.47 2.53 0.85 0 \n", - "\n", - "[200000 rows x 19 columns]" + "[313932 rows x 17 columns]" ] }, "execution_count": 8, @@ -697,9 +686,52 @@ } ], "source": [ + "df = get_smartmeter_df(max_files=12)\n", + "\n", + "# # Just get the first one for now\n", + "# dfs = list(dfs)\n", + "\n", + "# # df = df.resample(freq).first().dropna() # Where empty we will backfill, this will respect causality, and mostly maintain the mean\n", + "\n", + "df = df.tail(int(max_rows)).copy() # Just use last X rows\n", + "# df = pd.concat(dfs[:6], 0)\n", + "# # df = dfs[0]\n", + "print(df.block.value_counts())\n", "df" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T07:20:41.850970Z", + "start_time": "2020-10-19T07:20:41.747955Z" + }, + "lines_to_next_cell": 2 + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot/explore" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T07:21:39.815254Z", + "start_time": "2020-10-19T07:21:39.703940Z" + } + }, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -717,12 +749,22 @@ "execution_count": 9, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:15.348512Z", - "start_time": "2020-10-19T05:40:09.540943Z" + "end_time": "2020-10-19T09:45:00.737432Z", + "start_time": "2020-10-19T09:44:57.552213Z" }, "lines_to_next_cell": 2 }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n", + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/holoviews/operation/datashader.py:5: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working\n", + " from collections import Callable\n" + ] + }, { "data": { "application/javascript": [ @@ -2190,61 +2232,6 @@ }, "metadata": {}, "output_type": "display_data" - }, - { - "data": {}, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.holoviews_exec.v0+json": "", - "text/html": [ - "
\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "
\n", - "" - ], - "text/plain": [ - ":DynamicMap [Name]\n", - " :RGB [Date,energy(kWh/hh)] (R,G,B,A)" - ] - }, - "execution_count": 9, - "metadata": { - "application/vnd.holoviews_exec.v0+json": { - "id": "1001" - } - }, - "output_type": "execute_result" } ], "source": [ @@ -2261,22 +2248,22 @@ "hv.extension('bokeh')\n", "\n", "\n", - "def house_curve(Name=None):\n", - " if isinstance(Name, int):\n", - " name = df.LCLid.unique()[Name]\n", - " d = df[df.LCLid == Name]\n", - " d_curve = hv.Curve(d, 'Date', 'energy(kWh/hh)', label=Name)\n", - " return d_curve\n", + "# def house_curve(Name=None):\n", + "# if isinstance(Name, int):\n", + "# name = df.block.unique()[Name]\n", + "# d = df[df.block == Name]\n", + "# d_curve = hv.Curve(d, 'Date', 'energy(kWh/hh)', label=Name).opts(framewise=True)\n", + "# return d_curve\n", "\n", "\n", - "dmap = hv.DynamicMap(house_curve, kdims=['Name'])\n", - "dmap = dmap.redim.values(Name=list(df.LCLid.unique()))\n", - "dynspread(datashade(dmap).opts(width=800,\n", - " height=300,\n", - " tools=['xwheel_zoom', 'pan'],\n", - " active_tools=['xwheel_zoom', 'pan'],\n", - " default_tools=['reset', 'save', 'hover']\n", - " ))" + "# dmap = hv.DynamicMap(house_curve, kdims=['Name'])\n", + "# dmap = dmap.redim.values(Name=list(df.block.unique()))\n", + "# dynspread(datashade(dmap).opts(width=800,\n", + "# height=300,\n", + "# tools=['xwheel_zoom', 'pan'],\n", + "# active_tools=['xwheel_zoom', 'pan'],\n", + "# default_tools=['reset', 'save', 'hover']\n", + "# ))" ] }, { @@ -2303,11 +2290,20 @@ "execution_count": 10, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:15.418443Z", - "start_time": "2020-10-19T05:40:15.354154Z" + "end_time": "2020-10-19T09:45:00.790696Z", + "start_time": "2020-10-19T09:45:00.743705Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + } + ], "source": [ "# from pandas_profiling import ProfileReport\n", "# profile = ProfileReport(df, title=\"Pandas Profiling Report\", minimal=True)\n", @@ -2326,8 +2322,8 @@ "execution_count": 11, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:15.654837Z", - "start_time": "2020-10-19T05:40:15.422503Z" + "end_time": "2020-10-19T09:45:01.141061Z", + "start_time": "2020-10-19T09:45:00.796566Z" } }, "outputs": [ @@ -2373,73 +2369,73 @@ " \n", " \n", " count\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.00000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.00000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", - " 200000.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.00000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", + " 313932.000000\n", " \n", " \n", " mean\n", - " 0.680330\n", - " 6.750390\n", - " 15.802345\n", - " 27.45751\n", - " 11.504260\n", - " 15.000000\n", - " 2.994710\n", - " 11.352912\n", - " 194.297550\n", - " 11.36635\n", - " 7.243470\n", - " 1012.911028\n", - " 10.263340\n", - " 3.901174\n", - " 0.775153\n", - " 0.022905\n", + " 10.304546\n", + " 6.878713\n", + " 15.659187\n", + " 27.962578\n", + " 11.49956\n", + " 14.999427\n", + " 2.998203\n", + " 11.203636\n", + " 194.973128\n", + " 10.196924\n", + " 6.316654\n", + " 1012.613350\n", + " 8.845714\n", + " 3.968334\n", + " 0.784663\n", + " 0.022018\n", " \n", " \n", " std\n", - " 0.837963\n", - " 3.422923\n", - " 8.811981\n", - " 14.88508\n", - " 6.922627\n", - " 15.000038\n", - " 1.999133\n", - " 2.935302\n", - " 90.607297\n", - " 6.07569\n", - " 5.187453\n", - " 10.744543\n", - " 7.256847\n", - " 2.023303\n", - " 0.144399\n", - " 0.149601\n", + " 6.425374\n", + " 3.797205\n", + " 8.768608\n", + " 16.528737\n", + " 6.92243\n", + " 15.000024\n", + " 2.001349\n", + " 3.087941\n", + " 91.343087\n", + " 5.891891\n", + " 5.118656\n", + " 11.278742\n", + " 7.116397\n", + " 2.073511\n", + " 0.140025\n", + " 0.146741\n", " \n", " \n", " min\n", - " 0.001000\n", + " 1.634000\n", " 1.000000\n", " 1.000000\n", - " 1.00000\n", - " 0.000000\n", + " 1.000000\n", + " 0.00000\n", " 0.000000\n", " 0.000000\n", " 0.270000\n", " 0.000000\n", - " -3.86000\n", + " -3.860000\n", " -8.920000\n", " 975.740000\n", " -8.880000\n", @@ -2449,74 +2445,74 @@ " \n", " \n", " 25%\n", - " 0.138000\n", - " 4.000000\n", + " 6.121000\n", + " 3.000000\n", " 8.000000\n", - " 15.00000\n", - " 6.000000\n", + " 11.000000\n", + " 5.00000\n", " 0.000000\n", " 1.000000\n", - " 10.460000\n", - " 121.000000\n", - " 6.98000\n", - " 3.370000\n", - " 1006.910000\n", - " 4.430000\n", - " 2.420000\n", - " 0.690000\n", + " 10.120000\n", + " 119.000000\n", + " 6.050000\n", + " 2.560000\n", + " 1005.900000\n", + " 3.360000\n", + " 2.450000\n", + " 0.710000\n", " 0.000000\n", " \n", " \n", " 50%\n", - " 0.307000\n", - " 7.000000\n", + " 8.502000\n", + " 8.000000\n", " 16.000000\n", - " 28.00000\n", - " 12.000000\n", - " 15.000000\n", + " 31.000000\n", + " 11.00000\n", + " 0.000000\n", " 3.000000\n", - " 12.260000\n", - " 215.000000\n", - " 11.14000\n", - " 7.470000\n", - " 1013.730000\n", - " 11.140000\n", - " 3.670000\n", + " 12.230000\n", + " 216.000000\n", + " 9.580000\n", + " 6.460000\n", + " 1013.600000\n", + " 7.990000\n", + " 3.720000\n", " 0.810000\n", " 0.000000\n", " \n", " \n", " 75%\n", - " 0.872000\n", + " 12.126000\n", " 10.000000\n", " 23.000000\n", - " 40.00000\n", - " 18.000000\n", + " 43.000000\n", + " 17.00000\n", " 30.000000\n", " 5.000000\n", - " 13.100000\n", - " 254.000000\n", - " 15.76000\n", - " 11.380000\n", - " 1020.130000\n", - " 15.760000\n", - " 5.070000\n", + " 13.080000\n", + " 255.000000\n", + " 14.070000\n", + " 10.060000\n", + " 1020.550000\n", + " 14.070000\n", + " 5.160000\n", " 0.890000\n", " 0.000000\n", " \n", " \n", " max\n", - " 8.170999\n", + " 53.965000\n", " 12.000000\n", " 31.000000\n", - " 52.00000\n", - " 23.000000\n", + " 52.000000\n", + " 23.00000\n", " 30.000000\n", " 6.000000\n", " 16.090000\n", " 359.000000\n", - " 32.40000\n", - " 19.880000\n", + " 32.400000\n", + " 18.950000\n", " 1040.130000\n", " 32.420000\n", " 14.800000\n", @@ -2528,44 +2524,44 @@ "" ], "text/plain": [ - " energy(kWh/hh) month day week \\\n", - "count 200000.000000 200000.000000 200000.000000 200000.00000 \n", - "mean 0.680330 6.750390 15.802345 27.45751 \n", - "std 0.837963 3.422923 8.811981 14.88508 \n", - "min 0.001000 1.000000 1.000000 1.00000 \n", - "25% 0.138000 4.000000 8.000000 15.00000 \n", - "50% 0.307000 7.000000 16.000000 28.00000 \n", - "75% 0.872000 10.000000 23.000000 40.00000 \n", - "max 8.170999 12.000000 31.000000 52.00000 \n", + " energy(kWh/hh) month day week \\\n", + "count 313932.000000 313932.000000 313932.000000 313932.000000 \n", + "mean 10.304546 6.878713 15.659187 27.962578 \n", + "std 6.425374 3.797205 8.768608 16.528737 \n", + "min 1.634000 1.000000 1.000000 1.000000 \n", + "25% 6.121000 3.000000 8.000000 11.000000 \n", + "50% 8.502000 8.000000 16.000000 31.000000 \n", + "75% 12.126000 10.000000 23.000000 43.000000 \n", + "max 53.965000 12.000000 31.000000 52.000000 \n", "\n", - " hour minute dayofweek visibility \\\n", - "count 200000.000000 200000.000000 200000.000000 200000.000000 \n", - "mean 11.504260 15.000000 2.994710 11.352912 \n", - "std 6.922627 15.000038 1.999133 2.935302 \n", - "min 0.000000 0.000000 0.000000 0.270000 \n", - "25% 6.000000 0.000000 1.000000 10.460000 \n", - "50% 12.000000 15.000000 3.000000 12.260000 \n", - "75% 18.000000 30.000000 5.000000 13.100000 \n", - "max 23.000000 30.000000 6.000000 16.090000 \n", + " hour minute dayofweek visibility \\\n", + "count 313932.00000 313932.000000 313932.000000 313932.000000 \n", + "mean 11.49956 14.999427 2.998203 11.203636 \n", + "std 6.92243 15.000024 2.001349 3.087941 \n", + "min 0.00000 0.000000 0.000000 0.270000 \n", + "25% 5.00000 0.000000 1.000000 10.120000 \n", + "50% 11.00000 0.000000 3.000000 12.230000 \n", + "75% 17.00000 30.000000 5.000000 13.080000 \n", + "max 23.00000 30.000000 6.000000 16.090000 \n", "\n", - " windBearing temperature dewPoint pressure \\\n", - "count 200000.000000 200000.00000 200000.000000 200000.000000 \n", - "mean 194.297550 11.36635 7.243470 1012.911028 \n", - "std 90.607297 6.07569 5.187453 10.744543 \n", - "min 0.000000 -3.86000 -8.920000 975.740000 \n", - "25% 121.000000 6.98000 3.370000 1006.910000 \n", - "50% 215.000000 11.14000 7.470000 1013.730000 \n", - "75% 254.000000 15.76000 11.380000 1020.130000 \n", - "max 359.000000 32.40000 19.880000 1040.130000 \n", + " windBearing temperature dewPoint pressure \\\n", + "count 313932.000000 313932.000000 313932.000000 313932.000000 \n", + "mean 194.973128 10.196924 6.316654 1012.613350 \n", + "std 91.343087 5.891891 5.118656 11.278742 \n", + "min 0.000000 -3.860000 -8.920000 975.740000 \n", + "25% 119.000000 6.050000 2.560000 1005.900000 \n", + "50% 216.000000 9.580000 6.460000 1013.600000 \n", + "75% 255.000000 14.070000 10.060000 1020.550000 \n", + "max 359.000000 32.400000 18.950000 1040.130000 \n", "\n", " apparentTemperature windSpeed humidity holiday \n", - "count 200000.000000 200000.000000 200000.000000 200000.000000 \n", - "mean 10.263340 3.901174 0.775153 0.022905 \n", - "std 7.256847 2.023303 0.144399 0.149601 \n", + "count 313932.000000 313932.000000 313932.000000 313932.000000 \n", + "mean 8.845714 3.968334 0.784663 0.022018 \n", + "std 7.116397 2.073511 0.140025 0.146741 \n", "min -8.880000 0.040000 0.230000 0.000000 \n", - "25% 4.430000 2.420000 0.690000 0.000000 \n", - "50% 11.140000 3.670000 0.810000 0.000000 \n", - "75% 15.760000 5.070000 0.890000 0.000000 \n", + "25% 3.360000 2.450000 0.710000 0.000000 \n", + "50% 7.990000 3.720000 0.810000 0.000000 \n", + "75% 14.070000 5.160000 0.890000 0.000000 \n", "max 32.420000 14.800000 1.000000 1.000000 " ] }, @@ -2583,11 +2579,19 @@ "execution_count": 12, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:16.408599Z", - "start_time": "2020-10-19T05:40:15.658453Z" + "end_time": "2020-10-19T09:45:01.989650Z", + "start_time": "2020-10-19T09:45:01.146532Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, { "data": { "text/html": [ @@ -2625,9 +2629,7 @@ " windSpeed\n", " humidity\n", " holiday\n", - " Acorn_grouped\n", - " LCLid\n", - " stdorToU\n", + " block\n", " \n", " \n", " Date\n", @@ -2648,119 +2650,107 @@ " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", " \n", - " 2013-01-01 12:30:00\n", - " -0.612594\n", - " -1.679969\n", - " -1.679802\n", - " -1.777456\n", - " 0.071612\n", - " 1.0\n", - " -0.997790\n", - " 0.639489\n", - " 0.680989\n", - " -1.210787\n", - " -0.995379\n", - " 0.452228\n", - " -1.338510\n", - " 0.122981\n", - " 0.656841\n", - " 6.531354\n", - " 1.0\n", - " 0.0\n", + " 2012-09-01 00:00:00\n", + " -0.823540\n", + " 0.558645\n", + " -1.671783\n", + " 0.425770\n", + " -1.661205\n", + " -0.999962\n", + " 1.000225\n", + " 0.698319\n", + " 1.171704\n", + " 0.659055\n", + " 0.668799\n", + " 1.388158\n", + " 0.735526\n", + " -1.002328\n", + " -0.247549\n", + " -0.150044\n", " 0.0\n", " \n", " \n", - " 2013-01-01 13:00:00\n", - " -0.591113\n", - " -1.679969\n", - " -1.679802\n", - " -1.777456\n", - " 0.216066\n", - " -1.0\n", - " -0.997790\n", - " 0.615641\n", - " 0.625806\n", - " -1.222309\n", - " -0.985741\n", - " 0.508071\n", - " -1.320596\n", - " -0.050004\n", - " 0.726094\n", - " 6.531354\n", - " 1.0\n", - " 0.0\n", + " 2012-09-01 00:30:00\n", + " -0.801129\n", + " 0.558645\n", + " -1.671783\n", + " 0.425770\n", + " -1.661205\n", + " 1.000038\n", + " 1.000225\n", + " 0.698319\n", + " 1.171704\n", + " 0.659055\n", + " 0.668799\n", + " 1.388158\n", + " 0.735526\n", + " -1.002328\n", + " -0.247549\n", + " -0.150044\n", " 0.0\n", " \n", " \n", - " 2013-01-01 13:30:00\n", - " -0.597080\n", - " -1.679969\n", - " -1.679802\n", - " -1.777456\n", - " 0.216066\n", - " 1.0\n", - " -0.997790\n", - " 0.615641\n", - " 0.625806\n", - " -1.222309\n", - " -0.985741\n", - " 0.508071\n", - " -1.320596\n", - " -0.050004\n", - " 0.726094\n", - " 6.531354\n", - " 1.0\n", - " 0.0\n", + " 2012-09-01 01:00:00\n", + " -0.613902\n", + " 0.558645\n", + " -1.671783\n", + " 0.425770\n", + " -1.516747\n", + " -0.999962\n", + " 1.000225\n", + " 0.743657\n", + " 1.127913\n", + " 0.633597\n", + " 0.682474\n", + " 1.360673\n", + " 0.714448\n", + " -1.147010\n", + " -0.176133\n", + " -0.150044\n", " 0.0\n", " \n", " \n", - " 2013-01-01 14:00:00\n", - " -0.623334\n", - " -1.679969\n", - " -1.679802\n", - " -1.777456\n", - " 0.360520\n", - " -1.0\n", - " -0.997790\n", - " 0.639489\n", - " 0.570623\n", - " -1.316125\n", - " -1.005018\n", - " 0.579735\n", - " -1.364693\n", - " -0.321838\n", - " 0.933852\n", - " 6.531354\n", - " 1.0\n", - " 0.0\n", + " 2012-09-01 01:30:00\n", + " -0.746035\n", + " 0.558645\n", + " -1.671783\n", + " 0.425770\n", + " -1.516747\n", + " 1.000038\n", + " 1.000225\n", + " 0.743657\n", + " 1.127913\n", + " 0.633597\n", + " 0.682474\n", + " 1.360673\n", + " 0.714448\n", + " -1.147010\n", + " -0.176133\n", + " -0.150044\n", " 0.0\n", " \n", " \n", - " 2013-01-01 14:30:00\n", - " -0.573213\n", - " -1.679969\n", - " -1.679802\n", - " -1.777456\n", - " 0.360520\n", - " 1.0\n", - " -0.997790\n", - " 0.639489\n", - " 0.570623\n", - " -1.316125\n", - " -1.005018\n", - " 0.579735\n", - " -1.364693\n", - " -0.321838\n", - " 0.933852\n", - " 6.531354\n", - " 1.0\n", - " 0.0\n", + " 2012-09-01 02:00:00\n", + " -0.837703\n", + " 0.558645\n", + " -1.671783\n", + " 0.425770\n", + " -1.372289\n", + " -0.999962\n", + " 1.000225\n", + " 0.649743\n", + " 0.865167\n", + " 0.564009\n", + " 0.707872\n", + " 1.367766\n", + " 0.656834\n", + " -1.518362\n", + " 0.038114\n", + " -0.150044\n", " 0.0\n", " \n", " \n", @@ -2782,182 +2772,170 @@ " ...\n", " ...\n", " ...\n", - " ...\n", - " ...\n", " \n", " \n", " 2014-02-27 22:00:00\n", - " -0.594693\n", - " -1.387820\n", - " 1.270734\n", - " -1.240004\n", - " 1.516154\n", - " -1.0\n", - " 0.002646\n", - " 0.901813\n", - " 0.239523\n", - " -1.195974\n", - " -1.080200\n", - " -0.673928\n", - " -1.220001\n", - " -0.435514\n", - " 0.449083\n", - " -0.153108\n", - " 0.0\n", - " 6.0\n", - " 1.0\n", + " -0.075567\n", + " -1.284819\n", + " 1.293344\n", + " -1.147251\n", + " 1.516874\n", + " -0.999962\n", + " 0.000898\n", + " 0.905577\n", + " 0.230197\n", + " -1.034801\n", + " -0.913650\n", + " -0.615615\n", + " -1.044872\n", + " -0.457357\n", + " 0.395193\n", + " -0.150044\n", + " 11.0\n", " \n", " \n", " 2014-02-27 22:30:00\n", - " -0.666296\n", - " -1.387820\n", - " 1.270734\n", - " -1.240004\n", - " 1.516154\n", - " 1.0\n", - " 0.002646\n", - " 0.901813\n", - " 0.239523\n", - " -1.195974\n", - " -1.080200\n", - " -0.673928\n", - " -1.220001\n", - " -0.435514\n", - " 0.449083\n", - " -0.153108\n", - " 0.0\n", - " 6.0\n", - " 1.0\n", + " -0.235402\n", + " -1.284819\n", + " 1.293344\n", + " -1.147251\n", + " 1.516874\n", + " 1.000038\n", + " 0.000898\n", + " 0.905577\n", + " 0.230197\n", + " -1.034801\n", + " -0.913650\n", + " -0.615615\n", + " -1.044872\n", + " -0.457357\n", + " 0.395193\n", + " -0.150044\n", + " 11.0\n", " \n", " \n", " 2014-02-27 23:00:00\n", - " -0.644815\n", - " -1.387820\n", - " 1.270734\n", - " -1.240004\n", - " 1.660608\n", - " -1.0\n", - " 0.002646\n", - " 0.912034\n", - " 0.062936\n", - " -1.223955\n", - " -1.085983\n", - " -0.771652\n", - " -1.218623\n", - " -0.568959\n", - " 0.518336\n", - " -0.153108\n", - " 0.0\n", - " 6.0\n", - " 1.0\n", + " -0.345124\n", + " -1.284819\n", + " 1.293344\n", + " -1.147251\n", + " 1.661332\n", + " -0.999962\n", + " 0.000898\n", + " 0.915292\n", + " 0.055033\n", + " -1.063654\n", + " -0.919511\n", + " -0.708710\n", + " -1.043467\n", + " -0.587572\n", + " 0.466609\n", + " -0.150044\n", + " 11.0\n", " \n", " \n", " 2014-02-27 23:30:00\n", - " -0.582760\n", - " -1.387820\n", - " 1.270734\n", - " -1.240004\n", - " 1.660608\n", - " 1.0\n", - " 0.002646\n", - " 0.912034\n", - " 0.062936\n", - " -1.223955\n", - " -1.085983\n", - " -0.771652\n", - " -1.218623\n", - " -0.568959\n", - " 0.518336\n", - " -0.153108\n", - " 0.0\n", - " 6.0\n", - " 1.0\n", + " -0.496555\n", + " -1.284819\n", + " 1.293344\n", + " -1.147251\n", + " 1.661332\n", + " 1.000038\n", + " 0.000898\n", + " 0.915292\n", + " 0.055033\n", + " -1.063654\n", + " -0.919511\n", + " -0.708710\n", + " -1.043467\n", + " -0.587572\n", + " 0.466609\n", + " -0.150044\n", + " 11.0\n", " \n", " \n", " 2014-02-28 00:00:00\n", - " -0.706870\n", - " -1.387820\n", - " 1.384216\n", - " -1.240004\n", - " -1.661838\n", - " -1.0\n", - " 0.502864\n", - " 0.435080\n", - " -0.047431\n", - " -1.243706\n", - " -1.101405\n", - " -0.869376\n", - " -1.211733\n", - " -0.677692\n", - " 0.518336\n", - " -0.153108\n", - " 0.0\n", - " 6.0\n", - " 1.0\n", + " -0.469630\n", + " -1.284819\n", + " 1.407388\n", + " -1.147251\n", + " -1.661205\n", + " -0.999962\n", + " 0.500561\n", + " 0.461915\n", + " -0.054445\n", + " -1.084021\n", + " -0.935140\n", + " -0.801806\n", + " -1.036441\n", + " -0.693672\n", + " 0.466609\n", + " -0.150044\n", + " 11.0\n", " \n", " \n", "\n", - "

200000 rows × 19 columns

\n", + "

313932 rows × 17 columns

\n", "" ], "text/plain": [ " energy(kWh/hh) month day week hour \\\n", "Date \n", - "2013-01-01 12:30:00 -0.612594 -1.679969 -1.679802 -1.777456 0.071612 \n", - "2013-01-01 13:00:00 -0.591113 -1.679969 -1.679802 -1.777456 0.216066 \n", - "2013-01-01 13:30:00 -0.597080 -1.679969 -1.679802 -1.777456 0.216066 \n", - "2013-01-01 14:00:00 -0.623334 -1.679969 -1.679802 -1.777456 0.360520 \n", - "2013-01-01 14:30:00 -0.573213 -1.679969 -1.679802 -1.777456 0.360520 \n", + "2012-09-01 00:00:00 -0.823540 0.558645 -1.671783 0.425770 -1.661205 \n", + "2012-09-01 00:30:00 -0.801129 0.558645 -1.671783 0.425770 -1.661205 \n", + "2012-09-01 01:00:00 -0.613902 0.558645 -1.671783 0.425770 -1.516747 \n", + "2012-09-01 01:30:00 -0.746035 0.558645 -1.671783 0.425770 -1.516747 \n", + "2012-09-01 02:00:00 -0.837703 0.558645 -1.671783 0.425770 -1.372289 \n", "... ... ... ... ... ... \n", - "2014-02-27 22:00:00 -0.594693 -1.387820 1.270734 -1.240004 1.516154 \n", - "2014-02-27 22:30:00 -0.666296 -1.387820 1.270734 -1.240004 1.516154 \n", - "2014-02-27 23:00:00 -0.644815 -1.387820 1.270734 -1.240004 1.660608 \n", - "2014-02-27 23:30:00 -0.582760 -1.387820 1.270734 -1.240004 1.660608 \n", - "2014-02-28 00:00:00 -0.706870 -1.387820 1.384216 -1.240004 -1.661838 \n", + "2014-02-27 22:00:00 -0.075567 -1.284819 1.293344 -1.147251 1.516874 \n", + "2014-02-27 22:30:00 -0.235402 -1.284819 1.293344 -1.147251 1.516874 \n", + "2014-02-27 23:00:00 -0.345124 -1.284819 1.293344 -1.147251 1.661332 \n", + "2014-02-27 23:30:00 -0.496555 -1.284819 1.293344 -1.147251 1.661332 \n", + "2014-02-28 00:00:00 -0.469630 -1.284819 1.407388 -1.147251 -1.661205 \n", "\n", - " minute dayofweek visibility windBearing temperature \\\n", - "Date \n", - "2013-01-01 12:30:00 1.0 -0.997790 0.639489 0.680989 -1.210787 \n", - "2013-01-01 13:00:00 -1.0 -0.997790 0.615641 0.625806 -1.222309 \n", - "2013-01-01 13:30:00 1.0 -0.997790 0.615641 0.625806 -1.222309 \n", - "2013-01-01 14:00:00 -1.0 -0.997790 0.639489 0.570623 -1.316125 \n", - "2013-01-01 14:30:00 1.0 -0.997790 0.639489 0.570623 -1.316125 \n", - "... ... ... ... ... ... \n", - "2014-02-27 22:00:00 -1.0 0.002646 0.901813 0.239523 -1.195974 \n", - "2014-02-27 22:30:00 1.0 0.002646 0.901813 0.239523 -1.195974 \n", - "2014-02-27 23:00:00 -1.0 0.002646 0.912034 0.062936 -1.223955 \n", - "2014-02-27 23:30:00 1.0 0.002646 0.912034 0.062936 -1.223955 \n", - "2014-02-28 00:00:00 -1.0 0.502864 0.435080 -0.047431 -1.243706 \n", + " minute dayofweek visibility windBearing \\\n", + "Date \n", + "2012-09-01 00:00:00 -0.999962 1.000225 0.698319 1.171704 \n", + "2012-09-01 00:30:00 1.000038 1.000225 0.698319 1.171704 \n", + "2012-09-01 01:00:00 -0.999962 1.000225 0.743657 1.127913 \n", + "2012-09-01 01:30:00 1.000038 1.000225 0.743657 1.127913 \n", + "2012-09-01 02:00:00 -0.999962 1.000225 0.649743 0.865167 \n", + "... ... ... ... ... \n", + "2014-02-27 22:00:00 -0.999962 0.000898 0.905577 0.230197 \n", + "2014-02-27 22:30:00 1.000038 0.000898 0.905577 0.230197 \n", + "2014-02-27 23:00:00 -0.999962 0.000898 0.915292 0.055033 \n", + "2014-02-27 23:30:00 1.000038 0.000898 0.915292 0.055033 \n", + "2014-02-28 00:00:00 -0.999962 0.500561 0.461915 -0.054445 \n", "\n", - " dewPoint pressure apparentTemperature windSpeed \\\n", - "Date \n", - "2013-01-01 12:30:00 -0.995379 0.452228 -1.338510 0.122981 \n", - "2013-01-01 13:00:00 -0.985741 0.508071 -1.320596 -0.050004 \n", - "2013-01-01 13:30:00 -0.985741 0.508071 -1.320596 -0.050004 \n", - "2013-01-01 14:00:00 -1.005018 0.579735 -1.364693 -0.321838 \n", - "2013-01-01 14:30:00 -1.005018 0.579735 -1.364693 -0.321838 \n", - "... ... ... ... ... \n", - "2014-02-27 22:00:00 -1.080200 -0.673928 -1.220001 -0.435514 \n", - "2014-02-27 22:30:00 -1.080200 -0.673928 -1.220001 -0.435514 \n", - "2014-02-27 23:00:00 -1.085983 -0.771652 -1.218623 -0.568959 \n", - "2014-02-27 23:30:00 -1.085983 -0.771652 -1.218623 -0.568959 \n", - "2014-02-28 00:00:00 -1.101405 -0.869376 -1.211733 -0.677692 \n", + " temperature dewPoint pressure apparentTemperature \\\n", + "Date \n", + "2012-09-01 00:00:00 0.659055 0.668799 1.388158 0.735526 \n", + "2012-09-01 00:30:00 0.659055 0.668799 1.388158 0.735526 \n", + "2012-09-01 01:00:00 0.633597 0.682474 1.360673 0.714448 \n", + "2012-09-01 01:30:00 0.633597 0.682474 1.360673 0.714448 \n", + "2012-09-01 02:00:00 0.564009 0.707872 1.367766 0.656834 \n", + "... ... ... ... ... \n", + "2014-02-27 22:00:00 -1.034801 -0.913650 -0.615615 -1.044872 \n", + "2014-02-27 22:30:00 -1.034801 -0.913650 -0.615615 -1.044872 \n", + "2014-02-27 23:00:00 -1.063654 -0.919511 -0.708710 -1.043467 \n", + "2014-02-27 23:30:00 -1.063654 -0.919511 -0.708710 -1.043467 \n", + "2014-02-28 00:00:00 -1.084021 -0.935140 -0.801806 -1.036441 \n", "\n", - " humidity holiday Acorn_grouped LCLid stdorToU \n", - "Date \n", - "2013-01-01 12:30:00 0.656841 6.531354 1.0 0.0 0.0 \n", - "2013-01-01 13:00:00 0.726094 6.531354 1.0 0.0 0.0 \n", - "2013-01-01 13:30:00 0.726094 6.531354 1.0 0.0 0.0 \n", - "2013-01-01 14:00:00 0.933852 6.531354 1.0 0.0 0.0 \n", - "2013-01-01 14:30:00 0.933852 6.531354 1.0 0.0 0.0 \n", - "... ... ... ... ... ... \n", - "2014-02-27 22:00:00 0.449083 -0.153108 0.0 6.0 1.0 \n", - "2014-02-27 22:30:00 0.449083 -0.153108 0.0 6.0 1.0 \n", - "2014-02-27 23:00:00 0.518336 -0.153108 0.0 6.0 1.0 \n", - "2014-02-27 23:30:00 0.518336 -0.153108 0.0 6.0 1.0 \n", - "2014-02-28 00:00:00 0.518336 -0.153108 0.0 6.0 1.0 \n", + " windSpeed humidity holiday block \n", + "Date \n", + "2012-09-01 00:00:00 -1.002328 -0.247549 -0.150044 0.0 \n", + "2012-09-01 00:30:00 -1.002328 -0.247549 -0.150044 0.0 \n", + "2012-09-01 01:00:00 -1.147010 -0.176133 -0.150044 0.0 \n", + "2012-09-01 01:30:00 -1.147010 -0.176133 -0.150044 0.0 \n", + "2012-09-01 02:00:00 -1.518362 0.038114 -0.150044 0.0 \n", + "... ... ... ... ... \n", + "2014-02-27 22:00:00 -0.457357 0.395193 -0.150044 11.0 \n", + "2014-02-27 22:30:00 -0.457357 0.395193 -0.150044 11.0 \n", + "2014-02-27 23:00:00 -0.587572 0.466609 -0.150044 11.0 \n", + "2014-02-27 23:30:00 -0.587572 0.466609 -0.150044 11.0 \n", + "2014-02-28 00:00:00 -0.693672 0.466609 -0.150044 11.0 \n", "\n", - "[200000 rows x 19 columns]" + "[313932 rows x 17 columns]" ] }, "execution_count": 12, @@ -2987,11 +2965,19 @@ "execution_count": 13, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:16.481582Z", - "start_time": "2020-10-19T05:40:16.413550Z" + "end_time": "2020-10-19T09:45:02.066974Z", + "start_time": "2020-10-19T09:45:01.994653Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, { "data": { "text/plain": [ @@ -3008,13 +2994,20 @@ "output_scaler" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split" + ] + }, { "cell_type": "code", "execution_count": 14, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:16.692901Z", - "start_time": "2020-10-19T05:40:16.485394Z" + "end_time": "2020-10-19T09:45:02.328455Z", + "start_time": "2020-10-19T09:45:02.071659Z" } }, "outputs": [ @@ -3022,7 +3015,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "2013-10-08 00:00:00\n" + "2013-11-11 00:00:00\n" ] } ], @@ -3034,8 +3027,8 @@ "split_time = d0+(d1-d0)*0.8\n", "split_time = split_time.round('1D')\n", "print(split_time)\n", - "df_train = df_norm.groupby('LCLid').apply(lambda d:d.loc[:split_time]).reset_index(level=0, drop=True)\n", - "df_test = df_norm.groupby('LCLid').apply(lambda d:d.loc[split_time:]).reset_index(level=0, drop=True)\n", + "df_train = df_norm.groupby('block').apply(lambda d:d.loc[:split_time]).reset_index(level=0, drop=True)\n", + "df_test = df_norm.groupby('block').apply(lambda d:d.loc[split_time:]).reset_index(level=0, drop=True)\n", "# df_test" ] }, @@ -3044,45 +3037,153 @@ "execution_count": 15, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.037348Z", - "start_time": "2020-10-19T05:40:16.696237Z" + "end_time": "2020-10-19T09:45:02.388481Z", + "start_time": "2020-10-19T09:45:02.332008Z" + } + }, + "outputs": [], + "source": [ + "# # Show split\n", + "# df_train['energy(kWh/hh)'].plot(label='train')\n", + "# df_test['energy(kWh/hh)'].plot(label='test')\n", + "# plt.ylabel('energy(kWh/hh)')\n", + "# plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T09:45:05.419601Z", + "start_time": "2020-10-19T09:45:02.392108Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/bokeh/core/property/bases.py:241: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.\n", + " return new == old\n" + ] + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + ":DynamicMap [block]\n", + " :Overlay\n", + " .RGB.I :RGB [Date,energy(kWh/hh)] (R,G,B,A)\n", + " .RGB.II :RGB [Date,energy(kWh/hh)] (R,G,B,A)" + ] + }, + "execution_count": 16, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "1001" + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "# # Show split\n", + "scatter = dynspread(datashade(hv.Curve(df_train, kdims=['Date'], vdims=['energy(kWh/hh)', 'block']).groupby('block'), cmap='blue'))\n", + "scatter *= dynspread(datashade(hv.Curve(df_test, kdims=['Date'], vdims=['energy(kWh/hh)', 'block']).groupby('block'), cmap='red'))\n", + "scatter = scatter.opts(plot=dict(width=800))\n", + "scatter" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T07:26:08.140247Z", + "start_time": "2020-10-19T07:26:08.085737Z" + } + }, + "source": [ + "### Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T09:45:06.059409Z", + "start_time": "2020-10-19T09:45:05.424426Z" }, "lines_to_next_cell": 0 }, "outputs": [ { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - ", , , , , , ])>\n", - ", , , , , ])>\n" + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" ] }, { - "data": { - "image/png": "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LGAu5jOZTIiLi4Msy+jTpw9KSkosTe5BQUF4+umn8fzzzyMxMdEyBM2AAQNw6dIlfPDBBygrK8M777yDG2+80ZdPw6uYM+2YO23clbf27dujffv2vnwqXsOcacO8acO8aeeu3FVNQNUQ1IecBcQrlZiYiIkTJ6K4uBitWrVCXFwcgoODceLECcvFUZIk4ZFHHsGKFSss6/36669YvXo1evTogenTpzeoK3CZM+2YO22YN/WYM22YN22YN+2YO/XqS84Coo9yUlISsrKyMGjQIADA119/jfbt2yM0NBTx8fH4+OOPIcsyCgsLsWjRIowYMQIxMTFISkoCAHTr1s2X4fsEc6Ydc6cN86Yec6YN86YN86Ydc6defclZQLQod+zYEbfddpulf8qNN96I7OxsDB48GLIsIz4+HjqdDjk5OdDpdIiJiQFgTrK/JNrbmDPtmDttmDf1mDNtmDdtmDftmDv16kvOAqKPcs0BpP/44w/LhVFjx47Fli1bMHXqVKSlpSE2NtYXIfod5kw75k4b5k095kwb5k0b5k075k69+pKzgCiUq1T9KikoKEC/fv0AAOHh4Xjsscdw8eJFxMTEIDo62pch+h3mTDvmThvmTT3mTBvmTRvmTTvmTr1Az1lAFcqSJMFoNOKaa65BSkoKlixZgoiICIwePRpdu3b1dXh+iTnTjrnThnlTjznThnnThnnTjrlTL9BzFnCF8vnz57F7925kZmbizjvvxJAhQ3wdll9jzrRj7rRh3tRjzrRh3rRh3rRj7tQL9JwFxKgX1nJycrBz507cd999lkGoyTnmTDvmThvmTT3mTBvmTRvmTTvmTr1AzlnAFcpERERERN4QEMPDERERERF5GwtlIiIiIiI7WCgTEREREdnBQpmIiIiIyA4WykREREREdrBQJiIiIiKyI6AmHCEiaijGjRuH/Px8BAUFQafToW3bthg0aBBiY2Oh0zlv48jMzMT48eOxbNkyBAUFeSliIqL6h4UyEZGfeuONN9CrVy+UlJQgMTERixcvRnJyMsaOHevr0IiIGgQWykREfq5x48bo168fIiMj8dZbb+G+++5DdnY2li9fjoyMDDRu3Bh33nknhg8fDgB45513AACjRo0CAEyePBldunTB1q1bsW7dOuTn56NTp0547rnn0KJFC189LSIiv8c+ykREAaJTp06Ijo7GyZMnERYWhvHjx2Px4sWYOHEiNm/ejP379wMA3n33XQDAkiVLsHTpUnTp0gX79+/H6tWr8corr+Drr79G165dMWvWLF8+HSIiv8dCmYgogERHR6OoqAg9evRA+/btodPpcN111+GOO+5AYmKiw/USEhLw0EMPoW3btggKCsJDDz2ECxcuICsry4vRExEFFna9ICIKILm5uYiIiMCZM2fw/fffIzU1FUajEUajEbfeeqvD9bKysrB48WJ8++23lvuEEMjNzWX3CyIiB1goExEFiOTkZOTm5qJr166YNm0a/va3v+HNN99EaGgolixZgsLCQgCAJEm11tXr9Rg6dCgGDhzo7bCJiAIWu14QEfm5kpIS/P7775g1axYGDhyI9u3bo7S0FBEREQgNDUVycjJ2795tWb5p06aQJAkZGRmW++666y6sWbMGFy9etGzz119/9fpzISIKJJIQQvg6CCIismU9jrIkSWjbti0GDhyIu+++GzqdDvv27cO3336LoqIidO/eHS1atEBxcTFeeuklAEBcXBw2bdoEk8mESZMmoUuXLti5cyfWrl2L7OxsNG7cGH/605841BwRkRMslImIiIiI7GDXCyIiIiIiO1goExERERHZwUKZiIiIiMgOFspERERERHawUCYiIiIisoOFMhERERGRHSyUiYiIiIjsYKFMRERERGTH/wfTMW+yhbmHMAAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + ", , , , , , , , , , , ])>\n", + ", , , , , , , , , , , ])>\n" + ] } ], "source": [ - "# Show split\n", - "df_train['energy(kWh/hh)'].plot(label='train')\n", - "df_test['energy(kWh/hh)'].plot(label='test')\n", - "plt.ylabel('energy(kWh/hh)')\n", - "plt.legend()\n", + "\n", "# ### Dataset\n", "# These are the columns that we wont know in the future\n", "# We need to blank them out in x_future\n", "columns_blank=['visibility',\n", " 'windBearing', 'temperature', 'dewPoint', 'pressure',\n", " 'apparentTemperature', 'windSpeed', 'humidity']\n", - "df_trains = [d.resample(freq).first().ffill().dropna() for _,d in df_train.groupby('LCLid')]\n", - "df_tests = [d.resample(freq).first().ffill().dropna() for _,d in df_test.groupby('LCLid')]\n", + "df_trains = [d.resample(freq).first().ffill().dropna() for _,d in df_train.groupby('block')]\n", + "df_tests = [d.resample(freq).first().ffill().dropna() for _,d in df_test.groupby('block')]\n", "ds_train = Seq2SeqDataSets(df_trains,\n", " window_past=window_past,\n", " window_future=window_future,\n", @@ -3097,237 +3198,245 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 18, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.098542Z", - "start_time": "2020-10-19T05:40:18.040901Z" + "end_time": "2020-10-19T09:45:06.142475Z", + "start_time": "2020-10-19T09:45:06.063323Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, { "data": { "text/plain": [ - "[array([[ 0.6572206 , -0.09105182, 0.6410791 , ..., 0. ,\n", + "[array([[ 1.0853493 , -0.9875229 , 1.0307775 , ..., 0. ,\n", " -2. , 1. ],\n", - " [ 0.6572206 , -0.09105182, 0.6410791 , ..., 0. ,\n", + " [ 1.0853493 , -0.9875229 , 1.0307775 , ..., 0. ,\n", " -1.9791666 , 1. ],\n", - " [ 0.6572206 , -0.09105182, 0.6410791 , ..., 0. ,\n", + " [ 1.0853493 , -0.9875229 , 1.0307775 , ..., 0. ,\n", " -1.9583334 , 1. ],\n", " ...,\n", - " [ 0.6572206 , 0.02243031, 0.70826066, ..., 0. ,\n", + " [ 1.0853493 , -0.87347955, 1.0307775 , ..., 0. ,\n", " -0.0625 , 1. ],\n", - " [ 0.6572206 , 0.02243031, 0.70826066, ..., 0. ,\n", + " [ 1.0853493 , -0.75943613, 1.0307775 , ..., 0. ,\n", " -0.04166667, 1. ],\n", - " [ 0.6572206 , 0.13591245, 0.70826066, ..., 0. ,\n", + " [ 1.0853493 , -0.75943613, 1.0307775 , ..., 0. ,\n", " -0.02083333, 1. ]], dtype=float32),\n", - " array([[-0.6901632 ],\n", - " [-0.68300295],\n", - " [-0.6782295 ],\n", - " [-0.6961301 ],\n", - " [-0.6686825 ],\n", - " [-0.6997102 ],\n", - " [-0.6674891 ],\n", - " [-0.6006602 ],\n", - " [-0.6185608 ],\n", - " [-0.6495885 ],\n", - " [-0.663909 ],\n", - " [-0.6376548 ],\n", - " [-0.6281078 ],\n", - " [-0.70329034],\n", - " [-0.68777645],\n", - " [-0.7056771 ],\n", - " [ 0.14281139],\n", - " [-0.3774994 ],\n", - " [-0.53144455],\n", - " [ 0.71324384],\n", - " [-0.4896765 ],\n", - " [-0.71164393],\n", - " [-0.68061626],\n", - " [-0.2844163 ],\n", - " [-0.40972048],\n", - " [-0.63049453],\n", - " [-0.60782045],\n", - " [-0.6853897 ],\n", - " [-0.6865831 ],\n", - " [-0.7176108 ],\n", - " [-0.64600843],\n", - " [-0.60424036],\n", - " [-0.5195108 ],\n", - " [-0.6865831 ],\n", - " [-0.67106926],\n", - " [-0.475356 ],\n", - " [-0.45506868],\n", - " [-0.5386048 ],\n", - " [-0.37869278],\n", - " [-0.5016102 ],\n", - " [-0.5242843 ],\n", - " [-0.5517319 ],\n", - " [-0.6054337 ],\n", - " [-0.66987586],\n", - " [-0.66032887],\n", - " [-0.68300295],\n", - " [-0.6579421 ],\n", - " [-0.5529253 ],\n", - " [-0.6627156 ],\n", - " [-0.66152227],\n", - " [-0.67942286],\n", - " [-0.70209694],\n", - " [-0.66987586],\n", - " [-0.7044837 ],\n", - " [-0.6782295 ],\n", - " [-0.69851685],\n", - " [-0.68896985],\n", - " [-0.6901632 ],\n", - " [-0.69732344],\n", - " [-0.5397982 ],\n", - " [-0.5660524 ],\n", - " [-0.55889213],\n", - " [-0.71164393],\n", - " [-0.68419635],\n", - " [-0.7104506 ],\n", - " [-0.5624723 ],\n", - " [-0.66152227],\n", - " [-0.6245277 ],\n", - " [-0.68419635],\n", - " [-0.67106926],\n", - " [-0.70806384],\n", - " [-0.6185608 ],\n", - " [-0.71164393],\n", - " [-0.67942286],\n", - " [-0.5672458 ],\n", - " [ 0.1690656 ],\n", - " [-0.7235777 ],\n", - " [-0.68777645],\n", - " [-0.65078187],\n", - " [-0.58991987],\n", - " [-0.6281078 ],\n", - " [-0.5433783 ],\n", - " [-0.5302512 ],\n", - " [-0.53621805],\n", - " [-0.4538753 ],\n", - " [-0.5338313 ],\n", - " [-0.45984215],\n", - " [-0.55889213],\n", - " [-0.61259395],\n", - " [-0.6245277 ],\n", - " [-0.6627156 ],\n", - " [-0.6901632 ],\n", - " [-0.67942286],\n", - " [-0.7092572 ],\n", - " [-0.6853897 ],\n", - " [-0.70687044]], dtype=float32),\n", - " array([[0.6572206 , 0.13591245, 0.70826066, ..., 0. , 0. ,\n", - " 0. ],\n", - " [0.6572206 , 0.13591245, 0.70826066, ..., 0. , 0.02083333,\n", - " 0. ],\n", - " [0.6572206 , 0.13591245, 0.70826066, ..., 0. , 0.04166667,\n", - " 0. ],\n", + " array([[ 0.21577835],\n", + " [ 0.15010113],\n", + " [ 0.13095824],\n", + " [ 0.02481639],\n", + " [ 0.02030303],\n", + " [-0.0716762 ],\n", + " [ 0.15803841],\n", + " [ 0.02917414],\n", + " [-0.0674741 ],\n", + " [ 0.20052628],\n", + " [ 0.19009887],\n", + " [ 0.6498394 ],\n", + " [ 1.2491828 ],\n", + " [ 1.628461 ],\n", + " [ 1.5388163 ],\n", + " [ 1.9378599 ],\n", + " [ 1.5101798 ],\n", + " [ 1.8061942 ],\n", + " [ 1.569943 ],\n", + " [ 1.4147766 ],\n", + " [ 1.5297896 ],\n", + " [ 0.9147271 ],\n", + " [ 0.5668869 ],\n", + " [ 0.6613563 ],\n", + " [ 0.8767526 ],\n", + " [ 1.2315964 ],\n", + " [ 1.4297174 ],\n", + " [ 1.279687 ],\n", + " [ 1.4004583 ],\n", + " [ 1.1357263 ],\n", + " [ 0.991143 ],\n", + " [ 1.7546796 ],\n", + " [ 1.8547517 ],\n", + " [ 2.5337794 ],\n", + " [ 2.6925254 ],\n", + " [ 3.1499314 ],\n", + " [ 3.0293155 ],\n", + " [ 3.4837644 ],\n", + " [ 3.7531657 ],\n", + " [ 3.8403203 ],\n", + " [ 3.7007172 ],\n", + " [ 2.7031083 ],\n", + " [ 3.0036361 ],\n", + " [ 2.3289661 ],\n", + " [ 1.6462032 ],\n", + " [ 1.4122865 ],\n", + " [ 1.1221862 ],\n", + " [ 0.47366259],\n", + " [ 0.43179724],\n", + " [ 0.1378061 ],\n", + " [ 0.10450058],\n", + " [ 0.05890007],\n", + " [-0.01922781],\n", + " [ 0.01361078],\n", + " [ 0.25001764],\n", + " [ 0.20379458],\n", + " [ 0.15912783],\n", + " [ 0.03804521],\n", + " [ 0.0112763 ],\n", + " [ 0.40020368],\n", + " [ 0.9962789 ],\n", + " [ 1.5427071 ],\n", + " [ 1.4130647 ],\n", + " [ 1.1237426 ],\n", + " [ 1.6356201 ],\n", + " [ 2.0203454 ],\n", + " [ 1.6363983 ],\n", + " [ 1.2048274 ],\n", + " [ 1.2031155 ],\n", + " [ 1.6057385 ],\n", + " [ 1.4756292 ],\n", + " [ 0.93324745],\n", + " [ 1.3648183 ],\n", + " [ 2.0363758 ],\n", + " [ 1.6476039 ],\n", + " [ 2.2405665 ],\n", + " [ 2.4416447 ],\n", + " [ 2.1408055 ],\n", + " [ 1.6493158 ],\n", + " [ 2.2284272 ],\n", + " [ 2.4018025 ],\n", + " [ 2.8567183 ],\n", + " [ 2.898895 ],\n", + " [ 3.9316769 ],\n", + " [ 3.660097 ],\n", + " [ 3.2076712 ],\n", + " [ 3.409839 ],\n", + " [ 3.2286818 ],\n", + " [ 3.0336733 ],\n", + " [ 2.8353965 ],\n", + " [ 2.9273758 ],\n", + " [ 2.1327126 ],\n", + " [ 1.6311067 ],\n", + " [ 1.6121196 ],\n", + " [ 0.8972962 ],\n", + " [ 0.5648636 ]], dtype=float32),\n", + " array([[ 1.0853493 , -0.75943613, 1.0307775 , ..., 0. ,\n", + " 0. , 0. ],\n", + " [ 1.0853493 , -0.75943613, 1.0307775 , ..., 0. ,\n", + " 0.02083333, 0. ],\n", + " [ 1.0853493 , -0.75943613, 1.0307775 , ..., 0. ,\n", + " 0.04166667, 0. ],\n", " ...,\n", - " [0.6572206 , 0.2493946 , 0.70826066, ..., 0. , 1.9166666 ,\n", - " 0. ],\n", - " [0.6572206 , 0.2493946 , 0.70826066, ..., 0. , 1.9375 ,\n", - " 0. ],\n", - " [0.6572206 , 0.2493946 , 0.70826066, ..., 0. , 1.9583334 ,\n", - " 0. ]], dtype=float32),\n", - " array([[-0.67584276],\n", - " [-0.71164393],\n", - " [-0.6782295 ],\n", - " [-0.70209694],\n", - " [-0.6818096 ],\n", - " [-0.69374335],\n", - " [-0.6901632 ],\n", - " [-0.68777645],\n", - " [-0.69732344],\n", - " [-0.68061626],\n", - " [-0.70687044],\n", - " [-0.5660524 ],\n", - " [-0.51831746],\n", - " [-0.6197542 ],\n", - " [-0.7223843 ],\n", - " [-0.52189755],\n", - " [-0.57917947],\n", - " [-0.673456 ],\n", - " [-0.6782295 ],\n", - " [-0.6591355 ],\n", - " [-0.6901632 ],\n", - " [-0.6066271 ],\n", - " [-0.69254994],\n", - " [-0.6376548 ],\n", - " [-0.6066271 ],\n", - " [-0.5481518 ],\n", - " [-0.5755994 ],\n", - " [-0.34766507],\n", - " [-0.71283734],\n", - " [-0.69851685],\n", - " [-0.66987586],\n", - " [-0.6686825 ],\n", - " [-0.52189755],\n", - " [-0.50399697],\n", - " [-0.68896985],\n", - " [-0.5302512 ],\n", - " [-0.28202954],\n", - " [-0.5111572 ],\n", - " [-0.50399697],\n", - " [-0.5111572 ],\n", - " [-0.3942066 ],\n", - " [-0.5254777 ],\n", - " [-0.54576504],\n", - " [-0.56008554],\n", - " [-0.4347813 ],\n", - " [-0.6102072 ],\n", - " [-0.6770361 ],\n", - " [-0.69851685],\n", - " [-0.69374335],\n", - " [-0.68896985],\n", - " [-0.7104506 ],\n", - " [-0.6770361 ],\n", - " [-0.71283734],\n", - " [-0.6722626 ],\n", - " [-0.68419635],\n", - " [-0.67106926],\n", - " [-0.66629577],\n", - " [-0.6949367 ],\n", - " [-0.6913566 ],\n", - " [-0.5672458 ],\n", - " [-0.55053854],\n", - " [ 0.2860162 ],\n", - " [-0.66510236],\n", - " [-0.66629577],\n", - " [-0.5195108 ],\n", - " [-0.63168794],\n", - " [-0.7223843 ],\n", - " [-0.66032887],\n", - " [-0.68061626],\n", - " [-0.67464936],\n", - " [-0.5016102 ],\n", - " [-0.55053854],\n", - " [-0.6197542 ],\n", - " [-0.36079216],\n", - " [-0.49683672],\n", - " [ 0.26572883],\n", - " [-0.67942286],\n", - " [-0.69254994],\n", - " [-0.6531686 ],\n", - " [-0.5779861 ],\n", - " [-0.63049453],\n", - " [-0.65078187],\n", - " [-0.6627156 ],\n", - " [-0.60424036],\n", - " [-0.52667105],\n", - " [-0.51235056],\n", - " [-0.45506868],\n", - " [-0.48132288],\n", - " [-0.54218495],\n", - " [-0.39181986],\n", - " [-0.5612789 ],\n", - " [-0.6627156 ],\n", - " [-0.6770361 ],\n", - " [-0.6865831 ],\n", - " [-0.6818096 ]], dtype=float32)]" + " [ 1.0853493 , -0.6453928 , 1.0307775 , ..., 0. ,\n", + " 1.9166666 , 0. ],\n", + " [ 1.0853493 , -0.6453928 , 1.0307775 , ..., 0. ,\n", + " 1.9375 , 0. ],\n", + " [ 1.0853493 , -0.5313494 , 1.0912782 , ..., 0. ,\n", + " 1.9583334 , 0. ]], dtype=float32),\n", + " array([[ 1.9492349e-01],\n", + " [ 7.5397186e-02],\n", + " [ 2.3336489e-01],\n", + " [ 1.2053080e-01],\n", + " [ 2.2355998e-01],\n", + " [ 2.9982027e-01],\n", + " [ 1.5866096e-01],\n", + " [ 1.1866322e-01],\n", + " [ 1.0512313e-01],\n", + " [ 3.0122095e-01],\n", + " [ 2.1468890e-01],\n", + " [ 5.3949541e-01],\n", + " [ 8.2181406e-01],\n", + " [ 1.5501775e+00],\n", + " [ 1.8349863e+00],\n", + " [ 1.6644123e+00],\n", + " [ 2.1366036e+00],\n", + " [ 2.1674187e+00],\n", + " [ 1.9316344e+00],\n", + " [ 1.8812094e+00],\n", + " [ 2.2492819e+00],\n", + " [ 2.3697419e+00],\n", + " [ 1.8332744e+00],\n", + " [ 1.7370930e+00],\n", + " [ 2.1202619e+00],\n", + " [ 2.6394544e+00],\n", + " [ 2.0871119e+00],\n", + " [ 1.7694647e+00],\n", + " [ 2.0368426e+00],\n", + " [ 2.1297555e+00],\n", + " [ 2.0472701e+00],\n", + " [ 3.0395873e+00],\n", + " [ 3.2934251e+00],\n", + " [ 3.4733372e+00],\n", + " [ 3.8921461e+00],\n", + " [ 3.5867937e+00],\n", + " [ 3.4696019e+00],\n", + " [ 3.4269586e+00],\n", + " [ 2.8092501e+00],\n", + " [ 2.9440286e+00],\n", + " [ 2.4144087e+00],\n", + " [ 2.0331073e+00],\n", + " [ 2.2208011e+00],\n", + " [ 1.8822988e+00],\n", + " [ 1.5588930e+00],\n", + " [ 1.4409230e+00],\n", + " [ 1.1388389e+00],\n", + " [ 1.0885694e+00],\n", + " [ 5.5381370e-01],\n", + " [ 3.4310017e-02],\n", + " [ 1.3157757e-03],\n", + " [-1.2521403e-01],\n", + " [-7.3855065e-02],\n", + " [-1.2101193e-01],\n", + " [ 3.9912798e-02],\n", + " [ 1.2270970e-01],\n", + " [ 4.5204341e-02],\n", + " [-1.2677038e-01],\n", + " [-1.6115144e-02],\n", + " [ 2.1842413e-01],\n", + " [ 5.3249198e-01],\n", + " [ 4.2136979e-01],\n", + " [ 7.1224833e-01],\n", + " [ 1.4854342e+00],\n", + " [ 1.8214462e+00],\n", + " [ 1.6490046e+00],\n", + " [ 2.0604987e+00],\n", + " [ 2.0366869e+00],\n", + " [ 1.6323519e+00],\n", + " [ 1.3979683e+00],\n", + " [ 1.3878522e+00],\n", + " [ 1.4852785e+00],\n", + " [ 1.5033319e+00],\n", + " [ 1.9745893e+00],\n", + " [ 2.0606544e+00],\n", + " [ 1.8254926e+00],\n", + " [ 1.8941269e+00],\n", + " [ 2.4310615e+00],\n", + " [ 2.7108901e+00],\n", + " [ 2.6917472e+00],\n", + " [ 2.9974108e+00],\n", + " [ 3.7825804e+00],\n", + " [ 3.2772393e+00],\n", + " [ 3.5678065e+00],\n", + " [ 3.8865433e+00],\n", + " [ 3.7761993e+00],\n", + " [ 3.8535490e+00],\n", + " [ 3.9933076e+00],\n", + " [ 3.0651112e+00],\n", + " [ 2.7614708e+00],\n", + " [ 2.6290269e+00],\n", + " [ 2.4046037e+00],\n", + " [ 1.4166442e+00],\n", + " [ 1.4624003e+00],\n", + " [ 9.4772130e-01]], dtype=float32)]" ] }, - "execution_count": 16, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -3341,11 +3450,11 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 19, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.507696Z", - "start_time": "2020-10-19T05:40:18.102493Z" + "end_time": "2020-10-19T09:45:06.601270Z", + "start_time": "2020-10-19T09:45:06.146320Z" } }, "outputs": [ @@ -3385,9 +3494,7 @@ " windSpeed\n", " humidity\n", " holiday\n", - " Acorn_grouped\n", - " LCLid\n", - " stdorToU\n", + " block\n", " tsp_days\n", " is_past\n", " \n", @@ -3411,122 +3518,110 @@ " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", " \n", - " 2013-09-16 16:30:00\n", - " 0.657221\n", - " 0.02243\n", - " 0.708261\n", - " 0.649428\n", - " 1.0\n", - " -1.498008\n", - " 0.264739\n", - " 0.967943\n", - " 0.377514\n", - " -0.582844\n", - " -1.010844\n", - " 0.468064\n", - " 1.477205\n", - " -1.697750\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-08 17:00:00\n", + " 1.085349\n", + " -0.87348\n", + " 1.030777\n", + " 0.794583\n", + " -0.999962\n", + " 0.500561\n", + " -0.205197\n", + " 0.700950\n", + " -0.350809\n", + " 0.160852\n", + " -0.928594\n", + " -0.347889\n", + " -0.539344\n", + " 1.037935\n", + " -0.150044\n", " 0.0\n", " -0.104167\n", " 1.0\n", " \n", " \n", - " 2013-09-16 17:00:00\n", - " 0.657221\n", - " 0.02243\n", - " 0.708261\n", - " 0.793883\n", - " -1.0\n", - " -1.498008\n", - " 0.264739\n", - " 0.978979\n", - " 0.288635\n", - " -0.665737\n", - " -0.988507\n", - " 0.393651\n", - " 1.076869\n", - " -1.697750\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-08 17:30:00\n", + " 1.085349\n", + " -0.87348\n", + " 1.030777\n", + " 0.794583\n", + " 1.000038\n", + " 0.500561\n", + " -0.205197\n", + " 0.700950\n", + " -0.350809\n", + " 0.160852\n", + " -0.928594\n", + " -0.347889\n", + " -0.539344\n", + " 1.037935\n", + " -0.150044\n", " 0.0\n", " -0.083333\n", " 1.0\n", " \n", " \n", - " 2013-09-16 17:30:00\n", - " 0.657221\n", - " 0.02243\n", - " 0.708261\n", - " 0.793883\n", - " 1.0\n", - " -1.498008\n", - " 0.264739\n", - " 0.978979\n", - " 0.288635\n", - " -0.665737\n", - " -0.988507\n", - " 0.393651\n", - " 1.076869\n", - " -1.697750\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-08 18:00:00\n", + " 1.085349\n", + " -0.87348\n", + " 1.030777\n", + " 0.939042\n", + " -0.999962\n", + " 0.500561\n", + " 0.176935\n", + " 0.919905\n", + " -0.349112\n", + " 0.139362\n", + " -0.896675\n", + " -0.442038\n", + " 0.034563\n", + " 1.037935\n", + " -0.150044\n", " 0.0\n", " -0.062500\n", " 1.0\n", " \n", " \n", - " 2013-09-16 18:00:00\n", - " 0.657221\n", - " 0.02243\n", - " 0.708261\n", - " 0.938337\n", - " -1.0\n", - " -1.498008\n", - " 0.516843\n", - " 0.923796\n", - " 0.138857\n", - " -0.559712\n", - " -0.943833\n", - " 0.268252\n", - " 0.557914\n", - " -1.282234\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-08 18:30:00\n", + " 1.085349\n", + " -0.87348\n", + " 1.030777\n", + " 0.939042\n", + " 1.000038\n", + " 0.500561\n", + " 0.176935\n", + " 0.919905\n", + " -0.349112\n", + " 0.139362\n", + " -0.896675\n", + " -0.442038\n", + " 0.034563\n", + " 1.037935\n", + " -0.150044\n", " 0.0\n", " -0.041667\n", " 1.0\n", " \n", " \n", - " 2013-09-16 18:30:00\n", - " 0.657221\n", - " 0.02243\n", - " 0.708261\n", - " 0.938337\n", - " 1.0\n", - " -1.498008\n", - " 0.516843\n", - " 0.923796\n", - " 0.138857\n", - " -0.559712\n", - " -0.943833\n", - " 0.268252\n", - " 0.557914\n", - " -1.282234\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-08 19:00:00\n", + " 1.085349\n", + " -0.87348\n", + " 1.030777\n", + " 1.083500\n", + " -0.999962\n", + " 0.500561\n", + " 0.118644\n", + " 0.952749\n", + " -0.391543\n", + " -0.048187\n", + " -0.821312\n", + " -0.517919\n", + " 0.270877\n", + " 0.680856\n", + " -0.150044\n", " 0.0\n", " -0.020833\n", " 1.0\n", @@ -3536,46 +3631,46 @@ "" ], "text/plain": [ - " month day week hour minute dayofweek \\\n", - "Date \n", - "2013-09-16 16:30:00 0.657221 0.02243 0.708261 0.649428 1.0 -1.498008 \n", - "2013-09-16 17:00:00 0.657221 0.02243 0.708261 0.793883 -1.0 -1.498008 \n", - "2013-09-16 17:30:00 0.657221 0.02243 0.708261 0.793883 1.0 -1.498008 \n", - "2013-09-16 18:00:00 0.657221 0.02243 0.708261 0.938337 -1.0 -1.498008 \n", - "2013-09-16 18:30:00 0.657221 0.02243 0.708261 0.938337 1.0 -1.498008 \n", + " month day week hour minute \\\n", + "Date \n", + "2013-11-08 17:00:00 1.085349 -0.87348 1.030777 0.794583 -0.999962 \n", + "2013-11-08 17:30:00 1.085349 -0.87348 1.030777 0.794583 1.000038 \n", + "2013-11-08 18:00:00 1.085349 -0.87348 1.030777 0.939042 -0.999962 \n", + "2013-11-08 18:30:00 1.085349 -0.87348 1.030777 0.939042 1.000038 \n", + "2013-11-08 19:00:00 1.085349 -0.87348 1.030777 1.083500 -0.999962 \n", "\n", - " visibility windBearing temperature dewPoint pressure \\\n", - "Date \n", - "2013-09-16 16:30:00 0.264739 0.967943 0.377514 -0.582844 -1.010844 \n", - "2013-09-16 17:00:00 0.264739 0.978979 0.288635 -0.665737 -0.988507 \n", - "2013-09-16 17:30:00 0.264739 0.978979 0.288635 -0.665737 -0.988507 \n", - "2013-09-16 18:00:00 0.516843 0.923796 0.138857 -0.559712 -0.943833 \n", - "2013-09-16 18:30:00 0.516843 0.923796 0.138857 -0.559712 -0.943833 \n", + " dayofweek visibility windBearing temperature \\\n", + "Date \n", + "2013-11-08 17:00:00 0.500561 -0.205197 0.700950 -0.350809 \n", + "2013-11-08 17:30:00 0.500561 -0.205197 0.700950 -0.350809 \n", + "2013-11-08 18:00:00 0.500561 0.176935 0.919905 -0.349112 \n", + "2013-11-08 18:30:00 0.500561 0.176935 0.919905 -0.349112 \n", + "2013-11-08 19:00:00 0.500561 0.118644 0.952749 -0.391543 \n", "\n", - " apparentTemperature windSpeed humidity holiday \\\n", + " dewPoint pressure apparentTemperature windSpeed \\\n", "Date \n", - "2013-09-16 16:30:00 0.468064 1.477205 -1.697750 -0.153108 \n", - "2013-09-16 17:00:00 0.393651 1.076869 -1.697750 -0.153108 \n", - "2013-09-16 17:30:00 0.393651 1.076869 -1.697750 -0.153108 \n", - "2013-09-16 18:00:00 0.268252 0.557914 -1.282234 -0.153108 \n", - "2013-09-16 18:30:00 0.268252 0.557914 -1.282234 -0.153108 \n", + "2013-11-08 17:00:00 0.160852 -0.928594 -0.347889 -0.539344 \n", + "2013-11-08 17:30:00 0.160852 -0.928594 -0.347889 -0.539344 \n", + "2013-11-08 18:00:00 0.139362 -0.896675 -0.442038 0.034563 \n", + "2013-11-08 18:30:00 0.139362 -0.896675 -0.442038 0.034563 \n", + "2013-11-08 19:00:00 -0.048187 -0.821312 -0.517919 0.270877 \n", "\n", - " Acorn_grouped LCLid stdorToU tsp_days is_past \n", - "Date \n", - "2013-09-16 16:30:00 1.0 0.0 0.0 -0.104167 1.0 \n", - "2013-09-16 17:00:00 1.0 0.0 0.0 -0.083333 1.0 \n", - "2013-09-16 17:30:00 1.0 0.0 0.0 -0.062500 1.0 \n", - "2013-09-16 18:00:00 1.0 0.0 0.0 -0.041667 1.0 \n", - "2013-09-16 18:30:00 1.0 0.0 0.0 -0.020833 1.0 " + " humidity holiday block tsp_days is_past \n", + "Date \n", + "2013-11-08 17:00:00 1.037935 -0.150044 0.0 -0.104167 1.0 \n", + "2013-11-08 17:30:00 1.037935 -0.150044 0.0 -0.083333 1.0 \n", + "2013-11-08 18:00:00 1.037935 -0.150044 0.0 -0.062500 1.0 \n", + "2013-11-08 18:30:00 1.037935 -0.150044 0.0 -0.041667 1.0 \n", + "2013-11-08 19:00:00 0.680856 -0.150044 0.0 -0.020833 1.0 " ] }, - "execution_count": 17, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -3600,14 +3695,22 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 20, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.582960Z", - "start_time": "2020-10-19T05:40:18.511125Z" + "end_time": "2020-10-19T09:45:06.696089Z", + "start_time": "2020-10-19T09:45:06.605222Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, { "data": { "text/html": [ @@ -3644,9 +3747,7 @@ " windSpeed\n", " humidity\n", " holiday\n", - " Acorn_grouped\n", - " LCLid\n", - " stdorToU\n", + " block\n", " tsp_days\n", " is_past\n", " \n", @@ -3670,122 +3771,110 @@ " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", " \n", - " 2013-09-18 16:30:00\n", - " 0.657221\n", - " 0.249395\n", - " 0.708261\n", - " 0.649428\n", - " 1.0\n", - " -0.497572\n", - " 0.83027\n", - " 1.729473\n", - " 0.257362\n", - " 0.411866\n", - " 0.461535\n", - " 0.367469\n", - " -1.033547\n", - " 0.10282\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-10 17:00:00\n", + " 1.085349\n", + " -0.645393\n", + " 1.030777\n", + " 0.794583\n", + " -0.999962\n", + " 1.499889\n", + " -0.328257\n", + " 0.36157\n", + " 0.77956\n", + " 1.225586\n", + " -1.236252\n", + " 0.835296\n", + " 2.180685\n", + " 0.609441\n", + " -0.150044\n", " 0.0\n", " 1.895833\n", " 0.0\n", " \n", " \n", - " 2013-09-18 17:00:00\n", - " 0.657221\n", - " 0.249395\n", - " 0.708261\n", - " 0.793883\n", - " -1.0\n", - " -0.497572\n", - " 0.83027\n", - " 1.729473\n", - " 0.257362\n", - " 0.411866\n", - " 0.461535\n", - " 0.367469\n", - " -1.033547\n", - " 0.10282\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-10 17:30:00\n", + " 1.085349\n", + " -0.645393\n", + " 1.030777\n", + " 0.794583\n", + " 1.000038\n", + " 1.499889\n", + " -0.328257\n", + " 0.36157\n", + " 0.77956\n", + " 1.225586\n", + " -1.236252\n", + " 0.835296\n", + " 2.180685\n", + " 0.609441\n", + " -0.150044\n", " 0.0\n", " 1.916667\n", " 0.0\n", " \n", " \n", - " 2013-09-18 17:30:00\n", - " 0.657221\n", - " 0.249395\n", - " 0.708261\n", - " 0.793883\n", - " 1.0\n", - " -0.497572\n", - " 0.83027\n", - " 1.729473\n", - " 0.257362\n", - " 0.411866\n", - " 0.461535\n", - " 0.367469\n", - " -1.033547\n", - " 0.10282\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-10 18:00:00\n", + " 1.085349\n", + " -0.645393\n", + " 1.030777\n", + " 0.939042\n", + " -0.999962\n", + " 1.499889\n", + " -0.328257\n", + " 0.36157\n", + " 0.77956\n", + " 1.225586\n", + " -1.236252\n", + " 0.835296\n", + " 2.180685\n", + " 0.609441\n", + " -0.150044\n", " 0.0\n", " 1.937500\n", " 0.0\n", " \n", " \n", - " 2013-09-18 18:00:00\n", - " 0.657221\n", - " 0.249395\n", - " 0.708261\n", - " 0.938337\n", - " -1.0\n", - " -0.497572\n", - " 0.83027\n", - " 1.729473\n", - " 0.257362\n", - " 0.411866\n", - " 0.461535\n", - " 0.367469\n", - " -1.033547\n", - " 0.10282\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-10 18:30:00\n", + " 1.085349\n", + " -0.645393\n", + " 1.030777\n", + " 0.939042\n", + " 1.000038\n", + " 1.499889\n", + " -0.328257\n", + " 0.36157\n", + " 0.77956\n", + " 1.225586\n", + " -1.236252\n", + " 0.835296\n", + " 2.180685\n", + " 0.609441\n", + " -0.150044\n", " 0.0\n", " 1.958333\n", " 0.0\n", " \n", " \n", - " 2013-09-18 18:30:00\n", - " 0.657221\n", - " 0.249395\n", - " 0.708261\n", - " 0.938337\n", - " 1.0\n", - " -0.497572\n", - " 0.83027\n", - " 1.729473\n", - " 0.257362\n", - " 0.411866\n", - " 0.461535\n", - " 0.367469\n", - " -1.033547\n", - " 0.10282\n", - " -0.153108\n", - " 1.0\n", - " 0.0\n", + " 2013-11-10 19:00:00\n", + " 1.085349\n", + " -0.645393\n", + " 1.030777\n", + " 1.083500\n", + " -0.999962\n", + " 1.499889\n", + " -0.328257\n", + " 0.36157\n", + " 0.77956\n", + " 1.225586\n", + " -1.236252\n", + " 0.835296\n", + " 2.180685\n", + " 0.609441\n", + " -0.150044\n", " 0.0\n", " 1.979167\n", " 0.0\n", @@ -3795,48 +3884,40 @@ "" ], "text/plain": [ - " month day week hour minute \\\n", - "Date \n", - "2013-09-18 16:30:00 0.657221 0.249395 0.708261 0.649428 1.0 \n", - "2013-09-18 17:00:00 0.657221 0.249395 0.708261 0.793883 -1.0 \n", - "2013-09-18 17:30:00 0.657221 0.249395 0.708261 0.793883 1.0 \n", - "2013-09-18 18:00:00 0.657221 0.249395 0.708261 0.938337 -1.0 \n", - "2013-09-18 18:30:00 0.657221 0.249395 0.708261 0.938337 1.0 \n", + " month day week hour minute \\\n", + "Date \n", + "2013-11-10 17:00:00 1.085349 -0.645393 1.030777 0.794583 -0.999962 \n", + "2013-11-10 17:30:00 1.085349 -0.645393 1.030777 0.794583 1.000038 \n", + "2013-11-10 18:00:00 1.085349 -0.645393 1.030777 0.939042 -0.999962 \n", + "2013-11-10 18:30:00 1.085349 -0.645393 1.030777 0.939042 1.000038 \n", + "2013-11-10 19:00:00 1.085349 -0.645393 1.030777 1.083500 -0.999962 \n", "\n", " dayofweek visibility windBearing temperature \\\n", "Date \n", - "2013-09-18 16:30:00 -0.497572 0.83027 1.729473 0.257362 \n", - "2013-09-18 17:00:00 -0.497572 0.83027 1.729473 0.257362 \n", - "2013-09-18 17:30:00 -0.497572 0.83027 1.729473 0.257362 \n", - "2013-09-18 18:00:00 -0.497572 0.83027 1.729473 0.257362 \n", - "2013-09-18 18:30:00 -0.497572 0.83027 1.729473 0.257362 \n", + "2013-11-10 17:00:00 1.499889 -0.328257 0.36157 0.77956 \n", + "2013-11-10 17:30:00 1.499889 -0.328257 0.36157 0.77956 \n", + "2013-11-10 18:00:00 1.499889 -0.328257 0.36157 0.77956 \n", + "2013-11-10 18:30:00 1.499889 -0.328257 0.36157 0.77956 \n", + "2013-11-10 19:00:00 1.499889 -0.328257 0.36157 0.77956 \n", "\n", " dewPoint pressure apparentTemperature windSpeed \\\n", "Date \n", - "2013-09-18 16:30:00 0.411866 0.461535 0.367469 -1.033547 \n", - "2013-09-18 17:00:00 0.411866 0.461535 0.367469 -1.033547 \n", - "2013-09-18 17:30:00 0.411866 0.461535 0.367469 -1.033547 \n", - "2013-09-18 18:00:00 0.411866 0.461535 0.367469 -1.033547 \n", - "2013-09-18 18:30:00 0.411866 0.461535 0.367469 -1.033547 \n", + "2013-11-10 17:00:00 1.225586 -1.236252 0.835296 2.180685 \n", + "2013-11-10 17:30:00 1.225586 -1.236252 0.835296 2.180685 \n", + "2013-11-10 18:00:00 1.225586 -1.236252 0.835296 2.180685 \n", + "2013-11-10 18:30:00 1.225586 -1.236252 0.835296 2.180685 \n", + "2013-11-10 19:00:00 1.225586 -1.236252 0.835296 2.180685 \n", "\n", - " humidity holiday Acorn_grouped LCLid stdorToU \\\n", - "Date \n", - "2013-09-18 16:30:00 0.10282 -0.153108 1.0 0.0 0.0 \n", - "2013-09-18 17:00:00 0.10282 -0.153108 1.0 0.0 0.0 \n", - "2013-09-18 17:30:00 0.10282 -0.153108 1.0 0.0 0.0 \n", - "2013-09-18 18:00:00 0.10282 -0.153108 1.0 0.0 0.0 \n", - "2013-09-18 18:30:00 0.10282 -0.153108 1.0 0.0 0.0 \n", - "\n", - " tsp_days is_past \n", - "Date \n", - "2013-09-18 16:30:00 1.895833 0.0 \n", - "2013-09-18 17:00:00 1.916667 0.0 \n", - "2013-09-18 17:30:00 1.937500 0.0 \n", - "2013-09-18 18:00:00 1.958333 0.0 \n", - "2013-09-18 18:30:00 1.979167 0.0 " + " humidity holiday block tsp_days is_past \n", + "Date \n", + "2013-11-10 17:00:00 0.609441 -0.150044 0.0 1.895833 0.0 \n", + "2013-11-10 17:30:00 0.609441 -0.150044 0.0 1.916667 0.0 \n", + "2013-11-10 18:00:00 0.609441 -0.150044 0.0 1.937500 0.0 \n", + "2013-11-10 18:30:00 0.609441 -0.150044 0.0 1.958333 0.0 \n", + "2013-11-10 19:00:00 0.609441 -0.150044 0.0 1.979167 0.0 " ] }, - "execution_count": 18, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -3855,32 +3936,11 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 22, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.639326Z", - "start_time": "2020-10-19T05:40:18.586830Z" - }, - "lines_to_end_of_cell_marker": 2, - "lines_to_next_cell": 0 - }, - "outputs": [], - "source": [ - "from seq2seq_time.models.lstm_seq2seq import LSTMSeq2Seq\n", - "from seq2seq_time.models.lstm import LSTM\n", - "from seq2seq_time.models.baseline import BaselineLast\n", - "from seq2seq_time.models.transformer import Transformer\n", - "from seq2seq_time.models.transformer_seq2seq import TransformerSeq2Seq\n", - "# ## Plots" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.721649Z", - "start_time": "2020-10-19T05:40:18.644528Z" + "end_time": "2020-10-19T09:45:06.832460Z", + "start_time": "2020-10-19T09:45:06.770367Z" }, "lines_to_next_cell": 0 }, @@ -3932,8 +3992,9 @@ " \n", "def plot_performance(ds_preds, full=False):\n", " \"\"\"Multiple plots using xr_preds\"\"\"\n", + " print(f'mean_NLL {ds_preds.nll.mean().item():2.2f}')\n", " plot_prediction(ds_preds, 24)\n", - " plot_prediction(ds_preds, 480)\n", + "# plot_prediction(ds_preds, 480)\n", "\n", " ds_preds.mean('t_source').plot.scatter('t_ahead_hours', 'nll') # Mean over all predictions\n", " n = len(ds_preds.t_source)\n", @@ -3955,7 +4016,7 @@ " ds_preds.plot.scatter('y_true', 'y_pred', s=.01)\n", " plt.show()\n", " \n", - " print(f'mean_NLL {ds_preds.nll.mean().item():2.2f}')" + " " ] }, { @@ -3973,11 +4034,11 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 23, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.780864Z", - "start_time": "2020-10-19T05:40:18.727453Z" + "end_time": "2020-10-19T09:45:06.892147Z", + "start_time": "2020-10-19T09:45:06.838666Z" } }, "outputs": [], @@ -4003,11 +4064,11 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 104, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.846945Z", - "start_time": "2020-10-19T05:40:18.788688Z" + "end_time": "2020-10-19T12:49:22.400579Z", + "start_time": "2020-10-19T12:49:22.319919Z" } }, "outputs": [], @@ -4023,14 +4084,18 @@ "\n", " def forward(self, x_past, y_past, x_future, y_future=None):\n", " \"\"\"Eval/Predict\"\"\"\n", - " y_dist = self._model(x_past, y_past, x_future)\n", - " return y_dist\n", + " y_dist, extra = self._model(x_past, y_past, x_future, y_future)\n", + " return y_dist, extra\n", "\n", " def training_step(self, batch, batch_idx, phase='train'):\n", " x_past, y_past, x_future, y_future = batch\n", - " y_dist = self.forward(*batch)\n", + " y_dist, extra = self.forward(*batch)\n", " loss = -y_dist.log_prob(y_future).mean()\n", " self.log_dict({f'loss/{phase}':loss})\n", + " if ('loss' in extra) and (phase=='train'):\n", + " # some models have a special loss\n", + " loss = extra['loss']\n", + " self.log_dict({f'model_loss/{phase}':loss})\n", " return loss\n", "\n", " def validation_step(self, batch, batch_idx):\n", @@ -4049,11 +4114,11 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 105, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:18.963085Z", - "start_time": "2020-10-19T05:40:18.850277Z" + "end_time": "2020-10-19T12:49:22.606189Z", + "start_time": "2020-10-19T12:49:22.530196Z" }, "lines_to_next_cell": 2 }, @@ -4062,17 +4127,16 @@ "# # Run\n", "from torch.utils.data import DataLoader\n", "from pytorch_lightning.loggers import CSVLogger\n", - "from pl_bolts.callbacks import PrintTableMetricsCallback\n", "from pytorch_lightning.callbacks.early_stopping import EarlyStopping" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 106, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:19.027332Z", - "start_time": "2020-10-19T05:40:18.971531Z" + "end_time": "2020-10-19T12:49:22.754005Z", + "start_time": "2020-10-19T12:49:22.671054Z" } }, "outputs": [], @@ -4092,11 +4156,80 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 107, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T05:40:26.916992Z", - "start_time": "2020-10-19T05:40:19.031698Z" + "end_time": "2020-10-19T12:49:22.867376Z", + "start_time": "2020-10-19T12:49:22.795909Z" + }, + "lines_to_end_of_cell_marker": 2, + "lines_to_next_cell": 0 + }, + "outputs": [], + "source": [ + "from seq2seq_time.models.lstm_seq2seq import LSTMSeq2Seq\n", + "from seq2seq_time.models.lstm_seq import LSTMSeq\n", + "from seq2seq_time.models.lstm import LSTM\n", + "from seq2seq_time.models.baseline import BaselineLast\n", + "from seq2seq_time.models.transformer import Transformer\n", + "from seq2seq_time.models.transformer_seq2seq import TransformerSeq2Seq\n", + "from seq2seq_time.models.transformer_seq import TransformerSeq\n", + "from seq2seq_time.models.anp import RANP\n", + "# ## Plots" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T12:49:23.558447Z", + "start_time": "2020-10-19T12:49:23.423800Z" + } + }, + "outputs": [], + "source": [ + "models = [\n", + " RANP(input_size,\n", + " output_size),\n", + " LSTM(input_size,\n", + " output_size,\n", + " hidden_size=80,\n", + " lstm_layers=3,\n", + " lstm_dropout=0.3),\n", + "\n", + " LSTMSeq2Seq(input_size,\n", + " output_size,\n", + " hidden_size=64,\n", + " lstm_layers=2,\n", + " lstm_dropout=0.25),\n", + " TransformerSeq2Seq(input_size,\n", + " output_size,\n", + " hidden_size=64,\n", + " nhead=8,\n", + " nlayers=4,\n", + " attention_dropout=0.3),\n", + " Transformer(input_size,\n", + " output_size,\n", + " attention_dropout=0.3,\n", + " nhead=8,\n", + " nlayers=6,\n", + " hidden_size=64),\n", + " TransformerSeq(input_size,\n", + " output_size),\n", + " LSTMSeq(input_size,\n", + " output_size),\n", + " \n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T12:49:29.037699Z", + "start_time": "2020-10-19T12:49:23.618887Z" } }, "outputs": [ @@ -4130,7 +4263,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "2c4e5be7f11243a4b5d70e14c95e23b2", + "model_id": "d3512c67fdd642749a277977d92dde8b", "version_major": 2, "version_minor": 0 }, @@ -4166,12 +4299,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6d22af7a572d45c0bcf2769ce92dc32d", + "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HBox(children=(HTML(value='predict'), FloatProgress(value=0.0, max=27.0), HTML(value='')))" + "HBox(children=(HTML(value='predict'), FloatProgress(value=0.0, max=20.0), HTML(value='')))" ] }, "metadata": {}, @@ -4181,8 +4314,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", - "baseline nll: 1.8\n" + "baseline nll: 2.3\n" ] } ], @@ -4204,94 +4336,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 111, "metadata": { "ExecuteTime": { - "end_time": "2020-10-19T01:45:07.878992Z", - "start_time": "2020-10-19T01:45:07.775810Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "ExecuteTime": { - "end_time": "2020-10-19T05:40:27.042145Z", - "start_time": "2020-10-19T05:40:26.922340Z" - } - }, - "outputs": [], - "source": [ - "models = [\n", - "# BaselineLast(),\n", - " LSTM(input_size,\n", - " output_size,\n", - " hidden_size=80,\n", - " lstm_layers=3,\n", - " lstm_dropout=0.3),\n", - " Transformer(input_size,\n", - " output_size,\n", - " attention_dropout=0.3,\n", - " nhead=8,\n", - " nlayers=6,\n", - " hidden_size=64),\n", - " LSTMSeq2Seq(input_size,\n", - " output_size,\n", - " hidden_size=64,\n", - " lstm_layers=2,\n", - " lstm_dropout=0.25),\n", - " TransformerSeq2Seq(input_size,\n", - " output_size,\n", - " hidden_size=64,\n", - " nhead=8,\n", - " nlayers=4,\n", - " attention_dropout=0.3),\n", - "# Transformer(input_size,\n", - "# output_size,\n", - "# attention_dropout=0.2,\n", - "# nhead=8,\n", - "# nlayers=6,\n", - "# hidden_size=128),\n", - "# LSTM(input_size,\n", - "# output_size,\n", - "# hidden_size=128,\n", - "# lstm_layers=3,\n", - "# lstm_dropout=0.3),\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2020-10-19T05:22:41.150645Z", - "start_time": "2020-10-19T05:22:41.034632Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "start_time": "2020-10-19T05:28:34.600Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T12:49:36.538636Z", + "start_time": "2020-10-19T12:49:35.633700Z" } }, "outputs": [ @@ -4306,20 +4355,20 @@ "\n", " | Name | Type | Params\n", "--------------------------------\n", - "0 | _model | LSTM | 136 K \n" + "0 | _model | RANP | 58 K \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "LSTM\n" + "RANP\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "", + "model_id": "666a797e34c7447587ffd0236342302c", "version_major": 2, "version_minor": 0 }, @@ -4331,18 +4380,27 @@ "output_type": "display_data" }, { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0b42a6f196704822bb114aa11c3ffa5b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Training'), FloatProgress(value=1.0, bar_style='info', layout=Layout(flex='2'), max…" - ] - }, - "metadata": {}, - "output_type": "display_data" + "ename": "RuntimeError", + "evalue": "Tensor.__contains__ only supports Tensor or scalar, but you passed in a .", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;31m# Train\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 25\u001b[0;31m \u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdl_train\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdl_test\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 26\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/trainer/trainer.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, model, train_dataloader, val_dataloaders, datamodule)\u001b[0m\n\u001b[1;32m 438\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcall_hook\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'on_fit_start'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 439\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 440\u001b[0;31m \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maccelerator_backend\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 441\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maccelerator_backend\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mteardown\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 442\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/accelerators/gpu_accelerator.py\u001b[0m in \u001b[0;36mtrain\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0;31m# train or test\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrain_or_test\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresults\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/accelerators/accelerator.py\u001b[0m in \u001b[0;36mtrain_or_test\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_test\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 65\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresults\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/trainer/trainer.py\u001b[0m in \u001b[0;36mtrain\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 460\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mtrain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 462\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_sanity_check\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_model\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 463\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 464\u001b[0m \u001b[0;31m# enable train mode\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/trainer/trainer.py\u001b[0m in \u001b[0;36mrun_sanity_check\u001b[0;34m(self, ref_model)\u001b[0m\n\u001b[1;32m 646\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 647\u001b[0m \u001b[0;31m# run eval step\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 648\u001b[0;31m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0meval_results\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_evaluation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtest_mode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax_batches\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_sanity_val_batches\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 649\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 650\u001b[0m \u001b[0;31m# allow no returns from eval\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/trainer/trainer.py\u001b[0m in \u001b[0;36mrun_evaluation\u001b[0;34m(self, test_mode, max_batches)\u001b[0m\n\u001b[1;32m 566\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 567\u001b[0m \u001b[0;31m# lightning module methods\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 568\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevaluation_loop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevaluation_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtest_mode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch_idx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdataloader_idx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 569\u001b[0m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevaluation_loop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevaluation_step_end\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutput\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 570\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/trainer/evaluation_loop.py\u001b[0m in \u001b[0;36mevaluation_step\u001b[0;34m(self, test_mode, batch, batch_idx, dataloader_idx)\u001b[0m\n\u001b[1;32m 169\u001b[0m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maccelerator_backend\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtest_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 170\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 171\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maccelerator_backend\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidation_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 172\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 173\u001b[0m \u001b[0;31m# track batch size for weighted average\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/accelerators/gpu_accelerator.py\u001b[0m in \u001b[0;36mvalidation_step\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 74\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mamp_backend\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mAMPType\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNATIVE\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 75\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcuda\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mamp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautocast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 76\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__validation_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 77\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 78\u001b[0m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__validation_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/pytorch_lightning/accelerators/gpu_accelerator.py\u001b[0m in \u001b[0;36m__validation_step\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 84\u001b[0m \u001b[0mbatch\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_device\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 85\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbatch\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 86\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidation_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 87\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0moutput\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 88\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mvalidation_step\u001b[0;34m(self, batch, batch_idx)\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mvalidation_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch_idx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 27\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtraining_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch_idx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mphase\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'val'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 28\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mconfigure_optimizers\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mtraining_step\u001b[0;34m(self, batch, batch_idx, phase)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0my_dist\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog_prob\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_future\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34mf'loss/{phase}'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mloss\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'loss'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mextra\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mphase\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;34m'train'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;31m# some models have a special loss\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mextra\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/torch/tensor.py\u001b[0m in \u001b[0;36m__contains__\u001b[0;34m(self, element)\u001b[0m\n\u001b[1;32m 502\u001b[0m raise RuntimeError(\n\u001b[1;32m 503\u001b[0m \u001b[0;34m\"Tensor.__contains__ only supports Tensor or scalar, but you passed in a %s.\"\u001b[0m \u001b[0;34m%\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 504\u001b[0;31m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melement\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 505\u001b[0m )\n\u001b[1;32m 506\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mRuntimeError\u001b[0m: Tensor.__contains__ only supports Tensor or scalar, but you passed in a ." + ] } ], "source": [ @@ -4354,46 +4412,939 @@ " patience = 2\n", " model = PL_MODEL(pt_model, patience=patience, lr=3e-4).to(device)\n", "\n", - " # Trainer\n", - " \n", + " # Trainer \n", " trainer = pl.Trainer(gpus=1,\n", - " min_epochs=1,\n", + " min_epochs=2,\n", " max_epochs=10,\n", " amp_level='O1',\n", " precision=16,\n", - " gradient_clip_val=0.5,\n", + " gradient_clip_val=1,\n", " logger=CSVLogger(\"logs\",\n", " name=type(pt_model).__name__),\n", " callbacks=[\n", " EarlyStopping(monitor='loss/val', patience=patience*2),\n", - " PrintTableMetricsCallback()\n", + "# PrintTableMetricsCallback2()\n", " ],\n", " )\n", "\n", " # Train\n", " trainer.fit(model, dl_train, dl_test)\n", "\n", - " # Performance\n", - " print(plot_hist(trainer))\n", + "\n", "\n", " ds_preds = predict(model.to(device),\n", " ds_test.datasets[0],\n", " batch_size,\n", " device=device,\n", " scaler=output_scaler)\n", + " \n", + " print(name)\n", + " print(f'mean_NLL {ds_preds.nll.mean().item():2.2f}')\n", + " \n", + " # Performance\n", + " print(plot_hist(trainer))\n", " plot_performance(ds_preds)" ] }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T12:50:23.303860Z", + "start_time": "2020-10-19T12:49:59.765101Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> \u001b[0;32m/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/torch/tensor.py\u001b[0m(504)\u001b[0;36m__contains__\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 502 \u001b[0;31m raise RuntimeError(\n", + "\u001b[0m\u001b[0;32m 503 \u001b[0;31m \u001b[0;34m\"Tensor.__contains__ only supports Tensor or scalar, but you passed in a %s.\"\u001b[0m \u001b[0;34m%\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m--> 504 \u001b[0;31m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melement\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 505 \u001b[0;31m )\n", + "\u001b[0m\u001b[0;32m 506 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n", + "ipdb> u\n", + "> \u001b[0;32m\u001b[0m(20)\u001b[0;36mtraining_step\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 18 \u001b[0;31m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0my_dist\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog_prob\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_future\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 19 \u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34mf'loss/{phase}'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mloss\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m---> 20 \u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'loss'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mextra\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mphase\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;34m'train'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 21 \u001b[0;31m \u001b[0;31m# some models have a special loss\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 22 \u001b[0;31m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mextra\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n", + "ipdb> extra\n", + "tensor(3.4646, device='cuda:0')\n", + "ipdb> q\n" + ] + } + ], + "source": [ + "%debug" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:39:06.800Z" + "end_time": "2020-10-19T12:46:47.595985Z", + "start_time": "2020-10-19T12:46:44.000Z" } }, "outputs": [], - "source": [] + "source": [ + "ds_preds = predict(model.to(device),q\n", + " \n", + " ds_test.datasets[0],\n", + " batch_size,\n", + " device=device,\n", + " scaler=output_scaler)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T12:46:47.598417Z", + "start_time": "2020-10-19T12:46:44.300Z" + } + }, + "outputs": [], + "source": [ + "# ds_predss = predict_multi(model.to(device),\n", + "# ds_test.datasets,\n", + "# batch_size,\n", + "# device=device,\n", + "# scaler=output_scaler)" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T10:59:36.752961Z", + "start_time": "2020-10-19T10:59:36.673590Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, + { + "data": { + "text/plain": [ + "2014-01-06 21:30:00 1\n", + "2014-01-03 15:30:00 1\n", + "2013-12-04 18:30:00 1\n", + "2014-01-07 17:30:00 1\n", + "2013-11-30 07:00:00 1\n", + " ..\n", + "2013-11-26 21:30:00 1\n", + "2013-11-22 10:00:00 1\n", + "2014-01-25 16:30:00 1\n", + "2013-11-17 22:30:00 1\n", + "2013-11-11 07:00:00 1\n", + "Name: Date, Length: 5233, dtype: int64" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ds_test.datasets[0].df.index.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T11:01:57.088590Z", + "start_time": "2020-10-19T11:01:56.942038Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:        (t_ahead: 96, t_behind: 96, t_source: 2)\n",
+       "Coordinates:\n",
+       "  * t_source       (t_source) datetime64[ns] 2013-11-11T00:30:00 2013-11-11T0...\n",
+       "  * t_ahead        (t_ahead) timedelta64[ns] 00:00:00 ... 1 days 23:30:00\n",
+       "  * t_behind       (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...\n",
+       "    t_target       (t_source, t_ahead) datetime64[ns] 2013-11-11T00:30:00 ......\n",
+       "    t_past         (t_source, t_behind) datetime64[ns] 2013-11-09T00:30:00 .....\n",
+       "    t_ahead_hours  (t_ahead) float64 0.0 0.0 1.0 1.0 2.0 ... 46.0 46.0 47.0 47.0\n",
+       "Data variables:\n",
+       "    y_past         (t_source, t_behind) float32 13.901 14.189 ... 16.332 19.715\n",
+       "    nll            (t_source, t_ahead) float32 -0.14149201 ... 0.36666018\n",
+       "    y_pred         (t_source, t_ahead) float32 13.723726 12.490604 ... 22.930597\n",
+       "    y_pred_std     (t_source, t_ahead) float64 1.328 1.048 0.8472 ... 2.114 2.46\n",
+       "    y_true         (t_source, t_ahead) float32 15.073 14.09 ... 16.708 20.709
" + ], + "text/plain": [ + "\n", + "Dimensions: (t_ahead: 96, t_behind: 96, t_source: 2)\n", + "Coordinates:\n", + " * t_source (t_source) datetime64[ns] 2013-11-11T00:30:00 2013-11-11T0...\n", + " * t_ahead (t_ahead) timedelta64[ns] 00:00:00 ... 1 days 23:30:00\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...\n", + " t_target (t_source, t_ahead) datetime64[ns] 2013-11-11T00:30:00 ......\n", + " t_past (t_source, t_behind) datetime64[ns] 2013-11-09T00:30:00 .....\n", + " t_ahead_hours (t_ahead) float64 0.0 0.0 1.0 1.0 2.0 ... 46.0 46.0 47.0 47.0\n", + "Data variables:\n", + " y_past (t_source, t_behind) float32 13.901 14.189 ... 16.332 19.715\n", + " nll (t_source, t_ahead) float32 -0.14149201 ... 0.36666018\n", + " y_pred (t_source, t_ahead) float32 13.723726 12.490604 ... 22.930597\n", + " y_pred_std (t_source, t_ahead) float64 1.328 1.048 0.8472 ... 2.114 2.46\n", + " y_true (t_source, t_ahead) float32 15.073 14.09 ... 16.708 20.709" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# TODO why dup?\n", + "ds_preds.sel(t_source='2013-11-11 00:30:00')" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "ExecuteTime": { + "end_time": "2020-10-19T11:00:36.966816Z", + "start_time": "2020-10-19T11:00:36.899592Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "t_source\n", + "2013-11-11 00:00:00 2013-11-11 00:00:00\n", + "2013-11-11 00:30:00 2013-11-11 00:30:00\n", + "2013-11-11 00:30:00 2013-11-11 00:30:00\n", + "2013-11-11 01:00:00 2013-11-11 01:00:00\n", + "2013-11-11 01:00:00 2013-11-11 01:00:00\n", + " ... \n", + "2013-11-16 15:30:00 2013-11-16 15:30:00\n", + "2013-11-16 15:30:00 2013-11-16 15:30:00\n", + "2013-11-16 16:00:00 2013-11-16 16:00:00\n", + "2013-11-16 16:00:00 2013-11-16 16:00:00\n", + "2013-11-16 16:30:00 2013-11-16 16:30:00\n", + "Name: t_source, Length: 5041, dtype: datetime64[ns]" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# TODO why duplicates?\n", + "d = ds_preds.isel(t_ahead=0)\n", + "d.t_source.to_series().sort_index()#.value_counts()\n", + "# np.unique\n", + "# d" + ] }, { "cell_type": "markdown", @@ -4404,13 +5355,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:47:47.938752Z", + "start_time": "2020-10-19T10:47:47.880570Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + } + ], "source": [ "import holoviews as hv\n", "from holoviews import opts" @@ -4418,14 +5379,83 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:47:48.526627Z", + "start_time": "2020-10-19T10:47:47.942455Z" }, "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/bokeh/core/property/bases.py:241: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.\n", + " return new == old\n" + ] + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + ":DynamicMap [t_source]\n", + " :Overlay\n", + " .Scatter.True :Scatter [x] (y)\n", + " .Curve.Pred :Curve [x] (y)\n", + " .Area.A_2_times_std :Area [x] (y,y2)\n", + " .VLine.Now :VLine [x,y]" + ] + }, + "execution_count": 32, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "1443" + } + }, + "output_type": "execute_result" + } + ], "source": [ "def plot_prediction_now(t_source):\n", " \"\"\"Plot predictions with holoviews\"\"\"\n", @@ -4436,7 +5466,7 @@ "\n", " d = ds_preds.sel(t_source=t_source)\n", "\n", - " # Sometimes there are duplicate time, take the first\n", + " # Sometimes there are duplicate times, take the first\n", " if len(d.t_source.shape) and d.t_source.shape[0] > 0:\n", " d = d.isel(t_source=0)\n", " if len(d.t_source.shape) and d.t_source.shape[0] == 0:\n", @@ -4450,7 +5480,7 @@ " p = hv.Scatter({\n", " 'x': x,\n", " 'y': yt\n", - " }, label='true').opts(color='black', framewise=True)\n", + " }, label='true').opts(color='black')\n", "\n", " # Get arrays\n", " xf = d.t_target.values\n", @@ -4465,7 +5495,7 @@ " label='2*std').opts(alpha=0.5, line_width=0)\n", "\n", " # plot now line\n", - " p *= hv.VLine(now, label='now').opts(color='red')\n", + " p *= hv.VLine(now, label='now').opts(color='red', framewise=True)\n", " return p.opts(title=f'Prediction at {now}. NLL={d.nll.mean().item():2.2f}')\n", "\n", "\n", @@ -4479,18 +5509,208 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:57:43.721383Z", + "start_time": "2020-10-19T10:57:42.548727Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Dimensions: (t_behind: 96, t_source: 274)\n", + "Coordinates:\n", + " t_ahead timedelta64[ns] 00:00:00\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...\n", + " t_ahead_hours float64 0.0\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00\n", + "Data variables:\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59\n", + " nll (t_source) float32 -0.42425382 1.825292 ... 0.45063046\n", + " y_pred (t_source) float32 16.014568 24.125784 ... 21.401958\n", + " y_pred_std (t_source) float64 1.658 2.507 3.558 ... 1.876 2.285 2.487\n", + " y_true (t_source) float32 16.267 19.307001 23.038 ... 16.59 18.963\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/bokeh/core/property/bases.py:241: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.\n", + " return new == old\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 04:30:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 4.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 10.724 0.0037053227 ... 0.3161078
\n", + " y_pred (t_source) float32 10.76828 21.676603 ... 22.7903 22.420483
\n", + " y_pred_std (t_source) float64 0.6646 2.448 3.175 ... 2.839 2.836 2.874
\n", + " y_true (t_source) float32 14.034 22.449 ... 19.858002 20.595001
\n", + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 06:30:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 6.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 0.7417145 0.36029536 ... 0.22455204
\n", + " y_pred (t_source) float32 15.744131 21.442015 ... 21.529743
\n", + " y_pred_std (t_source) float64 1.607 2.483 2.928 ... 2.9 2.847 2.859
\n", + " y_true (t_source) float32 18.243 19.243 27.181002 ... 21.012 22.904
\n", + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 09:00:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 9.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 -0.07550305 0.59446204 ... 0.7492668
\n", + " y_pred (t_source) float32 23.871077 28.067057 ... 22.720411
\n", + " y_pred_std (t_source) float64 2.377 3.221 1.669 ... 2.932 3.001 3.046
\n", + " y_true (t_source) float32 23.867 25.310999 18.483 ... 16.969 19.449
\n", + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 10:30:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 10.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 -0.08419824 2.6844807 ... 0.8413604
\n", + " y_pred (t_source) float32 22.059172 38.408897 ... 26.288809 28.46659
\n", + " y_pred_std (t_source) float64 2.337 3.194 1.007 ... 3.247 3.347 3.389
\n", + " y_true (t_source) float32 21.762001 31.318 ... 29.953001 32.059998
\n", + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 16:30:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 16.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 0.1073612 0.22418153 ... 0.93859696
\n", + " y_pred (t_source) float32 24.415854 13.307469 ... 16.607029
\n", + " y_pred_std (t_source) float64 2.836 1.394 2.472 ... 2.501 2.243 1.79
\n", + " y_true (t_source) float32 24.737999 15.107 ... 23.396 19.491001
\n", + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 17:00:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 17.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 0.22898376 -0.8886603 ... -0.15025973
\n", + " y_pred (t_source) float32 27.6007 11.929974 ... 16.62101 15.153604
\n", + " y_pred_std (t_source) float64 3.214 1.054 2.7 3.47 ... 2.263 1.795 1.606
\n", + " y_true (t_source) float32 27.36 11.9279995 ... 19.491001 16.433
\n", + "
\n", + "Dimensions: (t_behind: 96, t_source: 274)
\n", + "Coordinates:
\n", + " t_ahead timedelta64[ns] 07:30:00
\n", + " * t_behind (t_behind) timedelta64[ns] -2 days +00:00:00 ... -1 days +...
\n", + " t_ahead_hours float64 7.0
\n", + " * t_source (t_source) datetime64[ns] 2013-11-11 ... 2013-11-16T16:30:00
\n", + "Data variables:
\n", + " y_past (t_source, t_behind) float32 16.394 13.901 ... 15.281 16.59
\n", + " nll (t_source) float32 0.047929287 1.9480975 ... 0.35706586
\n", + " y_pred (t_source) float32 23.83615 22.037819 ... 21.589767 21.60583
\n", + " y_pred_std (t_source) float64 2.305 2.585 2.597 ... 2.898 2.837 2.903
\n", + " y_true (t_source) float32 22.556 16.946 26.053 ... 23.376001 19.626
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + ":DynamicMap [it_ahead]\n", + " :Overlay\n", + " .Scatter.True :Scatter [x] (y)\n", + " .Curve.Pred :Curve [x] (y)\n", + " .Area.A_2_times_std :Area [x] (y,y2)" + ] + }, + "execution_count": 45, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "7323" + } + }, + "output_type": "execute_result" + } + ], "source": [ "def plot_predictions_vs_time(it_ahead):\n", " \"\"\"Plot predictions vs time with holoviews\"\"\"\n", "\n", " d = ds_preds.isel(t_ahead=it_ahead).groupby('t_source').first()\n", + " print(d)\n", "\n", " p = hv.Scatter({\n", " 'x': d.t_source,\n", @@ -4519,18 +5739,82 @@ " height=300, \n", " ))\n", "dmap_preds\n", - "# plot_prediction2(10).opts(width=800)" + "# TODO fixme" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:57:06.875280Z", + "start_time": "2020-10-19T10:57:06.661607Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + ":Curve [hours ahead] (nll)" + ] + }, + "execution_count": 44, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "7143" + } + }, + "output_type": "execute_result" + } + ], "source": [ "d = ds_preds.mean('t_source')['nll'].groupby('t_ahead_hours').mean()\n", "nll_vs_tahead = hv.Curve((d.t_ahead_hours, d)).redim(x='hours ahead', y='nll').opts(width=800)\n", @@ -4539,32 +5823,43 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:53:35.125269Z", + "start_time": "2020-10-19T10:53:35.053232Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + } + ], "source": [ - "d = ds_preds.mean('t_ahead')['nll'].groupby('t_source').mean()\n", - "nll_vs_time = hv.Curve(d).opts(width=800)\n", - "nll_vs_time" + "# d = ds_preds.mean('t_ahead')['nll'].groupby('t_source').mean()\n", + "# nll_vs_time = hv.Curve(d).opts(width=800)\n", + "# nll_vs_time" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:53:37.325570Z", + "start_time": "2020-10-19T10:53:37.258789Z" }, "scrolled": true }, "outputs": [], "source": [ - "true_vs_pred = hv.Scatter((ds_preds.y_true, ds_preds.y_pred))\n", - "dynspread(datashade(true_vs_pred))" + "# true_vs_pred = hv.Scatter((ds_preds.y_true, ds_preds.y_pred))\n", + "# dynspread(datashade(true_vs_pred))" ] }, { @@ -4583,27 +5878,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": { "ExecuteTime": { - "start_time": "2020-10-19T05:40:02.000Z" + "end_time": "2020-10-19T10:47:51.248969Z", + "start_time": "2020-10-19T10:47:51.198312Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/wassname/anaconda/envs/seq2seq-time/lib/python3.7/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n", + " and should_run_async(code)\n" + ] + } + ], "source": [ "\n", - "# Run learning rate finder\n", - "lr_finder = trainer.tuner.lr_find(model)\n", + "# # Run learning rate finder\n", + "# lr_finder = trainer.tuner.lr_find(model)\n", "\n", - "# Results can be found in\n", - "lr_finder.results\n", + "# # Results can be found in\n", + "# lr_finder.results\n", "\n", - "# Plot with\n", - "fig = lr_finder.plot(suggest=True)\n", - "fig.show()\n", + "# # Plot with\n", + "# fig = lr_finder.plot(suggest=True)\n", + "# fig.show()\n", "\n", - "# Pick point based on plot, or get suggestion\n", - "new_lr = lr_finder.suggestion()" + "# # Pick point based on plot, or get suggestion\n", + "# new_lr = lr_finder.suggestion()" ] }, { diff --git a/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.py b/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.py index f7cc8d4..0612317 100644 --- a/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.py +++ b/notebooks/02.0-mike-RNN_Timeseries_Seq2Seq.py @@ -61,8 +61,11 @@ from tqdm.auto import tqdm import pytorch_lightning as pl # - +import warnings +warnings.simplefilter('once') + from seq2seq_time.data.dataset import Seq2SeqDataSet, Seq2SeqDataSets -from seq2seq_time.predict import predict +from seq2seq_time.predict import predict, predict_multi import logging, sys # logging.basicConfig(stream=sys.stdout, level=logging.INFO) @@ -79,7 +82,7 @@ window_future = 48*2 batch_size = 256 num_workers = 5 freq = '30T' -max_rows = 2e5 +max_rows = 5e5 # - @@ -88,7 +91,7 @@ max_rows = 2e5 # + -def get_smartmeter_df(indir=Path('../data/raw/smart-meters-in-london'), max_files=1): +def get_smartmeter_df(indir=Path('../data/raw/smart-meters-in-london'), max_files=8): """ Data loading and cleanding is always messy, so understand this code is optional. """ @@ -96,62 +99,65 @@ def get_smartmeter_df(indir=Path('../data/raw/smart-meters-in-london'), max_file # Load csv files csv_files = sorted((indir/'halfhourly_dataset').glob('*.csv'))[:max_files] - # concatendate them - df = pd.concat([pd.read_csv(f, parse_dates=[1], na_values=['Null']) for f in csv_files]) + dfs = [] + for f in csv_files: + df = (pd.read_csv(f, parse_dates=[1], na_values=['Null']) + .groupby('tstp') + .sum() + .sort_index() + ) + df['block'] = f.stem + + # Drop nan and 0's + df = df[df['energy(kWh/hh)']!=0] + df = df.dropna() + + # Add time features + time = df.index.to_series() + df["month"] = time.dt.month + df['day'] = time.dt.day + df['week'] = time.dt.week + df['hour'] = time.dt.hour + df['minute'] = time.dt.minute + df['dayofweek'] = time.dt.dayofweek + + # Load weather data + df_weather = pd.read_csv(indir/'weather_hourly_darksky.csv', parse_dates=[3]) + use_cols = ['visibility', 'windBearing', 'temperature', 'time', 'dewPoint', + 'pressure', 'apparentTemperature', 'windSpeed', + 'humidity'] + df_weather = df_weather[use_cols].set_index('time') + + # Resample to match energy data + # Use first, since we have bearing, and you can't take mean + df_weather = df_weather.resample(freq).first().ffill() + + # Join weather and energy data + df = pd.merge(df, df_weather, how='inner', left_index=True, right_index=True, sort=True) + + # Holidays + df_hols = pd.read_csv(indir/'uk_bank_holidays.csv', parse_dates=[0]) + holidays = set(df_hols['Bank holidays'].dt.round('D')) + def is_holiday(dt): + return dt in holidays + days = df.index.floor('D') + holiday_mapping = days.unique().to_series().apply(is_holiday).astype(int).to_dict() + df['holiday'] = days.to_series().map(holiday_mapping).values + + # sort + df.index.name = 'Date' + df = df.loc['2012-09':] # Weird value before this - # Add ACORN categories - df_households = pd.read_csv(indir/'informations_households.csv') - df_households = df_households[['LCLid', 'stdorToU', 'Acorn_grouped']] - df = pd.merge(df, df_households, on='LCLid') + dfs.append(df) - - df = df.sort_values(['tstp', 'LCLid']) - - df = df.set_index('tstp') - - # Drop nan and 0's - df = df[df['energy(kWh/hh)']!=0] - df = df.dropna() - - # Add time features - time = df.index.to_series() - df["month"] = time.dt.month - df['day'] = time.dt.day - df['week'] = time.dt.week - df['hour'] = time.dt.hour - df['minute'] = time.dt.minute - df['dayofweek'] = time.dt.dayofweek - - # Load weather data - df_weather = pd.read_csv(indir/'weather_hourly_darksky.csv', parse_dates=[3]) - use_cols = ['visibility', 'windBearing', 'temperature', 'time', 'dewPoint', - 'pressure', 'apparentTemperature', 'windSpeed', - 'humidity'] - df_weather = df_weather[use_cols].set_index('time') - df_weather = df_weather.resample(freq).first().ffill() # Resample to match energy data - - # Join weather and energy data - df = pd.merge(df, df_weather, how='inner', left_index=True, right_index=True, sort=True) - - # Holidays - df_hols = pd.read_csv(indir/'uk_bank_holidays.csv', parse_dates=[0]) - holidays = set(df_hols['Bank holidays'].dt.round('D')) - def is_holiday(dt): - return dt in holidays - days = df.index.floor('D') - holiday_mapping = days.unique().to_series().apply(is_holiday).astype(int).to_dict() - df['holiday'] = days.to_series().map(holiday_mapping).values - - # sort - df = df.reset_index().sort_values(['LCLid', 'index']).set_index('index') - df.index.name = 'Date' - - return df + return pd.concat(dfs) # - + + # Our dataset is the london smartmeter data. But at half hour intervals # + -df = get_smartmeter_df() +df = get_smartmeter_df(max_files=12) # # Just get the first one for now # dfs = list(dfs) @@ -161,14 +167,15 @@ df = get_smartmeter_df() df = df.tail(int(max_rows)).copy() # Just use last X rows # df = pd.concat(dfs[:6], 0) # # df = dfs[0] -df.LCLid.value_counts() +print(df.block.value_counts()) +df # - # ### Plot/explore -df + @@ -186,22 +193,22 @@ from holoviews.operation import decimate hv.extension('bokeh') -def house_curve(Name=None): - if isinstance(Name, int): - name = df.LCLid.unique()[Name] - d = df[df.LCLid == Name] - d_curve = hv.Curve(d, 'Date', 'energy(kWh/hh)', label=Name) - return d_curve +# def house_curve(Name=None): +# if isinstance(Name, int): +# name = df.block.unique()[Name] +# d = df[df.block == Name] +# d_curve = hv.Curve(d, 'Date', 'energy(kWh/hh)', label=Name).opts(framewise=True) +# return d_curve -dmap = hv.DynamicMap(house_curve, kdims=['Name']) -dmap = dmap.redim.values(Name=list(df.LCLid.unique())) -dynspread(datashade(dmap).opts(width=800, - height=300, - tools=['xwheel_zoom', 'pan'], - active_tools=['xwheel_zoom', 'pan'], - default_tools=['reset', 'save', 'hover'] - )) +# dmap = hv.DynamicMap(house_curve, kdims=['Name']) +# dmap = dmap.redim.values(Name=list(df.block.unique())) +# dynspread(datashade(dmap).opts(width=800, +# height=300, +# tools=['xwheel_zoom', 'pan'], +# active_tools=['xwheel_zoom', 'pan'], +# default_tools=['reset', 'save', 'hover'] +# )) # - @@ -239,6 +246,8 @@ df_norm output_scaler = next(filter(lambda r:r[0][0] in columns_target, scaler.features))[-1] output_scaler +# ### Split + # + # split data, with the test in the future @@ -247,24 +256,36 @@ d1 = df_norm.index.max() split_time = d0+(d1-d0)*0.8 split_time = split_time.round('1D') print(split_time) -df_train = df_norm.groupby('LCLid').apply(lambda d:d.loc[:split_time]).reset_index(level=0, drop=True) -df_test = df_norm.groupby('LCLid').apply(lambda d:d.loc[split_time:]).reset_index(level=0, drop=True) +df_train = df_norm.groupby('block').apply(lambda d:d.loc[:split_time]).reset_index(level=0, drop=True) +df_test = df_norm.groupby('block').apply(lambda d:d.loc[split_time:]).reset_index(level=0, drop=True) # df_test + +# + +# # Show split +# df_train['energy(kWh/hh)'].plot(label='train') +# df_test['energy(kWh/hh)'].plot(label='test') +# plt.ylabel('energy(kWh/hh)') +# plt.legend() # - -# Show split -df_train['energy(kWh/hh)'].plot(label='train') -df_test['energy(kWh/hh)'].plot(label='test') -plt.ylabel('energy(kWh/hh)') -plt.legend() +# # Show split +scatter = dynspread(datashade(hv.Curve(df_train, kdims=['Date'], vdims=['energy(kWh/hh)', 'block']).groupby('block'), cmap='blue')) +scatter *= dynspread(datashade(hv.Curve(df_test, kdims=['Date'], vdims=['energy(kWh/hh)', 'block']).groupby('block'), cmap='red')) +scatter = scatter.opts(plot=dict(width=800)) +scatter + +# ### Dataset + +# + + # ### Dataset # These are the columns that we wont know in the future # We need to blank them out in x_future columns_blank=['visibility', 'windBearing', 'temperature', 'dewPoint', 'pressure', 'apparentTemperature', 'windSpeed', 'humidity'] -df_trains = [d.resample(freq).first().ffill().dropna() for _,d in df_train.groupby('LCLid')] -df_tests = [d.resample(freq).first().ffill().dropna() for _,d in df_test.groupby('LCLid')] +df_trains = [d.resample(freq).first().ffill().dropna() for _,d in df_train.groupby('block')] +df_tests = [d.resample(freq).first().ffill().dropna() for _,d in df_test.groupby('block')] ds_train = Seq2SeqDataSets(df_trains, window_past=window_past, window_future=window_future, @@ -275,6 +296,7 @@ ds_test = Seq2SeqDataSets(df_tests, columns_blank=columns_blank) print(ds_train) print(ds_test) +# - # we can treat it like an array ds_train[0] len(ds_train) @@ -297,14 +319,9 @@ x_past.tail() # Notice we've hidden some future columns to prevent cheating x_future.tail() + # ## Plot helpers -from seq2seq_time.models.lstm_seq2seq import LSTMSeq2Seq -from seq2seq_time.models.lstm import LSTM -from seq2seq_time.models.baseline import BaselineLast -from seq2seq_time.models.transformer import Transformer -from seq2seq_time.models.transformer_seq2seq import TransformerSeq2Seq -# ## Plots # + def plot_prediction(ds_preds, i): """Plot a prediction into the future, at a single point in time.""" @@ -352,8 +369,9 @@ def plot_prediction(ds_preds, i): def plot_performance(ds_preds, full=False): """Multiple plots using xr_preds""" + print(f'mean_NLL {ds_preds.nll.mean().item():2.2f}') plot_prediction(ds_preds, 24) - plot_prediction(ds_preds, 480) +# plot_prediction(ds_preds, 480) ds_preds.mean('t_source').plot.scatter('t_ahead_hours', 'nll') # Mean over all predictions n = len(ds_preds.t_source) @@ -375,7 +393,7 @@ def plot_performance(ds_preds, full=False): ds_preds.plot.scatter('y_true', 'y_pred', s=.01) plt.show() - print(f'mean_NLL {ds_preds.nll.mean().item():2.2f}') + # - @@ -406,14 +424,18 @@ class PL_MODEL(pl.LightningModule): def forward(self, x_past, y_past, x_future, y_future=None): """Eval/Predict""" - y_dist = self._model(x_past, y_past, x_future) - return y_dist + y_dist, extra = self._model(x_past, y_past, x_future, y_future) + return y_dist, extra def training_step(self, batch, batch_idx, phase='train'): x_past, y_past, x_future, y_future = batch - y_dist = self.forward(*batch) + y_dist, extra = self.forward(*batch) loss = -y_dist.log_prob(y_future).mean() self.log_dict({f'loss/{phase}':loss}) + if ('loss' in extra) and (phase=='train'): + # some models have a special loss + loss = extra['loss'] + self.log_dict({f'model_loss/{phase}':loss}) return loss def validation_step(self, batch, batch_idx): @@ -435,7 +457,6 @@ class PL_MODEL(pl.LightningModule): # # Run from torch.utils.data import DataLoader from pytorch_lightning.loggers import CSVLogger -from pl_bolts.callbacks import PrintTableMetricsCallback from pytorch_lightning.callbacks.early_stopping import EarlyStopping @@ -453,6 +474,50 @@ dl_train = DataLoader(ds_train, dl_test = DataLoader(ds_test, batch_size=batch_size, num_workers=num_workers) # - +from seq2seq_time.models.lstm_seq2seq import LSTMSeq2Seq +from seq2seq_time.models.lstm_seq import LSTMSeq +from seq2seq_time.models.lstm import LSTM +from seq2seq_time.models.baseline import BaselineLast +from seq2seq_time.models.transformer import Transformer +from seq2seq_time.models.transformer_seq2seq import TransformerSeq2Seq +from seq2seq_time.models.transformer_seq import TransformerSeq +from seq2seq_time.models.anp import RANP +# ## Plots +# + +models = [ + RANP(input_size, + output_size), + LSTM(input_size, + output_size, + hidden_size=80, + lstm_layers=3, + lstm_dropout=0.3), + + LSTMSeq2Seq(input_size, + output_size, + hidden_size=64, + lstm_layers=2, + lstm_dropout=0.25), + TransformerSeq2Seq(input_size, + output_size, + hidden_size=64, + nhead=8, + nlayers=4, + attention_dropout=0.3), + Transformer(input_size, + output_size, + attention_dropout=0.3, + nhead=8, + nlayers=6, + hidden_size=64), + TransformerSeq(input_size, + output_size), + LSTMSeq(input_size, + output_size), + +] +# - + # Baseline model pt_model = BaselineLast() model = PL_MODEL(pt_model).to(device) @@ -467,49 +532,6 @@ print(plot_hist(trainer)) ds_preds = predict(model.to(device), ds_test.datasets[0], batch_size, device=device, scaler=output_scaler) print(f'baseline nll: {ds_preds.nll.mean().item():2.2g}') - - -models = [ -# BaselineLast(), - LSTM(input_size, - output_size, - hidden_size=80, - lstm_layers=3, - lstm_dropout=0.3), - Transformer(input_size, - output_size, - attention_dropout=0.3, - nhead=8, - nlayers=6, - hidden_size=64), - LSTMSeq2Seq(input_size, - output_size, - hidden_size=64, - lstm_layers=2, - lstm_dropout=0.25), - TransformerSeq2Seq(input_size, - output_size, - hidden_size=64, - nhead=8, - nlayers=4, - attention_dropout=0.3), -# Transformer(input_size, -# output_size, -# attention_dropout=0.2, -# nhead=8, -# nlayers=6, -# hidden_size=128), -# LSTM(input_size, -# output_size, -# hidden_size=128, -# lstm_layers=3, -# lstm_dropout=0.3), -] - - - - - for pt_model in models: name = type(pt_model).__name__ print(name) @@ -518,36 +540,66 @@ for pt_model in models: patience = 2 model = PL_MODEL(pt_model, patience=patience, lr=3e-4).to(device) - # Trainer - + # Trainer trainer = pl.Trainer(gpus=1, - min_epochs=1, + min_epochs=2, max_epochs=10, amp_level='O1', precision=16, - gradient_clip_val=0.5, + gradient_clip_val=1, logger=CSVLogger("logs", name=type(pt_model).__name__), callbacks=[ EarlyStopping(monitor='loss/val', patience=patience*2), - PrintTableMetricsCallback() +# PrintTableMetricsCallback2() ], ) # Train trainer.fit(model, dl_train, dl_test) - # Performance - print(plot_hist(trainer)) + ds_preds = predict(model.to(device), ds_test.datasets[0], batch_size, device=device, scaler=output_scaler) + + print(name) + print(f'mean_NLL {ds_preds.nll.mean().item():2.2f}') + + # Performance + print(plot_hist(trainer)) plot_performance(ds_preds) +# %debug +ds_preds = predict(model.to(device),q + + ds_test.datasets[0], + batch_size, + device=device, + scaler=output_scaler) + +# + +# ds_predss = predict_multi(model.to(device), +# ds_test.datasets, +# batch_size, +# device=device, +# scaler=output_scaler) +# - + +ds_test.datasets[0].df.index.value_counts() + +# TODO why dup? +ds_preds.sel(t_source='2013-11-11 00:30:00') + +# TODO why duplicates? +d = ds_preds.isel(t_ahead=0) +d.t_source.to_series().sort_index()#.value_counts() +# np.unique +# d # # holoviews pred @@ -565,7 +617,7 @@ def plot_prediction_now(t_source): d = ds_preds.sel(t_source=t_source) - # Sometimes there are duplicate time, take the first + # Sometimes there are duplicate times, take the first if len(d.t_source.shape) and d.t_source.shape[0] > 0: d = d.isel(t_source=0) if len(d.t_source.shape) and d.t_source.shape[0] == 0: @@ -579,7 +631,7 @@ def plot_prediction_now(t_source): p = hv.Scatter({ 'x': x, 'y': yt - }, label='true').opts(color='black', framewise=True) + }, label='true').opts(color='black') # Get arrays xf = d.t_target.values @@ -594,7 +646,7 @@ def plot_prediction_now(t_source): label='2*std').opts(alpha=0.5, line_width=0) # plot now line - p *= hv.VLine(now, label='now').opts(color='red') + p *= hv.VLine(now, label='now').opts(color='red', framewise=True) return p.opts(title=f'Prediction at {now}. NLL={d.nll.mean().item():2.2f}') @@ -611,6 +663,7 @@ def plot_predictions_vs_time(it_ahead): """Plot predictions vs time with holoviews""" d = ds_preds.isel(t_ahead=it_ahead).groupby('t_source').first() + print(d) p = hv.Scatter({ 'x': d.t_source, @@ -639,19 +692,22 @@ dmap_preds = (hv.DynamicMap(plot_predictions_vs_time, kdims=['it_ahead']) height=300, )) dmap_preds -# plot_prediction2(10).opts(width=800) +# TODO fixme # - d = ds_preds.mean('t_source')['nll'].groupby('t_ahead_hours').mean() nll_vs_tahead = hv.Curve((d.t_ahead_hours, d)).redim(x='hours ahead', y='nll').opts(width=800) nll_vs_tahead -d = ds_preds.mean('t_ahead')['nll'].groupby('t_source').mean() -nll_vs_time = hv.Curve(d).opts(width=800) -nll_vs_time +# + +# d = ds_preds.mean('t_ahead')['nll'].groupby('t_source').mean() +# nll_vs_time = hv.Curve(d).opts(width=800) +# nll_vs_time -true_vs_pred = hv.Scatter((ds_preds.y_true, ds_preds.y_pred)) -dynspread(datashade(true_vs_pred)) +# + +# true_vs_pred = hv.Scatter((ds_preds.y_true, ds_preds.y_pred)) +# dynspread(datashade(true_vs_pred)) +# - # # Summarize experiments @@ -659,18 +715,18 @@ dynspread(datashade(true_vs_pred)) # + -# Run learning rate finder -lr_finder = trainer.tuner.lr_find(model) +# # Run learning rate finder +# lr_finder = trainer.tuner.lr_find(model) -# Results can be found in -lr_finder.results +# # Results can be found in +# lr_finder.results -# Plot with -fig = lr_finder.plot(suggest=True) -fig.show() +# # Plot with +# fig = lr_finder.plot(suggest=True) +# fig.show() -# Pick point based on plot, or get suggestion -new_lr = lr_finder.suggestion() +# # Pick point based on plot, or get suggestion +# new_lr = lr_finder.suggestion() # - diff --git a/seq2seq_time/models/anp.py b/seq2seq_time/models/anp.py new file mode 100644 index 0000000..526d7e4 --- /dev/null +++ b/seq2seq_time/models/anp.py @@ -0,0 +1,473 @@ +"""Recurrent Attentive Neural Process.""" + +import torch +from torch import nn +import torch.nn.functional as F +import math + + +class LSTMBlock(nn.Module): + def __init__( + self, + in_channels, + out_channels, + dropout=0, + batchnorm=False, + bias=False, + num_layers=1, + ): + super().__init__() + self._lstm = nn.LSTM( + input_size=in_channels, + hidden_size=out_channels, + num_layers=num_layers, + dropout=dropout, + batch_first=True, + bias=bias, + ) + + def forward(self, x): + return self._lstm(x)[0] + + +class NPBlockRelu2d(nn.Module): + """Block for Neural Processes.""" + + def __init__( + self, in_channels, out_channels, dropout=0, batchnorm=False, bias=False + ): + super().__init__() + self.linear = nn.Linear(in_channels, out_channels, bias=bias) + self.act = nn.ReLU() + self.dropout = nn.Dropout2d(dropout) + self.norm = nn.BatchNorm2d(out_channels) if batchnorm else False + + def forward(self, x): + # x.shape is (Batch, Sequence, Channels) + # We pass a linear over it which operates on the Channels + x = self.act(self.linear(x)) + + # Now we want to apply batchnorm and dropout to the channels. So we put it in shape + # (Batch, Channels, Sequence, None) so we can use Dropout2d & BatchNorm2d + x = x.permute(0, 2, 1)[:, :, :, None] + + if self.norm: + x = self.norm(x) + + x = self.dropout(x) + return x[:, :, :, 0].permute(0, 2, 1) + + +class BatchMLP(nn.Module): + """Apply MLP to the final axis of a 3D tensor (reusing already defined MLPs). + + Args: + input: input tensor of shape [B,n,d_in]. + output_sizes: An iterable containing the output sizes of the MLP as defined + in `basic.Linear`. + Returns: + tensor of shape [B,n,d_out] where d_out=output_size + """ + + def __init__( + self, input_size, output_size, num_layers=2, dropout=0, batchnorm=False + ): + super().__init__() + self.input_size = input_size + self.output_size = output_size + self.num_layers = num_layers + + self.initial = NPBlockRelu2d( + input_size, output_size, dropout=dropout, batchnorm=batchnorm + ) + self.encoder = nn.Sequential( + *[ + NPBlockRelu2d( + output_size, output_size, dropout=dropout, batchnorm=batchnorm + ) + for _ in range(num_layers - 2) + ] + ) + self.final = nn.Linear(output_size, output_size) + + def forward(self, x): + x = self.initial(x) + x = self.encoder(x) + return self.final(x) + + +class Attention(nn.Module): + def __init__( + self, + hidden_dim, + attention_type, + attention_layers=2, + n_heads=8, + x_dim=1, + rep="mlp", + dropout=0, + batchnorm=False, + ): + super().__init__() + self._rep = rep + + if self._rep == "mlp": + self.batch_mlp_k = BatchMLP( + x_dim, + hidden_dim, + attention_layers, + dropout=dropout, + batchnorm=batchnorm, + ) + self.batch_mlp_q = BatchMLP( + x_dim, + hidden_dim, + attention_layers, + dropout=dropout, + batchnorm=batchnorm, + ) + + self._W = torch.nn.MultiheadAttention( + hidden_dim, n_heads, bias=False, dropout=dropout + ) + self._attention_func = self._pytorch_multihead_attention + + def forward(self, k, v, q): + if self._rep == "mlp": + k = self.batch_mlp_k(k) + q = self.batch_mlp_q(q) + rep = self._attention_func(k, v, q) + return rep + + def _pytorch_multihead_attention(self, k, v, q): + # Pytorch multiheaded attention takes inputs if diff order and permutation + q = q.permute(1, 0, 2) + k = k.permute(1, 0, 2) + v = v.permute(1, 0, 2) + o = self._W(q, k, v)[0] + return o.permute(1, 0, 2) + + +class LatentEncoder(nn.Module): + def __init__( + self, + input_dim, + hidden_dim=32, + latent_dim=32, + self_attention_type="dot", + n_encoder_layers=3, + min_std=0.01, + batchnorm=False, + dropout=0, + attention_dropout=0, + use_self_attn=True, + attention_layers=2, + use_lstm=False, + ): + super().__init__() + # self._input_layer = nn.Linear(input_dim, hidden_dim) + if use_lstm: + self._encoder = LSTMBlock( + input_dim, + hidden_dim, + batchnorm=batchnorm, + dropout=dropout, + num_layers=n_encoder_layers, + ) + else: + self._encoder = BatchMLP( + input_dim, + hidden_dim, + batchnorm=batchnorm, + dropout=dropout, + num_layers=n_encoder_layers, + ) + if use_self_attn: + self._self_attention = Attention( + hidden_dim, + self_attention_type, + attention_layers, + rep="identity", + dropout=attention_dropout, + ) + self._penultimate_layer = nn.Linear(hidden_dim, hidden_dim) + self._mean = nn.Linear(hidden_dim, latent_dim) + self._log_var = nn.Linear(hidden_dim, latent_dim) + self._min_std = min_std + self._use_lstm = use_lstm + self._use_self_attn = use_self_attn + + def forward(self, x, y): + encoder_input = torch.cat([x, y], dim=-1) + + # Pass final axis through MLP + encoded = self._encoder(encoder_input) + + # Aggregator: take the mean over all points + if self._use_self_attn: + attention_output = self._self_attention(encoded, encoded, encoded) + mean_repr = attention_output.mean(dim=1) + else: + mean_repr = encoded.mean(dim=1) + + # Have further MLP layers that map to the parameters of the Gaussian latent + mean_repr = torch.relu(self._penultimate_layer(mean_repr)) + + # Then apply further linear layers to output latent mu and log sigma + mean = self._mean(mean_repr) + log_var = self._log_var(mean_repr) + + sigma = self._min_std + (1 - self._min_std) * torch.sigmoid(log_var * 0.5) + dist = torch.distributions.Normal(mean, sigma) + return dist, log_var + + +class DeterministicEncoder(nn.Module): + def __init__( + self, + input_dim, + x_dim, + hidden_dim=32, + n_d_encoder_layers=3, + self_attention_type="dot", + cross_attention_type="dot", + use_self_attn=True, + attention_layers=2, + batchnorm=False, + dropout=0, + attention_dropout=0, + use_lstm=False, + ): + super().__init__() + self._use_self_attn = use_self_attn + # self._input_layer = nn.Linear(input_dim, hidden_dim) + if use_lstm: + self._d_encoder = LSTMBlock( + input_dim, + hidden_dim, + batchnorm=batchnorm, + dropout=dropout, + num_layers=n_d_encoder_layers, + ) + else: + self._d_encoder = BatchMLP( + input_dim, + hidden_dim, + batchnorm=batchnorm, + dropout=dropout, + num_layers=n_d_encoder_layers, + ) + if use_self_attn: + self._self_attention = Attention( + hidden_dim, + self_attention_type, + attention_layers, + rep="identity", + dropout=attention_dropout, + ) + self._cross_attention = Attention( + hidden_dim, + cross_attention_type, + x_dim=x_dim, + attention_layers=attention_layers, + ) + + def forward(self, past_x, past_y, future_x): + # Concatenate x and y along the filter axes + d_encoder_input = torch.cat([past_x, past_y], dim=-1) + + # Pass final axis through MLP + d_encoded = self._d_encoder(d_encoder_input) + + if self._use_self_attn: + d_encoded = self._self_attention(d_encoded, d_encoded, d_encoded) + + # Apply attention as mean aggregation + h = self._cross_attention(past_x, d_encoded, future_x) + + return h + + +class Decoder(nn.Module): + def __init__( + self, + x_dim, + y_dim, + hidden_dim=32, + latent_dim=32, + n_decoder_layers=3, + use_deterministic_path=True, + min_std=0.01, + batchnorm=False, + dropout=0, + use_lstm=False, + ): + super(Decoder, self).__init__() + self._future_transform = nn.Linear(x_dim, hidden_dim) + if use_deterministic_path: + hidden_dim_2 = 2 * hidden_dim + latent_dim + else: + hidden_dim_2 = hidden_dim + latent_dim + + if use_lstm: + self._decoder = LSTMBlock( + hidden_dim_2, + hidden_dim_2, + batchnorm=batchnorm, + dropout=dropout, + num_layers=n_decoder_layers, + ) + else: + self._decoder = BatchMLP( + hidden_dim_2, + hidden_dim_2, + batchnorm=batchnorm, + dropout=dropout, + num_layers=n_decoder_layers, + ) + self._mean = nn.Linear(hidden_dim_2, y_dim) + self._std = nn.Linear(hidden_dim_2, y_dim) + self._use_deterministic_path = use_deterministic_path + self._min_std = min_std + + def forward(self, r, z, future_x): + # concatenate future_x and representation + x = self._future_transform(future_x) + + if self._use_deterministic_path: + z = torch.cat([r, z], dim=-1) + + r = torch.cat([z, x], dim=-1) + + r = self._decoder(r) + + # Get the mean and the variance + mean = self._mean(r) + log_sigma = self._std(r) + + # Bound or clamp the variance + sigma = self._min_std + (1 - self._min_std) * F.softplus(log_sigma) + + dist = torch.distributions.Normal(mean, sigma) + return dist, log_sigma + + +class RANP(nn.Module): + """Recurrent Attentive Neural Process for Sequential Data.""" + def __init__( + self, + x_dim, # features in input + y_dim, # number of features in output + hidden_dim=32, # size of hidden space + latent_dim=32, # size of latent space + n_latent_encoder_layers=2, + n_det_encoder_layers=2, # number of deterministic encoder layers + n_decoder_layers=2, + use_deterministic_path=True, + min_std=0.01, # To avoid collapse use a minimum standard deviation, should be much smaller than variation in labels + dropout=0, + use_self_attn=True, + attention_dropout=0, + batchnorm=False, + attention_layers=2, + use_rnn=True, # use RNN/LSTM + use_lstm_le=False, # use another LSTM in latent encoder instead of MLP + use_lstm_de=False, # use another LSTM in determinstic encoder instead of MLP + use_lstm_d=False, # use another lstm in decoder instead of MLP + **kwargs, + ): + + super().__init__() + + self._use_rnn = use_rnn + + if self._use_rnn: + self._lstm = nn.LSTM( + input_size=x_dim, + hidden_size=hidden_dim, + num_layers=attention_layers, + dropout=dropout, + batch_first=True, + ) + x_dim = hidden_dim + + self._latent_encoder = LatentEncoder( + x_dim + y_dim, + hidden_dim=hidden_dim, + latent_dim=latent_dim, + n_encoder_layers=n_latent_encoder_layers, + attention_layers=attention_layers, + dropout=dropout, + use_self_attn=use_self_attn, + attention_dropout=attention_dropout, + batchnorm=batchnorm, + min_std=min_std, + use_lstm=use_lstm_le, + ) + + self._deterministic_encoder = DeterministicEncoder( + input_dim=x_dim + y_dim, + x_dim=x_dim, + hidden_dim=hidden_dim, + n_d_encoder_layers=n_det_encoder_layers, + attention_layers=attention_layers, + use_self_attn=use_self_attn, + dropout=dropout, + batchnorm=batchnorm, + attention_dropout=attention_dropout, + use_lstm=use_lstm_de, + ) + + self._decoder = Decoder( + x_dim, + y_dim, + hidden_dim=hidden_dim, + latent_dim=latent_dim, + dropout=dropout, + batchnorm=batchnorm, + min_std=min_std, + n_decoder_layers=n_decoder_layers, + use_deterministic_path=use_deterministic_path, + use_lstm=use_lstm_d, + ) + self._use_deterministic_path = use_deterministic_path + + def forward(self, past_x, past_y, future_x, future_y=None): + + if self._use_rnn: + # see https://arxiv.org/abs/1910.09323 where x is substituted with h = RNN(x) + # x need to be provided as [B, T, H] + future_x, _ = self._lstm(future_x) + past_x, _ = self._lstm(past_x) + + dist_prior, log_var_prior = self._latent_encoder(past_x, past_y) + + if future_y is not None: + dist_post, log_var_post = self._latent_encoder(future_x, future_y) + z = dist_post.loc + else: + z = dist_prior.loc + + num_targets = future_x.size(1) + z = z.unsqueeze(1).repeat(1, num_targets, 1) # [B, T_target, H] + + if self._use_deterministic_path: + r = self._deterministic_encoder( + past_x, past_y, future_x + ) # [B, T_target, H] + else: + r = None + + dist, log_sigma = self._decoder(r, z, future_x) + loss = None + if future_y is not None: + log_p = dist.log_prob(future_y).mean(-1) + kl_loss = torch.distributions.kl_divergence(dist_post, dist_prior).mean( + -1 + ) # [B, R].mean(-1) + kl_loss = kl_loss[:, None].expand(log_p.shape) + mse_loss = F.mse_loss(dist.loc, future_y, reduction="none")[ + :, : past_x.size(1) + ].mean() + loss = (kl_loss - log_p).mean() + return dist, {'loss':loss} diff --git a/seq2seq_time/models/baseline.py b/seq2seq_time/models/baseline.py index 08e76d8..bbff483 100644 --- a/seq2seq_time/models/baseline.py +++ b/seq2seq_time/models/baseline.py @@ -12,4 +12,4 @@ class BaselineLast(nn.Module): B, S, F = future_x.shape mean = past_y[:, -1:].repeat(1, S, 1) std = (self.std * 1.0).repeat(1, S, 1) - return torch.distributions.Normal(mean, std) + return torch.distributions.Normal(mean, std), {} diff --git a/seq2seq_time/models/lstm.py b/seq2seq_time/models/lstm.py index f2e16a5..0b9002a 100644 --- a/seq2seq_time/models/lstm.py +++ b/seq2seq_time/models/lstm.py @@ -3,7 +3,7 @@ from torch import nn from torch.nn import functional as F class LSTM(nn.Module): - def __init__(self, input_size, output_size, hidden_size=32, lstm_layers=2, lstm_dropout=0, _min_std = 0.05, nan_value=0): + def __init__(self, input_size, output_size, hidden_size=64, lstm_layers=3, lstm_dropout=0, _min_std = 0.05, nan_value=0): super().__init__() self._min_std = _min_std self.nan_value = nan_value @@ -36,4 +36,4 @@ class LSTM(nn.Module): log_sigma = self.std(outputs) sigma = self._min_std + (1 - self._min_std) * F.softplus(log_sigma) y_dist = torch.distributions.Normal(mean, sigma) - return y_dist + return y_dist, {} diff --git a/seq2seq_time/models/lstm_seq.py b/seq2seq_time/models/lstm_seq.py new file mode 100644 index 0000000..85c1d72 --- /dev/null +++ b/seq2seq_time/models/lstm_seq.py @@ -0,0 +1,34 @@ +import torch +from torch import nn +from torch.nn import functional as F + +class LSTMSeq(nn.Module): + def __init__(self, input_size, output_size, hidden_size=32, lstm_layers=2, lstm_dropout=0, _min_std = 0.05, nan_value=0): + super().__init__() + self._min_std = _min_std + self.nan_value = nan_value + + self.lstm = nn.LSTM( + input_size=input_size + output_size, + hidden_size=hidden_size, + batch_first=True, + num_layers=lstm_layers, + dropout=lstm_dropout, + ) + self.mean = nn.Linear(hidden_size, output_size) + self.std = nn.Linear(hidden_size, output_size) + + def forward(self, past_x, past_y, future_x, future_y=None): + device = next(self.parameters()).device + x = torch.cat([past_x, past_y], -1).detach() + + steps = future_x.shape[1] + outputs, _ = self.lstm(x) + outputs = outputs[:, -steps:, :] + + # outputs: [B, T, num_direction * H] + mean = self.mean(outputs) + log_sigma = self.std(outputs) + sigma = self._min_std + (1 - self._min_std) * F.softplus(log_sigma) + y_dist = torch.distributions.Normal(mean, sigma) + return y_dist, {} diff --git a/seq2seq_time/models/predict_model.py b/seq2seq_time/models/predict_model.py deleted file mode 100644 index e69de29..0000000 diff --git a/seq2seq_time/models/train_model.py b/seq2seq_time/models/train_model.py deleted file mode 100644 index e69de29..0000000 diff --git a/seq2seq_time/models/transformer.py b/seq2seq_time/models/transformer.py index 51c8609..9aba7c0 100644 --- a/seq2seq_time/models/transformer.py +++ b/seq2seq_time/models/transformer.py @@ -55,5 +55,5 @@ class Transformer(nn.Module): log_sigma = self.std(outputs)[:, steps:, :] sigma = self._min_std + (1 - self._min_std) * F.softplus(log_sigma) - return torch.distributions.Normal(mean, sigma) + return torch.distributions.Normal(mean, sigma), {} diff --git a/seq2seq_time/models/transformer_seq.py b/seq2seq_time/models/transformer_seq.py new file mode 100644 index 0000000..613bbf2 --- /dev/null +++ b/seq2seq_time/models/transformer_seq.py @@ -0,0 +1,54 @@ +import torch +from torch import nn +from torch.nn import functional as F + + +class TransformerSeq(nn.Module): + """ + A single transformer, masking nan or 0 + """ + def __init__(self, x_dim, y_dim, attention_dropout=0, nhead=8, nlayers=2, hidden_size=16, nan_value=0, min_std=0.01): + super().__init__() + self._min_std = min_std + self.nan_value = nan_value + enc_x_dim = x_dim + y_dim + + self.enc_emb = nn.Linear(enc_x_dim, hidden_size) + encoder_norm = nn.LayerNorm(hidden_size) + layer_enc = nn.TransformerEncoderLayer( + d_model=hidden_size, + dim_feedforward=hidden_size*4, + dropout=attention_dropout, + nhead=nhead, + # activation + ) + self.encoder = nn.TransformerEncoder( + layer_enc, num_layers=nlayers, norm=encoder_norm + ) + self.mean = nn.Linear(hidden_size, y_dim) + self.std = nn.Linear(hidden_size, y_dim) + + def forward(self, past_x, past_y, future_x, future_y=None): + device = next(self.parameters()).device + x = torch.cat([past_x, past_y], -1).detach() + + # Masks + x_mask = torch.isfinite(x) & (x != self.nan_value) + x[~x_mask] = 0 + x = x.detach() + x_key_padding_mask = ~x_mask.any(-1) + + x = self.enc_emb(x).permute(1, 0, 2) + + outputs = self.encoder(x, src_key_padding_mask=x_key_padding_mask).permute( + 1, 0, 2 + ) + + # Seems to help a little, especially with extrapolating out of bounds + steps = future_x.shape[1] + mean = self.mean(outputs)[:, -steps:, :] + log_sigma = self.std(outputs)[:, -steps:, :] + + sigma = self._min_std + (1 - self._min_std) * F.softplus(log_sigma) + return torch.distributions.Normal(mean, sigma), {} + diff --git a/seq2seq_time/models/transformer_seq2seq.py b/seq2seq_time/models/transformer_seq2seq.py index 4a05ac1..717de50 100644 --- a/seq2seq_time/models/transformer_seq2seq.py +++ b/seq2seq_time/models/transformer_seq2seq.py @@ -76,5 +76,5 @@ class TransformerSeq2Seq(nn.Module): mean = self.mean(outputs) log_sigma = self.std(outputs) sigma = self._min_std + (1 - self._min_std) * F.softplus(log_sigma) - return torch.distributions.Normal(mean, sigma) + return torch.distributions.Normal(mean, sigma), {} diff --git a/seq2seq_time/predict.py b/seq2seq_time/predict.py index 8f0d2c9..dbe979e 100644 --- a/seq2seq_time/predict.py +++ b/seq2seq_time/predict.py @@ -19,11 +19,11 @@ def predict(model, ds_test, batch_size, device='cpu', scaler=None): load_test = torch.utils.data.dataloader.DataLoader(ds_test, batch_size=batch_size) freq = ds_test.df.index.freq xrs = [] - for i, batch in enumerate(tqdm(load_test, desc='predict')): + for i, batch in enumerate(tqdm(load_test, desc='predict', leave=False)): model.eval() with torch.no_grad(): x_past, y_past, x_future, y_future = [d.to(device) for d in batch] - y_dist = model(x_past, y_past, x_future, y_future) + y_dist, extra = model(x_past, y_past, x_future) nll = -y_dist.log_prob(y_future) # Convert to numpy @@ -70,3 +70,12 @@ def predict(model, ds_test, batch_size, device='cpu', scaler=None): # Some plots don't like timedeltas, so lets make a coordinate for time ahead in hours ds_preds = ds_preds.assign_coords(t_ahead_hours=(ds_preds.t_ahead*1.0e-9/60/60).astype(float)) return ds_preds + +def predict_multi(model, datasets, batch_size, device='cpu', scaler=None): + """Predict over multiple datasets.""" + ds_preds = [predict(model.to(device), + d, + batch_size, + device=device, + scaler=output_scaler) for d in tqdm(datasets)] + return xr.concat(ds_preds, dim='block')