{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Lyft Baseline\nThe following notebook performs evaluation using a simple baseline.\nThe baseline has been **trained for 100k iterations with batch size 64 and history_num_frames 10** on the `train.zarr` dataset. All other parameters have been set to their default values as in [the original training configuration](https://github.com/lyft/l5kit/blob/3e3403b4d85fb99e7068cdffd0cd01d3f0d83138/examples/agent_motion_prediction/agent_motion_config.yaml)\n\n**Note:** The notebook has been updated to work with L5Kit 1.1.0 (already available in Kaggle)\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"!jupyter nbconvert --version\n!papermill --version","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ensure version of L5Kit\nimport l5kit\nassert l5kit.__version__ == \"1.1.0\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport os\nimport torch\n\nfrom torch import nn, optim\nfrom torch.utils.data import DataLoader\nfrom torchvision.models.resnet import resnet50\nfrom tqdm import tqdm\nfrom typing import Dict\n\nfrom l5kit.data import LocalDataManager, ChunkedDataset\nfrom l5kit.geometry import transform_points\nfrom l5kit.dataset import AgentDataset\nfrom l5kit.evaluation import write_pred_csv\nfrom l5kit.rasterization import build_rasterizer","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> ## Build Baseline Model"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def build_model(cfg: Dict) -> torch.nn.Module:\n    # load pre-trained Conv2D model\n    model = resnet50(pretrained=False)\n\n    # change input channels number to match the rasterizer's output\n    num_history_channels = (cfg[\"model_params\"][\"history_num_frames\"] + 1) * 2\n    num_in_channels = 3 + num_history_channels\n    model.conv1 = nn.Conv2d(\n        num_in_channels,\n        model.conv1.out_channels,\n        kernel_size=model.conv1.kernel_size,\n        stride=model.conv1.stride,\n        padding=model.conv1.padding,\n        bias=False,\n    )\n    # change output size to (X, Y) * number of future states\n    num_targets = 2 * cfg[\"model_params\"][\"future_num_frames\"]\n    model.fc = nn.Linear(in_features=2048, out_features=num_targets)\n\n    return model\n\ndef forward(data, model, device):\n    inputs = data[\"image\"].to(device)\n    target_availabilities = data[\"target_availabilities\"].unsqueeze(-1).to(device)\n    targets = data[\"target_positions\"].to(device)\n    # Forward pass\n    outputs = model(inputs).reshape(targets.shape)\n    return outputs","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Set the Configuration for the experiment"},{"metadata":{"trusted":true},"cell_type":"code","source":"os.environ[\"L5KIT_DATA_FOLDER\"] = \"/kaggle/input/lyft-motion-prediction-autonomous-vehicles\"\ndm = LocalDataManager(None)\n\ncfg = {\n    'format_version': 4,\n    'model_params': {\n        'history_num_frames': 10,\n        'history_step_size': 1,\n        'history_delta_time': 0.1,\n        'future_num_frames': 50,\n        'future_step_size': 1,\n        'future_delta_time': 0.1\n    },\n    \n    'raster_params': {\n        'raster_size': [224, 224],\n        'pixel_size': [0.5, 0.5],\n        'ego_center': [0.25, 0.5],\n        'map_type': 'py_semantic',\n        'semantic_map_key': 'semantic_map/semantic_map.pb',\n        'dataset_meta_key': 'meta.json',\n        'filter_agents_threshold': 0.5\n    },\n    \n    'test_data_loader': {\n        'key': 'scenes/test.zarr',\n        'batch_size': 12,\n        'shuffle': False,\n        'num_workers': 0\n    }\n\n}","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Build Dataset (with mask) and Dataloader"},{"metadata":{"trusted":true},"cell_type":"code","source":"# ===== INIT DATASET\ntest_cfg = cfg[\"test_data_loader\"]\n\ntest_zarr = ChunkedDataset(dm.require(test_cfg[\"key\"])).open()\ntest_mask = np.load(\"/kaggle/input/lyft-motion-prediction-autonomous-vehicles/scenes/mask.npz\")[\"arr_0\"]\n\nrasterizer = build_rasterizer(cfg, dm)\ntest_dataset = AgentDataset(cfg, test_zarr, rasterizer, agents_mask=test_mask)\ntest_dataloader = DataLoader(test_dataset,\n                             shuffle=test_cfg[\"shuffle\"],\n                             batch_size=test_cfg[\"batch_size\"],\n                             num_workers=test_cfg[\"num_workers\"])\nprint(test_dataset)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Instantiate the Model and Load Weights"},{"metadata":{"trusted":true},"cell_type":"code","source":"# ==== INIT MODEL\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = build_model(cfg).to(device)\n\nmodel.load_state_dict(torch.load(\"/kaggle/input/baseline-weights/baseline_weights.pth\", map_location=device))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Ensure coordinates are stored in the correct reference system\nBecause predictions are now (from l5kit 1.1.0) in `agent` space we need to convert them back to `world` displacements before storing them."},{"metadata":{"trusted":true},"cell_type":"code","source":"# ==== EVAL LOOP\nmodel.eval()\ntorch.set_grad_enabled(False)\n\n# store information for evaluation\nfuture_coords_offsets_pd = []\ntimestamps = []\nagent_ids = []\n\nprogress_bar = tqdm(test_dataloader)\nfor data in progress_bar:\n    \n    # convert agent coordinates into world offsets\n    agents_coords = forward(data, model, device).cpu().numpy().copy()\n    world_from_agents = data[\"world_from_agent\"].numpy()\n    centroids = data[\"centroid\"].numpy()\n    coords_offset = []\n    \n    for agent_coords, world_from_agent, centroid in zip(agents_coords, world_from_agents, centroids):\n        coords_offset.append(transform_points(agent_coords, world_from_agent) - centroid[:2])\n    \n    future_coords_offsets_pd.append(np.stack(coords_offset))\n    timestamps.append(data[\"timestamp\"].numpy().copy())\n    agent_ids.append(data[\"track_id\"].numpy().copy())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"write_pred_csv(\"submission.csv\",\n               timestamps=np.concatenate(timestamps),\n               track_ids=np.concatenate(agent_ids),\n               coords=np.concatenate(future_coords_offsets_pd),\n              )","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}