2301 lines
316 KiB
Text
2301 lines
316 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Goal of this notebook: implement some basic RNN/LSTM/GRU to _forecast_ trajectories based on VIRAT and/or the custom _hof_ dataset.\n",
|
|
"\n",
|
|
"Somewhat based on [test_custom_rnn](test_custom_rnn.ipynb) for the network and [test_trajectron_maps](test_trajectron_maps.ipynb) for the dataloading. And many thanks to [seq2seq-time-series-forecasting-fully-recurrent](https://github.com/maxbrenner-ai/seq2seq-time-series-forecasting-fully-recurrent/blob/main/notebook.ipynb) by maxbrenner-ai.\n",
|
|
"\n",
|
|
"TODO: Look into [TimeSeriesTransformerForPrediction](https://huggingface.co/docs/transformers/main/model_doc/time_series_transformer#transformers.TimeSeriesTransformerForPrediction) from huggingface"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"from pathlib import Path\n",
|
|
"from trap.frame_emitter import Camera\n",
|
|
"from trap.utils import ImageMap\n",
|
|
"import cv2\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import numpy as np\n",
|
|
"import torch\n",
|
|
"import pandas as pd\n",
|
|
"import torch.nn as nn\n",
|
|
"\n",
|
|
"from torch import optim\n",
|
|
"import torch.nn.functional as F"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Configuration"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Track dataset options"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"path = Path(\"EXPERIMENTS/raw/hof3/\")\n",
|
|
"calibration_path = Path(\"../DATASETS/hof3/calibration.json\")\n",
|
|
"homography_path = Path(\"../DATASETS/hof3/homography.json\")\n",
|
|
"device = device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
|
|
"camera = Camera.from_paths(calibration_path, homography_path, 12)\n",
|
|
"\n",
|
|
"# when using a map encoder:\n",
|
|
"image_path = Path(\"../DATASETS/hof3/map-undistorted-H-2.png\")\n",
|
|
"assert image_path.exists()\n",
|
|
"\n",
|
|
"CACHE_DIR = Path(\"/tmp/cache-custom-rnn\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Network and training parameters"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"input_seq_length = 36\n",
|
|
"output_seq_length = 36\n",
|
|
"\n",
|
|
"lr = 0.00005\n",
|
|
"num_epochs = 100\n",
|
|
"batch_size = 512\n",
|
|
"hidden_size = 32\n",
|
|
"num_gru_layers = 1\n",
|
|
"grad_clip = 1.0\n",
|
|
"scheduled_sampling_decay = 10\n",
|
|
"dropout = 0.\n",
|
|
"\n",
|
|
"# As opposed to point-wise (assumes Gaussian)\n",
|
|
"probabilistic = True\n",
|
|
"\n",
|
|
"use_attention = True"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"('At epoch 0 teacher force prob will be 0.9090909090909091',\n",
|
|
" 'At epoch 100 teacher force prob will be 0.0005014951969411607')"
|
|
]
|
|
},
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# decay is used to determine \"forced teacher\" or 'freerunning' in recurrent learning\n",
|
|
"# inverse sigmoid decay from https://arxiv.org/pdf/1506.03099.pdf\n",
|
|
"import math\n",
|
|
"\n",
|
|
"\n",
|
|
"def inverse_sigmoid_decay(decay):\n",
|
|
" def compute(indx):\n",
|
|
" return decay / (decay + math.exp(indx / decay))\n",
|
|
" return compute\n",
|
|
"calc_teacher_force_prob = inverse_sigmoid_decay(scheduled_sampling_decay)\n",
|
|
"\n",
|
|
"f'At epoch 0 teacher force prob will be {calc_teacher_force_prob(0)}', \\\n",
|
|
"f'At epoch {num_epochs} teacher force prob will be {calc_teacher_force_prob(num_epochs-1)}'\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Map encoding as used in Trajectron++."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"(1440, 2560, 3)\n",
|
|
"(72, 128, 3)\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<matplotlib.image.AxesImage at 0x7f0b8c9f3520>"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"homography_matrix = np.array([\n",
|
|
" [5, 0,0],\n",
|
|
" [0, 5,0],\n",
|
|
" [0,0,1],\n",
|
|
" ]) # 100 scale\n",
|
|
"img = cv2.imread(image_path)\n",
|
|
"print(img.shape)\n",
|
|
"img = cv2.resize(img, (img.shape[1]//20, img.shape[0]//20))\n",
|
|
"\n",
|
|
"print(img.shape)\n",
|
|
"imgmap = ImageMap(img, homography_matrix, \"hof3-undistorted-H-2\")\n",
|
|
"# img = cv2.imread(image_path)\n",
|
|
"\n",
|
|
"plt.imshow(img)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from trap.tracker import TrackReader\n",
|
|
"\n",
|
|
"\n",
|
|
"reader = TrackReader(path, camera.fps, exclude_whitelisted = False, include_blacklisted=False)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from typing import List\n",
|
|
"from trap.frame_emitter import Track\n",
|
|
"from trap.tracker import FinalDisplacementFilter\n",
|
|
"\n",
|
|
"# \n",
|
|
"# make sure we have all points for all tracks\n",
|
|
"tracks: List[Track] = [t.get_with_interpolated_history() for t in reader]\n",
|
|
"# t = Smoother().smooth_track(t)\n",
|
|
"track_filter = FinalDisplacementFilter(2)\n",
|
|
"tracks = track_filter.apply(tracks, camera)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def flatten_multicolumn(df : pd.DataFrame):\n",
|
|
" \"Multicolumn index to a flattended index, e.g. velocity_x\"\n",
|
|
" df.columns = ['_'.join(col).strip() for col in df.columns.values]\n",
|
|
"\n",
|
|
"def preprocess_track(track: Track, camera: Camera) -> pd.DataFrame:\n",
|
|
" df = track.to_dataframe(camera)\n",
|
|
"\n",
|
|
" flatten_multicolumn(df)\n",
|
|
" \n",
|
|
" df['dx'] = df['velocity_x'] / track.fps\n",
|
|
" df['dy'] = df['velocity_y'] / track.fps\n",
|
|
" return df"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# track_dfs = [t.to_dataframe(camera) for t in tracks[:10]]\n",
|
|
"# def flatten_multicolumn(df : pd.DataFrame):\n",
|
|
"# \"Multicolumn index to a flattended index, e.g. velocity_x\"\n",
|
|
"# df.columns = ['_'.join(col).strip() for col in df.columns.values]\n",
|
|
"\n",
|
|
"# for df in track_dfs:\n",
|
|
"# flatten_multicolumn(df)\n",
|
|
" \n",
|
|
"# for df, track in zip(track_dfs, tracks):\n",
|
|
"# df['dx'] = df['velocity_x'] / track.fps\n",
|
|
"# df['dy'] = df['velocity_y'] / track.fps\n",
|
|
" "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# for track in tracks:\n",
|
|
"# history = track.get_projected_history(None, camera)\n",
|
|
"# points = imgmap.to_map_points(history)\n",
|
|
"# # print(history, points)\n",
|
|
"# break\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"target_indices = [0, 1]\n",
|
|
"in_fields = [ 'dx', 'dy', 'position_x', 'position_y', 'velocity_x', 'velocity_y', 'acceleration_x', 'acceleration_y'] #, 'dt'] (WARNING: dt column contains NaN)\n",
|
|
"# out_fields = ['v', 'heading']\n",
|
|
"# velocity cannot be negative, and heading is circular (modulo), this makes it harder to optimise than a linear space, so try to use components\n",
|
|
"# an we can use simple MSE loss (I guess?)\n",
|
|
"out_fields = ['dx', 'dy']\n",
|
|
"# SAMPLE_STEP = 5 # 1/5, for 12fps leads to effectively 12/5=2.4fps\n",
|
|
"# GRID_SIZE = 2 # round items on a grid of 2 points per meter (None to disable rounding)\n",
|
|
"# window = 8 #int(FPS*1.5 / SAMPLE_STEP)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"100"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Set device\n",
|
|
"# device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
|
|
"# print(device)\n",
|
|
"\n",
|
|
"# Hyperparameters\n",
|
|
"input_size = len(in_fields) #in_d\n",
|
|
"# hidden_size = 64 # hidden_d\n",
|
|
"# num_layers = 1 # num_hidden\n",
|
|
"output_size = len(out_fields) # out_d\n",
|
|
"# learning_rate = 0.005 #0.01 #0.005\n",
|
|
"# batch_size = 512\n",
|
|
"num_epochs\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"cache_path = Path(CACHE_DIR)\n",
|
|
"cache_path.mkdir(parents=True, exist_ok=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# from trap.tools import load_tracks_from_csv\n",
|
|
"from trap.tools import filter_short_tracks, normalise_position\n",
|
|
"\n",
|
|
"# data= load_tracks_from_csv(Path(SRC_CSV), FPS, GRID_SIZE, SAMPLE_STEP )"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# create x-norm, y_norm columns\n",
|
|
"# data, mu, std = normalise_position(data)\n",
|
|
"# data = filter_short_tracks(data, window+1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Create splits, 80% of the tracks to testing."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"1903 training tracks, 476 test tracks\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"np.random.shuffle(tracks)\n",
|
|
"test_offset_idx = int(len(tracks) * .8)\n",
|
|
"\n",
|
|
"training_tracks, test_tracks = tracks[:test_offset_idx], tracks[test_offset_idx:]\n",
|
|
"# print(len(training_tracks))\n",
|
|
"print(f\"{len(training_tracks)} training tracks, {len(test_tracks)} test tracks\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# # track_ids = data.index.unique('track_id').to_numpy()\n",
|
|
"# track_ids = reader.track_ids()\n",
|
|
"# np.random.shuffle(track_ids)\n",
|
|
"# test_offset_idx = int(len(track_ids) * .8)\n",
|
|
"# training_ids, test_ids = track_ids[:test_offset_idx], track_ids[test_offset_idx:]\n",
|
|
"# print(f\"{len(training_ids)} training tracks, {len(test_ids)} test tracks\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# import random\n",
|
|
"# def plot_track(track_id: int):\n",
|
|
"# ax = plt.scatter(\n",
|
|
"# data.loc[track_id,:]['x_norm'],\n",
|
|
"# data.loc[track_id,:]['y_norm'],\n",
|
|
"# marker=\"*\") \n",
|
|
"# plt.plot(\n",
|
|
"# data.loc[track_id,:]['x_norm'],\n",
|
|
"# data.loc[track_id,:]['y_norm']\n",
|
|
"# )\n",
|
|
"\n",
|
|
"# # print(filtered_data.loc[track_id,:]['proj_x'])\n",
|
|
"# # _track_id = 2188\n",
|
|
"# _track_id = random.choice(track_ids)\n",
|
|
"# print(_track_id)\n",
|
|
"# plot_track(_track_id)\n",
|
|
"\n",
|
|
"# for track_id in random.choices(track_ids, k=100):\n",
|
|
"# plot_track(track_id)\n",
|
|
" \n",
|
|
"# # print(mean_x, mean_y)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Now make the dataset:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# print(len(reader.get(\"24229\").history))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" 0%| | 0/1903 [00:00<?, ?it/s]"
|
|
]
|
|
},
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"100%|██████████| 1903/1903 [03:08<00:00, 10.09it/s]\n",
|
|
"100%|██████████| 476/476 [00:40<00:00, 11.71it/s]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from copy import deepcopy\n",
|
|
"from pandas import DataFrame\n",
|
|
"from tqdm import tqdm\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"def create_dataset(tracks: list[Track], input_seq_length: int, output_seq_length: int, in_fields: list[str], out_fields: list[str], camera: Camera, only_last=False, device='cpu') -> dict[str, torch.Tensor]:\n",
|
|
" encoder_X, decoder_X, decoder_y, = [], [], []\n",
|
|
" # factor = SAMPLE_STEP if SAMPLE_STEP is not None else 1\n",
|
|
" for track in tqdm(tracks):\n",
|
|
" # track = reader.get(track_id)\n",
|
|
" if len(track.history) < 2:\n",
|
|
" print(track.track_id, \"too short\")\n",
|
|
" df: DataFrame = preprocess_track(track, camera)\n",
|
|
" # df = data.loc[track_id]\n",
|
|
" # print(df)\n",
|
|
" # start_frame = min(df.index.tolist())\n",
|
|
" for timestep in range(df.shape[0] - (input_seq_length + output_seq_length) + 1):\n",
|
|
"\n",
|
|
" # enc_inputs: (input seq len, num features)\n",
|
|
" # print(df[timestep:timestep+input_seq_length][['velocity_x', 'velocity_y']])\n",
|
|
" enc_inputs_at_t = deepcopy(df[timestep : timestep + input_seq_length][in_fields])\n",
|
|
" dec_at_t = deepcopy(df[timestep + input_seq_length - 1 : timestep + input_seq_length + output_seq_length])\n",
|
|
" # dec_targets: (output seq len, num features)\n",
|
|
" dec_inputs_at_t = deepcopy(dec_at_t[:-1][in_fields])\n",
|
|
" # dec_targets: (output seq len, num targets)\n",
|
|
" dec_targets_at_t = deepcopy(dec_at_t[1:][out_fields])\n",
|
|
" \n",
|
|
" # # for step in range(len(df)-window-1):\n",
|
|
" # i = int(start_frame) + (step*factor)\n",
|
|
" # # print(step, int(start_frame), i)\n",
|
|
" # feature = df.loc[i:i+(window*factor)][in_fields]\n",
|
|
" # # target = df.loc[i+1:i+window+1][out_fields]\n",
|
|
" # # print(i, window*factor, factor, i+window*factor+factor, df['idx_in_track'])\n",
|
|
" # # print(i+window*factor+factor)\n",
|
|
" # if only_last:\n",
|
|
" # target = df.loc[i+window*factor+factor][out_fields]\n",
|
|
" # else:\n",
|
|
" # target = df.loc[i+factor:i+window*factor+factor][out_fields]\n",
|
|
"\n",
|
|
" encoder_X.append(enc_inputs_at_t.values)\n",
|
|
" decoder_X.append(dec_inputs_at_t.values)\n",
|
|
" decoder_y.append(dec_targets_at_t.values)\n",
|
|
" \n",
|
|
" return {'enc_inputs': torch.tensor(np.array(encoder_X), device=device, dtype=torch.float), \n",
|
|
" 'dec_inputs': torch.tensor(np.array(decoder_X), device=device, dtype=torch.float), \n",
|
|
" 'dec_outputs': torch.tensor(np.array(decoder_y), device=device, dtype=torch.float)}\n",
|
|
"\n",
|
|
"train_data = create_dataset(training_tracks, input_seq_length, output_seq_length, in_fields, out_fields, camera, False, device)\n",
|
|
"test_data = create_dataset(test_tracks, input_seq_length, output_seq_length, in_fields, out_fields, camera, False, device)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# X_train, y_train = X_train.to(device=device), y_train.to(device=device)\n",
|
|
"# X_test, y_test = X_test.to(device=device), y_test.to(device=device)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# from torch.utils.data import TensorDataset, DataLoader\n",
|
|
"# dataset_train = TensorDataset(X_train, y_train)\n",
|
|
"# loader_train = DataLoader(dataset_train, shuffle=True, batch_size=batch_size)\n",
|
|
"# dataset_test = TensorDataset(X_test, y_test)\n",
|
|
"# loader_test = DataLoader(dataset_test, shuffle=False, batch_size=batch_size)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Model give output for all timesteps, this should improve training. But we use only the last timestep for the prediction process"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Seq2seq encoder/decoder with attention"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Encoder(nn.Module):\n",
|
|
" def __init__(self, input_size, hidden_size, num_gru_layers, dropout_p=0.1):\n",
|
|
" super().__init__()\n",
|
|
" self.hidden_size = hidden_size\n",
|
|
"\n",
|
|
" # self.embedding = nn.Embedding(input_size, hidden_size)\n",
|
|
" self.gru = nn.GRU(input_size, hidden_size, num_gru_layers, batch_first=True)\n",
|
|
" # self.dropout = nn.Dropout(dropout_p) # TODO)) How to bring this back, see \n",
|
|
"\n",
|
|
" def forward(self, inputs):\n",
|
|
" # inputs: (batch size, input seq len, num enc features)\n",
|
|
" # embedded = self.dropout(self.embedding(input))\n",
|
|
"\n",
|
|
" # output: (batch size, input seq len, hidden size)\n",
|
|
" # hidden: (num gru layers, batch size, hidden size)\n",
|
|
" output, hidden = self.gru(inputs)\n",
|
|
" return output, hidden\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Decoder superclass whose forward is called by Seq2Seq but other methods filled out by subclasses\n",
|
|
"import random\n",
|
|
"\n",
|
|
"\n",
|
|
"class DecoderBase(nn.Module):\n",
|
|
" def __init__(self, device, dec_target_size, target_indices, dist_size, probabilistic):\n",
|
|
" super().__init__()\n",
|
|
" self.device = device\n",
|
|
" self.target_indices = target_indices # indices of desired output in the training input vector, used for force teaching\n",
|
|
" self.target_size = dec_target_size\n",
|
|
" self.dist_size = dist_size\n",
|
|
" self.probabilistic = probabilistic\n",
|
|
" \n",
|
|
" # Have to run one step at a time unlike with the encoder since sometimes not teacher forcing\n",
|
|
" def run_single_recurrent_step(self, inputs, hidden, enc_outputs):\n",
|
|
" raise NotImplementedError()\n",
|
|
" \n",
|
|
" def forward(self, inputs, hidden, enc_outputs, teacher_force_prob=None):\n",
|
|
" # inputs: (batch size, output seq length, num dec features)\n",
|
|
" # hidden: (num gru layers, batch size, hidden dim), ie the last hidden state\n",
|
|
" # enc_outputs: (batch size, input seq len, hidden size)\n",
|
|
" \n",
|
|
" batch_size, dec_output_seq_length, _ = inputs.shape\n",
|
|
" \n",
|
|
" # Store decoder outputs\n",
|
|
" # outputs: (batch size, output seq len, num targets, num dist params)\n",
|
|
" outputs = torch.zeros(batch_size, dec_output_seq_length, self.target_size, self.dist_size, dtype=torch.float).to(self.device)\n",
|
|
"\n",
|
|
" # curr_input: (batch size, 1, num dec features)\n",
|
|
" curr_input = inputs[:, 0:1, :]\n",
|
|
" \n",
|
|
" for t in range(dec_output_seq_length):\n",
|
|
" # dec_output: (batch size, 1, num targets, num dist params)\n",
|
|
" # hidden: (num gru layers, batch size, hidden size)\n",
|
|
" dec_output, hidden = self.run_single_recurrent_step(curr_input, hidden, enc_outputs)\n",
|
|
" # Save prediction\n",
|
|
" outputs[:, t:t+1, :, :] = dec_output\n",
|
|
" # dec_output: (batch size, 1, num targets)\n",
|
|
" dec_output = Seq2Seq.sample_from_output(dec_output)\n",
|
|
" \n",
|
|
" # If teacher forcing, use target from this timestep as next input o.w. use prediction\n",
|
|
" teacher_force: bool = random.random() < teacher_force_prob if teacher_force_prob is not None else False\n",
|
|
" \n",
|
|
" curr_input = inputs[:, t:t+1, :].clone()\n",
|
|
" if not teacher_force:\n",
|
|
" curr_input[:, :, self.target_indices] = dec_output\n",
|
|
" return outputs"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def layer_init(layer, w_scale=1.0):\n",
|
|
" nn.init.kaiming_uniform_(layer.weight.data)\n",
|
|
" layer.weight.data.mul_(w_scale)\n",
|
|
" nn.init.constant_(layer.bias.data, 0.)\n",
|
|
" return layer"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 28,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"class DecoderVanilla(DecoderBase):\n",
|
|
" def __init__(self, dec_feature_size, dec_target_size, hidden_size, \n",
|
|
" num_gru_layers, target_indices, dropout, dist_size,\n",
|
|
" probabilistic, device):\n",
|
|
" super().__init__(device, dec_target_size, target_indices, dist_size, probabilistic)\n",
|
|
" self.gru = nn.GRU(dec_feature_size, hidden_size, num_gru_layers, batch_first=True, dropout=dropout)\n",
|
|
" self.out = layer_init(nn.Linear(hidden_size + dec_feature_size, dec_target_size * dist_size))\n",
|
|
" \n",
|
|
" def run_single_recurrent_step(self, inputs, hidden, enc_outputs):\n",
|
|
" # inputs: (batch size, 1, num dec features)\n",
|
|
" # hidden: (num gru layers, batch size, hidden size)\n",
|
|
" \n",
|
|
" output, hidden = self.gru(inputs, hidden)\n",
|
|
" output = self.out(torch.cat((output, inputs), dim=2))\n",
|
|
" output = output.reshape(output.shape[0], output.shape[1], self.target_size, self.dist_size)\n",
|
|
" \n",
|
|
" # output: (batch size, 1, num targets, num dist params)\n",
|
|
" # hidden: (num gru layers, batch size, hidden size)\n",
|
|
" return output, hidden\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Attention(nn.Module):\n",
|
|
" def __init__(self, hidden_size, num_gru_layers):\n",
|
|
" super().__init__()\n",
|
|
" # NOTE: the hidden size for the output of attn (and input of v) can actually be any number \n",
|
|
" # Also, using two layers allows for a non-linear act func inbetween\n",
|
|
" self.attn = nn.Linear(2 * hidden_size, hidden_size)\n",
|
|
" self.v = nn.Linear(hidden_size, 1, bias=False)\n",
|
|
" \n",
|
|
" def forward(self, decoder_hidden_final_layer, encoder_outputs):\n",
|
|
" # decoder_hidden_final_layer: (batch size, hidden size)\n",
|
|
" # encoder_outputs: (batch size, input seq len, hidden size)\n",
|
|
" \n",
|
|
" # Repeat decoder hidden state input seq len times\n",
|
|
" hidden = decoder_hidden_final_layer.unsqueeze(1).repeat(1, encoder_outputs.shape[1], 1)\n",
|
|
" \n",
|
|
" # Compare decoder hidden state with each encoder output using a learnable tanh layer\n",
|
|
" energy = torch.tanh(self.attn(torch.cat((hidden, encoder_outputs), dim=2)))\n",
|
|
" \n",
|
|
" # Then compress into single values for each comparison (energy)\n",
|
|
" attention = self.v(energy).squeeze(2)\n",
|
|
" \n",
|
|
" # Then softmax so the weightings add up to 1\n",
|
|
" weightings = F.softmax(attention, dim=1)\n",
|
|
" \n",
|
|
" # weightings: (batch size, input seq len)\n",
|
|
" return weightings"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class DecoderWithAttention(DecoderBase):\n",
|
|
" def __init__(self, dec_feature_size, dec_target_size, hidden_size, \n",
|
|
" num_gru_layers, target_indices, dropout, dist_size,\n",
|
|
" probabilistic, device):\n",
|
|
" super().__init__(device, dec_target_size, target_indices, dist_size, probabilistic)\n",
|
|
" self.attention_model = Attention(hidden_size, num_gru_layers)\n",
|
|
" # GRU takes previous timestep target and weighted sum of encoder hidden states\n",
|
|
" self.gru = nn.GRU(dec_feature_size + hidden_size, hidden_size, num_gru_layers, batch_first=True, dropout=dropout)\n",
|
|
" # Output layer takes decoder hidden state output, weighted sum and decoder input\n",
|
|
" # NOTE: Feeding decoder input into the output layer essentially acts as a skip connection\n",
|
|
" self.out = layer_init(nn.Linear(hidden_size + hidden_size + dec_feature_size, dec_target_size * dist_size))\n",
|
|
"\n",
|
|
" def run_single_recurrent_step(self, inputs, hidden, enc_outputs):\n",
|
|
" # inputs: (batch size, 1, num dec features)\n",
|
|
" # hidden: (num gru layers, batch size, hidden size)\n",
|
|
" # enc_outputs: (batch size, input seq len, hidden size)\n",
|
|
" \n",
|
|
" # Get attention weightings\n",
|
|
" # weightings: (batch size, input seq len)\n",
|
|
" weightings = self.attention_model(hidden[-1], enc_outputs)\n",
|
|
" \n",
|
|
" # Then compute weighted sum\n",
|
|
" # weighted_sum: (batch size, 1, hidden size)\n",
|
|
" weighted_sum = torch.bmm(weightings.unsqueeze(1), enc_outputs)\n",
|
|
" \n",
|
|
" # Then input into GRU\n",
|
|
" # gru inputs: (batch size, 1, num dec features + hidden size)\n",
|
|
" # output: (batch size, 1, hidden size)\n",
|
|
" output, hidden = self.gru(torch.cat((inputs, weighted_sum), dim=2), hidden)\n",
|
|
" \n",
|
|
" # Get prediction\n",
|
|
" # out input: (batch size, 1, hidden size + hidden size + num targets)\n",
|
|
" output = self.out(torch.cat((output, weighted_sum, inputs), dim=2))\n",
|
|
" output = output.reshape(output.shape[0], output.shape[1], self.target_size, self.dist_size)\n",
|
|
" \n",
|
|
" # output: (batch size, 1, num targets, num dist params)\n",
|
|
" # hidden: (num gru layers, batch size, hidden size)\n",
|
|
" return output, hidden\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Seq2Seq(nn.Module):\n",
|
|
" def __init__(self, encoder: Encoder, decoder: DecoderBase, lr, grad_clip, probabilistic):\n",
|
|
" super().__init__()\n",
|
|
" self.encoder = encoder\n",
|
|
" self.decoder = decoder\n",
|
|
"\n",
|
|
" self.opt = torch.optim.Adam(self.parameters(), lr)\n",
|
|
" self.loss_func = nn.GaussianNLLLoss() if probabilistic else nn.L1Loss()\n",
|
|
" self.grad_clip = grad_clip\n",
|
|
"\n",
|
|
" self.probabilistic = probabilistic\n",
|
|
" \n",
|
|
" @staticmethod\n",
|
|
" def compute_smape(prediction, target):\n",
|
|
" return torch.mean(torch.abs(prediction - target) / ((torch.abs(target) + torch.abs(prediction)) / 2. + 1e-8)) * 100.\n",
|
|
" \n",
|
|
" @staticmethod\n",
|
|
" def get_dist_params(output):\n",
|
|
" mu = output[:, :, :, 0]\n",
|
|
" # softplus to constrain to positive\n",
|
|
" sigma = F.softplus(output[:, :, :, 1])\n",
|
|
" return mu, sigma\n",
|
|
" \n",
|
|
" @staticmethod\n",
|
|
" def sample_from_output(output):\n",
|
|
" # in - output: (batch size, dec seq len, num targets, num dist params)\n",
|
|
" # out - output: (batch size, dec seq len, num targets)\n",
|
|
" if output.shape[-1] > 1: # probabilistic can be assumed\n",
|
|
" mu, sigma = Seq2Seq.get_dist_params(output)\n",
|
|
" # sigma = torch.tensor([0,0], device='cuda')\n",
|
|
" return torch.normal(mu, sigma)\n",
|
|
" # No sample just reshape if pointwise\n",
|
|
" return output.squeeze(-1)\n",
|
|
" \n",
|
|
" def forward(self, enc_inputs, dec_inputs, teacher_force_prob=None):\n",
|
|
" # enc_inputs: (batch size, input seq length, num enc features)\n",
|
|
" # dec_inputs: (batch size, output seq length, num dec features)\n",
|
|
" \n",
|
|
" # enc_outputs: (batch size, input seq len, hidden size)\n",
|
|
" # hidden: (num gru layers, batch size, hidden dim), ie the last hidden state\n",
|
|
" enc_outputs, hidden = self.encoder(enc_inputs)\n",
|
|
" \n",
|
|
" # outputs: (batch size, output seq len, num targets, num dist params)\n",
|
|
" outputs = self.decoder(dec_inputs, hidden, enc_outputs, teacher_force_prob)\n",
|
|
" \n",
|
|
" return outputs\n",
|
|
"\n",
|
|
" def compute_loss(self, prediction, target, override_func=None):\n",
|
|
" # prediction: (batch size, dec seq len, num targets, num dist params)\n",
|
|
" # target: (batch size, dec seq len, num targets)\n",
|
|
" if self.probabilistic:\n",
|
|
" mu, sigma = Seq2Seq.get_dist_params(prediction)\n",
|
|
" var = sigma ** 2\n",
|
|
" loss = self.loss_func(mu, target, var)\n",
|
|
" else:\n",
|
|
" loss = self.loss_func(prediction.squeeze(-1), target)\n",
|
|
" return loss if self.training else loss.item()\n",
|
|
" \n",
|
|
" def optimize(self, prediction, target):\n",
|
|
" # prediction & target: (batch size, seq len, output dim)\n",
|
|
" self.opt.zero_grad()\n",
|
|
" loss = self.compute_loss(prediction, target)\n",
|
|
" loss.backward()\n",
|
|
" if self.grad_clip is not None:\n",
|
|
" torch.nn.utils.clip_grad_norm_(self.parameters(), self.grad_clip)\n",
|
|
" self.opt.step()\n",
|
|
" return loss.item()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## run training"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 32,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# New generator every epoch\n",
|
|
"def batch_generator(data, batch_size):\n",
|
|
" enc_inputs, dec_inputs, dec_targets, scalers = \\\n",
|
|
" data['enc_inputs'], data['dec_inputs'], data['dec_outputs'], None #, data['scalers']\n",
|
|
" indices = torch.randperm(enc_inputs.shape[0])\n",
|
|
" for i in range(0, len(indices), batch_size):\n",
|
|
" batch_indices = indices[i : i + batch_size]\n",
|
|
" batch_enc_inputs = enc_inputs[batch_indices]\n",
|
|
" batch_dec_inputs = dec_inputs[batch_indices]\n",
|
|
" batch_dec_targets = dec_targets[batch_indices]\n",
|
|
" batch_scalers = None\n",
|
|
" \n",
|
|
" # No remainder\n",
|
|
" if batch_enc_inputs.shape[0] < batch_size:\n",
|
|
" break\n",
|
|
" yield batch_enc_inputs, batch_dec_inputs, batch_dec_targets, batch_scalers"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 33,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def train(model, train_data, batch_size, teacher_force_prob):\n",
|
|
" model.train()\n",
|
|
" \n",
|
|
" epoch_loss = 0.\n",
|
|
" num_batches = 0\n",
|
|
" \n",
|
|
" for batch_enc_inputs, batch_dec_inputs, batch_dec_targets, _ in batch_generator(train_data, batch_size):\n",
|
|
" output = model(batch_enc_inputs, batch_dec_inputs, teacher_force_prob)\n",
|
|
" loss = model.optimize(output, batch_dec_targets)\n",
|
|
" \n",
|
|
" epoch_loss += loss\n",
|
|
" num_batches += 1\n",
|
|
" return epoch_loss / num_batches"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 34,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def evaluate(model, val_data, batch_size):\n",
|
|
" model.eval()\n",
|
|
" \n",
|
|
" epoch_loss = 0.\n",
|
|
" num_batches = 0\n",
|
|
" \n",
|
|
" with torch.no_grad():\n",
|
|
" for batch_enc_inputs, batch_dec_inputs, batch_dec_targets, _ in batch_generator(val_data, batch_size):\n",
|
|
" output = model(batch_enc_inputs, batch_dec_inputs)\n",
|
|
" loss = model.compute_loss(output, batch_dec_targets)\n",
|
|
"\n",
|
|
" epoch_loss += loss\n",
|
|
" num_batches += 1\n",
|
|
" \n",
|
|
" return epoch_loss / num_batches\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 35,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"dist_size = 2 if probabilistic else 1\n",
|
|
"enc_feature_size = train_data['enc_inputs'].shape[-1]\n",
|
|
"dec_feature_size = train_data['dec_inputs'].shape[-1]\n",
|
|
"dec_target_size = train_data['dec_outputs'].shape[-1]\n",
|
|
"\n",
|
|
"encoder = Encoder(enc_feature_size, hidden_size, num_gru_layers, dropout)\n",
|
|
"decoder_args = (dec_feature_size, dec_target_size, hidden_size, num_gru_layers, target_indices, dropout, dist_size, probabilistic, device)\n",
|
|
"decoder = DecoderWithAttention(*decoder_args) if use_attention else DecoderVanilla(*decoder_args)\n",
|
|
"seq2seq = Seq2Seq(encoder, decoder, lr, grad_clip, probabilistic).to(device)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 39,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def load_cache(model: Seq2Seq, epoch=None, path=None):\n",
|
|
" if path is None:\n",
|
|
" if epoch is None:\n",
|
|
" raise RuntimeError(\"Either path or epoch must be given\")\n",
|
|
" path = cache_path / f\"checkpoint-{model.__class__.__name__}_{epoch:05d}.pt\"\n",
|
|
" else:\n",
|
|
" print (path.stem)\n",
|
|
" epoch = int(path.stem[-5:])\n",
|
|
"\n",
|
|
" cached = torch.load(path)\n",
|
|
" \n",
|
|
" # optimizer.load_state_dict(cached['optimizer_state_dict'])\n",
|
|
" model.load_state_dict(cached['model_state_dict'])\n",
|
|
" return epoch, cached['train_loss']\n",
|
|
" \n",
|
|
"\n",
|
|
"def cache(model: Seq2Seq, epoch, loss):\n",
|
|
" path = cache_path / f\"checkpoint-{model.__class__.__name__}_{epoch:05d}.pt\"\n",
|
|
" print(f\"Cache to {path}\")\n",
|
|
" torch.save({\n",
|
|
" 'epoch': epoch,\n",
|
|
" 'model_state_dict': model.state_dict(),\n",
|
|
" 'train_loss': loss,\n",
|
|
" }, path)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"load /tmp/cache-custom-rnn/checkpoint-Seq2Seq_00100.pt\n",
|
|
"checkpoint-Seq2Seq_00100\n",
|
|
"Loaded epoch=100 with train_loss=-3.9480560053240117\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import time\n",
|
|
"\n",
|
|
"CACHE_FILE = Path(\"/tmp/cache-custom-rnn/checkpoint-Seq2Seq_00100.pt\")\n",
|
|
"if CACHE_FILE.exists():\n",
|
|
" print(f\"load {CACHE_FILE}\")\n",
|
|
" best_model = deepcopy(seq2seq)\n",
|
|
" epoch, train_loss = load_cache(best_model, path=CACHE_FILE)\n",
|
|
" print(f\"Loaded {epoch=} with {train_loss=}\")\n",
|
|
"else:\n",
|
|
"\n",
|
|
" val_data = test_data\n",
|
|
"\n",
|
|
" best_val, best_model = float('inf'), None\n",
|
|
" for epoch in range(num_epochs):\n",
|
|
" start_t = time.time()\n",
|
|
" teacher_force_prob = calc_teacher_force_prob(epoch)\n",
|
|
" train_loss = train(seq2seq, train_data, batch_size, teacher_force_prob)\n",
|
|
" val_loss = evaluate(seq2seq, val_data, batch_size)\n",
|
|
"\n",
|
|
" new_best_val = False\n",
|
|
" if val_loss < best_val:\n",
|
|
" new_best_val = True\n",
|
|
" best_val = val_loss\n",
|
|
" best_model = deepcopy(seq2seq)\n",
|
|
" print(f'Epoch {epoch+1} => Train loss: {train_loss:.5f},',\n",
|
|
" f'Val: {val_loss:.5f},',\n",
|
|
" f'Teach: {teacher_force_prob:.2f},',\n",
|
|
" f'Took {(time.time() - start_t):.1f} s{\" (NEW BEST)\" if new_best_val else \"\"}')\n",
|
|
" \n",
|
|
" \n",
|
|
" cache(best_model, 100, train_loss)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 49,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"\n",
|
|
"data_to_eval = test_data\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"/home/ruben/suspicion/trap/.venv/lib/python3.10/site-packages/torch/nn/modules/rnn.py:950: UserWarning: RNN module weights are not part of single contiguous chunk of memory. This means they need to be compacted at every call, possibly greatly increasing memory usage. To compact weights again call flatten_parameters(). (Triggered internally at ../aten/src/ATen/native/cudnn/RNN.cpp:968.)\n",
|
|
" result = _VF.gru(input, hx, self._flat_weights, self.bias, self.num_layers,\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"torch.Size([1, 50, 36, 2])\n",
|
|
"[36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71]\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 1000x500 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Visualize\n",
|
|
"target_to_vis = 0\n",
|
|
"num_vis = 1\n",
|
|
"num_rollouts = 50 if probabilistic else 1\n",
|
|
"\n",
|
|
"best_model.eval()\n",
|
|
"\n",
|
|
"with torch.no_grad():\n",
|
|
" \n",
|
|
" batch_enc_inputs, batch_dec_inputs, batch_dec_targets, scalers = next(batch_generator(data_to_eval, num_vis))\n",
|
|
" \n",
|
|
" outputs = []\n",
|
|
" for r in range(num_rollouts):\n",
|
|
" mo = best_model(batch_enc_inputs, batch_dec_inputs)\n",
|
|
" output = Seq2Seq.sample_from_output(mo)\n",
|
|
" outputs.append(output)\n",
|
|
" outputs = torch.stack(outputs, dim=1)\n",
|
|
" print(outputs.shape)\n",
|
|
"\n",
|
|
"for indx in range(batch_enc_inputs.shape[0]):\n",
|
|
" # scaler = scalers[indx]\n",
|
|
" sample_enc_inputs, sample_dec_inputs, sample_dec_targets = \\\n",
|
|
" (batch_enc_inputs[indx])[:, target_to_vis].cpu().numpy().tolist(),\\\n",
|
|
" (batch_dec_inputs[indx])[:, target_to_vis].cpu().numpy().tolist(), \\\n",
|
|
" (batch_dec_targets[indx])[:, target_to_vis].cpu().numpy().tolist()\n",
|
|
" output_rollouts = []\n",
|
|
" for output_rollout in outputs[indx]:\n",
|
|
" output_rollouts.append((output_rollout)[:, target_to_vis].cpu().numpy().tolist())\n",
|
|
" output_rollouts = np.array(output_rollouts)\n",
|
|
"\n",
|
|
" plt.figure(figsize=(10,5))\n",
|
|
" x = list(range(len(sample_enc_inputs) + len(sample_dec_targets)))\n",
|
|
" # Plot inputs\n",
|
|
" plt.plot(x, sample_enc_inputs + sample_dec_targets)\n",
|
|
" # Plot median\n",
|
|
" output_x = list(range(len(sample_enc_inputs), len(x)))\n",
|
|
" print(output_x)\n",
|
|
" plt.plot(output_x, np.median(output_rollouts, axis=0))\n",
|
|
" # Plot quantiles\n",
|
|
" plt.fill_between(\n",
|
|
" output_x,\n",
|
|
" np.quantile(output_rollouts, 0.05, axis=0), \n",
|
|
" np.quantile(output_rollouts, 0.95, axis=0), \n",
|
|
" alpha=0.3, \n",
|
|
" interpolate=True\n",
|
|
" )\n",
|
|
" plt.gca().set_axis_off()\n",
|
|
" plt.show()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## RNN"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class SimpleRnn(nn.Module):\n",
|
|
" def __init__(self, in_d=2, out_d=2, hidden_d=4, num_hidden=1):\n",
|
|
" super(SimpleRnn, self).__init__()\n",
|
|
" self.rnn = nn.RNN(input_size=in_d, hidden_size=hidden_d, num_layers=num_hidden)\n",
|
|
" self.fc = nn.Linear(hidden_d, out_d)\n",
|
|
"\n",
|
|
" def forward(self, x, h0):\n",
|
|
" r, h = self.rnn(x, h0)\n",
|
|
" # r = r[:, -1,:]\n",
|
|
" y = self.fc(r) # no activation on the output\n",
|
|
" return y, h\n",
|
|
"rnn = SimpleRnn(input_size, output_size, hidden_size, num_layers).to(device)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## LSTM"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"For optional LSTM-GAN, see https://discuss.pytorch.org/t/how-to-use-lstm-to-construct-gan/12419\n",
|
|
"\n",
|
|
"Or VAE (variational Auto encoder):\n",
|
|
"\n",
|
|
"> The only constraint on the latent vector representation for traditional autoencoders is that latent vectors should be easily decodable back into the original image. As a result, the latent space $Z$ can become disjoint and non-continuous. Variational autoencoders try to solve this problem. [Alexander van de Kleut](https://avandekleut.github.io/vae/)\n",
|
|
"\n",
|
|
"For LSTM based generative VAE: https://github.com/Khamies/LSTM-Variational-AutoEncoder/blob/main/model.py\n",
|
|
"\n",
|
|
"http://web.archive.org/web/20210119121802/https://towardsdatascience.com/time-series-generation-with-vae-lstm-5a6426365a1c?gi=29d8b029a386\n",
|
|
"\n",
|
|
"https://youtu.be/qJeaCHQ1k2w?si=30aAdqqwvz0DpR-x&t=687 VAE generate mu and sigma of a Normal distribution. Thus, they don't map the input to a single point, but a gausian distribution."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 328,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class LSTMModel(nn.Module):\n",
|
|
" # input_size : number of features in input at each time step\n",
|
|
" # hidden_size : Number of LSTM units \n",
|
|
" # num_layers : number of LSTM layers \n",
|
|
" def __init__(self, input_size, hidden_size, num_layers): \n",
|
|
" super(LSTMModel, self).__init__() #initializes the parent class nn.Module\n",
|
|
" # We _could_ train the h0: https://discuss.pytorch.org/t/learn-initial-hidden-state-h0-for-rnn/10013 \n",
|
|
" # self.lin1 = nn.Linear(input_size, hidden_size)\n",
|
|
" self.num_layers = num_layers\n",
|
|
" self.hidden_size = hidden_size\n",
|
|
" self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)\n",
|
|
" self.linear = nn.Linear(hidden_size, output_size)\n",
|
|
" # self.activation_v = nn.LeakyReLU(.01)\n",
|
|
" # self.activation_heading = torch.remainder()\n",
|
|
"\n",
|
|
" \n",
|
|
" def get_hidden_state(self, batch_size, device):\n",
|
|
" h = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)\n",
|
|
" c = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)\n",
|
|
" return (h, c)\n",
|
|
"\n",
|
|
" def forward(self, x, hidden_state): # defines forward pass of the neural network\n",
|
|
" # out = self.lin1(x)\n",
|
|
" \n",
|
|
" out, hidden_state = self.lstm(x, hidden_state)\n",
|
|
" # extract only the last time step, see https://machinelearningmastery.com/lstm-for-time-series-prediction-in-pytorch/\n",
|
|
" # print(out.shape)\n",
|
|
" # TODO)) Might want to remove this below: as it might improve training\n",
|
|
" # out = out[:, -1,:]\n",
|
|
" # print(out.shape)\n",
|
|
" out = self.linear(out)\n",
|
|
" \n",
|
|
" # torch.remainder(out[1], 360)\n",
|
|
" # print('o',out.shape)\n",
|
|
" return out, hidden_state\n",
|
|
"\n",
|
|
"lstm = LSTMModel(input_size, hidden_size, num_layers).to(device)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 329,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# model = rnn\n",
|
|
"model = lstm\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 330,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n",
|
|
"loss_fn = nn.MSELoss()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 331,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def evaluate():\n",
|
|
" # toggle evaluation mode\n",
|
|
" model.eval()\n",
|
|
" with torch.no_grad():\n",
|
|
" batch_size, seq_len, feature_dim = X_train.shape\n",
|
|
" y_pred, _ = model(\n",
|
|
" X_train.to(device=device),\n",
|
|
" model.get_hidden_state(batch_size, device)\n",
|
|
" )\n",
|
|
" train_rmse = torch.sqrt(loss_fn(y_pred, y_train))\n",
|
|
" # print(y_pred)\n",
|
|
"\n",
|
|
" batch_size, seq_len, feature_dim = X_test.shape\n",
|
|
" y_pred, _ = model(\n",
|
|
" X_test.to(device=device),\n",
|
|
" model.get_hidden_state(batch_size, device)\n",
|
|
" )\n",
|
|
" # print(loss_fn(y_pred, y_test))\n",
|
|
" test_rmse = torch.sqrt(loss_fn(y_pred, y_test))\n",
|
|
" print(\"Epoch ??: train RMSE %.4f, test RMSE %.4f\" % ( train_rmse, test_rmse))\n",
|
|
"\n",
|
|
"def load_most_recent():\n",
|
|
" paths = list(cache_path.glob(f\"checkpoint-{model._get_name()}_*.pt\"))\n",
|
|
" if len(paths) < 1:\n",
|
|
" print('Nothing found to load')\n",
|
|
" return None, None\n",
|
|
" paths.sort()\n",
|
|
"\n",
|
|
" print(f\"Loading {paths[-1]}\")\n",
|
|
" return load_cache(path=paths[-1])\n",
|
|
"\n",
|
|
"def load_cache(epoch=None, path=None):\n",
|
|
" if path is None:\n",
|
|
" if epoch is None:\n",
|
|
" raise RuntimeError(\"Either path or epoch must be given\")\n",
|
|
" path = cache_path / f\"checkpoint-{model._get_name()}_{epoch:05d}.pt\"\n",
|
|
" else:\n",
|
|
" print (path.stem)\n",
|
|
" epoch = int(path.stem[-5:])\n",
|
|
"\n",
|
|
" cached = torch.load(path)\n",
|
|
" \n",
|
|
" optimizer.load_state_dict(cached['optimizer_state_dict'])\n",
|
|
" model.load_state_dict(cached['model_state_dict'])\n",
|
|
" return epoch, cached['loss']\n",
|
|
" \n",
|
|
"\n",
|
|
"def cache(epoch, loss):\n",
|
|
" path = cache_path / f\"checkpoint-{model._get_name()}_{epoch:05d}.pt\"\n",
|
|
" print(f\"Cache to {path}\")\n",
|
|
" torch.save({\n",
|
|
" 'epoch': epoch,\n",
|
|
" 'model_state_dict': model.state_dict(),\n",
|
|
" 'optimizer_state_dict': optimizer.state_dict(),\n",
|
|
" 'loss': loss,\n",
|
|
" }, path)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"TODO)) See [this notebook](https://www.cs.toronto.edu/~lczhang/aps360_20191/lec/w08/rnn.html) For initialization (with random or not) and the use of GRU"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 332,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Loading EXPERIMENTS/cache/hof2/checkpoint-LSTMModel_01000.pt\n",
|
|
"checkpoint-LSTMModel_01000\n",
|
|
"starting from epoch 1000 (loss: 0.014368701726198196)\n",
|
|
"Epoch ??: train RMSE 0.0849, test RMSE 0.0866\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"0it [00:00, ?it/s]"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch ??: train RMSE 0.0849, test RMSE 0.0866\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"start_epoch, loss = load_most_recent()\n",
|
|
"if start_epoch is None:\n",
|
|
" start_epoch = 0\n",
|
|
"else:\n",
|
|
" print(f\"starting from epoch {start_epoch} (loss: {loss})\")\n",
|
|
" evaluate()\n",
|
|
"\n",
|
|
"loss_log = []\n",
|
|
"# Train Network\n",
|
|
"for epoch in tqdm(range(start_epoch+1,num_epochs+1)):\n",
|
|
" # toggle train mode\n",
|
|
" model.train()\n",
|
|
" for batch_idx, (x, targets) in enumerate(loader_train):\n",
|
|
" # Get x to cuda if possible\n",
|
|
" x = x.to(device=device).squeeze(1)\n",
|
|
" targets = targets.to(device=device)\n",
|
|
"\n",
|
|
" # forward\n",
|
|
" scores, _ = model(\n",
|
|
" x,\n",
|
|
" torch.zeros(num_layers, x.shape[2], hidden_size, dtype=torch.float).to(device=device),\n",
|
|
" torch.zeros(num_layers, x.shape[2], hidden_size, dtype=torch.float).to(device=device)\n",
|
|
" )\n",
|
|
" # print(scores)\n",
|
|
" loss = loss_fn(scores, targets)\n",
|
|
"\n",
|
|
" # backward\n",
|
|
" optimizer.zero_grad()\n",
|
|
" loss.backward()\n",
|
|
"\n",
|
|
" # gradient descent update step/adam step\n",
|
|
" optimizer.step()\n",
|
|
"\n",
|
|
" loss_log.append(loss.item())\n",
|
|
"\n",
|
|
" if epoch % 5 != 0:\n",
|
|
" continue\n",
|
|
"\n",
|
|
" cache(epoch, loss)\n",
|
|
" evaluate()\n",
|
|
"\n",
|
|
"evaluate()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 333,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# print(loss)\n",
|
|
"# print(len(loss_log))\n",
|
|
"# plt.plot(loss_log)\n",
|
|
"# plt.ylabel('Loss')\n",
|
|
"# plt.xlabel('iteration')\n",
|
|
"# plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 335,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"torch.Size([49999, 9, 2]) torch.Size([49999, 9, 2])\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"model.eval()\n",
|
|
"\n",
|
|
"with torch.no_grad():\n",
|
|
" y_pred, _ = model(X_train.to(device=device),\n",
|
|
" model.get_hidden_state(X_train.shape[0], device))\n",
|
|
" \n",
|
|
" print(y_pred.shape, y_train.shape)\n",
|
|
"# y_train, y_pred"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 336,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import scipy\n",
|
|
"\n",
|
|
"def ceil_away_from_0(a):\n",
|
|
" return np.sign(a) * np.ceil(np.abs(a))\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 343,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def predict_and_plot(model, feature, steps = 50):\n",
|
|
" lenght = feature.shape[0]\n",
|
|
"\n",
|
|
" dt = (1/ FPS) * SAMPLE_STEP\n",
|
|
"\n",
|
|
" trajectory = feature\n",
|
|
"\n",
|
|
" # feature = filtered_data.loc[_track_id,:].iloc[:5][in_fields].values\n",
|
|
" # nxt = filtered_data.loc[_track_id,:].iloc[5][out_fields]\n",
|
|
" with torch.no_grad():\n",
|
|
" # h = torch.zeros(num_layers, window+1, hidden_size, dtype=torch.float).to(device=device)\n",
|
|
" # c = torch.zeros(num_layers, window+1, hidden_size, dtype=torch.float).to(device=device)\n",
|
|
" h = torch.zeros(num_layers, 1, hidden_size, dtype=torch.float).to(device=device)\n",
|
|
" c = torch.zeros(num_layers, 1, hidden_size, dtype=torch.float).to(device=device)\n",
|
|
" hidden_state = (h, c)\n",
|
|
" # X = torch.tensor([feature], dtype=torch.float).to(device)\n",
|
|
" # y, (h, c) = model(X, h, c)\n",
|
|
" for i in range(steps):\n",
|
|
" # predict_f = scipy.ndimage.uniform_filter(feature)\n",
|
|
" # predict_f = scipy.interpolate.splrep(feature[:][0], feature[:][1],)\n",
|
|
" # predict_f = scipy.signal.spline_feature(feature, lmbda=.1)\n",
|
|
" # bathc size of one, so feature as single item in array\n",
|
|
" # print(X.shape)\n",
|
|
" X = torch.tensor([feature], dtype=torch.float).to(device)\n",
|
|
" # print(type(model))\n",
|
|
" y, hidden_state, *_ = model(X, hidden_state)\n",
|
|
" # print(hidden_state.shape)\n",
|
|
"\n",
|
|
" s = y[-1][-1].cpu()\n",
|
|
"\n",
|
|
" # proj_x proj_y v heading a d_heading\n",
|
|
" # next_step = feature\n",
|
|
"\n",
|
|
" dx, dy = s\n",
|
|
" \n",
|
|
" dx = (dx * GRID_SIZE).round() / GRID_SIZE\n",
|
|
" dy = (dy * GRID_SIZE).round() / GRID_SIZE\n",
|
|
" vx, vy = dx / dt, dy / dt\n",
|
|
"\n",
|
|
" v = np.sqrt(s[0]**2 + s[1]**2)\n",
|
|
" heading = (np.arctan2(s[1], s[0]) * 180 / np.pi) % 360\n",
|
|
" # a = (v - feature[-1][2]) / dt\n",
|
|
" ax = (vx - feature[-1][2]) / dt\n",
|
|
" ay = (vx - feature[-1][3]) / dt\n",
|
|
" # d_heading = (heading - feature[-1][5])\n",
|
|
" # print(s)\n",
|
|
" # ['x', 'y', 'vx', 'vy', 'ax', 'ay'] \n",
|
|
" x = feature[-1][0] + dx\n",
|
|
" y = feature[-1][1] + dy\n",
|
|
" if GRID_SIZE is not None:\n",
|
|
" # put points back on grid\n",
|
|
" x = (x*GRID_SIZE).round() / GRID_SIZE\n",
|
|
" y = (y*GRID_SIZE).round() / GRID_SIZE\n",
|
|
"\n",
|
|
" feature = [[x, y, vx, vy, ax, ay]]\n",
|
|
" \n",
|
|
" trajectory = np.append(trajectory, feature, axis=0)\n",
|
|
" # f = [feature[-1][0] + s[0]*dt, feature[-1][1] + s[1]*dt, v, heading, a, d_heading ]\n",
|
|
" # feature = np.append(feature, [feature], axis=0)\n",
|
|
" \n",
|
|
" # print(next_step, nxt)\n",
|
|
" # print(trajectory)\n",
|
|
" plt.plot(trajectory[:lenght,0], trajectory[:lenght,1], c='orange')\n",
|
|
" plt.plot(trajectory[lenght-1:,0], trajectory[lenght-1:,1], c='red')\n",
|
|
" plt.scatter(trajectory[lenght:,0], trajectory[lenght:,1], c='red', marker='x')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"1301\n",
|
|
"(10, 6) (10, 6)\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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LYQQuOaaa3D//ffjd7/7HZYuXTrlY/i+j02bNmH+/PkNOMPGKRaLeOONN8Y971a9p/u788470d3djYsuumhK+7XqfV26dCl6e3vr7l0+n8czzzwz7r07mPf8bBEGHlu2bMEjjzyCzs7OKR/jQO+F2eqtt97C4ODguOfdyvc1dPvtt2P58uU45ZRTprzvbLmvB/qcWb58OQzDqLtPmzdvxvbt28e9TwfzPj+YE2+6e+65R1iWJdasWSP+9Kc/ic9//vMinU6L3bt3CyGE+PSnPy2+/vWvy+2feOIJoeu6+Nd//Vfx6quvihtuuEEYhiE2bdo0E6c/aV/60pdEKpUS69atE7t27ZJf5XJZbrP/td54443i4YcfFm+88YbYsGGD+MQnPiEikYh45ZVXZuISJu2rX/2qWLdundi6dat44oknxKpVq0RXV5fYs2ePEGLu3NORfN8XixcvFtdff/2o77XyfS0UCuL5558Xzz//vAAgvvvd74rnn39ezvC4+eabRTqdFg888IB46aWXxCWXXCKWLl0qKpWKPMY555wjvv/978vHB3rPz5SJrtVxHHHxxReLhQsXihdeeKHuPWzbtjzG/td6oPfCTJnoWguFgvja174mnnrqKbF161bxyCOPiNNOO0284x3vENVqVR5jLtzXUC6XE7FYTNxyyy1jHqNV7utkPme++MUvisWLF4vf/e534o9//KNYuXKlWLlyZd1xjj32WPGLX/xCPp7M+/xQzEjwIYQQ3//+98XixYuFaZrijDPOEE8//bT83vve9z5xxRVX1G1/7733imOOOUaYpilOOOEE8eCDDzb5jKcOwJhfd955p9xm/2u97rrr5L9LT0+P+OAHPyg2btzY/JOfoo9//ONi/vz5wjRNsWDBAvHxj39cvP766/L7c+WejvTwww8LAGLz5s2jvtfK9/Wxxx4b8+c2vJ4gCMQ3v/lN0dPTIyzLEueee+6of4MlS5aIG264oe65id7zM2Wia926deu47+HHHntMHmP/az3Qe2GmTHSt5XJZnHfeeWLevHnCMAyxZMkS8bnPfW5UEDEX7mvo1ltvFdFoVGSz2TGP0Sr3dTKfM5VKRXz5y18W7e3tIhaLiQ9/+MNi165do44zcp/JvM8PhTL8okRERERNwbVdiIiIqKkYfBAREVFTMfggIiKipmLwQURERE3F4IOIiIiaisEHERERNRWDDyIiImoqBh9ERETUVAw+iIiIqKkYfBAREVFTMfggIiKipmLwQURERE31/wFwRYUJ3YTkmwAAAABJRU5ErkJggg==",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"# print(filtered_data.loc[track_id,:]['proj_x'])\n",
|
|
"_track_id = 8701 # random.choice(track_ids)\n",
|
|
"_track_id = 3880 # random.choice(track_ids)\n",
|
|
"\n",
|
|
"# _track_id = 2780\n",
|
|
"\n",
|
|
"for batch_idx in range(100):\n",
|
|
" _track_id = random.choice(track_ids)\n",
|
|
" plt.plot(\n",
|
|
" data.loc[_track_id,:]['x'],\n",
|
|
" data.loc[_track_id,:]['y'],\n",
|
|
" c='grey', alpha=.2\n",
|
|
" )\n",
|
|
"\n",
|
|
"_track_id = random.choice(track_ids)\n",
|
|
"# _track_id = 1096\n",
|
|
"_track_id = 1301\n",
|
|
"print(_track_id)\n",
|
|
"ax = plt.scatter(\n",
|
|
" data.loc[_track_id,:]['x'],\n",
|
|
" data.loc[_track_id,:]['y'],\n",
|
|
" marker=\"*\") \n",
|
|
"plt.plot(\n",
|
|
" data.loc[_track_id,:]['x'],\n",
|
|
" data.loc[_track_id,:]['y']\n",
|
|
")\n",
|
|
"\n",
|
|
"X = data.loc[_track_id,:].iloc[:][in_fields].values\n",
|
|
"# Adding randomness might be a cheat to get multiple features from current position\n",
|
|
"rnd = np.random.random_sample(X.shape) / 10\n",
|
|
"# print(rnd)\n",
|
|
"\n",
|
|
"print(X[:10].shape, (X[:10] + rnd[:10]).shape)\n",
|
|
"\n",
|
|
"# predict_and_plot(data.loc[_track_id,:].iloc[:5][in_fields].values)\n",
|
|
"# predict_and_plot(model, data.loc[_track_id,:].iloc[:5][in_fields].values, 50)\n",
|
|
"# predict_and_plot(model, data.loc[_track_id,:].iloc[:10][in_fields].values, 50)\n",
|
|
"# predict_and_plot(model, data.loc[_track_id,:].iloc[:20][in_fields].values)\n",
|
|
"# predict_and_plot(model, data.loc[_track_id,:].iloc[:30][in_fields].values)\n",
|
|
"predict_and_plot(model, X[:12])\n",
|
|
"predict_and_plot(model, X[:12] + rnd[:12])\n",
|
|
"predict_and_plot(model, data.loc[_track_id,:].iloc[:][in_fields].values)\n",
|
|
"# predict_and_plot(filtered_data.loc[_track_id,:].iloc[:70][in_fields].values)\n",
|
|
"# predict_and_plot(filtered_data.loc[_track_id,:].iloc[:115][in_fields].values)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## VAE"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# From https://github.com/CUN-bjy/lstm-vae-torch/blob/main/src/models.py (MIT)\n",
|
|
"\n",
|
|
"from typing import Optional\n",
|
|
"\n",
|
|
"\n",
|
|
"class Encoder(nn.Module):\n",
|
|
" def __init__(self, input_size=4096, hidden_size=1024, num_layers=2):\n",
|
|
" super(Encoder, self).__init__()\n",
|
|
" self.hidden_size = hidden_size\n",
|
|
" self.num_layers = num_layers\n",
|
|
" self.lstm = nn.LSTM(\n",
|
|
" input_size,\n",
|
|
" hidden_size,\n",
|
|
" num_layers,\n",
|
|
" batch_first=True,\n",
|
|
" bidirectional=False,\n",
|
|
" )\n",
|
|
"\n",
|
|
" def get_hidden_state(self, batch_size, device):\n",
|
|
" h = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)\n",
|
|
" c = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)\n",
|
|
" return (h, c)\n",
|
|
"\n",
|
|
" def forward(self, x, hidden_state):\n",
|
|
" # x: tensor of shape (batch_size, seq_length, hidden_size)\n",
|
|
" outputs, (hidden, cell) = self.lstm(x, hidden_state)\n",
|
|
" return outputs, (hidden, cell)\n",
|
|
"\n",
|
|
"\n",
|
|
"class Decoder(nn.Module):\n",
|
|
" def __init__(\n",
|
|
" self, input_size=4096, hidden_size=1024, output_size=4096, num_layers=2\n",
|
|
" ):\n",
|
|
" super(Decoder, self).__init__()\n",
|
|
" self.hidden_size = hidden_size\n",
|
|
" self.output_size = output_size\n",
|
|
" self.num_layers = num_layers\n",
|
|
" self.lstm = nn.LSTM(\n",
|
|
" input_size,\n",
|
|
" hidden_size,\n",
|
|
" num_layers,\n",
|
|
" batch_first=True,\n",
|
|
" bidirectional=False,\n",
|
|
" )\n",
|
|
" self.fc = nn.Linear(hidden_size, output_size)\n",
|
|
" \n",
|
|
" def get_hidden_state(self, batch_size, device):\n",
|
|
" h = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)\n",
|
|
" c = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)\n",
|
|
" return (h, c)\n",
|
|
"\n",
|
|
" def forward(self, x, hidden):\n",
|
|
" # x: tensor of shape (batch_size, seq_length, hidden_size)\n",
|
|
" output, (hidden, cell) = self.lstm(x, hidden)\n",
|
|
" prediction = self.fc(output)\n",
|
|
" return prediction, (hidden, cell)\n",
|
|
"\n",
|
|
"\n",
|
|
"class LSTMVAE(nn.Module):\n",
|
|
" \"\"\"LSTM-based Variational Auto Encoder\"\"\"\n",
|
|
"\n",
|
|
" def __init__(\n",
|
|
" self, input_size, output_size, hidden_size, latent_size, device=torch.device(\"cuda\")\n",
|
|
" ):\n",
|
|
" \"\"\"\n",
|
|
" input_size: int, batch_size x sequence_length x input_dim\n",
|
|
" hidden_size: int, output size of LSTM AE\n",
|
|
" latent_size: int, latent z-layer size\n",
|
|
" num_lstm_layer: int, number of layers in LSTM\n",
|
|
" \"\"\"\n",
|
|
" super(LSTMVAE, self).__init__()\n",
|
|
" self.device = device\n",
|
|
"\n",
|
|
" # dimensions\n",
|
|
" self.input_size = input_size\n",
|
|
" self.hidden_size = hidden_size\n",
|
|
" self.latent_size = latent_size\n",
|
|
" self.num_layers = 1\n",
|
|
"\n",
|
|
" # lstm ae\n",
|
|
" self.lstm_enc = Encoder(\n",
|
|
" input_size=input_size, hidden_size=hidden_size, num_layers=self.num_layers\n",
|
|
" )\n",
|
|
" self.lstm_dec = Decoder(\n",
|
|
" input_size=latent_size,\n",
|
|
" output_size=output_size,\n",
|
|
" hidden_size=hidden_size,\n",
|
|
" num_layers=self.num_layers,\n",
|
|
" )\n",
|
|
"\n",
|
|
" self.fc21 = nn.Linear(self.hidden_size, self.latent_size)\n",
|
|
" self.fc22 = nn.Linear(self.hidden_size, self.latent_size)\n",
|
|
" self.fc3 = nn.Linear(self.latent_size, self.hidden_size)\n",
|
|
"\n",
|
|
" def reparametize(self, mu, logvar):\n",
|
|
" std = torch.exp(0.5 * logvar)\n",
|
|
" noise = torch.randn_like(std).to(self.device)\n",
|
|
"\n",
|
|
" z = mu + noise * std\n",
|
|
" return z\n",
|
|
"\n",
|
|
" def forward(self, x, hidden_state_encoder: Optional[tuple]=None):\n",
|
|
" batch_size, seq_len, feature_dim = x.shape\n",
|
|
"\n",
|
|
" if hidden_state_encoder is None:\n",
|
|
" hidden_state_encoder = self.lstm_enc.get_hidden_state(batch_size, self.device)\n",
|
|
"\n",
|
|
" # encode input space to hidden space\n",
|
|
" prediction, hidden_state = self.lstm_enc(x, hidden_state_encoder)\n",
|
|
" enc_h = hidden_state[0].view(batch_size, self.hidden_size).to(self.device)\n",
|
|
"\n",
|
|
" # extract latent variable z(hidden space to latent space)\n",
|
|
" mean = self.fc21(enc_h)\n",
|
|
" logvar = self.fc22(enc_h)\n",
|
|
" z = self.reparametize(mean, logvar) # batch_size x latent_size\n",
|
|
"\n",
|
|
" # initialize hidden state as inputs\n",
|
|
" h_ = self.fc3(z)\n",
|
|
" \n",
|
|
" # decode latent space to input space\n",
|
|
" z = z.repeat(1, seq_len, 1)\n",
|
|
" z = z.view(batch_size, seq_len, self.latent_size).to(self.device)\n",
|
|
"\n",
|
|
" # initialize hidden state\n",
|
|
" hidden = (h_.contiguous(), h_.contiguous())\n",
|
|
" # TODO)) the above is not the right dimensions, but this changes architecture\n",
|
|
" hidden = self.lstm_dec.get_hidden_state(batch_size, self.device)\n",
|
|
" reconstruct_output, hidden = self.lstm_dec(z, hidden)\n",
|
|
"\n",
|
|
" x_hat = reconstruct_output\n",
|
|
" \n",
|
|
" return x_hat, hidden_state, mean, logvar\n",
|
|
"\n",
|
|
" def loss_function(self, *args, **kwargs) -> dict:\n",
|
|
" \"\"\"\n",
|
|
" Computes the VAE loss function.\n",
|
|
" KL(N(\\mu, \\sigma), N(0, 1)) = \\log \\frac{1}{\\sigma} + \\frac{\\sigma^2 + \\mu^2}{2} - \\frac{1}{2}\n",
|
|
" :param args:\n",
|
|
" :param kwargs:\n",
|
|
" :return:\n",
|
|
" \"\"\"\n",
|
|
" predicted = args[0]\n",
|
|
" target = args[1]\n",
|
|
" mu = args[2]\n",
|
|
" log_var = args[3]\n",
|
|
"\n",
|
|
" kld_weight = 0.00025 # Account for the minibatch samples from the dataset\n",
|
|
" recons_loss = torch.nn.functional.mse_loss(predicted, target=target)\n",
|
|
"\n",
|
|
" kld_loss = torch.mean(\n",
|
|
" -0.5 * torch.sum(1 + log_var - mu**2 - log_var.exp(), dim=1), dim=0\n",
|
|
" )\n",
|
|
"\n",
|
|
" loss = recons_loss + kld_weight * kld_loss\n",
|
|
" return {\n",
|
|
" \"loss\": loss,\n",
|
|
" \"Reconstruction_Loss\": recons_loss.detach(),\n",
|
|
" \"KLD\": -kld_loss.detach(),\n",
|
|
" }\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 303,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"vae = LSTMVAE(input_size, output_size, hidden_size, 1024, device=device)\n",
|
|
"vae.to(device)\n",
|
|
"vae_optimizer = torch.optim.Adam(vae.parameters(), lr=learning_rate)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 304,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def train_vae(model, train_loader, test_loader, max_iter, learning_rate):\n",
|
|
" # optimizer\n",
|
|
" optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n",
|
|
"\n",
|
|
" ## interation setup\n",
|
|
" epochs = tqdm(range(max_iter // len(train_loader) + 1))\n",
|
|
" epochs = tqdm(range(max_iter))\n",
|
|
"\n",
|
|
" ## training\n",
|
|
" count = 0\n",
|
|
" for epoch in epochs:\n",
|
|
" model.train()\n",
|
|
" optimizer.zero_grad()\n",
|
|
" train_iterator = tqdm(\n",
|
|
" enumerate(train_loader), total=len(train_loader), desc=\"training\"\n",
|
|
" )\n",
|
|
"\n",
|
|
" # if count > max_iter:\n",
|
|
" # print(\"max!\")\n",
|
|
" # return model\n",
|
|
"\n",
|
|
" for batch_idx, (x, targets) in train_iterator:\n",
|
|
" count += 1\n",
|
|
"\n",
|
|
" # future_data, past_data = batch_data\n",
|
|
"\n",
|
|
" ## reshape\n",
|
|
" batch_size = x.size(0)\n",
|
|
" example_size = x.size(1)\n",
|
|
" # image_size = past_data.size(2), past_data.size(3)\n",
|
|
" # past_data = (\n",
|
|
" # past_data.view(batch_size, example_size, -1).float().to(args.device) # flattens image, we don't need this\n",
|
|
" # )\n",
|
|
" # future_data = future_data.view(batch_size, example_size, -1).float().to(args.device)\n",
|
|
"\n",
|
|
" y, hidden_state, mean, logvar = model(x)\n",
|
|
"\n",
|
|
" # calculate vae loss\n",
|
|
" # print(y.shape, targets.shape)\n",
|
|
" losses = model.loss_function(y, targets, mean, logvar)\n",
|
|
" mloss, recon_loss, kld_loss = (\n",
|
|
" losses[\"loss\"],\n",
|
|
" losses[\"Reconstruction_Loss\"],\n",
|
|
" losses[\"KLD\"],\n",
|
|
" )\n",
|
|
"\n",
|
|
" # Backward and optimize\n",
|
|
" optimizer.zero_grad()\n",
|
|
" mloss.mean().backward()\n",
|
|
" optimizer.step()\n",
|
|
"\n",
|
|
" train_iterator.set_postfix({\"train_loss\": float(mloss.mean())})\n",
|
|
" print(\"train_loss\", float(mloss.mean()), epoch)\n",
|
|
"\n",
|
|
" model.eval()\n",
|
|
" eval_loss = 0\n",
|
|
" test_iterator = tqdm(\n",
|
|
" enumerate(test_loader), total=len(test_loader), desc=\"testing\"\n",
|
|
" )\n",
|
|
"\n",
|
|
" with torch.no_grad():\n",
|
|
" for batch_idx, (x, targets) in test_iterator:\n",
|
|
" # future_data, past_data = batch_data\n",
|
|
"\n",
|
|
" ## reshape\n",
|
|
" batch_size = x.size(0)\n",
|
|
" example_size = x.size(1)\n",
|
|
" # past_data = (\n",
|
|
" # past_data.view(batch_size, example_size, -1).float().to(args.device)\n",
|
|
" # )\n",
|
|
" # future_data = future_data.view(batch_size, example_size, -1).float().to(args.device)\n",
|
|
"\n",
|
|
" y, hidden_state, mean, logvar = model(x)\n",
|
|
"\n",
|
|
" # calculate vae loss\n",
|
|
" losses = model.loss_function(y, targets, mean, logvar)\n",
|
|
" mloss, recon_loss, kld_loss = (\n",
|
|
" losses[\"loss\"],\n",
|
|
" losses[\"Reconstruction_Loss\"],\n",
|
|
" losses[\"KLD\"],\n",
|
|
" )\n",
|
|
"\n",
|
|
" eval_loss += mloss.mean().item()\n",
|
|
"\n",
|
|
" test_iterator.set_postfix({\"eval_loss\": float(mloss.mean())})\n",
|
|
"\n",
|
|
" # if batch_idx == 0:\n",
|
|
" # nhw_orig = past_data[0].view(example_size, image_size[0], -1)\n",
|
|
" # nhw_recon = recon_x[0].view(example_size, image_size[0], -1)\n",
|
|
" # imshow(nhw_orig.cpu(), f\"orig{epoch}\")\n",
|
|
" # imshow(nhw_recon.cpu(), f\"recon{epoch}\")\n",
|
|
" # writer.add_images(f\"original{i}\", nchw_orig, epoch)\n",
|
|
" # writer.add_images(f\"reconstructed{i}\", nchw_recon, epoch)\n",
|
|
"\n",
|
|
" eval_loss = eval_loss / len(test_loader)\n",
|
|
" # writer.add_scalar(\"eval_loss\", float(eval_loss), epoch)\n",
|
|
" print(\"Evaluation Score : [{}]\".format(eval_loss))\n",
|
|
"\n",
|
|
" print(\"Done :-)\")\n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 305,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" 0%| | 0/11 [00:00<?, ?it/s]\n",
|
|
"training: 0%| | 0/98 [00:00<?, ?it/s]\n",
|
|
" 0%| | 0/1000 [00:00<?, ?it/s]\n"
|
|
]
|
|
},
|
|
{
|
|
"ename": "RuntimeError",
|
|
"evalue": "For batched 3-D input, hx and cx should also be 3-D but got (2-D, 2-D) tensors",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)",
|
|
"Cell \u001b[0;32mIn[305], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mtrain_vae\u001b[49m\u001b[43m(\u001b[49m\u001b[43mvae\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mloader_train\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mloader_test\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_epochs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlearning_rate\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m10\u001b[39;49m\u001b[43m)\u001b[49m\n",
|
|
"Cell \u001b[0;32mIn[304], line 36\u001b[0m, in \u001b[0;36mtrain_vae\u001b[0;34m(model, train_loader, test_loader, max_iter, learning_rate)\u001b[0m\n\u001b[1;32m 29\u001b[0m example_size \u001b[38;5;241m=\u001b[39m x\u001b[38;5;241m.\u001b[39msize(\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m 30\u001b[0m \u001b[38;5;66;03m# image_size = past_data.size(2), past_data.size(3)\u001b[39;00m\n\u001b[1;32m 31\u001b[0m \u001b[38;5;66;03m# past_data = (\u001b[39;00m\n\u001b[1;32m 32\u001b[0m \u001b[38;5;66;03m# past_data.view(batch_size, example_size, -1).float().to(args.device) # flattens image, we don't need this\u001b[39;00m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;66;03m# )\u001b[39;00m\n\u001b[1;32m 34\u001b[0m \u001b[38;5;66;03m# future_data = future_data.view(batch_size, example_size, -1).float().to(args.device)\u001b[39;00m\n\u001b[0;32m---> 36\u001b[0m y, hidden_state, mean, logvar \u001b[38;5;241m=\u001b[39m \u001b[43mmodel\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;66;03m# calculate vae loss\u001b[39;00m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;66;03m# print(y.shape, targets.shape)\u001b[39;00m\n\u001b[1;32m 40\u001b[0m losses \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mloss_function(y, targets, mean, logvar)\n",
|
|
"File \u001b[0;32m~/suspicion/trap/.venv/lib/python3.10/site-packages/torch/nn/modules/module.py:1130\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m 1126\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1127\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1128\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1129\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1130\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1131\u001b[0m \u001b[38;5;66;03m# Do not call functions when jit is used\u001b[39;00m\n\u001b[1;32m 1132\u001b[0m full_backward_hooks, non_full_backward_hooks \u001b[38;5;241m=\u001b[39m [], []\n",
|
|
"Cell \u001b[0;32mIn[302], line 128\u001b[0m, in \u001b[0;36mLSTMVAE.forward\u001b[0;34m(self, x, hidden_state_encoder)\u001b[0m\n\u001b[1;32m 125\u001b[0m hidden \u001b[38;5;241m=\u001b[39m (h_\u001b[38;5;241m.\u001b[39mcontiguous(), h_\u001b[38;5;241m.\u001b[39mcontiguous())\n\u001b[1;32m 126\u001b[0m \u001b[38;5;66;03m# TODO)) the above is not the right dimensions, but this changes architecture\u001b[39;00m\n\u001b[1;32m 127\u001b[0m \u001b[38;5;66;03m# hidden = self.lstm_dec.get_hidden_state(batch_size, self.device)\u001b[39;00m\n\u001b[0;32m--> 128\u001b[0m reconstruct_output, hidden \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlstm_dec\u001b[49m\u001b[43m(\u001b[49m\u001b[43mz\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhidden\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 130\u001b[0m x_hat \u001b[38;5;241m=\u001b[39m reconstruct_output\n\u001b[1;32m 132\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m x_hat, hidden_state, mean, logvar\n",
|
|
"File \u001b[0;32m~/suspicion/trap/.venv/lib/python3.10/site-packages/torch/nn/modules/module.py:1130\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m 1126\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1127\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1128\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1129\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1130\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1131\u001b[0m \u001b[38;5;66;03m# Do not call functions when jit is used\u001b[39;00m\n\u001b[1;32m 1132\u001b[0m full_backward_hooks, non_full_backward_hooks \u001b[38;5;241m=\u001b[39m [], []\n",
|
|
"Cell \u001b[0;32mIn[302], line 54\u001b[0m, in \u001b[0;36mDecoder.forward\u001b[0;34m(self, x, hidden)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mforward\u001b[39m(\u001b[38;5;28mself\u001b[39m, x, hidden):\n\u001b[1;32m 53\u001b[0m \u001b[38;5;66;03m# x: tensor of shape (batch_size, seq_length, hidden_size)\u001b[39;00m\n\u001b[0;32m---> 54\u001b[0m output, (hidden, cell) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlstm\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhidden\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 55\u001b[0m prediction \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfc(output)\n\u001b[1;32m 56\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m prediction, (hidden, cell)\n",
|
|
"File \u001b[0;32m~/suspicion/trap/.venv/lib/python3.10/site-packages/torch/nn/modules/module.py:1130\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m 1126\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1127\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1128\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1129\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1130\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1131\u001b[0m \u001b[38;5;66;03m# Do not call functions when jit is used\u001b[39;00m\n\u001b[1;32m 1132\u001b[0m full_backward_hooks, non_full_backward_hooks \u001b[38;5;241m=\u001b[39m [], []\n",
|
|
"File \u001b[0;32m~/suspicion/trap/.venv/lib/python3.10/site-packages/torch/nn/modules/rnn.py:755\u001b[0m, in \u001b[0;36mLSTM.forward\u001b[0;34m(self, input, hx)\u001b[0m\n\u001b[1;32m 752\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (hx[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mdim() \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m3\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m hx[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39mdim() \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m3\u001b[39m):\n\u001b[1;32m 753\u001b[0m msg \u001b[38;5;241m=\u001b[39m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFor batched 3-D input, hx and cx should \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 754\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124malso be 3-D but got (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mhx[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mdim()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m-D, \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mhx[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39mdim()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m-D) tensors\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 755\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(msg)\n\u001b[1;32m 756\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 757\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m hx[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mdim() \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m2\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m hx[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39mdim() \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m2\u001b[39m:\n",
|
|
"\u001b[0;31mRuntimeError\u001b[0m: For batched 3-D input, hx and cx should also be 3-D but got (2-D, 2-D) tensors"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"train_vae(vae, loader_train, loader_test, num_epochs, learning_rate*10)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 300,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"1301\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"# VAE Predict and plot\n",
|
|
"_track_id = 8701 # random.choice(track_ids)\n",
|
|
"_track_id = 3880 # random.choice(track_ids)\n",
|
|
"\n",
|
|
"# _track_id = 2780\n",
|
|
"\n",
|
|
"for batch_idx in range(100):\n",
|
|
" _track_id = random.choice(track_ids)\n",
|
|
" plt.plot(\n",
|
|
" data.loc[_track_id,:]['x'],\n",
|
|
" data.loc[_track_id,:]['y'],\n",
|
|
" c='grey', alpha=.2\n",
|
|
" )\n",
|
|
"\n",
|
|
"_track_id = random.choice(track_ids)\n",
|
|
"# _track_id = 1096\n",
|
|
"_track_id = 1301\n",
|
|
"print(_track_id)\n",
|
|
"ax = plt.scatter(\n",
|
|
" data.loc[_track_id,:]['x'],\n",
|
|
" data.loc[_track_id,:]['y'],\n",
|
|
" marker=\"*\") \n",
|
|
"plt.plot(\n",
|
|
" data.loc[_track_id,:]['x'],\n",
|
|
" data.loc[_track_id,:]['y']\n",
|
|
")\n",
|
|
"\n",
|
|
"# predict_and_plot(data.loc[_track_id,:].iloc[:5][in_fields].values)\n",
|
|
"predict_and_plot(vae, data.loc[_track_id,:].iloc[:5][in_fields].values, 50)\n",
|
|
"# predict_and_plot(vae, data.loc[_track_id,:].iloc[:10][in_fields].values, 50)\n",
|
|
"# predict_and_plot(vae, data.loc[_track_id,:].iloc[:20][in_fields].values)\n",
|
|
"# predict_and_plot(vae, data.loc[_track_id,:].iloc[:30][in_fields].values)\n",
|
|
"# predict_and_plot(filtered_data.loc[_track_id,:].iloc[:70][in_fields].values)\n",
|
|
"# predict_and_plot(filtered_data.loc[_track_id,:].iloc[:115][in_fields].values)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "AttributeError",
|
|
"evalue": "'LSTM_VAE' object has no attribute 'embed_size'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
|
"Cell \u001b[0;32mIn[103], line 268\u001b[0m\n\u001b[1;32m 261\u001b[0m \u001b[38;5;66;03m# Statistics.\u001b[39;00m\n\u001b[1;32m 262\u001b[0m \u001b[38;5;66;03m# if batch_num % 20 ==0:\u001b[39;00m\n\u001b[1;32m 263\u001b[0m \u001b[38;5;66;03m# print('| epoch {:3d} | elbo_loss {:5.6f} | kl_loss {:5.6f} | recons_loss {:5.6f} '.format(\u001b[39;00m\n\u001b[1;32m 264\u001b[0m \u001b[38;5;66;03m# epoch, mloss.item(), KL_loss.item(), recon_loss.item()))\u001b[39;00m\n\u001b[1;32m 266\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m test_losses\n\u001b[0;32m--> 268\u001b[0m vae \u001b[38;5;241m=\u001b[39m \u001b[43mLSTM_VAE\u001b[49m\u001b[43m(\u001b[49m\u001b[43minput_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moutput_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhidden_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m16\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mto(device)\n\u001b[1;32m 270\u001b[0m vae_loss \u001b[38;5;241m=\u001b[39m VAE_Loss()\n\u001b[1;32m 271\u001b[0m optimizer \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39moptim\u001b[38;5;241m.\u001b[39mAdam(vae\u001b[38;5;241m.\u001b[39mparameters(), lr\u001b[38;5;241m=\u001b[39m learning_rate)\n",
|
|
"Cell \u001b[0;32mIn[103], line 73\u001b[0m, in \u001b[0;36mLSTM_VAE.__init__\u001b[0;34m(self, input_size, output_size, hidden_size, latent_size, num_layers, device)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[38;5;66;03m# Decoder Part\u001b[39;00m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minit_hidden_decoder \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mnn\u001b[38;5;241m.\u001b[39mLinear(in_features\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlatent_size, out_features\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhidden_size \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlstm_factor)\n\u001b[0;32m---> 73\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdecoder_lstm \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mnn\u001b[38;5;241m.\u001b[39mLSTM(input_size\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43membed_size\u001b[49m, hidden_size\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhidden_size, batch_first \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m, num_layers \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_layers)\n\u001b[1;32m 74\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mnn\u001b[38;5;241m.\u001b[39mLinear(in_features\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhidden_size \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlstm_factor, out_features\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_size)\n",
|
|
"File \u001b[0;32m~/suspicion/trap/.venv/lib/python3.10/site-packages/torch/nn/modules/module.py:1207\u001b[0m, in \u001b[0;36mModule.__getattr__\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 1205\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m name \u001b[38;5;129;01min\u001b[39;00m modules:\n\u001b[1;32m 1206\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m modules[name]\n\u001b[0;32m-> 1207\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m object has no attribute \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(\n\u001b[1;32m 1208\u001b[0m \u001b[38;5;28mtype\u001b[39m(\u001b[38;5;28mself\u001b[39m)\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m, name))\n",
|
|
"\u001b[0;31mAttributeError\u001b[0m: 'LSTM_VAE' object has no attribute 'embed_size'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# import torch\n",
|
|
"\n",
|
|
"class VAE_Loss(torch.nn.Module):\n",
|
|
" \"\"\"\n",
|
|
" Adapted from https://github.com/Khamies/LSTM-Variational-AutoEncoder/blob/main/model.py\n",
|
|
" \"\"\"\n",
|
|
" def __init__(self):\n",
|
|
" super(VAE_Loss, self).__init__()\n",
|
|
" self.nlloss = torch.nn.NLLLoss()\n",
|
|
" \n",
|
|
" def KL_loss (self, mu, log_var, z):\n",
|
|
" kl = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())\n",
|
|
" kl = kl.sum(-1) # to go from multi-dimensional z to single dimensional z : (batch_size x latent_size) ---> (batch_size) \n",
|
|
" # i.e Z = [ [z1_1, z1_2 , ...., z1_lt] ] ------> z = [ z1] \n",
|
|
" # [ [z2_1, z2_2, ....., z2_lt] ] [ z2]\n",
|
|
" # . [ . ]\n",
|
|
" # . [ . ]\n",
|
|
" # [[zn_1, zn_2, ....., zn_lt] ] [ zn]\n",
|
|
" \n",
|
|
" # lt=latent_size \n",
|
|
" kl = kl.mean()\n",
|
|
" \n",
|
|
" return kl\n",
|
|
"\n",
|
|
" def reconstruction_loss(self, x_hat_param, x):\n",
|
|
"\n",
|
|
" x = x.view(-1).contiguous()\n",
|
|
" x_hat_param = x_hat_param.view(-1, x_hat_param.size(2))\n",
|
|
"\n",
|
|
" recon = self.nlloss(x_hat_param, x)\n",
|
|
"\n",
|
|
" return recon\n",
|
|
" \n",
|
|
"\n",
|
|
" def forward(self, mu, log_var,z, x_hat_param, x):\n",
|
|
" kl_loss = self.KL_loss(mu, log_var, z)\n",
|
|
" recon_loss = self.reconstruction_loss(x_hat_param, x)\n",
|
|
"\n",
|
|
"\n",
|
|
" elbo = kl_loss + recon_loss # we use + because recon loss is a NLLoss (cross entropy) and it's negative in its own, and in the ELBO equation we have\n",
|
|
" # elbo = KL_loss - recon_loss, therefore, ELBO = KL_loss - (NLLoss) = KL_loss + NLLoss\n",
|
|
"\n",
|
|
" return elbo, kl_loss, recon_loss\n",
|
|
" \n",
|
|
"class LSTM_VAE(torch.nn.Module):\n",
|
|
" \"\"\"\n",
|
|
" Adapted from https://github.com/Khamies/LSTM-Variational-AutoEncoder/blob/main/model.py\n",
|
|
" \"\"\"\n",
|
|
" def __init__(self, input_size, output_size, hidden_size, latent_size, num_layers=1, device=\"cuda\"):\n",
|
|
" super(LSTM_VAE, self).__init__()\n",
|
|
"\n",
|
|
" self.device = device\n",
|
|
" \n",
|
|
" # Variables\n",
|
|
" self.num_layers = num_layers\n",
|
|
" self.lstm_factor = num_layers\n",
|
|
" self.input_size = input_size\n",
|
|
" self.hidden_size = hidden_size\n",
|
|
" self.latent_size = latent_size\n",
|
|
" self.output_size = output_size\n",
|
|
"\n",
|
|
" # X: bsz * seq_len * vocab_size \n",
|
|
" # X: bsz * seq_len * embed_size\n",
|
|
"\n",
|
|
" # Encoder Part\n",
|
|
" self.encoder_lstm = torch.nn.LSTM(input_size= input_size,hidden_size= self.hidden_size, batch_first=True, num_layers= self.num_layers)\n",
|
|
" self.mean = torch.nn.Linear(in_features= self.hidden_size * self.lstm_factor, out_features= self.latent_size)\n",
|
|
" self.log_variance = torch.nn.Linear(in_features= self.hidden_size * self.lstm_factor, out_features= self.latent_size)\n",
|
|
"\n",
|
|
" # Decoder Part\n",
|
|
" \n",
|
|
" self.hidden_decoder_linear = torch.nn.Linear(in_features= self.latent_size, out_features= self.hidden_size * self.lstm_factor)\n",
|
|
" self.decoder_lstm = torch.nn.LSTM(input_size= self.embed_size, hidden_size= self.hidden_size, batch_first = True, num_layers = self.num_layers)\n",
|
|
" self.output = torch.nn.Linear(in_features= self.hidden_size * self.lstm_factor, out_features= self.output_size)\n",
|
|
" # self.log_softmax = torch.nn.LogSoftmax(dim=2)\n",
|
|
"\n",
|
|
" def get_hidden_state(self, batch_size):\n",
|
|
" h = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(self.device)\n",
|
|
" c = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(self.device)\n",
|
|
" return (h, c)\n",
|
|
"\n",
|
|
"\n",
|
|
" def encoder(self, x, hidden_state):\n",
|
|
"\n",
|
|
" # pad the packed input.\n",
|
|
"\n",
|
|
" out, (h,c) = self.encoder_lstm(x, hidden_state)\n",
|
|
" # output_encoder, _ = torch.nn.utils.rnn.pad_packed_sequence(packed_output_encoder, batch_first=True, total_length= total_padding_length)\n",
|
|
"\n",
|
|
" # Extimate the mean and the variance of q(z|x)\n",
|
|
" mean = self.mean(h)\n",
|
|
" log_var = self.log_variance(h)\n",
|
|
" std = torch.exp(0.5 * log_var) # e^(0.5 log_var) = var^0.5\n",
|
|
" \n",
|
|
" # Generate a unit gaussian noise.\n",
|
|
" # batch_size = output_encoder.size(0)\n",
|
|
" # seq_len = output_encoder.size(1)\n",
|
|
" # noise = torch.randn(batch_size, self.latent_size).to(self.device)\n",
|
|
" noise = torch.randn(self.latent_size).to(self.device)\n",
|
|
" \n",
|
|
" z = noise * std + mean\n",
|
|
"\n",
|
|
" return z, mean, log_var, (h,c)\n",
|
|
"\n",
|
|
"\n",
|
|
" def decoder(self, z, x):\n",
|
|
"\n",
|
|
" hidden_decoder = self.hidden_decoder_linear(z)\n",
|
|
" hidden_decoder = (hidden_decoder, hidden_decoder)\n",
|
|
"\n",
|
|
" # pad the packed input.\n",
|
|
" packed_output_decoder, hidden_decoder = self.decoder_lstm(packed_x_embed,hidden_decoder) \n",
|
|
" output_decoder, _ = torch.nn.utils.rnn.pad_packed_sequence(packed_output_decoder, batch_first=True, total_length= total_padding_length)\n",
|
|
"\n",
|
|
"\n",
|
|
" x_hat = self.output(output_decoder)\n",
|
|
" \n",
|
|
" # x_hat = self.log_softmax(x_hat)\n",
|
|
"\n",
|
|
"\n",
|
|
" return x_hat\n",
|
|
"\n",
|
|
" \n",
|
|
"\n",
|
|
" def forward(self, x, hidden_state):\n",
|
|
" \n",
|
|
" \"\"\"\n",
|
|
" x : bsz * seq_len\n",
|
|
" \n",
|
|
" hidden_encoder: ( num_lstm_layers * bsz * hidden_size, num_lstm_layers * bsz * hidden_size)\n",
|
|
"\n",
|
|
" \"\"\"\n",
|
|
" # Get Embeddings\n",
|
|
" # x_embed, maximum_padding_length = self.get_embedding(x)\n",
|
|
"\n",
|
|
" # Packing the input\n",
|
|
" # packed_x_embed = torch.nn.utils.rnn.pack_padded_sequence(input= x_embed, lengths= sentences_length, batch_first=True, enforce_sorted=False)\n",
|
|
"\n",
|
|
"\n",
|
|
" # Encoder\n",
|
|
" z, mean, log_var, hidden_encoder = self.encoder(x, maximum_padding_length, hidden_encoder)\n",
|
|
"\n",
|
|
" # Decoder\n",
|
|
" x_hat = self.decoder(z, packed_x_embed, maximum_padding_length)\n",
|
|
" \n",
|
|
" return x_hat, mean, log_var, z, hidden_encoder\n",
|
|
"\n",
|
|
" \n",
|
|
"\n",
|
|
" def inference(self, n_samples, x, z):\n",
|
|
"\n",
|
|
" # generate random z \n",
|
|
" batch_size = 1\n",
|
|
" seq_len = 1\n",
|
|
" idx_sample = []\n",
|
|
"\n",
|
|
"\n",
|
|
" hidden = self.hidden_decoder_linear(z)\n",
|
|
" hidden = (hidden, hidden)\n",
|
|
" \n",
|
|
" for i in range(n_samples):\n",
|
|
" \n",
|
|
" output,hidden = self.decoder_lstm(x, hidden)\n",
|
|
" output = self.output(output)\n",
|
|
" # output = self.log_softmax(output)\n",
|
|
" # output = output.exp()\n",
|
|
" _, s = torch.topk(output, 1)\n",
|
|
" idx_sample.append(s.item())\n",
|
|
" x = s.squeeze(0)\n",
|
|
"\n",
|
|
" w_sample = [self.dictionary.get_i2w()[str(idx)] for idx in idx_sample]\n",
|
|
" w_sample = \" \".join(w_sample)\n",
|
|
"\n",
|
|
" return w_sample\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"def get_batch(batch):\n",
|
|
" sentences = batch[\"input\"]\n",
|
|
" target = batch[\"target\"]\n",
|
|
" sentences_length = batch[\"length\"]\n",
|
|
"\n",
|
|
" return sentences, target, sentences_length\n",
|
|
"\n",
|
|
"class Trainer:\n",
|
|
"\n",
|
|
" def __init__(self, train_loader, test_loader, model, loss, optimizer) -> None:\n",
|
|
" self.train_loader = train_loader\n",
|
|
" self.test_loader = test_loader\n",
|
|
" self.model = model\n",
|
|
" self.loss = loss\n",
|
|
" self.optimizer = optimizer\n",
|
|
" self.device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
|
|
" self.interval = 200\n",
|
|
"\n",
|
|
"\n",
|
|
" def train(self, train_losses, epoch, batch_size, clip) -> list: \n",
|
|
" # Initialization of RNN hidden, and cell states.\n",
|
|
" states = self.model.init_hidden(batch_size) \n",
|
|
"\n",
|
|
" for batch_idx, (x, targets) in enumerate(self.train_loader):\n",
|
|
" # Get x to cuda if possible\n",
|
|
" x = x.to(device=device).squeeze(1)\n",
|
|
" targets = targets.to(device=device)\n",
|
|
"\n",
|
|
" # for batch_num, batch in enumerate(self.train_loader): # loop over the data, and jump with step = bptt.\n",
|
|
" # get the labels\n",
|
|
" source, target, source_lengths = get_batch(batch)\n",
|
|
" source = source.to(self.device)\n",
|
|
" target = target.to(self.device)\n",
|
|
"\n",
|
|
"\n",
|
|
" x_hat_param, mu, log_var, z, states = self.model(source,source_lengths, states)\n",
|
|
"\n",
|
|
" # detach hidden states\n",
|
|
" states = states[0].detach(), states[1].detach()\n",
|
|
"\n",
|
|
" # compute the loss\n",
|
|
" mloss, KL_loss, recon_loss = self.loss(mu = mu, log_var = log_var, z = z, x_hat_param = x_hat_param , x = target)\n",
|
|
"\n",
|
|
" train_losses.append((mloss , KL_loss.item(), recon_loss.item()))\n",
|
|
"\n",
|
|
" mloss.backward()\n",
|
|
"\n",
|
|
" torch.nn.utils.clip_grad_norm_(self.model.parameters(), clip)\n",
|
|
"\n",
|
|
" self.optimizer.step()\n",
|
|
"\n",
|
|
" self.optimizer.zero_grad()\n",
|
|
"\n",
|
|
"\n",
|
|
" if batch_num % self.interval == 0 and batch_num > 0:\n",
|
|
" \n",
|
|
" print('| epoch {:3d} | elbo_loss {:5.6f} | kl_loss {:5.6f} | recons_loss {:5.6f} '.format(\n",
|
|
" epoch, mloss.item(), KL_loss.item(), recon_loss.item()))\n",
|
|
"\n",
|
|
" return train_losses\n",
|
|
"\n",
|
|
" def test(self, test_losses, epoch, batch_size) -> list:\n",
|
|
"\n",
|
|
" with torch.no_grad():\n",
|
|
"\n",
|
|
" states = self.model.init_hidden(batch_size) \n",
|
|
"\n",
|
|
" for batch_num, batch in enumerate(self.test_loader): # loop over the data, and jump with step = bptt.\n",
|
|
" # get the labels\n",
|
|
" source, target, source_lengths = get_batch(batch)\n",
|
|
" source = source.to(self.device)\n",
|
|
" target = target.to(self.device)\n",
|
|
"\n",
|
|
"\n",
|
|
" x_hat_param, mu, log_var, z, states = self.model(source,source_lengths, states)\n",
|
|
"\n",
|
|
" # detach hidden states\n",
|
|
" states = states[0].detach(), states[1].detach()\n",
|
|
"\n",
|
|
" # compute the loss\n",
|
|
" mloss, KL_loss, recon_loss = self.loss(mu = mu, log_var = log_var, z = z, x_hat_param = x_hat_param , x = target)\n",
|
|
"\n",
|
|
" test_losses.append((mloss , KL_loss.item(), recon_loss.item()))\n",
|
|
"\n",
|
|
" # Statistics.\n",
|
|
" # if batch_num % 20 ==0:\n",
|
|
" # print('| epoch {:3d} | elbo_loss {:5.6f} | kl_loss {:5.6f} | recons_loss {:5.6f} '.format(\n",
|
|
" # epoch, mloss.item(), KL_loss.item(), recon_loss.item()))\n",
|
|
"\n",
|
|
" return test_losses\n",
|
|
"\n",
|
|
"vae = LSTM_VAE(input_size, output_size, hidden_size, 16, 1, device).to(device)\n",
|
|
"\n",
|
|
"vae_loss = VAE_Loss()\n",
|
|
"optimizer = torch.optim.Adam(vae.parameters(), lr= learning_rate)\n",
|
|
"\n",
|
|
"trainer = Trainer(loader_train, loader_test, vae, vae_loss, optimizer)\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".venv",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.10.4"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|