{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "# 06　PyTorchで学習の準備\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",
    "w = torch.tensor(1.0,requires_grad=True)\n",
    "loss = (w*2-6)**2\n",
    "loss.backward()\n",
    "print(w.grad.item())"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-one",
   "metadata": {},
   "source": [
    "**確かめ方**：wを少し増やすと損失が下がる方向なので、勾配は負です。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "part-two",
   "metadata": {},
   "source": [
    "## 2　更新を1回だけ試す\n",
    "\n",
    "勾配が出たら、学習率を掛けて重みを直します。繰り返し学習では、前回の勾配を消してから次を計算します。"
   ]
  },
  {
   "cell_type": "code",
   "id": "demo-two",
   "metadata": {},
   "source": [
    "with torch.no_grad():\n",
    "    w -= 0.1*w.grad\n",
    "print(round(w.item(),2))\n",
    "print(round((w*2-6).pow(2).item(),2))"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "explain-two",
   "metadata": {},
   "source": [
    "**結果を読む**：最初の損失16から小さくなりました。学習率を大きくしすぎると逆に不安定になります。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "experiment",
   "metadata": {},
   "source": [
    "## 3　値を変えて比べる\n",
    "\n",
    "次のセルでは、表示される値や条件を変えて、何が結果を決めるかを確かめます。長くかかる実験は、少数の合成データで行います。"
   ]
  },
  {
   "cell_type": "code",
   "id": "lab",
   "metadata": {},
   "source": [
    "# 1つの重みを何度か更新し、損失の変化を追う\n",
    "w = torch.tensor(1.0,requires_grad=True)\n",
    "for step in range(5):\n",
    "    loss = (w*2-6)**2\n",
    "    loss.backward()\n",
    "    with torch.no_grad():\n",
    "        w -= 0.1*w.grad\n",
    "    print(step+1,round(w.item(),3),round(loss.item(),3))\n",
    "    w.grad.zero_()\n"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "extra-guide-1",
   "metadata": {},
   "source": [
    "## 追加実習 1　学習率を変えて比べる\n",
    "\n",
    "同じ初期値から更新します。学習率が大きすぎると損失が上下することを確かめましょう。\n",
    "\n",
    "**実行前に予想**：何が変わり、何が変わらないでしょうか。"
   ]
  },
  {
   "cell_type": "code",
   "id": "extra-code-1",
   "metadata": {},
   "source": [
    "for rate in [0.02, 0.1, 0.5]:\n",
    "    trial = torch.tensor(1.0, requires_grad=True)\n",
    "    history = []\n",
    "    for _ in range(5):\n",
    "        trial_loss = (trial*2-6)**2\n",
    "        history.append(round(trial_loss.item(), 3))\n",
    "        trial_loss.backward()\n",
    "        with torch.no_grad():\n",
    "            trial -= rate*trial.grad\n",
    "        trial.grad.zero_()\n",
    "    print('学習率', rate, '損失', history)\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": "06-pytorch.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
