(epoch, model, model_mol, device, loader, n_bins, writer, loss_fn, bins_values, train_BS, test_BS)
| 30 | random.seed(worker_seed) |
| 31 | |
| 32 | def evaluate_model(epoch, model, model_mol, device, loader, n_bins, writer, loss_fn, bins_values, train_BS, test_BS): |
| 33 | model.eval() |
| 34 | |
| 35 | eval_loss = 0. |
| 36 | |
| 37 | all_survival_probs = np.zeros((len(loader), n_bins)) |
| 38 | all_risk_scores = np.zeros((len(loader))) # This is the computed risk score. |
| 39 | all_censorships = np.zeros((len(loader))) # This is the binary censorship status: 1 censored; 0 uncensored (reccured). |
| 40 | all_event_times = np.zeros((len(loader))) |
| 41 | |
| 42 | with torch.no_grad(): |
| 43 | for batch_idx, (data, features_flattened, label, event_time, censorship, stage, _) in enumerate(loader): |
| 44 | data, label, censorship, stage = data.to(device), label.to(device), censorship.to(device), stage.to(device) |
| 45 | _, _, Y_hat, _, _ = model_mol(features_flattened.to(device)) |
| 46 | |
| 47 | hazards_prob, survival_prob, Y_hat, _, _ = model(data, stage, Y_hat.squeeze(1)) # Returns hazards, survival, Y_hat, A_raw, M. |
| 48 | |
| 49 | # We can emphasize on the contribution of uncensored patient cases only in training by minimizing a weighted sum of the 2 losses |
| 50 | loss = loss_fn(hazards=hazards_prob, S=survival_prob, Y=label, c=censorship, alpha=0) |
| 51 | eval_loss += loss.item() |
| 52 | |
| 53 | risk = -torch.sum(survival_prob, dim=1).cpu().numpy() |
| 54 | all_risk_scores[batch_idx] = risk |
| 55 | all_censorships[batch_idx] = censorship.cpu().numpy() |
| 56 | all_event_times[batch_idx] = event_time |
| 57 | all_survival_probs[batch_idx] = survival_prob.cpu().numpy() |
| 58 | |
| 59 | eval_loss /= len(loader) |
| 60 | |
| 61 | # Compute a few survival metrics. |
| 62 | c_index = concordance_index_censored( |
| 63 | event_indicator=(1-all_censorships).astype(bool), |
| 64 | event_time=all_event_times, |
| 65 | estimate=all_risk_scores, tied_tol=1e-08)[0] |
| 66 | |
| 67 | # Years of interest can be adapted in utils.py |
| 68 | (BS, years_of_interest), (IBS, yearI_of_interest, yearF_of_interest), (_, meanAUC), (c_index_ipcw) = compute_surv_metrics_eval(bins_values, all_survival_probs, all_risk_scores, train_BS, test_BS) |
| 69 | |
| 70 | print(f'Eval epoch: {epoch}, loss: {eval_loss}, c_index: {c_index}, BS at each {years_of_interest}Y: {BS}, IBS and mean cumAUC from {yearI_of_interest}Y to {yearF_of_interest}Y: {IBS} and {meanAUC}') |
| 71 | |
| 72 | writer.add_scalar("Loss/eval", eval_loss, epoch) |
| 73 | writer.add_scalar("C_index/eval", c_index, epoch) |
| 74 | for i in range(len(years_of_interest)): |
| 75 | writer.add_scalar(f"eval_metrics/BS_{str(years_of_interest[i])}Y", BS[i], epoch) |
| 76 | writer.add_scalar(f"eval_metrics/IBS_{str(yearI_of_interest)}Y-{str(yearF_of_interest)}Y", IBS, epoch) |
| 77 | writer.add_scalar(f"eval_metrics/meanAUC_{str(yearI_of_interest)}Y-{str(yearF_of_interest)}Y", meanAUC, epoch) |
| 78 | |
| 79 | return eval_loss, c_index, (BS, IBS, meanAUC, c_index_ipcw) |
| 80 | |
| 81 | def train_one_epoch(epoch, model, model_mol, device, train_loader, optimizer, n_bins, writer, loss_fn): |
| 82 |
no test coverage detected