title: How to solve ValueError: not enough values to unpack error
body: <p>These are pytorch-yolo v3 code. I downloaded it in github. (<a href="https://github.com/eriklindernoren/PyTorch-YOLOv3" rel="nofollow noreferrer">https://github.com/eriklindernoren/PyTorch-YOLOv3</a>)
  I tuned this for two classes. And while I'm doing trainning, there is still an error.</p>
  
  <p>This is test.py code.</p>
  
  <pre><code>from __future__ import division
  
  from models import *
  from utils.utils import *
  from utils.datasets import *
  from utils.parse_config import *
  
  import os
  import sys
  import time
  import datetime
  import argparse
  import tqdm
  
  import torch
  from torch.utils.data import DataLoader
  from torchvision import datasets
  from torchvision import transforms
  from torch.autograd import Variable
  import torch.optim as optim
  
  
  def evaluate(model, path, iou_thres, conf_thres, nms_thres, img_size, batch_size):
      model.eval()
  
      # Get dataloader
      dataset = ListDataset(path, img_size=img_size, augment=False, multiscale=False)
      dataloader = torch.utils.data.DataLoader(
          dataset, batch_size=batch_size, shuffle=False, num_workers=1, collate_fn=dataset.collate_fn
      )
  
      Tensor = torch.cuda.FloatTensor if torch.cuda.is_available() else torch.FloatTensor
  
      labels = []
      sample_metrics = []  # List of tuples (TP, confs, pred)
      for batch_i, (_, imgs, targets) in enumerate(tqdm.tqdm(dataloader, desc="Detecting objects")):
  
          # Extract labels
          labels += targets[:, 1].tolist()
          # Rescale target
          targets[:, 2:] = xywh2xyxy(targets[:, 2:])
          targets[:, 2:] *= img_size
  
          imgs = Variable(imgs.type(Tensor), requires_grad=False)
  
          with torch.no_grad():
              outputs = model(imgs)
              outputs = non_max_suppression(outputs, conf_thres=conf_thres, nms_thres=nms_thres)
  
          sample_metrics += get_batch_statistics(outputs, targets, iou_threshold=iou_thres)
  
      # Concatenate sample statistics
      true_positives, pred_scores, pred_labels = [np.concatenate(x, 0) for x in list(zip(*sample_metrics))]
      precision, recall, AP, f1, ap_class = ap_per_class(true_positives, pred_scores, pred_labels, labels)
  
      return precision, recall, AP, f1, ap_class
  
  
  if __name__ == "__main__":
      parser = argparse.ArgumentParser()
      parser.add_argument("--batch_size", type=int, default=8, help="size of each image batch")
      parser.add_argument("--model_def", type=str, default="config/yolov3.cfg", help="path to model definition file")
      parser.add_argument("--data_config", type=str, default="config/coco.data", help="path to data config file")
      parser.add_argument("--weights_path", type=str, default="weights/yolov3.weights", help="path to weights file")
      parser.add_argument("--class_path", type=str, default="data/coco.names", help="path to class label file")
      parser.add_argument("--iou_thres", type=float, default=0.5, help="iou threshold required to qualify as detected")
      parser.add_argument("--conf_thres", type=float, default=0.001, help="object confidence threshold")
      parser.add_argument("--nms_thres", type=float, default=0.5, help="iou thresshold for non-maximum suppression")
      parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation")
      parser.add_argument("--img_size", type=int, default=416, help="size of each image dimension")
      opt = parser.parse_args()
      print(opt)
  
      device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
  
      data_config = parse_data_config(opt.data_config)
      valid_path = data_config["valid"]
      class_names = load_classes(data_config["names"])
  
      # Initiate model
      model = Darknet(opt.model_def).to(device)
      if opt.weights_path.endswith(".weights"):
          # Load darknet weights
          model.load_darknet_weights(opt.weights_path)
      else:
          # Load checkpoint weights
          model.load_state_dict(torch.load(opt.weights_path))
  
      print("Compute mAP...")
  
      precision, recall, AP, f1, ap_class = evaluate(
          model,
          path=valid_path,
          iou_thres=opt.iou_thres,
          conf_thres=opt.conf_thres,
          nms_thres=opt.nms_thres,
          img_size=opt.img_size,
          batch_size=8,
      )
  
      print("Average Precisions:")
      for i, c in enumerate(ap_class):
          print(f"+ Class '{c}' ({class_names[c]}) - AP: {AP[i]}")
  
      print(f"mAP: {AP.mean()}")
  
  </code></pre>
  
  <p>And, this is trainplate.py code. (Originally, this is train.py. But, I renamed it.)</p>
  
  <pre><code>
  from models import *
  from utils.logger import *
  from utils.utils import *
  from utils.datasets import *
  from utils.parse_config import *
  from test import evaluate
  
  from terminaltables import AsciiTable
  
  import os
  import sys
  import time
  import datetime
  import argparse
  
  import torch
  from torch.utils.data import DataLoader
  from torchvision import datasets
  from torchvision import transforms
  from torch.autograd import Variable
  import torch.optim as optim
  
  if __name__ == "__main__":
      parser = argparse.ArgumentParser()
      parser.add_argument("--epochs", type=int, default=3, help="number of epochs")
      parser.add_argument("--batch_size", type=int, default=8, help="size of each image batch")
      parser.add_argument("--gradient_accumulations", type=int, default=2, help="number of gradient accums before step")
      parser.add_argument("--model_def", type=str, default="config/yolov3plate.cfg", help="path to model definition file")
      parser.add_argument("--data_config", type=str, default="config/plate.data", help="path to data config file")
      parser.add_argument("--pretrained_weights", type=str, help="if specified starts from checkpoint model")
      parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation")
      parser.add_argument("--img_size", type=int, default=416, help="size of each image dimension")
      parser.add_argument("--checkpoint_interval", type=int, default=1, help="interval between saving model weights")
      parser.add_argument("--evaluation_interval", type=int, default=1, help="interval evaluations on validation set")
      parser.add_argument("--compute_map", default=False, help="if True computes mAP every tenth batch")
      parser.add_argument("--multiscale_training", default=True, help="allow for multi-scale training")
      opt = parser.parse_args()
      print(opt)
  
      logger = Logger("logs")
  
      device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
  
      os.makedirs("output", exist_ok=True)
      os.makedirs("checkpoints", exist_ok=True)
  
      # Get data configuration
      data_config = parse_data_config(opt.data_config)
      train_path = data_config["train"]
      valid_path = data_config["valid"]
      class_names = load_classes(data_config["names"])
  
      # Initiate model
      model = Darknet(opt.model_def).to(device)
      model.apply(weights_init_normal)
  
      # If specified we start from checkpoint
      if opt.pretrained_weights:
          if opt.pretrained_weights.endswith(".pth"):
              model.load_state_dict(torch.load(opt.pretrained_weights))
          else:
              model.load_darknet_weights(opt.pretrained_weights)
  
      # Get dataloader
      dataset = ListDataset(train_path, augment=True, multiscale=opt.multiscale_training)
      dataloader = torch.utils.data.DataLoader(
          dataset,
          batch_size=opt.batch_size,
          shuffle=True,
          num_workers=opt.n_cpu,
          pin_memory=True,
          collate_fn=dataset.collate_fn,
      )
  
      optimizer = torch.optim.Adam(model.parameters())
  
      metrics = [
          "grid_size",
          "loss",
          "x",
          "y",
          "w",
          "h",
          "conf",
          "cls",
          "cls_acc",
          "recall50",
          "recall75",
          "precision",
          "conf_obj",
          "conf_noobj",
      ]
  
      for epoch in range(opt.epochs):
          model.train()
          start_time = time.time()
          for batch_i, (_, imgs, targets) in enumerate(dataloader):
              batches_done = len(dataloader) * epoch + batch_i
  
              imgs = Variable(imgs.to(device))
              targets = Variable(targets.to(device), requires_grad=False)
  
              loss, outputs = model(imgs, targets)
              loss.backward()
  
              if batches_done % opt.gradient_accumulations:
                  # Accumulates gradient before each step
                  optimizer.step()
                  optimizer.zero_grad()
  
              # ----------------
              #   Log progress
              # ----------------
  
              log_str = "\n---- [Epoch %d/%d, Batch %d/%d] ----\n" % (epoch, opt.epochs, batch_i, len(dataloader))
  
              metric_table = [["Metrics", *[f"YOLO Layer {i}" for i in range(len(model.yolo_layers))]]]
  
              # Log metrics at each YOLO layer
              for i, metric in enumerate(metrics):
                  formats = {m: "%.6f" for m in metrics}
                  formats["grid_size"] = "%2d"
                  formats["cls_acc"] = "%.2f%%"
                  row_metrics = [formats[metric] % yolo.metrics.get(metric, 0) for yolo in model.yolo_layers]
                  metric_table += [[metric, *row_metrics]]
  
                  # Tensorboard logging
                  tensorboard_log = []
                  for j, yolo in enumerate(model.yolo_layers):
                      for name, metric in yolo.metrics.items():
                          if name != "grid_size":
                              tensorboard_log += [(f"{name}_{j+1}", metric)]
                  tensorboard_log += [("loss", loss.item())]
                  logger.list_of_scalars_summary(tensorboard_log, batches_done)
  
              log_str += AsciiTable(metric_table).table
              log_str += f"\nTotal loss {loss.item()}"
  
              # Determine approximate time left for epoch
              epoch_batches_left = len(dataloader) - (batch_i + 1)
              time_left = datetime.timedelta(seconds=epoch_batches_left * (time.time() - start_time) / (batch_i + 1))
              log_str += f"\n---- ETA {time_left}"
  
              print(log_str)
  
              model.seen += imgs.size(0)
  
          if epoch % opt.evaluation_interval == 0:
              print("\n---- Evaluating Model ----")
              # Evaluate the model on the validation set
              precision, recall, AP, f1, ap_class = evaluate(
                  model,
                  path=valid_path,
                  iou_thres=0.5,
                  conf_thres=0.5,
                  nms_thres=0.5,
                  img_size=opt.img_size,
                  batch_size=8,
              )
              evaluation_metrics = [
                  ("val_precision", precision.mean()),
                  ("val_recall", recall.mean()),
                  ("val_mAP", AP.mean()),
                  ("val_f1", f1.mean()),
              ]
              logger.list_of_scalars_summary(evaluation_metrics, epoch)
  
              # Print class APs and mAP
              ap_table = [["Index", "Class name", "AP"]]
              for i, c in enumerate(ap_class):
                  ap_table += [[c, class_names[c], "%.5f" % AP[i]]]
              print(AsciiTable(ap_table).table)
              print(f"---- mAP {AP.mean()}")
  
          if epoch % opt.checkpoint_interval == 0:
              torch.save(model.state_dict(), f"checkpoints/yolov3_ckpt_%d.pth" % epoch)
  </code></pre>
  
  <p>Whenever I run the trainplate.py code, I get the following ValueErrorr: What should I do?</p>
  
  <pre><code>---- Evaluating Model ----
  Detecting objects: 0it [00:00, ?it/s]
  Traceback (most recent call last):
    File "C:/Users/jr291/Desktop/연구/PyTorch-YOLOv3/trainplate.py", line 160, in &lt;module&gt;
      batch_size=8,
    File "C:\Users\jr291\Desktop\연구\PyTorch-YOLOv3\test.py", line 53, in evaluate
      true_positives, pred_scores, pred_labels = [np.concatenate(x, 0) for x in list(zip(*sample_metrics))]
  ValueError: not enough values to unpack (expected 3, got 0)
  
  </code></pre>
  
  <p>Also, get_batch_statistics function is like below.</p>
  
  <pre><code>def get_batch_statistics(outputs, targets, iou_threshold):
      """ Compute true positives, predicted scores and predicted labels per sample """
      batch_metrics = []
      for sample_i in range(len(outputs)):
  
          if outputs[sample_i] is None:
              continue
  
          output = outputs[sample_i]
          pred_boxes = output[:, :4]
          pred_scores = output[:, 4]
          pred_labels = output[:, -1]
  
          true_positives = np.zeros(pred_boxes.shape[0])
  
          annotations = targets[targets[:, 0] == sample_i][:, 1:]
          target_labels = annotations[:, 0] if len(annotations) else []
          if len(annotations):
              detected_boxes = []
              target_boxes = annotations[:, 1:]
  
              for pred_i, (pred_box, pred_label) in enumerate(zip(pred_boxes, pred_labels)):
  
                  # If targets are found break
                  if len(detected_boxes) == len(annotations):
                      break
  
                  # Ignore if label is not one of the target labels
                  if pred_label not in target_labels:
                      continue
  
                  iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)
                  if iou &gt;= iou_threshold and box_index not in detected_boxes:
                      true_positives[pred_i] = 1
                      detected_boxes += [box_index]
          batch_metrics.append([true_positives, pred_scores, pred_labels])
      return batch_metrics
  </code></pre>