Kaggle competition: Lyft Motion Prediction for Autonomous Vehicles
<SOS> metric: PostProcessorKernel Kaggle data source: lyft-motion-prediction-autonomous-vehicles<train_model>
warnings.filterwarnings("ignore")
 print(l5kit.__version__ )
print(model )<init_hyperparams>
def memory(verbose=True):
mem = psutil.virtual_memory()
gb = 1024*1024*1024
if verbose:
print('Physical memory:',
'%.2f GB(used),'%(( mem.total - mem.available)/ gb),
'%.2f GB(available)'%(( mem.available)/ gb), '/',
'%.2f GB'%(mem.total / gb))
return(mem.total - mem.available)/ gb
def gc_memory(verbose=True):
m = gc.collect()
if verbose:
print('GC:', m, end=' | ')
 memory()
memory() ;
if cfg["model_params"]["train"]:
tr_it = iter(train_dataloader)
 progress_bar = tqdm(range(cfg["train_params"]["max_num_steps"]))
num_iter = cfg["train_params"]["max_num_steps"]
losses_train = []
iterations = []
metrics = []
times = []
model_name = cfg["model_params"]["model_name"]
start = time.time()
for i in progress_bar:
try:
data = next(tr_it)
 except StopIteration:
tr_it = iter(train_dataloader)
 data = next(tr_it)
 model.train()
torch.set_grad_enabled(True)
 loss, _, _ = forward(data, model, device)
 optimizer.zero_grad()
loss.backward()
optimizer.step()
losses_train.append(loss.item())
 progress_bar.set_description(f"loss: {loss.item() } loss(avg): {np.mean(losses_train)}")
 if i % cfg['train_params']['checkpoint_every_n_steps'] == 0:
torch.save(model.state_dict() , f'{model_name}_{i}.pth')
 iterations.append(i)
 metrics.append(np.mean(losses_train))
times.append(( time.time() -start)/60)
 results = pd.DataFrame({'iterations': iterations, 'metrics(avg)': metrics, 'elapsed_time(mins)': times})
 results.to_csv(f"train_metrics_{model_name}_{num_iter}.csv", index = False)
 print(f"Total training time is {(time.time() -start)/60} mins")
 print(results.head() )<save_to_csv>
def set_seed(seed):
random.seed(seed)
 np.random.seed(seed)
 os.environ["PYTHONHASHSEED"] = str(seed)
 torch.manual_seed(seed)
 torch.cuda.manual_seed(seed)
 set_seed(42 )
pred_path = 'submission.csv'
write_pred_csv(pred_path,
timestamps=np.concatenate(timestamps),
track_ids=np.concatenate(agent_ids),
coords=np.concatenate(future_coords_offsets_pd),
confs = np.concatenate(confidences_list)
 )<set_options>
cfg = {
'format_version': 4,
'data_path': '/kaggle/input/lyft-motion-prediction-autonomous-vehicles',
'model_params': {
'first_layer_bias': False,
'pretrained': True,
'multi_mode': True,
'model_architecture': 'resnet101',
'history_num_frames': 10,
'history_step_size': 1,
'history_delta_time': 0.1,
'future_num_frames': 50,
'future_step_size': 1,
'future_delta_time': 0.1,
'model_name': "model_resnet34_output",
'lr': 1e-5,
'weight_path': '.. /input/resnet101-best-weights-epoch2/model_state_280000.pth',
'train': False,
'predict': True,
},
'raster_params': {
'raster_size': [224, 224],
'pixel_size': [0.5, 0.5],
'ego_center': [0.25, 0.5],
'map_type': 'py_semantic',
'satellite_map_key': 'aerial_map/aerial_map.png',
'semantic_map_key': 'semantic_map/semantic_map.pb',
'dataset_meta_key': 'meta.json',
'filter_agents_threshold': 0.5,
},
'train_data_loader': {
'key': 'scenes/train.zarr',
'batch_size': 16,
'shuffle': True,
'num_workers': 4,
},
'test_data_loader': {
'key': 'scenes/test.zarr',
'batch_size': 32,
'shuffle': False,
'num_workers': 4,
},
'train_params': {
'steps': 1000,
'update_steps': 100,
'checkpoint_steps': 1000,
},
'combine': True
}
DIR_INPUT = cfg["data_path"]
os.environ["L5KIT_DATA_FOLDER"] = DIR_INPUT
dm = LocalDataManager()
rasterizer = build_rasterizer(cfg, dm)
 test_cfg = cfg["test_data_loader"]
test_zarr = ChunkedDataset(dm.require(test_cfg["key"])).open(cached=False)
 test_mask = np.load(f"{DIR_INPUT}/scenes/mask.npz")["arr_0"]
test_dataset = AgentDataset(cfg, test_zarr, rasterizer, agents_mask=test_mask)
 test_dataloader = DataLoader(test_dataset, shuffle=test_cfg["shuffle"],
batch_size=test_cfg["batch_size"], num_workers=test_cfg["num_workers"])
 print(test_dataset)
 def pytorch_neg_multi_log_likelihood_batch(
 gt: Tensor, pred: Tensor, confidences: Tensor, avails: Tensor 
)-> Tensor:

 assert len(pred.shape)== 4, f"expected 3D(MxTxC)array for pred, got {pred.shape}"
batch_size, num_modes, future_len, num_coords = pred.shape
assert gt.shape ==(batch_size, future_len, num_coords), f"expected 2D(Time x Coords)array for gt, got {gt.shape}"
assert confidences.shape ==(batch_size, num_modes), f"expected 1D(Modes)array for gt, got {confidences.shape}"
assert torch.allclose(torch.sum(confidences, dim=1), confidences.new_ones(( batch_size,))), "confidences should sum to 1"
assert avails.shape ==(batch_size, future_len), f"expected 1D(Time)array for gt, got {avails.shape}"
assert torch.isfinite(pred ).all() , "invalid value found in pred"
assert torch.isfinite(gt ).all() , "invalid value found in gt"
assert torch.isfinite(confidences ).all() , "invalid value found in confidences"
assert torch.isfinite(avails ).all() , "invalid value found in avails"
gt = torch.unsqueeze(gt, 1)
 avails = avails[:, None, :, None]
error = torch.sum(((gt - pred)* avails)** 2, dim=-1)
 with np.errstate(divide="ignore"):
error = torch.log(confidences)- 0.5 * torch.sum(error, dim=-1)
 max_value, _ = error.max(dim=1, keepdim=True)
 error = -torch.log(torch.sum(torch.exp(error - max_value), dim=-1, keepdim=True)) - max_value
return torch.mean(error)
 def pytorch_neg_multi_log_likelihood_single(
 gt: Tensor, pred: Tensor, avails: Tensor 
)-> Tensor:

 batch_size, future_len, num_coords = pred.shape
confidences = pred.new_ones(( batch_size, 1))
return pytorch_neg_multi_log_likelihood_batch(gt, pred.unsqueeze(1), confidences, avails)
 class LyftMultiModel(nn.Module):
def __init__(self, conf: Dict):
super().__init__()
self.future_num_frames = cfg["model_params"]["future_num_frames"]
target_count = 2 * self.future_num_frames
if cfg["model_params"]["multi_mode"]:
self.multi_mode = True
target_count += 1
target_count *= 3
else:
self.multi_mode = False
history_channel_count =(conf["model_params"]["history_num_frames"] + 1)* 2
total_channel_count = 3 + history_channel_count
architecture = cfg["model_params"]["model_architecture"]
if architecture == "resnet50":
backbone = resnet50(pretrained=cfg["model_params"]["pretrained"])
 elif architecture == "resnet101":
backbone = resnet101(pretrained=cfg["model_params"]["pretrained"])
 elif architecture == "resnet34":
backbone = resnet34(pretrained=cfg["model_params"]["pretrained"])
 if architecture in ["resnet50", "resnet101", "resnet34"]:
backbone.conv1 = nn.Conv2d(
 total_channel_count,
backbone.conv1.out_channels,
kernel_size=backbone.conv1.kernel_size,
stride=backbone.conv1.stride,
padding=backbone.conv1.padding,
bias=cfg["model_params"]["first_layer_bias"], 
)
 if architecture == "resnet34":
backbone.fc = nn.Linear(in_features=512, out_features=target_count)
 else:
backbone.fc = nn.Linear(in_features=2048, out_features=target_count)
 self.backbone = backbone
def forward(self, x):
y = self.backbone(x)
 if self.multi_mode:
batches, _ = y.shape
pred, confidences = torch.split(y, self.future_num_frames * 3 * 2, dim=1)
 pred = pred.view(batches, 3, self.future_num_frames, 2)
 confidences = torch.softmax(confidences, dim=1)
 return pred, confidences
else:
return y
def forward(data, model, device, criterion=pytorch_neg_multi_log_likelihood_batch, compute_loss=True):
inputs = data["image"].to(device)
 target_availabilities = data["target_availabilities"].to(device)
 targets = data["target_positions"].to(device)
 preds, confidences = model(inputs)
 loss = criterion(targets, preds, confidences, target_availabilities)if compute_loss else 0
return loss, preds, confidences
def execute(path):
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
 model = LyftMultiModel(cfg)
 weight_path = cfg["model_params"]["weight_path"]
if weight_path:
model.load_state_dict(torch.load(weight_path))
model.to(device)
 optimizer = optim.Adam(model.parameters() , lr=cfg["model_params"]["lr"])
 print(f'device {device}')
 if cfg["model_params"]["predict"]:
model.eval()
torch.set_grad_enabled(False)
 future_coords_offsets_pd = []
timestamps = []
confidences_list = []
agent_ids = []
memorys_pred = []
t0 = time.time()
times_pred = []
iterations_pred = []
for i, data in enumerate(tqdm_notebook(test_dataloader, mininterval=5.)):
_, preds, confidences = forward(data, model, device, compute_loss=False)
 preds = torch.einsum('bmti,bji->bmtj',
preds.double() ,
data["world_from_agent"].to(device)[:, :2, :2] ).cpu().numpy()
future_coords_offsets_pd.append(preds.copy())
 confidences_list.append(confidences.cpu().numpy().copy())
 timestamps.append(data["timestamp"].numpy().copy())
 agent_ids.append(data["track_id"].numpy().copy())
 if i%50 == 0:
t =(( time.time() - t0)/ 60)
 print('%4d'%i, '%6.2fmins'%t, end=' | ')
 mem = memory()
iterations_pred.append(i)
 memorys_pred.append(mem)
 times_pred.append(t)
 print('Total timespent: %6.2fmins'%(( time.time() - t0)/ 60))
memory()
pred_path = path
write_pred_csv(
 pred_path,
timestamps=np.concatenate(timestamps),
track_ids=np.concatenate(agent_ids),
coords=np.concatenate(future_coords_offsets_pd),
confs=np.concatenate(confidences_list), 
)
 df_sub = pd.read_csv(pred_path)
 display(df_sub )
pd.options.display.max_columns=305<define_variables>
if cfg['combine']:
execute('submission_1.csv')
 cfg["model_params"]["weight_path"] = '.. /input/resnet34-bestscore-epoch-weights/model_state_last.pth'
cfg['model_params']['model_architecture'] = 'resnet34'
execute('submission_2.csv')
 else:
execute('submission.csv')
<define_variables><EOS> 
if cfg['combine']:
pd.options.display.max_columns=305
paths = [
"submission_1.csv",
"submission_2.csv",
]
weights = [0.2, 0.8]
conf_cols = np.array(["conf_0", "conf_1", "conf_2"])
 xy_cols = [[],[],[]]
for i in range(50):
for j in range(3):
xy_cols[j].append(f"coord_x{j}{i}")
 xy_cols[j].append(f"coord_y{j}{i}")
 xy_cols[0][:10]
COLUMNS = ["timestamp", "track_id"] + list(conf_cols)+ xy_cols[0] + xy_cols[1] + xy_cols[2]
def sort_df(df, sort_timestamp_track_id=True):
conf_orders = np.argsort(-df[conf_cols].values,1)
 XY = np.stack([df[xy_cols[0]].values,df[xy_cols[1]].values, df[xy_cols[2]].values], axis=1)
 XY = XY[np.arange(len(XY)) [:, None], conf_orders]
df2 = pd.DataFrame(columns = COLUMNS)
 df2["timestamp"] = df["timestamp"].values
df2["track_id"] = df["track_id"].values
df2[xy_cols[0] + xy_cols[1] + xy_cols[2]] = XY.reshape(-1,300)
 df2[conf_cols] = df[conf_cols].values[np.arange(len(df)) [:, None], conf_orders]
if sort_timestamp_track_id:
df2.sort_values(["timestamp", "track_id"], inplace=True)
 df2.reset_index(inplace=True, drop=True)
 return df2
df = None
for path,w in zip(paths,weights):
print(w, path)
 temp = pd.read_csv(path)
 temp = sort_df(temp)
 temp[COLUMNS[5:]] *= w
if df is None:
df = temp
else:
df[COLUMNS[2:]] += temp[COLUMNS[2:]]
df[conf_cols] /= df[conf_cols].sum(1 ).values[:, None]
sample = pd.read_csv(".. /input/lyft-motion-prediction-autonomous-vehicles/multi_mode_sample_submission.csv")
 df = sample[["timestamp", "track_id"]].merge(df, on=["timestamp", "track_id"])
 sample.shape, df.shape
df.to_csv("submission.csv", index=False, float_format='%.6f' )