{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "# 12　覚えすぎを防ぐ\n",
    "\n",
    "FUJIMOTO LAB 深層学習コース。Web教材の図と説明を読んでから実行してください。Pythonの計算はColabの実行環境で行います。\n",
    "\n",
    "**この回の目標**：過学習を見つけ、2つの手法の違いを言える\n",
    "\n",
    "このノートブックは小さな合成データを使用し、元の教材の固定Driveパスや動画を必要としません。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "predict",
   "metadata": {},
   "source": [
    "## 1　まず予想する\n",
    "\n",
    "コードを実行する前に、表示される値や形を予想してください。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-one",
   "metadata": {},
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "torch.manual_seed(3)\n",
    "drop = nn.Dropout(p=0.5)\n",
    "x = torch.ones(8)\n",
    "print(drop(x))\n",
    "drop.eval(); print(drop(x))"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-one",
   "metadata": {},
   "source": [
    "**確かめ方**：学習時の残った値は期待値を保つよう調整されます。評価時はDropoutを止めます。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "part-two",
   "metadata": {},
   "source": [
    "## 2　BatchNormは何を調整する？\n",
    "\n",
    "Batch Normalizationはバッチの統計を使って中間の値を整えます。学習時と評価時で使う統計が異なるため、評価前にeval()へ切り替えます。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-two",
   "metadata": {},
   "source": [
    "bn = nn.BatchNorm1d(2)\n",
    "bn.train(); print(bn(torch.tensor([[1.,3.],[3.,5.]])).shape)\n",
    "bn.eval(); print(bn(torch.tensor([[2.,4.]])).shape)"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-two",
   "metadata": {},
   "source": [
    "**結果を読む**：BatchNormは出力の形を変えません。Dropoutと同じ操作ではありません。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "experiment",
   "metadata": {},
   "source": [
    "## 3　値を変えて比べる\n",
    "\n",
    "次のセルでは、表示される値や条件を変えて、何が結果を決めるかを確かめます。長くかかる実験は、少数の合成データで行います。"
   ]
  },
  {
   "cell_type": "code",
   "id": "lab",
   "metadata": {},
   "source": [
    "# 同じ入力でも、学習時と評価時でDropoutの動きが異なる\n",
    "torch.manual_seed(10)\n",
    "drop.train()\n",
    "print('学習:',drop(torch.ones(12)))\n",
    "drop.eval()\n",
    "print('評価:',drop(torch.ones(12)))\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-guide-1",
   "metadata": {},
   "source": [
    "## 追加実習 1　同じ入力を何度も通す\n",
    "\n",
    "Dropoutは学習時だけ一部をランダムに落とします。評価時には同じ入力から同じ結果が出ます。\n",
    "\n",
    "**実行前に予想**：何が変わり、何が変わらないでしょうか。"
   ]
  },
  {
   "cell_type": "code",
   "id": "extra-code-1",
   "metadata": {},
   "source": [
    "drop.train()\n",
    "training_outputs = [drop(torch.ones(8)) for _ in range(3)]\n",
    "drop.eval()\n",
    "evaluation_outputs = [drop(torch.ones(8)) for _ in range(3)]\n",
    "print('学習時の1回目:', training_outputs[0])\n",
    "print('学習時の2回目:', training_outputs[1])\n",
    "print('評価時は同じ?:', torch.equal(evaluation_outputs[0], evaluation_outputs[1]))\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-reflect-1",
   "metadata": {},
   "source": [
    "**確認**：予想と違った点を一つ書き、値を一つ変えて再実行してください。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "reflection",
   "metadata": {},
   "source": [
    "## 自分の言葉で答えよう\n",
    "\n",
    "PyTorchのDropout(p=0.2)は？\n",
    "\n",
    "- まず予想を書く\n",
    "- コードのどの行が答えを決めるか指す\n",
    "- 条件や値を1つ変えて、予想と実行結果を比べる\n",
    "\n",
    "**ヒント**：pは0にする確率です。"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "12-generalization.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
