YOLO-Object-Detection / yolo_loss_debug_tool.ipynb
yolo_loss_debug_tool.ipynb
Raw
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from yolo_loss import YoloLoss\n",
    "%matplotlib inline\n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Yolo Loss Debug Tool\n",
    "We provide a simple debug tool for you to debug each part of the YoloLoss class. \n",
    "\n",
    "This tool is just for helping debug and you don't need to submit any results from this notebook. \n",
    "\n",
    "We highly suggest that you first make sure your yolo function works properly, before massive training. \n",
    "\n",
    "__NOTE__:\n",
    "This tool is designed to run on CPU. If you want to run on GPU, for every input data and output data loaded, add ```.to(device)```\n",
    "- if you get device (cpu/gpu) mis-match error like \"expected type torch.FloatTensor but got torch.cuda.FloatTensor\n",
    "\", make sure all your variables have consistent device assignment inside functions.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# some help function\n",
    "def test_error(diff, test='', eps=1e-5):\n",
    "    if isinstance(diff, torch.Tensor):\n",
    "        diff = diff.cpu().detach().float()\n",
    "    print('Error is %f.' % diff)\n",
    "    if diff < eps:\n",
    "        print(\"- You pass the test for %s!\" % test)\n",
    "    else:\n",
    "        print(\"- emm.. something wrong. maybe double check your implemention.\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create A YoloLoss Instance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# don't change the hyperparameter here\n",
    "yolo = YoloLoss(S=14, B=2, l_coord=5, l_noobj=0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([4])\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor([1, 2, 3, 4])\n",
    "print(x.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test get_class_prediction_loss function\n",
    "- run the following block to check if your ```YoloLoss.get_class_prediction_loss()``` function implementation correctly.\n",
    "- Note: this test doesn't test edge cases, so passing this test doesn't guarantee bug-free. However, if you can't pass this test, then your implementation must have bug.\n",
    "- Note: This test assume your reduction method is 'sum'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "class prediction torch.Size([42, 20])\n",
      "torch.Size([42, 20])\n",
      "class target torch.Size([42, 20])\n",
      "{'class_loss': tensor(5.2598)}\n",
      "tensor(5.2598)\n",
      "Error is 0.000000.\n",
      "- You pass the test for get_class_prediction!\n"
     ]
    }
   ],
   "source": [
    "# load test cases\n",
    "func_name = 'get_class_prediction'\n",
    "input_data = torch.load(\"test_cases/%s_input.pt\" % func_name)\n",
    "class_pred = input_data['classes_pred']\n",
    "#print(class_pred.size())\n",
    "print(\"class prediction\",class_pred.shape)\n",
    "class_target = input_data['classes_target']\n",
    "print(class_target.shape)\n",
    "# print(class_target)\n",
    "# print(class_target[...,0:20])\n",
    "print(\"class target\",class_target.shape)\n",
    "output_data = torch.load(\"test_cases/%s_output.pt\" % func_name)\n",
    "print(output_data)\n",
    "gt_loss = output_data['class_loss']\n",
    "print(gt_loss)\n",
    "\n",
    "\n",
    "\n",
    "# calculate my implemented loss\n",
    "my_loss = yolo.get_class_prediction_loss(class_pred, class_target)\n",
    "\n",
    "# test the difference between my loss and the gt loss\n",
    "loss_diff = torch.sum((gt_loss - my_loss) ** 2)\n",
    "test_error(loss_diff, test=func_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test get_regression_loss function\n",
    "- run the following block to check if your ```YoloLoss.get_regression_loss()``` function implementation correctly.\n",
    "- Note: this test doesn't test edge cases, so passing this test doesn't guarantee bug-free. However, if you can't pass this test, then your implementation must have bug.\n",
    "- Note: This test assume your reduction method is 'sum'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(4.2675)\n",
      "Error is 0.000000.\n",
      "- You pass the test for get_regression!\n"
     ]
    }
   ],
   "source": [
    "# load test cases\n",
    "func_name = \"get_regression\"\n",
    "input_data = torch.load(\"test_cases/%s_input.pt\" % func_name)\n",
    "box_pred_response = input_data['box_pred_response']\n",
    "#print(box_pred_response)\n",
    "box_target_response = input_data['box_target_response']\n",
    "#print(box_pred_response)\n",
    "output_data = torch.load(\"test_cases/%s_output.pt\" % func_name)\n",
    "gt_loss = output_data['reg_loss']\n",
    "\n",
    "# calculate my implemented loss\n",
    "#my_loss = yolo.get_regression_loss(box_pred_response.cuda(), box_target_response.cuda())\n",
    "my_loss = yolo.get_regression_loss(box_pred_response , box_target_response )\n",
    "print(gt_loss)\n",
    "# test the difference between my loss and the gt loss\n",
    "loss_diff = torch.sum((gt_loss - my_loss) ** 2)\n",
    "\n",
    "test_error(loss_diff, test=func_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test get_contain_conf_loss function\n",
    "- run the following block to check if your ```YoloLoss.get_contain_conf_loss()``` function implementation correctly.\n",
    "- Note: this test doesn't test edge cases, so passing this test doesn't guarantee bug-free. However, if you can't pass this test, then your implementation must have bug."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(13.9620)\n",
      "Error is 0.000000.\n",
      "- You pass the test for get_contain_conf!\n"
     ]
    }
   ],
   "source": [
    "func_name = \"get_contain_conf\"\n",
    "input_data = torch.load(\"test_cases/%s_input.pt\" % func_name)\n",
    "box_pred_response = input_data['box_pred_response']\n",
    "box_target_response_iou = input_data['box_target_response_iou']\n",
    "output_data = torch.load(\"test_cases/%s_output.pt\" % func_name)\n",
    "gt_loss = output_data['contain_loss']\n",
    "\n",
    "# calculate my implemented loss\n",
    "my_loss = yolo.get_contain_conf_loss(box_pred_response, box_target_response_iou)\n",
    "print(gt_loss)\n",
    "# test the difference between my loss and the gt loss\n",
    "loss_diff = torch.sum((gt_loss - my_loss) ** 2)\n",
    "\n",
    "test_error(loss_diff, test=func_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test get_no_object_loss function\n",
    "- run the following block to check if your ```YoloLoss.get_no_object_loss()``` function implementation correctly.\n",
    "- Note: this test doesn't test edge cases, so passing this test doesn't guarantee bug-free. However, if you can't pass this test, then your implementation must have bug."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([24, 14, 14, 30])\n",
      "torch.Size([24, 14, 14, 30])\n",
      "torch.Size([24, 14, 14, 30])\n",
      "tensor(6.8953)\n",
      "Error is 0.000000.\n",
      "- You pass the test for no_object_loss!\n"
     ]
    }
   ],
   "source": [
    "# load test cases input\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\", category=UserWarning)\n",
    "func_name = \"no_object_loss\"\n",
    "input_data = torch.load(\"test_cases/%s_input.pt\" % func_name)\n",
    "target_tensor = input_data['target_tensor']\n",
    "pred_tensor = input_data['pred_tensor']\n",
    "no_object_mask = input_data['no_object_mask']\n",
    "output_data = torch.load(\"test_cases/%s_output.pt\" % func_name)\n",
    "gt_loss = output_data['no_object_loss']\n",
    "print(pred_tensor.shape)\n",
    "print(target_tensor.shape)\n",
    "print(no_object_mask.shape)\n",
    "\n",
    "# calculate my implemented loss\n",
    "my_loss = yolo.get_no_object_loss(target_tensor, pred_tensor, no_object_mask)\n",
    "print(my_loss)\n",
    "# test the difference between my loss and the gt loss\n",
    "loss_diff = torch.sum((gt_loss - my_loss) ** 2)\n",
    "\n",
    "test_error(loss_diff, test=func_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test find_best_iou_boxes function\n",
    "- run the following block to check if your ```YoloLoss.find_best_iou_boxes()``` function implementation correctly.\n",
    "- Note: this test doesn't test edge cases, so passing this test doesn't guarantee bug-free. However, if you can't pass this test, then your implementation must have bug."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Error is 0.000000.\n",
      "- You pass the test for the first output of best_iou_boxes!\n",
      "Error is 0.000000.\n",
      "- You pass the test for the second output of best_iou_boxes!\n",
      "False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "# load test cases input\n",
    "func_name = \"best_iou_boxes\"\n",
    "input_data = torch.load(\"test_cases/%s_input.pt\" % func_name)\n",
    "bounding_box_target = input_data['bounding_box_target']\n",
    "\n",
    "bounding_box_pred = input_data['bounding_box_pred']\n",
    "# print(bounding_box_pred.shape)\n",
    "# print(bounding_box_pred)\n",
    "output_data = torch.load(\"test_cases/%s_output.pt\" % func_name)\n",
    "gt_box_target_iou = output_data['box_target_iou']\n",
    "#print(gt_box_target_iou.shape)\n",
    "gt_contains_object_response_mask = output_data['contains_object_response_mask']\n",
    "#print(gt_contains_object_response_mask.shape)\n",
    "bounding_box_pred.requires_grad = True\n",
    "\n",
    "#print(gt_box_target_iou)\n",
    "# calculate my implemented loss\n",
    "my_box_target_iou, my_contains_object_response_mask = yolo.find_best_iou_boxes(bounding_box_target, bounding_box_pred)\n",
    "\n",
    "\n",
    "# test the error for the first output\n",
    "#print(gt_box_target_iou-my_box_target_iou < 10**-4)\n",
    "#print()\n",
    "#print(gt_box_target_iou)\n",
    "#print(my_box_target_iou)\n",
    "# for x in range(0,gt_box_target_iou.size()[0]):\n",
    "#     print(gt_box_target_iou[x,4], my_box_target_iou[x,4])\n",
    "\n",
    "iou_diff = torch.sum((gt_box_target_iou - my_box_target_iou) ** 2)\n",
    "test_error(iou_diff, test=\"the first output of %s\" % func_name) \n",
    "\n",
    "# test the error for the second output\n",
    "# print(gt_contains_object_response_mask)\n",
    "# print()\n",
    "# print(my_contains_object_response_mask)\n",
    "mask_diff = torch.sum((gt_contains_object_response_mask.long() - my_contains_object_response_mask.long()) ** 2)\n",
    "# print(\"this is the difference\", mask_diff)\n",
    "#print(gt_contains_object_response_mask.long() - my_contains_object_response_mask.long())\n",
    "#print(gt_contains_object_response_mask.long()== my_contains_object_response_mask.long())\n",
    "test_error(mask_diff, test=\"the second output of %s\" % func_name) \n",
    "print(my_box_target_iou.requires_grad)\n",
    "print(my_contains_object_response_mask.requires_grad)\n",
    "# print(gt_contains_object_response_mask)\n",
    "# print( my_contains_object_response_mask)\n",
    "#print(gt_contains_object_response_mask.long() - my_contains_object_response_mask.long())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test YoloLoss function\n",
    "- run the following block to check if your ```YoloLoss.forward()``` function implementation correctly.\n",
    "- Note: this test doesn't test edge cases, so passing this test doesn't guarantee bug-free. However, if you can't pass this test, then your implementation must have bug."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Error is 0.000000.\n",
      "- You pass the test for yolo!\n"
     ]
    }
   ],
   "source": [
    "# input_data = torch.load(\"test_cases/full_input.pt\")\n",
    "# pred_tensor = input_data['pred_tensor']\n",
    "# target_tensor = input_data['target_tensor']\n",
    "# output_data = torch.load(\"test_cases/full_output.pt\")\n",
    "# gt_loss = output_data['total_loss']\n",
    "\n",
    "# # calculate my implemented loss\n",
    "# my_loss = yolo(pred_tensor, target_tensor)\n",
    "\n",
    "# # test the difference between my loss and the gt loss\n",
    "# test_error(loss_diff, test=\"yolo\")    \n",
    "\n",
    "\n",
    "input_data = torch.load(\"test_cases/full_input.pt\")\n",
    "pred_tensor = input_data['pred_tensor']\n",
    "target_tensor = input_data['target_tensor']\n",
    "output_data = torch.load(\"test_cases/full_output.pt\")\n",
    "gt_loss = output_data['total_loss']\n",
    "##################################\n",
    "# from new_yolo_loss import yoloLoss\n",
    "# new_yolo = yoloLoss(S=14, B=2, l_coord=5, l_noobj=0.5)\n",
    "# my_loss = new_yolo(pred_tensor, target_tensor)\n",
    "################################\n",
    "# calculate my implemented loss\n",
    "my_loss = yolo(pred_tensor, target_tensor)\n",
    "\n",
    "# (this line was missing)\n",
    "loss_diff = torch.sum((gt_loss - my_loss) ** 2)\n",
    "\n",
    "# test the difference between my loss and the gt loss\n",
    "test_error(loss_diff, test=\"yolo\")   \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}