RetinaNet临床图像细胞识别训练遇UserWarning问题咨询
临床图像细胞识别RetinaNet训练中Torchmetrics警告的成因与解决办法
问题背景
使用RetinaNet模型开展临床图像的细胞识别任务,训练过程中出现UserWarning提示,模型可继续训练,但需明确警告成因及修正方法。
警告信息
EPOCH 1 of 50 Training Loss: 1.0731: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [41:57<00:00, 25.17s/it] Validating 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:40<00:00, 13.61s/it] C:\anaconda\lib\site-packages\torchmetrics\utilities\prints.py:42: UserWarning: Encountered more than 100 detections in a single image. This means that certain detections with the lowest scores will be ignored, that may have an undesirable impact on performance. Please consider adjusting the `max_detection_threshold` to suit your use case. To disable this warning, set attribute class `warn_on_many_detections=False`, after initializing the metric. warnings.warn(*args, **kwargs) # noqa: B028
核心训练代码
### train.py def train(train_data_loader, model): print('Training') model.train() # initialize tqdm progress bar prog_bar = tqdm(train_data_loader, total=len(train_data_loader)) for i, data in enumerate(prog_bar): optimizer.zero_grad() images, targets = data images = list(image.to(DEVICE) for image in images) targets = [{k: v.to(DEVICE) for k, v in t.items()} for t in targets] loss_dict = model(images, targets) losses = sum(loss for loss in loss_dict.values()) loss_value = losses.item() train_loss_hist.send(loss_value) losses.backward() optimizer.step() # update the loss value beside the progress bar for each iteration prog_bar.set_description(desc=f"Loss: {loss_value:.4f}") return loss_value def validate(valid_data_loader, model): print('Validating') model.eval() # Initialize tqdm progress bar. prog_bar = tqdm(valid_data_loader, total=len(valid_data_loader)) target = [] preds = [] for i, data in enumerate(prog_bar): images, targets = data images = list(image.to(DEVICE) for image in images) targets = [{k: v.to(DEVICE) for k, v in t.items()} for t in targets] with torch.no_grad(): outputs = model(images, targets) # For mAP calculation using Torchmetrics. ##################################### for i in range(len(images)): true_dict = dict() preds_dict = dict() true_dict['boxes'] = targets[i]['boxes'].detach().cpu() true_dict['labels'] = targets[i]['labels'].detach().cpu() preds_dict['boxes'] = outputs[i]['boxes'].detach().cpu() preds_dict['scores'] = outputs[i]['scores'].detach().cpu() preds_dict['labels'] = outputs[i]['labels'].detach().cpu() preds.append(preds_dict) target.append(true_dict) ##################################### metric.reset() metric.update(preds, target) metric_summary = metric.compute() return metric_summary if __name__ == '__main__': os.makedirs('outputs', exist_ok=True) train_dataset = create_train_dataset(TRAIN_DIR) valid_dataset = create_valid_dataset(VALID_DIR) train_loader = create_train_loader(train_dataset, NUM_WORKERS) valid_loader = create_valid_loader(valid_dataset, NUM_WORKERS) print(f"Number of training samples: {len(train_dataset)}") print(f"Number of validation samples: {len(valid_dataset)}\n") # Initialize the model and move to the computation device. model = create_model(num_classes=NUM_CLASSES) model = model.to(DEVICE) print(model) # Total parameters and trainable parameters. total_params = sum(p.numel() for p in model.parameters()) print(f"{total_params:,} total parameters.") total_trainable_params = sum( p.numel() for p in model.parameters() if p.requires_grad) print(f"{total_trainable_params:,} training parameters.") params = [p for p in model.parameters() if p.requires_grad] optimizer = torch.optim.SGD(params, lr=0.001, momentum=0.9, nesterov=True) scheduler = StepLR( optimizer=optimizer, step_size=15, gamma=0.1, verbose=True ) # To monitor training loss train_loss_hist = Averager() # To store training loss and mAP values. train_loss_list = [] map_50_list = [] map_list = [] # Mame to save the trained model with. MODEL_NAME = 'model' # Whether to show transformed images from data loader or not. if VISUALIZE_TRANSFORMED_IMAGES: from custom_utils import show_tranformed_image show_tranformed_image(train_loader) # To save best model. save_best_model = SaveBestModel() metric = MeanAveragePrecision() # Training loop. for epoch in range(NUM_EPOCHS): print(f"\nEPOCH {epoch+1} of {NUM_EPOCHS}") # Reset the training loss histories for the current epoch. train_loss_hist.reset() # Start timer and carry out training and validation. start = time.time() train_loss = train(train_loader, model) metric_summary = validate(valid_loader, model) print(f"Epoch #{epoch+1} train loss: {train_loss_hist.value:.3f}") print(f"Epoch #{epoch+1} mAP: {metric_summary['map']*100}") end = time.time() print(f"Took {((end - start) / 60):.3f} minutes for epoch {epoch}") train_loss_list.append(train_loss) map_50_list.append(metric_summary['map_50']) map_list.append(metric_summary['map']) # save the best model till now. save_best_model( model, float(metric_summary['map']), epoch, 'outputs' ) # Save the current epoch model. save_model(epoch, model, optimizer) # Save loss plot. save_loss_plot(OUT_DIR, train_loss_list) # Save mAP plot. save_mAP(OUT_DIR, map_50_list, map_list) # scheduler.step()
警告成因
你使用的Torchmetrics库中MeanAveragePrecision指标默认仅保留单张图像内得分最高的100个检测结果。而临床图像中细胞数量通常较多,模型输出的检测框数量超过了这个阈值,超出部分的低得分检测会被自动丢弃,可能导致mAP评估结果不准确,因此触发该警告。
解决办法
方法1:调整max_detection_threshold参数(推荐)
初始化MeanAveragePrecision时,直接传入该参数,设置一个符合你数据集细胞数量的阈值(比如200或更高),确保所有有效细胞检测结果都能被纳入mAP计算:
metric = MeanAveragePrecision(max_detection_threshold=200)
方法2:关闭警告(仅在确认丢弃不影响结果时使用)
若你确认超出100个的低得分检测均为无效结果,不会影响评估准确性,可以在初始化指标后关闭警告:
metric = MeanAveragePrecision() metric.warn_on_many_detections = False
内容的提问来源于stack exchange,提问作者yordan salvador romani
相关产品推荐
相关产品推荐

