{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "# 10　画像の数値を同じ基準で比べる\n",
    "\n",
    "FUJIMOTO LAB 深層学習コース。Web教材の図と説明を読んでから実行してください。Pythonの計算はColabの実行環境で行います。\n",
    "\n",
    "**この回の目標**：画像の数値を正規化する理由と、平均・標準偏差の役割を説明できる\n",
    "\n",
    "このノートブックは小さな合成データを使用し、元の教材の固定Driveパスや動画を必要としません。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "predict",
   "metadata": {},
   "source": [
    "## 1　まず予想する\n",
    "\n",
    "コードを実行する前に、表示される値や形を予想してください。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-one",
   "metadata": {},
   "source": [
    "import torch\n",
    "image = torch.tensor([[0.,2.],[4.,6.]])\n",
    "mean = image.mean()\n",
    "std = image.std(unbiased=False)\n",
    "print(mean.item(),round(std.item(),3))"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-one",
   "metadata": {},
   "source": [
    "**確かめ方**：4画素の平均は3です。このコードでは計算のしくみを示すため1枚の例を使いますが、実際に学習へ使う平均と標準偏差は学習用画像全体から求めます。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "part-two",
   "metadata": {},
   "source": [
    "## 2　同じ基準で変換する\n",
    "\n",
    "テスト用画像ごとに平均と標準偏差を求め直さず、学習用画像から決めた値を使います。そうすれば、学習時と評価時に同じ計算を適用できます。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-two",
   "metadata": {},
   "source": [
    "normalized = (image-mean)/std\n",
    "print(normalized.mean().item())\n",
    "print(torch.round(normalized*100)/100)"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-two",
   "metadata": {},
   "source": [
    "**結果を読む**：平均を引いて中心を0にします。標準偏差が0に近い場合は、割り算の前に対策が必要です。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "experiment",
   "metadata": {},
   "source": [
    "## 3　値を変えて比べる\n",
    "\n",
    "次のセルでは、表示される値や条件を変えて、何が結果を決めるかを確かめます。長くかかる実験は、少数の合成データで行います。"
   ]
  },
  {
   "cell_type": "code",
   "id": "lab",
   "metadata": {},
   "source": [
    "# 学習用で決めた基準を、別の画像にも同じように使う\n",
    "test_image = torch.tensor([[1.,3.],[5.,7.]])\n",
    "print(torch.round(((test_image-mean)/std)*100)/100)\n",
    "print('学習用で求めた平均:',mean.item())\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-guide-1",
   "metadata": {},
   "source": [
    "## 追加実習 1　標準化の目安を確かめる\n",
    "\n",
    "平均を引いて標準偏差で割ると、学習用画像の平均はほぼ0、標準偏差はほぼ1になります。\n",
    "\n",
    "**実行前に予想**：何が変わり、何が変わらないでしょうか。"
   ]
  },
  {
   "cell_type": "code",
   "id": "extra-code-1",
   "metadata": {},
   "source": [
    "print('元の平均・標準偏差:', image.mean().item(), image.std(unbiased=False).item())\n",
    "print('標準化後の平均:', round(normalized.mean().item(), 6))\n",
    "print('標準化後の標準偏差:', round(normalized.std(unbiased=False).item(), 6))\n",
    "print('画像の値が全部同じなら標準偏差0になり、割れません。')\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-reflect-1",
   "metadata": {},
   "source": [
    "**確認**：予想と違った点を一つ書き、値を一つ変えて再実行してください。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "reflection",
   "metadata": {},
   "source": [
    "## 自分の言葉で答えよう\n",
    "\n",
    "テスト画像を正規化するときの平均は？\n",
    "\n",
    "- まず予想を書く\n",
    "- コードのどの行が答えを決めるか指す\n",
    "- 条件や値を1つ変えて、予想と実行結果を比べる\n",
    "\n",
    "**ヒント**：テストへも学習用で決めた同じ基準を適用します。"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "10-normalization.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
