├── LICENSE ├── README.md ├── section_1 ├── 02_exercise.ipynb └── 01_tensor.ipynb ├── python_basic ├── python_basic_4.ipynb ├── python_basic_1.ipynb ├── python_basic_3.ipynb └── python_basic_2.ipynb ├── section_3 ├── 03_vgg.ipynb ├── 01_alexnet.ipynb ├── 02_googlenet.ipynb └── 04_exercise.ipynb ├── section_4 ├── 01_resnet.ipynb ├── 03_mobilenet.ipynb ├── 02_densenet.ipynb └── 04_exercise.ipynb ├── section_5 └── 01_vision_transformer.ipynb └── section_2 ├── 01_data_augmentation.ipynb ├── 02_cnn.ipynb └── 03_exercise.ipynb /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 yuky_az 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AIによる画像分類を学ぼう!【PyTorch+Colab】 2 | 「AIによる画像分類を学ぼう!」は、CNN(畳み込みニューラルネットワーク)などをベースにした画像分類技術を学ぶ講座です。 3 | フレームワークにPyTorchを使い、Google Colaboratory環境で様々な画像分類のモデルを実装します。 4 | AIによる画像分類は第3次AIブームのきっかけになった技術であり、応用範囲が広く多様な分野で使われています。 5 | 6 | Section1. 画像分類の概要 7 | → 画像分類の概要、および開発環境について学びます。 8 | 9 | Section2. CNNの基礎 10 | → 様々な画像分類技術のベースとなる、CNN(畳み込みニューラルネットワーク)について学びます。 11 | 12 | Section3. Section4. 有名モデルの実装 13 | → AlexNet、ResNet、MobileNetなどの様々な有名モデルを実装します。 14 | 15 | Section5. Transformerの利用 16 | → 「Transoformer」を利用した画像分類モデルを構築します。 17 | 18 | Udemyコース: [AIによる画像分類を学ぼう!](https://www.udemy.com/course/image-classification/?referralCode=88A1CF3B4CB8B36E2FEF) 19 | 20 | ### 自由研究室 AIRS-Lab(コミュニティ) 21 | 「AI」をテーマに交流し、創造するWeb上のコミュニティです。 22 | https://www.airs-lab.jp/ 23 | 24 | ### News! AIRS-Lab(メルマガ) 25 | AIの話題、講義動画、Udemyコース割引などのAIRS-Lab最新コンテンツをメールで配信します。 26 | https://www.airs-lab.jp/newsletter 27 | 28 | ### AI教室 AIRS-Lab(YouTubeチャンネル) 29 | 毎週月曜日21時に、YouTubeでライブ講義を開催しています。 30 | https://www.youtube.com/channel/UCT_HwlT8bgYrpKrEvw0jH7Q 31 | 32 | ### Udemyコース 33 | オンライン動画学習プラットフォームUdemyで、AI関連のコースを複数展開しています。 34 | https://www.airs-lab.jp/lectures 35 | -------------------------------------------------------------------------------- /section_1/02_exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "02_exercise.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyMxO9hS1zzHAL995I+28SD5", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "language_info": { 17 | "name": "python" 18 | } 19 | }, 20 | "cells": [ 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "id": "view-in-github", 25 | "colab_type": "text" 26 | }, 27 | "source": [ 28 | "\"Open" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": { 34 | "id": "l1iDDDhCGdRk" 35 | }, 36 | "source": [ 37 | "# 演習\n", 38 | "Tensor同士の演算を練習しましょう。 " 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "source": [ 44 | "## Tensor同士の演算\n", 45 | "以下のコードにおけるTensor、`a`と`b`の間で演算を行い、結果を表示しましょう。 \n", 46 | "`a`は2次元のTensorで`b`は1次元のTensorなので、ブロードキャストが必要です。 " 47 | ], 48 | "metadata": { 49 | "id": "Jc1YsICDjmgv" 50 | } 51 | }, 52 | { 53 | "cell_type": "code", 54 | "metadata": { 55 | "id": "vQjm5IIwFzfQ" 56 | }, 57 | "source": [ 58 | "import torch\n", 59 | "\n", 60 | "a = torch.tensor([[11, 12, 13],\n", 61 | " [14, 15, 16]])\n", 62 | "b = torch.tensor([1, 2, 3]) \n", 63 | "\n", 64 | "print(\"--- 和 ---\")\n", 65 | "\n", 66 | "\n", 67 | "print(\"--- 差 ---\")\n", 68 | "\n", 69 | "\n", 70 | "print(\"--- 積 ---\")\n", 71 | "\n", 72 | "\n", 73 | "print(\"--- 商(小数) ---\")\n", 74 | "\n", 75 | "\n", 76 | "print(\"--- 商(整数) ---\")\n", 77 | "\n", 78 | "\n", 79 | "print(\"--- 余り ---\")\n" 80 | ], 81 | "execution_count": null, 82 | "outputs": [] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": { 87 | "id": "BEW_lUs3PJCQ" 88 | }, 89 | "source": [ 90 | "### 〇解答例\n", 91 | "以下は解答例です。" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "metadata": { 97 | "id": "imyJ_CUEPNgW" 98 | }, 99 | "source": [ 100 | "import torch\n", 101 | "\n", 102 | "a = torch.tensor([[11, 12, 13],\n", 103 | " [14, 15, 16]])\n", 104 | "b = torch.tensor([1, 2, 3]) \n", 105 | "\n", 106 | "print(\"--- 和 ---\")\n", 107 | "print(a + b)\n", 108 | "\n", 109 | "print(\"--- 差 ---\")\n", 110 | "print(a - b)\n", 111 | "\n", 112 | "print(\"--- 積 ---\")\n", 113 | "print(a * b)\n", 114 | "\n", 115 | "print(\"--- 商(小数) ---\")\n", 116 | "print(a / b)\n", 117 | "\n", 118 | "print(\"--- 商(整数) ---\")\n", 119 | "print(a // b)\n", 120 | "\n", 121 | "print(\"--- 余り ---\")\n", 122 | "print(a % b)" 123 | ], 124 | "execution_count": null, 125 | "outputs": [] 126 | } 127 | ] 128 | } -------------------------------------------------------------------------------- /python_basic/python_basic_4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "python_basic_4.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyN3hNu8RarK8NNezVjCT2mF", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "ewg_pUrO-m3m" 32 | }, 33 | "source": [ 34 | "# Pythonの基礎4\n", 35 | "Pythonの特殊なメソッドを解説します。 \n", 36 | "これらを活用することで、より短くて読みやすいコードを記述することが可能になります。" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": { 42 | "id": "BxlxFRAm-m3o" 43 | }, 44 | "source": [ 45 | "## ●`__init__`メソッド\n", 46 | "**`__init__`**は特殊なメソッドで、イニシャライザ、もしくはコンストラクタと呼ばれています。 \n", 47 | "このメソッドでは、インスタンスの生成時にインスタンスの初期設定を行うことができます。 \n", 48 | "以下のクラスでは、`__init__`メソッドでインスタンス変数aの初期設定を行っています。 " 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "metadata": { 54 | "id": "xftbx6T4-m3p" 55 | }, 56 | "source": [ 57 | "class Calc: # Calcクラス\n", 58 | " def __init__(self, a): # __init__メソッド\n", 59 | " self.a = a\n", 60 | "\n", 61 | " def add(self, b): # addメソッド\n", 62 | " print(self.a + b)\n", 63 | "\n", 64 | " def multiply(self, b): # multiplyメソッド\n", 65 | " print(self.a * b)" 66 | ], 67 | "execution_count": null, 68 | "outputs": [] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "metadata": { 73 | "id": "wrO8sv-WZHuo" 74 | }, 75 | "source": [ 76 | "# 練習用\n" 77 | ], 78 | "execution_count": null, 79 | "outputs": [] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": { 84 | "id": "L8xd1JMv-m3s" 85 | }, 86 | "source": [ 87 | "以下では、インスタンスの生成時に、3という値をインスタンスに渡しています。 \n", 88 | "この保持された値は、後で計算に利用することができます。 " 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "metadata": { 94 | "id": "-Tnd7UjE-m3t" 95 | }, 96 | "source": [ 97 | "cl = Calc(3) # インスタンスclを生成\n", 98 | "cl.add(4) # 3 + 4\n", 99 | "cl.multiply(4) # 3 × 4" 100 | ], 101 | "execution_count": null, 102 | "outputs": [] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "metadata": { 107 | "id": "cAZfsS-vZKeC" 108 | }, 109 | "source": [ 110 | "# 練習用\n" 111 | ], 112 | "execution_count": null, 113 | "outputs": [] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": { 118 | "id": "jH5DBIKLMpTn" 119 | }, 120 | "source": [ 121 | "このように、`__init__`メソッドを使えばインスタンスの生成時にインスタンスに値を渡すことができます。 \n", 122 | "そのため、何度も繰り返して使用したり、複数のメソッドで使う値があれば、`__init__`メソッドで設定するのが効率的になります。" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": { 128 | "id": "5iaX234BO1_c" 129 | }, 130 | "source": [ 131 | "## ●`__call__`メソッド\n", 132 | "`__call__`メソッドは、インスタンス名を使って呼び出すことができます。 \n", 133 | "以下では、`Calc`クラスに`__init__`メソッドの他に`__call__`メソッドを実装しています。" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "metadata": { 139 | "id": "_7Ct9UGnO1_p" 140 | }, 141 | "source": [ 142 | "class Calc: # Calcクラス\n", 143 | " def __init__(self, a): # __init__メソッド\n", 144 | " self.a = a\n", 145 | "\n", 146 | " def __call__(self, c): # __call__メソッド\n", 147 | " print(self.a * c + c)\n", 148 | "\n", 149 | " def add(self, b): # addメソッド\n", 150 | " print(self.a + b)\n", 151 | "\n", 152 | " def multiply(self, b): # multiplyメソッド\n", 153 | " print(self.a * b)" 154 | ], 155 | "execution_count": null, 156 | "outputs": [] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "metadata": { 161 | "id": "8t66JIKtO1_q" 162 | }, 163 | "source": [ 164 | "# 練習用\n" 165 | ], 166 | "execution_count": null, 167 | "outputs": [] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": { 172 | "id": "zk0O973kRR88" 173 | }, 174 | "source": [ 175 | "以下では、インスタンスの名`cl`を使って`__call__`メソッドを呼び出しています。 " 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "metadata": { 181 | "id": "TJnm8GNxRR9I" 182 | }, 183 | "source": [ 184 | "cl = Calc(3) # インスタンスclを生成\n", 185 | "\n", 186 | "# インスタンス名clを使って__call__メソッドを呼ぶ\n", 187 | "cl(5) # 3 × 5 + 5" 188 | ], 189 | "execution_count": null, 190 | "outputs": [] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "metadata": { 195 | "id": "JXfHeV4ORR9J" 196 | }, 197 | "source": [ 198 | "# 練習用\n" 199 | ], 200 | "execution_count": null, 201 | "outputs": [] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": { 206 | "id": "5Vw5ZL6xRR9J" 207 | }, 208 | "source": [ 209 | "このように、`__call__`メソッドを使えばメソッド名を記述する必要が無くなります。 \n", 210 | "頻繁に用いる処理を`__call__`メソッドに記述しておくことで、コードの記述量が少なくて済むようになります。" 211 | ] 212 | } 213 | ] 214 | } -------------------------------------------------------------------------------- /section_3/03_vgg.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "03_vgg.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# VGGの実装\n", 35 | "PyTorchを使って、VGGを実装します。 \n", 36 | "torchvisionには訓練済みのVGGがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、VGGに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | "\n", 54 | "VGG(PyTorch): https://pytorch.org/hub/pytorch_vision_vgg/" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "7t3NRHjhKyC0" 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "\n", 67 | "transform = transforms.Compose([\n", 68 | " transforms.Resize(256), # 短い方の辺を256に\n", 69 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 72 | "])\n", 73 | "\n", 74 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 75 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 76 | "\n", 77 | "# DataLoaderの設定\n", 78 | "batch_size = 64\n", 79 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 80 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": { 88 | "id": "FalXNYaJPkoE" 89 | }, 90 | "source": [ 91 | "## モデルの読み込み\n", 92 | "torchvisionを使い、VGGの訓練済みモデルを読み込みます。 \n", 93 | "https://pytorch.org/vision/stable/generated/torchvision.models.vgg11.html \n", 94 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "source": [ 100 | "import torchvision.models as models\n", 101 | "\n", 102 | "net = models.vgg11(pretrained=True)\n", 103 | "print(net)" 104 | ], 105 | "metadata": { 106 | "id": "miHLxB2xVAmz" 107 | }, 108 | "execution_count": null, 109 | "outputs": [] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "source": [ 114 | "## 各層の設定\n", 115 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 116 | "今回は、分類器の出力層のみ訓練します。 \n" 117 | ], 118 | "metadata": { 119 | "id": "Se1cFI_GEisR" 120 | } 121 | }, 122 | { 123 | "cell_type": "code", 124 | "metadata": { 125 | "id": "SuqqZmsh_jNK" 126 | }, 127 | "source": [ 128 | "import torch.nn as nn\n", 129 | "\n", 130 | "# 全ての層のパラメータを訓練不可に\n", 131 | "for param in net.parameters():\n", 132 | " param.requires_grad = False\n", 133 | "\n", 134 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 135 | "net.classifier[6] = nn.Linear(4096,10)\n", 136 | "\n", 137 | "net.cuda() # GPU対応\n", 138 | "print(net)" 139 | ], 140 | "execution_count": null, 141 | "outputs": [] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": { 146 | "id": "qsW5zCKhQE9p" 147 | }, 148 | "source": [ 149 | "## 学習\n", 150 | "モデルの訓練を行います。 \n", 151 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "metadata": { 157 | "id": "u6zwN3nArbGC" 158 | }, 159 | "source": [ 160 | "from typing import NewType\n", 161 | "from torch import optim\n", 162 | "\n", 163 | "# 交差エントロピー誤差関数\n", 164 | "loss_fnc = nn.CrossEntropyLoss()\n", 165 | "\n", 166 | "# 最適化アルゴリズム\n", 167 | "optimizer = optim.Adam(net.parameters())\n", 168 | "\n", 169 | "# 損失のログ\n", 170 | "record_loss_train = []\n", 171 | "record_loss_test = []\n", 172 | "\n", 173 | "# 学習\n", 174 | "for i in range(6): # 6エポック学習\n", 175 | " net.train() # 訓練モード\n", 176 | " loss_train = 0\n", 177 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 178 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 179 | " y = net(x)\n", 180 | " loss = loss_fnc(y, t)\n", 181 | " loss_train += loss.item()\n", 182 | " optimizer.zero_grad()\n", 183 | " loss.backward()\n", 184 | " optimizer.step()\n", 185 | " loss_train /= j+1\n", 186 | " record_loss_train.append(loss_train)\n", 187 | "\n", 188 | " net.eval() # 評価モード\n", 189 | " loss_test = 0\n", 190 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 191 | " x, t = x.cuda(), t.cuda()\n", 192 | " y = net(x)\n", 193 | " loss = loss_fnc(y, t)\n", 194 | " loss_test += loss.item()\n", 195 | " loss_test /= j+1\n", 196 | " record_loss_test.append(loss_test)\n", 197 | "\n", 198 | " if i%1 == 0:\n", 199 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 200 | ], 201 | "execution_count": null, 202 | "outputs": [] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": { 207 | "id": "rJwwrWTw43rx" 208 | }, 209 | "source": [ 210 | "## 誤差の推移\n", 211 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "metadata": { 217 | "id": "OaJx4swE45XI" 218 | }, 219 | "source": [ 220 | "import matplotlib.pyplot as plt\n", 221 | "\n", 222 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 223 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 224 | "plt.legend()\n", 225 | "\n", 226 | "plt.xlabel(\"Epochs\")\n", 227 | "plt.ylabel(\"Error\")\n", 228 | "plt.show()" 229 | ], 230 | "execution_count": null, 231 | "outputs": [] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": { 236 | "id": "iMrpac0m4Nct" 237 | }, 238 | "source": [ 239 | "## 正解率\n", 240 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "metadata": { 246 | "id": "IRkGCYMM_N35" 247 | }, 248 | "source": [ 249 | "correct = 0\n", 250 | "total = 0\n", 251 | "net.eval() # 評価モード\n", 252 | "for i, (x, t) in enumerate(test_loader):\n", 253 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 254 | " y = net(x)\n", 255 | " correct += (y.argmax(1) == t).sum().item()\n", 256 | " total += len(x)\n", 257 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 258 | ], 259 | "execution_count": null, 260 | "outputs": [] 261 | } 262 | ] 263 | } -------------------------------------------------------------------------------- /section_4/01_resnet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "01_resnet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# ResNetの実装\n", 35 | "PyTorchを使って、ResNetを実装します。 \n", 36 | "torchvisionには訓練済みのResNetがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、ResNetに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | "\n", 54 | "ResNet(PyTorch): https://pytorch.org/hub/pytorch_vision_resnet/" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "7t3NRHjhKyC0" 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "\n", 67 | "transform = transforms.Compose([\n", 68 | " transforms.Resize(256), # 短い方の辺を256に\n", 69 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 72 | "])\n", 73 | "\n", 74 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 75 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 76 | "\n", 77 | "# DataLoaderの設定\n", 78 | "batch_size = 64\n", 79 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 80 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": { 88 | "id": "FalXNYaJPkoE" 89 | }, 90 | "source": [ 91 | "## モデルの読み込み\n", 92 | "torchvisionを使い、ResNetの訓練済みモデルを読み込みます。 \n", 93 | "今回は、層の数が一番少なくてシンプルな`resnet18`を使用します。 \n", 94 | "https://pytorch.org/vision/stable/generated/torchvision.models.resnet18.html \n", 95 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "source": [ 101 | "import torchvision.models as models\n", 102 | "\n", 103 | "net = models.resnet18(pretrained=True)\n", 104 | "print(net)" 105 | ], 106 | "metadata": { 107 | "id": "miHLxB2xVAmz" 108 | }, 109 | "execution_count": null, 110 | "outputs": [] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "source": [ 115 | "## 各層の設定\n", 116 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 117 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n" 118 | ], 119 | "metadata": { 120 | "id": "Se1cFI_GEisR" 121 | } 122 | }, 123 | { 124 | "cell_type": "code", 125 | "metadata": { 126 | "id": "SuqqZmsh_jNK" 127 | }, 128 | "source": [ 129 | "import torch.nn as nn\n", 130 | "\n", 131 | "# 全ての層のパラメータを訓練不可に\n", 132 | "for param in net.parameters():\n", 133 | " param.requires_grad = False\n", 134 | "\n", 135 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 136 | "net.fc = nn.Linear(512, 10)\n", 137 | "\n", 138 | "net.cuda() # GPU対応\n", 139 | "print(net)" 140 | ], 141 | "execution_count": null, 142 | "outputs": [] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": { 147 | "id": "qsW5zCKhQE9p" 148 | }, 149 | "source": [ 150 | "## 学習\n", 151 | "モデルを訓練します。 \n", 152 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "metadata": { 158 | "id": "u6zwN3nArbGC" 159 | }, 160 | "source": [ 161 | "from torch import optim\n", 162 | "\n", 163 | "# 交差エントロピー誤差関数\n", 164 | "loss_fnc = nn.CrossEntropyLoss()\n", 165 | "\n", 166 | "# 最適化アルゴリズム\n", 167 | "optimizer = optim.Adam(net.parameters())\n", 168 | "\n", 169 | "# 損失のログ\n", 170 | "record_loss_train = []\n", 171 | "record_loss_test = []\n", 172 | "\n", 173 | "# 学習\n", 174 | "for i in range(6): # 6エポック学習\n", 175 | " net.train() # 訓練モード\n", 176 | " loss_train = 0\n", 177 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 178 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 179 | " y = net(x)\n", 180 | " loss = loss_fnc(y, t)\n", 181 | " loss_train += loss.item()\n", 182 | " optimizer.zero_grad()\n", 183 | " loss.backward()\n", 184 | " optimizer.step()\n", 185 | " loss_train /= j+1\n", 186 | " record_loss_train.append(loss_train)\n", 187 | "\n", 188 | " net.eval() # 評価モード\n", 189 | " loss_test = 0\n", 190 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 191 | " x, t = x.cuda(), t.cuda()\n", 192 | " y = net(x)\n", 193 | " loss = loss_fnc(y, t)\n", 194 | " loss_test += loss.item()\n", 195 | " loss_test /= j+1\n", 196 | " record_loss_test.append(loss_test)\n", 197 | "\n", 198 | " if i%1 == 0:\n", 199 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 200 | ], 201 | "execution_count": null, 202 | "outputs": [] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": { 207 | "id": "rJwwrWTw43rx" 208 | }, 209 | "source": [ 210 | "## 誤差の推移\n", 211 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "metadata": { 217 | "id": "OaJx4swE45XI" 218 | }, 219 | "source": [ 220 | "import matplotlib.pyplot as plt\n", 221 | "\n", 222 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 223 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 224 | "plt.legend()\n", 225 | "\n", 226 | "plt.xlabel(\"Epochs\")\n", 227 | "plt.ylabel(\"Error\")\n", 228 | "plt.show()" 229 | ], 230 | "execution_count": null, 231 | "outputs": [] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": { 236 | "id": "iMrpac0m4Nct" 237 | }, 238 | "source": [ 239 | "## 正解率\n", 240 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "metadata": { 246 | "id": "IRkGCYMM_N35" 247 | }, 248 | "source": [ 249 | "correct = 0\n", 250 | "total = 0\n", 251 | "net.eval() # 評価モード\n", 252 | "for i, (x, t) in enumerate(test_loader):\n", 253 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 254 | " y = net(x)\n", 255 | " correct += (y.argmax(1) == t).sum().item()\n", 256 | " total += len(x)\n", 257 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 258 | ], 259 | "execution_count": null, 260 | "outputs": [] 261 | } 262 | ] 263 | } -------------------------------------------------------------------------------- /section_4/03_mobilenet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "03_mobilenet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# MobileNetの実装\n", 35 | "PyTorchを使って、MobileNetを実装します。 \n", 36 | "torchvisionには訓練済みのMobileNetがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、MobileNetに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | "\n", 54 | "MobileNet V2(PyTorch): https://pytorch.org/hub/pytorch_vision_mobilenet_v2/" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "7t3NRHjhKyC0" 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "\n", 67 | "transform = transforms.Compose([\n", 68 | " transforms.Resize(256), # 短い方の辺を256に\n", 69 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 72 | "])\n", 73 | "\n", 74 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 75 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 76 | "\n", 77 | "# DataLoaderの設定\n", 78 | "batch_size = 64\n", 79 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 80 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": { 88 | "id": "FalXNYaJPkoE" 89 | }, 90 | "source": [ 91 | "## モデルの読み込み\n", 92 | "torchvisionを使い、MobileNetの訓練済みモデルを読み込みます。 \n", 93 | "https://pytorch.org/vision/stable/generated/torchvision.models.mobilenet_v2.html \n", 94 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "source": [ 100 | "import torchvision.models as models\n", 101 | "\n", 102 | "net = models.mobilenet_v2(pretrained=True)\n", 103 | "print(net)" 104 | ], 105 | "metadata": { 106 | "id": "miHLxB2xVAmz" 107 | }, 108 | "execution_count": null, 109 | "outputs": [] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "source": [ 114 | "## 各層の設定\n", 115 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 116 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n" 117 | ], 118 | "metadata": { 119 | "id": "Se1cFI_GEisR" 120 | } 121 | }, 122 | { 123 | "cell_type": "code", 124 | "metadata": { 125 | "id": "SuqqZmsh_jNK" 126 | }, 127 | "source": [ 128 | "import torch.nn as nn\n", 129 | "\n", 130 | "# 全ての層のパラメータを訓練不可に\n", 131 | "for param in net.parameters():\n", 132 | " param.requires_grad = False\n", 133 | "\n", 134 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 135 | "net.classifier[1] = nn.Linear(1280, 10)\n", 136 | "\n", 137 | "net.cuda() # GPU対応\n", 138 | "print(net)" 139 | ], 140 | "execution_count": null, 141 | "outputs": [] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": { 146 | "id": "qsW5zCKhQE9p" 147 | }, 148 | "source": [ 149 | "## 学習\n", 150 | "モデルを訓練します。 \n", 151 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "metadata": { 157 | "id": "u6zwN3nArbGC" 158 | }, 159 | "source": [ 160 | "from torch import optim\n", 161 | "\n", 162 | "# 交差エントロピー誤差関数\n", 163 | "loss_fnc = nn.CrossEntropyLoss()\n", 164 | "\n", 165 | "# 最適化アルゴリズム\n", 166 | "optimizer = optim.Adam(net.parameters())\n", 167 | "\n", 168 | "# 損失のログ\n", 169 | "record_loss_train = []\n", 170 | "record_loss_test = []\n", 171 | "\n", 172 | "# 学習\n", 173 | "for i in range(6): # 6エポック学習\n", 174 | " net.train() # 訓練モード\n", 175 | " loss_train = 0\n", 176 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 177 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 178 | " y = net(x)\n", 179 | " loss = loss_fnc(y, t)\n", 180 | " loss_train += loss.item()\n", 181 | " optimizer.zero_grad()\n", 182 | " loss.backward()\n", 183 | " optimizer.step()\n", 184 | " loss_train /= j+1\n", 185 | " record_loss_train.append(loss_train)\n", 186 | "\n", 187 | " net.eval() # 評価モード\n", 188 | " loss_test = 0\n", 189 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 190 | " x, t = x.cuda(), t.cuda()\n", 191 | " y = net(x)\n", 192 | " loss = loss_fnc(y, t)\n", 193 | " loss_test += loss.item()\n", 194 | " loss_test /= j+1\n", 195 | " record_loss_test.append(loss_test)\n", 196 | "\n", 197 | " if i%1 == 0:\n", 198 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 199 | ], 200 | "execution_count": null, 201 | "outputs": [] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": { 206 | "id": "rJwwrWTw43rx" 207 | }, 208 | "source": [ 209 | "## 誤差の推移\n", 210 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "metadata": { 216 | "id": "OaJx4swE45XI" 217 | }, 218 | "source": [ 219 | "import matplotlib.pyplot as plt\n", 220 | "\n", 221 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 222 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 223 | "plt.legend()\n", 224 | "\n", 225 | "plt.xlabel(\"Epochs\")\n", 226 | "plt.ylabel(\"Error\")\n", 227 | "plt.show()" 228 | ], 229 | "execution_count": null, 230 | "outputs": [] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": { 235 | "id": "iMrpac0m4Nct" 236 | }, 237 | "source": [ 238 | "## 正解率\n", 239 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "metadata": { 245 | "id": "IRkGCYMM_N35" 246 | }, 247 | "source": [ 248 | "correct = 0\n", 249 | "total = 0\n", 250 | "net.eval() # 評価モード\n", 251 | "for i, (x, t) in enumerate(test_loader):\n", 252 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 253 | " y = net(x)\n", 254 | " correct += (y.argmax(1) == t).sum().item()\n", 255 | " total += len(x)\n", 256 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 257 | ], 258 | "execution_count": null, 259 | "outputs": [] 260 | } 261 | ] 262 | } -------------------------------------------------------------------------------- /section_4/02_densenet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "02_densenet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# DenseNetの実装\n", 35 | "PyTorchを使って、DenseNetを実装します。 \n", 36 | "torchvisionには訓練済みのDenseNetがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、DenseNetに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | "\n", 54 | "DenseNet(PyTorch): https://pytorch.org/hub/pytorch_vision_densenet/" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "7t3NRHjhKyC0" 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "\n", 67 | "transform = transforms.Compose([\n", 68 | " transforms.Resize(256), # 短い方の辺を256に\n", 69 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 72 | "])\n", 73 | "\n", 74 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 75 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 76 | "\n", 77 | "# DataLoaderの設定\n", 78 | "batch_size = 64\n", 79 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 80 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": { 88 | "id": "FalXNYaJPkoE" 89 | }, 90 | "source": [ 91 | "## モデルの読み込み\n", 92 | "torchvisionを使い、DenseNetの訓練済みモデルを読み込みます。 \n", 93 | "今回は、層の数が一番少なくてシンプルな`densenet121`を使用します。 \n", 94 | "https://pytorch.org/vision/stable/generated/torchvision.models.densenet121.html \n", 95 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "source": [ 101 | "import torchvision.models as models\n", 102 | "\n", 103 | "net = models.densenet121(pretrained=True)\n", 104 | "print(net)" 105 | ], 106 | "metadata": { 107 | "id": "miHLxB2xVAmz" 108 | }, 109 | "execution_count": null, 110 | "outputs": [] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "source": [ 115 | "## 各層の設定\n", 116 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 117 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n" 118 | ], 119 | "metadata": { 120 | "id": "Se1cFI_GEisR" 121 | } 122 | }, 123 | { 124 | "cell_type": "code", 125 | "metadata": { 126 | "id": "SuqqZmsh_jNK" 127 | }, 128 | "source": [ 129 | "import torch.nn as nn\n", 130 | "\n", 131 | "# 全ての層のパラメータを訓練不可に\n", 132 | "for param in net.parameters():\n", 133 | " param.requires_grad = False\n", 134 | "\n", 135 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 136 | "net.classifier = nn.Linear(1024, 10)\n", 137 | "\n", 138 | "net.cuda() # GPU対応\n", 139 | "print(net)" 140 | ], 141 | "execution_count": null, 142 | "outputs": [] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": { 147 | "id": "qsW5zCKhQE9p" 148 | }, 149 | "source": [ 150 | "## 学習\n", 151 | "モデルを訓練します。 \n", 152 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "metadata": { 158 | "id": "u6zwN3nArbGC" 159 | }, 160 | "source": [ 161 | "from torch import optim\n", 162 | "\n", 163 | "# 交差エントロピー誤差関数\n", 164 | "loss_fnc = nn.CrossEntropyLoss()\n", 165 | "\n", 166 | "# 最適化アルゴリズム\n", 167 | "optimizer = optim.Adam(net.parameters())\n", 168 | "\n", 169 | "# 損失のログ\n", 170 | "record_loss_train = []\n", 171 | "record_loss_test = []\n", 172 | "\n", 173 | "# 学習\n", 174 | "for i in range(6): # 6エポック学習\n", 175 | " net.train() # 訓練モード\n", 176 | " loss_train = 0\n", 177 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 178 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 179 | " y = net(x)\n", 180 | " loss = loss_fnc(y, t)\n", 181 | " loss_train += loss.item()\n", 182 | " optimizer.zero_grad()\n", 183 | " loss.backward()\n", 184 | " optimizer.step()\n", 185 | " loss_train /= j+1\n", 186 | " record_loss_train.append(loss_train)\n", 187 | "\n", 188 | " net.eval() # 評価モード\n", 189 | " loss_test = 0\n", 190 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 191 | " x, t = x.cuda(), t.cuda()\n", 192 | " y = net(x)\n", 193 | " loss = loss_fnc(y, t)\n", 194 | " loss_test += loss.item()\n", 195 | " loss_test /= j+1\n", 196 | " record_loss_test.append(loss_test)\n", 197 | "\n", 198 | " if i%1 == 0:\n", 199 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 200 | ], 201 | "execution_count": null, 202 | "outputs": [] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": { 207 | "id": "rJwwrWTw43rx" 208 | }, 209 | "source": [ 210 | "## 誤差の推移\n", 211 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "metadata": { 217 | "id": "OaJx4swE45XI" 218 | }, 219 | "source": [ 220 | "import matplotlib.pyplot as plt\n", 221 | "\n", 222 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 223 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 224 | "plt.legend()\n", 225 | "\n", 226 | "plt.xlabel(\"Epochs\")\n", 227 | "plt.ylabel(\"Error\")\n", 228 | "plt.show()" 229 | ], 230 | "execution_count": null, 231 | "outputs": [] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": { 236 | "id": "iMrpac0m4Nct" 237 | }, 238 | "source": [ 239 | "## 正解率\n", 240 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "metadata": { 246 | "id": "IRkGCYMM_N35" 247 | }, 248 | "source": [ 249 | "correct = 0\n", 250 | "total = 0\n", 251 | "net.eval() # 評価モード\n", 252 | "for i, (x, t) in enumerate(test_loader):\n", 253 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 254 | " y = net(x)\n", 255 | " correct += (y.argmax(1) == t).sum().item()\n", 256 | " total += len(x)\n", 257 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 258 | ], 259 | "execution_count": null, 260 | "outputs": [] 261 | } 262 | ] 263 | } -------------------------------------------------------------------------------- /section_3/01_alexnet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "01_alexnet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# AlexNetの実装\n", 35 | "PyTorchを使って、AlexNetを実装します。 \n", 36 | "torchvisionには訓練済みのAlexNetがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、AlexNetに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | "\n", 54 | "AlexNet(PyTorch): https://pytorch.org/hub/pytorch_vision_alexnet/" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "7t3NRHjhKyC0" 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "\n", 67 | "transform = transforms.Compose([\n", 68 | " transforms.Resize(256), # 短い方の辺を256に\n", 69 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 72 | "])\n", 73 | "\n", 74 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 75 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 76 | "\n", 77 | "# DataLoaderの設定\n", 78 | "batch_size = 64\n", 79 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 80 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": { 88 | "id": "FalXNYaJPkoE" 89 | }, 90 | "source": [ 91 | "## モデルの読み込み\n", 92 | "torchvisionを使い、AlexNetの訓練済みモデルを読み込みます。 \n", 93 | "https://pytorch.org/vision/stable/generated/torchvision.models.alexnet.html \n", 94 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "source": [ 100 | "import torchvision.models as models\n", 101 | "\n", 102 | "net = models.alexnet(pretrained=True)\n", 103 | "print(net)" 104 | ], 105 | "metadata": { 106 | "id": "miHLxB2xVAmz" 107 | }, 108 | "execution_count": null, 109 | "outputs": [] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "source": [ 114 | "## 各層の設定\n", 115 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 116 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n" 117 | ], 118 | "metadata": { 119 | "id": "Se1cFI_GEisR" 120 | } 121 | }, 122 | { 123 | "cell_type": "code", 124 | "metadata": { 125 | "id": "SuqqZmsh_jNK" 126 | }, 127 | "source": [ 128 | "import torch.nn as nn\n", 129 | "\n", 130 | "# 全ての層のパラメータを訓練不可に\n", 131 | "for param in net.parameters():\n", 132 | " param.requires_grad = False\n", 133 | "\n", 134 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 135 | "net.classifier[1] = nn.Linear(9216,4096)\n", 136 | "net.classifier[4] = nn.Linear(4096,1024)\n", 137 | "net.classifier[6] = nn.Linear(1024,10)\n", 138 | "\n", 139 | "net.cuda() # GPU対応\n", 140 | "print(net)" 141 | ], 142 | "execution_count": null, 143 | "outputs": [] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "metadata": { 148 | "id": "qsW5zCKhQE9p" 149 | }, 150 | "source": [ 151 | "## 学習\n", 152 | "モデルを訓練します。 \n", 153 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "metadata": { 159 | "id": "u6zwN3nArbGC" 160 | }, 161 | "source": [ 162 | "from torch import optim\n", 163 | "\n", 164 | "# 交差エントロピー誤差関数\n", 165 | "loss_fnc = nn.CrossEntropyLoss()\n", 166 | "\n", 167 | "# 最適化アルゴリズム\n", 168 | "optimizer = optim.Adam(net.parameters())\n", 169 | "\n", 170 | "# 損失のログ\n", 171 | "record_loss_train = []\n", 172 | "record_loss_test = []\n", 173 | "\n", 174 | "# 学習\n", 175 | "for i in range(6): # 6エポック学習\n", 176 | " net.train() # 訓練モード\n", 177 | " loss_train = 0\n", 178 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 179 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 180 | " y = net(x)\n", 181 | " loss = loss_fnc(y, t)\n", 182 | " loss_train += loss.item()\n", 183 | " optimizer.zero_grad()\n", 184 | " loss.backward()\n", 185 | " optimizer.step()\n", 186 | " loss_train /= j+1\n", 187 | " record_loss_train.append(loss_train)\n", 188 | "\n", 189 | " net.eval() # 評価モード\n", 190 | " loss_test = 0\n", 191 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 192 | " x, t = x.cuda(), t.cuda()\n", 193 | " y = net(x)\n", 194 | " loss = loss_fnc(y, t)\n", 195 | " loss_test += loss.item()\n", 196 | " loss_test /= j+1\n", 197 | " record_loss_test.append(loss_test)\n", 198 | "\n", 199 | " if i%1 == 0:\n", 200 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 201 | ], 202 | "execution_count": null, 203 | "outputs": [] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": { 208 | "id": "rJwwrWTw43rx" 209 | }, 210 | "source": [ 211 | "## 誤差の推移\n", 212 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "metadata": { 218 | "id": "OaJx4swE45XI" 219 | }, 220 | "source": [ 221 | "import matplotlib.pyplot as plt\n", 222 | "\n", 223 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 224 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 225 | "plt.legend()\n", 226 | "\n", 227 | "plt.xlabel(\"Epochs\")\n", 228 | "plt.ylabel(\"Error\")\n", 229 | "plt.show()" 230 | ], 231 | "execution_count": null, 232 | "outputs": [] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": { 237 | "id": "iMrpac0m4Nct" 238 | }, 239 | "source": [ 240 | "## 正解率\n", 241 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "metadata": { 247 | "id": "IRkGCYMM_N35" 248 | }, 249 | "source": [ 250 | "correct = 0\n", 251 | "total = 0\n", 252 | "net.eval() # 評価モード\n", 253 | "for i, (x, t) in enumerate(test_loader):\n", 254 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 255 | " y = net(x)\n", 256 | " correct += (y.argmax(1) == t).sum().item()\n", 257 | " total += len(x)\n", 258 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 259 | ], 260 | "execution_count": null, 261 | "outputs": [] 262 | } 263 | ] 264 | } -------------------------------------------------------------------------------- /section_5/01_vision_transformer.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "01_vision_transformer.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# Vision Transformerの実装\n", 35 | "PyTorchを使って、Vision Transformerを実装します。 \n", 36 | "torchvisionには訓練済みのVision Transformerがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、Vision Transformerに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | "\n", 54 | "OPTIMIZING VISION TRANSFORMER MODEL FOR DEPLOYMENT: https://pytorch.org/tutorials/beginner/vt_tutorial.html" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "7t3NRHjhKyC0" 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "\n", 67 | "transform = transforms.Compose([\n", 68 | " transforms.Resize(256), # 短い方の辺を256に\n", 69 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 72 | "])\n", 73 | "\n", 74 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 75 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 76 | "\n", 77 | "# DataLoaderの設定\n", 78 | "batch_size = 64\n", 79 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 80 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": { 88 | "id": "FalXNYaJPkoE" 89 | }, 90 | "source": [ 91 | "## モデルの読み込み\n", 92 | "torchvisionを使い、Vision Transformerの訓練済みモデルを読み込みます。 \n", 93 | "https://pytorch.org/vision/stable/generated/torchvision.models.vit_b_16.html \n", 94 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "source": [ 100 | "import torchvision.models as models\n", 101 | "\n", 102 | "net = models.vit_b_16(pretrained=True)\n", 103 | "print(net)" 104 | ], 105 | "metadata": { 106 | "id": "miHLxB2xVAmz" 107 | }, 108 | "execution_count": null, 109 | "outputs": [] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "source": [ 114 | "## 各層の設定\n", 115 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 116 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n" 117 | ], 118 | "metadata": { 119 | "id": "Se1cFI_GEisR" 120 | } 121 | }, 122 | { 123 | "cell_type": "code", 124 | "metadata": { 125 | "id": "SuqqZmsh_jNK" 126 | }, 127 | "source": [ 128 | "import torch.nn as nn\n", 129 | "\n", 130 | "# 全ての層のパラメータを訓練不可に\n", 131 | "for param in net.parameters():\n", 132 | " param.requires_grad = False\n", 133 | "\n", 134 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 135 | "net.heads[0] = nn.Linear(768, 10)\n", 136 | "\n", 137 | "net.cuda() # GPU対応\n", 138 | "print(net)" 139 | ], 140 | "execution_count": null, 141 | "outputs": [] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": { 146 | "id": "qsW5zCKhQE9p" 147 | }, 148 | "source": [ 149 | "## 学習\n", 150 | "モデルを訓練します。 \n", 151 | "最適化アルゴリズムには、元論文に合わせてMomentumを0.9に設定したSGDを使います。 \n", 152 | "https://arxiv.org/abs/2010.11929 \n", 153 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "metadata": { 159 | "id": "u6zwN3nArbGC" 160 | }, 161 | "source": [ 162 | "from torch import optim\n", 163 | "\n", 164 | "# 交差エントロピー誤差関数\n", 165 | "loss_fnc = nn.CrossEntropyLoss()\n", 166 | "\n", 167 | "# 最適化アルゴリズム\n", 168 | "optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)\n", 169 | "\n", 170 | "# 損失のログ\n", 171 | "record_loss_train = []\n", 172 | "record_loss_test = []\n", 173 | "\n", 174 | "# 学習\n", 175 | "for i in range(6): # 6エポック学習\n", 176 | " net.train() # 訓練モード\n", 177 | " loss_train = 0\n", 178 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 179 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 180 | " y = net(x)\n", 181 | " loss = loss_fnc(y, t)\n", 182 | " loss_train += loss.item()\n", 183 | " optimizer.zero_grad()\n", 184 | " loss.backward()\n", 185 | " optimizer.step()\n", 186 | " loss_train /= j+1\n", 187 | " record_loss_train.append(loss_train)\n", 188 | "\n", 189 | " net.eval() # 評価モード\n", 190 | " loss_test = 0\n", 191 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 192 | " x, t = x.cuda(), t.cuda()\n", 193 | " y = net(x)\n", 194 | " loss = loss_fnc(y, t)\n", 195 | " loss_test += loss.item()\n", 196 | " loss_test /= j+1\n", 197 | " record_loss_test.append(loss_test)\n", 198 | "\n", 199 | " if i%1 == 0:\n", 200 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 201 | ], 202 | "execution_count": null, 203 | "outputs": [] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": { 208 | "id": "rJwwrWTw43rx" 209 | }, 210 | "source": [ 211 | "## 誤差の推移\n", 212 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "metadata": { 218 | "id": "OaJx4swE45XI" 219 | }, 220 | "source": [ 221 | "import matplotlib.pyplot as plt\n", 222 | "\n", 223 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 224 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 225 | "plt.legend()\n", 226 | "\n", 227 | "plt.xlabel(\"Epochs\")\n", 228 | "plt.ylabel(\"Error\")\n", 229 | "plt.show()" 230 | ], 231 | "execution_count": null, 232 | "outputs": [] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": { 237 | "id": "iMrpac0m4Nct" 238 | }, 239 | "source": [ 240 | "## 正解率\n", 241 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "metadata": { 247 | "id": "IRkGCYMM_N35" 248 | }, 249 | "source": [ 250 | "correct = 0\n", 251 | "total = 0\n", 252 | "net.eval() # 評価モード\n", 253 | "for i, (x, t) in enumerate(test_loader):\n", 254 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 255 | " y = net(x)\n", 256 | " correct += (y.argmax(1) == t).sum().item()\n", 257 | " total += len(x)\n", 258 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 259 | ], 260 | "execution_count": null, 261 | "outputs": [] 262 | } 263 | ] 264 | } -------------------------------------------------------------------------------- /section_3/02_googlenet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "02_googlenet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# GoogLeNetの実装\n", 35 | "PyTorchを使って、GoogLeNetを実装します。 \n", 36 | "torchvisionには訓練済みのGoogLeNetがあるので、これを読み込んだ上で一部の層をタスクに合わせて入れ替えます。 \n", 37 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "vsncPqQ-gZJr" 44 | }, 45 | "source": [ 46 | "## データの前処理\n", 47 | "入力画像は、GoogLeNetに合わせてサイズが224の正方形に変換します。 \n", 48 | "以下の行でRGBの各値の平均値と標準偏差を設定しますが、これらの設定値はImageNetによる学習済みモデルの設定値で、PyTorchの公式ドキュメントを参考にしています。 \n", 49 | "\n", 50 | "```\n", 51 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 52 | "```\n", 53 | " \n", 54 | "GoogLeNet(PyTorch): https://pytorch.org/hub/pytorch_vision_googlenet/\n", 55 | "\n" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "metadata": { 61 | "id": "7t3NRHjhKyC0" 62 | }, 63 | "source": [ 64 | "from torchvision.datasets import CIFAR10\n", 65 | "import torchvision.transforms as transforms\n", 66 | "from torch.utils.data import DataLoader\n", 67 | "\n", 68 | "transform = transforms.Compose([\n", 69 | " transforms.Resize(256), # 短い方の辺を256に\n", 70 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 71 | " transforms.ToTensor(),\n", 72 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 73 | "])\n", 74 | "\n", 75 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 76 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 77 | "\n", 78 | "# DataLoaderの設定\n", 79 | "batch_size = 64\n", 80 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 81 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 82 | ], 83 | "execution_count": null, 84 | "outputs": [] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": { 89 | "id": "FalXNYaJPkoE" 90 | }, 91 | "source": [ 92 | "## モデルの読み込み\n", 93 | "torchvisionを使い、GoogLeNetの訓練済みモデルを読み込みます。 \n", 94 | "https://pytorch.org/vision/stable/generated/torchvision.models.googlenet.html \n", 95 | "`pretrained=True`と設定することで、パラメータが訓練済みとなります。 " 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "source": [ 101 | "import torchvision.models as models\n", 102 | "\n", 103 | "net = models.googlenet(pretrained=True, aux_logits=True, transform_input=False)\n", 104 | "print(net)" 105 | ], 106 | "metadata": { 107 | "id": "miHLxB2xVAmz" 108 | }, 109 | "execution_count": null, 110 | "outputs": [] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "source": [ 115 | "## 各層の設定\n", 116 | "分類器として機能する全結合層を、10クラス分類に合わせて入れ替えます。 \n", 117 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n" 118 | ], 119 | "metadata": { 120 | "id": "Se1cFI_GEisR" 121 | } 122 | }, 123 | { 124 | "cell_type": "code", 125 | "metadata": { 126 | "id": "SuqqZmsh_jNK" 127 | }, 128 | "source": [ 129 | "import torch.nn as nn\n", 130 | "\n", 131 | "# 全ての層のパラメータを訓練不可に\n", 132 | "for param in net.parameters():\n", 133 | " param.requires_grad = False\n", 134 | "\n", 135 | "# 補助の分類器 (Auxiliary Classifier) の出力層を入れ替え(デフォルトで訓練可能)\n", 136 | "net.aux1.fc2 = nn.Linear(1024,10)\n", 137 | "net.aux2.fc2 = nn.Linear(1024,10)\n", 138 | "\n", 139 | "# 最後の出力層を入れ替え(デフォルトで訓練可能)\n", 140 | "net.fc = nn.Linear(1024,10)\n", 141 | "\n", 142 | "net.cuda() # GPU対応\n", 143 | "print(net)" 144 | ], 145 | "execution_count": null, 146 | "outputs": [] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": { 151 | "id": "qsW5zCKhQE9p" 152 | }, 153 | "source": [ 154 | "## 学習\n", 155 | "モデルを訓練します。 \n", 156 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "metadata": { 162 | "id": "u6zwN3nArbGC" 163 | }, 164 | "source": [ 165 | "from typing import NewType\n", 166 | "from torch import optim\n", 167 | "\n", 168 | "# 交差エントロピー誤差関数\n", 169 | "loss_fnc = nn.CrossEntropyLoss()\n", 170 | "\n", 171 | "# 最適化アルゴリズム\n", 172 | "optimizer = optim.Adam(net.parameters())\n", 173 | "\n", 174 | "# 損失のログ\n", 175 | "record_loss_train = []\n", 176 | "record_loss_test = []\n", 177 | "\n", 178 | "# 学習\n", 179 | "for i in range(6): # 6エポック学習\n", 180 | " net.train() # 訓練モード\n", 181 | " loss_train = 0\n", 182 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 183 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 184 | " y = net(x)\n", 185 | " loss_main = loss_fnc(y[0], t) # 最後の出力層の損失\n", 186 | " loss_aux1 = loss_fnc(y[1], t) # 補助の分類器の損失\n", 187 | " loss_aux2 = loss_fnc(y[2], t) # 補助の分類器の損失\n", 188 | " loss = loss_main + 0.3*loss_aux1 + 0.3*loss_aux2\n", 189 | " loss_train += loss.item()\n", 190 | " optimizer.zero_grad()\n", 191 | " loss.backward()\n", 192 | " optimizer.step()\n", 193 | " loss_train /= j+1\n", 194 | " record_loss_train.append(loss_train)\n", 195 | "\n", 196 | " net.eval() # 評価モード\n", 197 | " loss_test = 0\n", 198 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 199 | " x, t = x.cuda(), t.cuda()\n", 200 | " y = net(x)\n", 201 | " loss = loss_fnc(y, t)\n", 202 | " loss_test += loss.item()\n", 203 | " loss_test /= j+1\n", 204 | " record_loss_test.append(loss_test)\n", 205 | "\n", 206 | " if i%1 == 0:\n", 207 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 208 | ], 209 | "execution_count": null, 210 | "outputs": [] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": { 215 | "id": "rJwwrWTw43rx" 216 | }, 217 | "source": [ 218 | "## 誤差の推移\n", 219 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "metadata": { 225 | "id": "OaJx4swE45XI" 226 | }, 227 | "source": [ 228 | "import matplotlib.pyplot as plt\n", 229 | "\n", 230 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 231 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 232 | "plt.legend()\n", 233 | "\n", 234 | "plt.xlabel(\"Epochs\")\n", 235 | "plt.ylabel(\"Error\")\n", 236 | "plt.show()" 237 | ], 238 | "execution_count": null, 239 | "outputs": [] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": { 244 | "id": "iMrpac0m4Nct" 245 | }, 246 | "source": [ 247 | "## 正解率\n", 248 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "metadata": { 254 | "id": "IRkGCYMM_N35" 255 | }, 256 | "source": [ 257 | "correct = 0\n", 258 | "total = 0\n", 259 | "net.eval() # 評価モード\n", 260 | "for i, (x, t) in enumerate(test_loader):\n", 261 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 262 | " y = net(x)\n", 263 | " correct += (y.argmax(1) == t).sum().item()\n", 264 | " total += len(x)\n", 265 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 266 | ], 267 | "execution_count": null, 268 | "outputs": [] 269 | } 270 | ] 271 | } -------------------------------------------------------------------------------- /section_4/04_exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "collapsed_sections": [], 8 | "include_colab_link": true 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "accelerator": "GPU" 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "id": "view-in-github", 21 | "colab_type": "text" 22 | }, 23 | "source": [ 24 | "\"Open" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": { 30 | "id": "Niaz8_W6OX34" 31 | }, 32 | "source": [ 33 | "# 演習\n", 34 | "`resnet152`および「CIFAR100」を使って、100クラス分類を実装しましょう。 \n", 35 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": { 41 | "id": "vsncPqQ-gZJr" 42 | }, 43 | "source": [ 44 | "## データの前処理" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "metadata": { 50 | "id": "7t3NRHjhKyC0" 51 | }, 52 | "source": [ 53 | "from torchvision.datasets import CIFAR100\n", 54 | "import torchvision.transforms as transforms\n", 55 | "from torch.utils.data import DataLoader\n", 56 | "\n", 57 | "transform = transforms.Compose([\n", 58 | " transforms.Resize(256), # 短い方の辺を256に\n", 59 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 60 | " transforms.ToTensor(),\n", 61 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 62 | "])\n", 63 | "\n", 64 | "cifar100_train = CIFAR100(\"./data\", train=True, download=True, transform=transform)\n", 65 | "cifar100_test = CIFAR100(\"./data\", train=False, download=True, transform=transform)\n", 66 | "\n", 67 | "# DataLoaderの設定\n", 68 | "batch_size = 64\n", 69 | "train_loader = DataLoader(cifar100_train, batch_size=batch_size, shuffle=True)\n", 70 | "test_loader = DataLoader(cifar100_test, batch_size=batch_size, shuffle=False)" 71 | ], 72 | "execution_count": null, 73 | "outputs": [] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": { 78 | "id": "FalXNYaJPkoE" 79 | }, 80 | "source": [ 81 | "## モデルの読み込み\n", 82 | "torchvisionを使い、`resnet152`を読み込みます。 \n", 83 | "https://pytorch.org/vision/main/models/generated/torchvision.models.resnet152.html \n", 84 | "上記のリンクを参考に、以下のセルにコードを追記して`resnet152`の訓練済みモデルを読み込みましょう。" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "source": [ 90 | "import torchvision.models as models\n", 91 | "\n", 92 | "net = # ←ここにコードを追記\n", 93 | "print(net)" 94 | ], 95 | "metadata": { 96 | "id": "miHLxB2xVAmz" 97 | }, 98 | "execution_count": null, 99 | "outputs": [] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "source": [ 104 | "## 各層の設定\n", 105 | "分類器として機能する全結合層を、100クラス分類に合わせて入れ替えます。 \n", 106 | "今回は特徴抽出に用いた箇所は追加で訓練を行わず、分類器のみ訓練します。 \n", 107 | "以下のセルにコードを追記し、一部の層を入れ替えましょう。\n" 108 | ], 109 | "metadata": { 110 | "id": "Se1cFI_GEisR" 111 | } 112 | }, 113 | { 114 | "cell_type": "code", 115 | "metadata": { 116 | "id": "SuqqZmsh_jNK" 117 | }, 118 | "source": [ 119 | "import torch.nn as nn\n", 120 | "\n", 121 | "# 全ての層のパラメータを訓練不可に\n", 122 | "for param in net.parameters():\n", 123 | " param.requires_grad = False\n", 124 | "\n", 125 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 126 | "# ------- 以下にコードを書く -------\n", 127 | "\n", 128 | "# ------- ここまで -------\n", 129 | "\n", 130 | "net.cuda() # GPU対応\n", 131 | "print(net)" 132 | ], 133 | "execution_count": null, 134 | "outputs": [] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": { 139 | "id": "qsW5zCKhQE9p" 140 | }, 141 | "source": [ 142 | "## 学習 " 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "metadata": { 148 | "id": "u6zwN3nArbGC" 149 | }, 150 | "source": [ 151 | "from typing import NewType\n", 152 | "from torch import optim\n", 153 | "\n", 154 | "# 交差エントロピー誤差関数\n", 155 | "loss_fnc = nn.CrossEntropyLoss()\n", 156 | "\n", 157 | "# 最適化アルゴリズム\n", 158 | "optimizer = optim.Adam(net.parameters())\n", 159 | "\n", 160 | "# 損失のログ\n", 161 | "record_loss_train = []\n", 162 | "record_loss_test = []\n", 163 | "\n", 164 | "# 学習\n", 165 | "for i in range(6): # 6エポック学習\n", 166 | " net.train() # 訓練モード\n", 167 | " loss_train = 0\n", 168 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 169 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 170 | " y = net(x)\n", 171 | " loss = loss_fnc(y, t)\n", 172 | " loss_train += loss.item()\n", 173 | " optimizer.zero_grad()\n", 174 | " loss.backward()\n", 175 | " optimizer.step()\n", 176 | " loss_train /= j+1\n", 177 | " record_loss_train.append(loss_train)\n", 178 | "\n", 179 | " net.eval() # 評価モード\n", 180 | " loss_test = 0\n", 181 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 182 | " x, t = x.cuda(), t.cuda()\n", 183 | " y = net(x)\n", 184 | " loss = loss_fnc(y, t)\n", 185 | " loss_test += loss.item()\n", 186 | " loss_test /= j+1\n", 187 | " record_loss_test.append(loss_test)\n", 188 | "\n", 189 | " if i%1 == 0:\n", 190 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 191 | ], 192 | "execution_count": null, 193 | "outputs": [] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": { 198 | "id": "rJwwrWTw43rx" 199 | }, 200 | "source": [ 201 | "## 誤差の推移" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "metadata": { 207 | "id": "OaJx4swE45XI" 208 | }, 209 | "source": [ 210 | "import matplotlib.pyplot as plt\n", 211 | "\n", 212 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 213 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 214 | "plt.legend()\n", 215 | "\n", 216 | "plt.xlabel(\"Epochs\")\n", 217 | "plt.ylabel(\"Error\")\n", 218 | "plt.show()" 219 | ], 220 | "execution_count": null, 221 | "outputs": [] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": { 226 | "id": "iMrpac0m4Nct" 227 | }, 228 | "source": [ 229 | "## 正解率" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "metadata": { 235 | "id": "IRkGCYMM_N35" 236 | }, 237 | "source": [ 238 | "correct = 0\n", 239 | "total = 0\n", 240 | "net.eval() # 評価モード\n", 241 | "for i, (x, t) in enumerate(test_loader):\n", 242 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 243 | " y = net(x)\n", 244 | " correct += (y.argmax(1) == t).sum().item()\n", 245 | " total += len(x)\n", 246 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 247 | ], 248 | "execution_count": null, 249 | "outputs": [] 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "metadata": { 254 | "id": "VEBDnUbHZ21y" 255 | }, 256 | "source": [ 257 | "# 解答例\n", 258 | "以下は解答例です。" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "source": [ 264 | "import torchvision.models as models\n", 265 | "\n", 266 | "net = models.resnet152(pretrained=True) # ←ここにコードを追記\n", 267 | "print(net)" 268 | ], 269 | "metadata": { 270 | "id": "-g1BvwSju8Gm" 271 | }, 272 | "execution_count": null, 273 | "outputs": [] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "source": [ 278 | "import torch.nn as nn\n", 279 | "\n", 280 | "# 全ての層のパラメータを訓練不可に\n", 281 | "for param in net.parameters():\n", 282 | " param.requires_grad = False\n", 283 | "\n", 284 | "# 一部の層を入れ替え(デフォルトで訓練可能)\n", 285 | "# ------- 以下にコードを書く -------\n", 286 | "net.fc = nn.Linear(2048, 100)\n", 287 | "# ------- ここまで -------\n", 288 | "\n", 289 | "net.cuda() # GPU対応\n", 290 | "print(net)" 291 | ], 292 | "metadata": { 293 | "id": "Rvaa0URyupB_" 294 | }, 295 | "execution_count": null, 296 | "outputs": [] 297 | } 298 | ] 299 | } -------------------------------------------------------------------------------- /section_2/01_data_augmentation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "authorship_tag": "ABX9TyOqDQRMdOfO0UrcPDH0/wSL", 8 | "include_colab_link": true 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github", 23 | "colab_type": "text" 24 | }, 25 | "source": [ 26 | "\"Open" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "HWC_y_52fJZ2" 33 | }, 34 | "source": [ 35 | "# データ拡張\n", 36 | "データ拡張では、汎化性能の向上のために画像の「水増し」を行います。 \n", 37 | "今回は、`torchvision.transforms`を使い、回転、拡大/縮小などによるデータ拡張のデモを行います。 \n", 38 | " \n", 39 | "`torchvision.transforms`は様々なデータの変形を用意しています。 \n", 40 | "興味のある方は、公式ドキュメントを読んでみましょう。 \n", 41 | "https://pytorch.org/vision/stable/transforms.html" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": { 47 | "id": "jpMObJX-c6CW" 48 | }, 49 | "source": [ 50 | "## CIFAR-10\n", 51 | "今回のデモには、CIFAR-10というデータセットを使います。 \n", 52 | "CIFARは、以下の特徴を持ちます。 \n", 53 | "\n", 54 | "* 約6万枚のラベル付き画像\n", 55 | "* RGBカラー\n", 56 | "* ラベルはairplaneやautomobileなどの乗り物と、birdやcatなどの動物\n", 57 | "* 画像サイズは32×32\n", 58 | " \n", 59 | "以下のコードは、`torchvision.datasets`を使ってCIFAR-10を読み込み、ランダムな36枚の画像を表示します。" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "metadata": { 65 | "id": "CbolmAveUtJ4" 66 | }, 67 | "source": [ 68 | "from torchvision.datasets import CIFAR10\n", 69 | "import torchvision.transforms as transforms\n", 70 | "from torch.utils.data import DataLoader\n", 71 | "import matplotlib.pyplot as plt\n", 72 | "\n", 73 | "cifar10_data = CIFAR10(root=\"./data\",\n", 74 | " train=False,download=True,\n", 75 | " transform=transforms.ToTensor())\n", 76 | "cifar10_classes = [\"airplane\", \"automobile\", \"bird\",\n", 77 | " \"cat\", \"deer\", \"dog\", \"frog\",\n", 78 | " \"horse\", \"ship\", \"truck\"]\n", 79 | "print(\"データの数:\", len(cifar10_data))\n", 80 | "\n", 81 | "n_image = 36 # 表示する画像の数\n", 82 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 83 | "dataiter = iter(cifar10_loader) # イテレータ: 要素を順番に取り出す\n", 84 | "images, labels = next(dataiter) # 最初のバッチ\n", 85 | "\n", 86 | "plt.figure(figsize=(12,12)) # 画像の表示サイズ\n", 87 | "for i in range(n_image):\n", 88 | " ax = plt.subplot(6, 6 ,i+1)\n", 89 | " ax.imshow(images[i].permute(1, 2, 0)) # 一番後の次元をチャンネルに\n", 90 | " label = cifar10_classes[labels[i]]\n", 91 | " ax.set_title(label)\n", 92 | " ax.get_xaxis().set_visible(False) # 軸を非表示に\n", 93 | " ax.get_yaxis().set_visible(False)\n", 94 | "\n", 95 | "plt.show()" 96 | ], 97 | "execution_count": null, 98 | "outputs": [] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": { 103 | "id": "24KV93msd3i-" 104 | }, 105 | "source": [ 106 | "## 回転とリサイズ\n", 107 | "`transforms.RandomAffine()`を使って、画像に-45〜45°の範囲の回転、および0.5〜1.5倍の範囲のリサイズを加えます。 " 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "metadata": { 113 | "id": "TVWgInj2luno" 114 | }, 115 | "source": [ 116 | "transform = transforms.Compose([transforms.RandomAffine((-45, 45), scale=(0.5, 1.5)), # 回転とリサイズ\n", 117 | " transforms.ToTensor()])\n", 118 | "cifar10_data = CIFAR10(root=\"./data\",\n", 119 | " train=False,download=True,\n", 120 | " transform=transform)\n", 121 | "\n", 122 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 123 | "dataiter = iter(cifar10_loader)\n", 124 | "images, labels = next(dataiter)\n", 125 | "\n", 126 | "plt.figure(figsize=(12,12)) # 画像の表示サイズ\n", 127 | "for i in range(n_image):\n", 128 | " ax = plt.subplot(6, 6, i+1)\n", 129 | " ax.imshow(images[i].permute(1, 2, 0))\n", 130 | " label = cifar10_classes[labels[i]]\n", 131 | " ax.set_title(label)\n", 132 | " ax.get_xaxis().set_visible(False)\n", 133 | " ax.get_yaxis().set_visible(False)\n", 134 | " \n", 135 | "plt.show()" 136 | ], 137 | "execution_count": null, 138 | "outputs": [] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": { 143 | "id": "2K6ei7g0R542" 144 | }, 145 | "source": [ 146 | "## シフト\n", 147 | "`transforms.RandomAffine()`を使って、画像サイズの0.5倍以内のシフトを、水平方向、垂直方向それぞれに加えます。 " 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "metadata": { 153 | "id": "mk0PYfSmR543" 154 | }, 155 | "source": [ 156 | "transform = transforms.Compose([transforms.RandomAffine((0, 0), translate=(0.5, 0.5)), # 上下左右へのシフト\n", 157 | " transforms.ToTensor()])\n", 158 | "cifar10_data = CIFAR10(root=\"./data\",\n", 159 | " train=False,download=True,\n", 160 | " transform=transform)\n", 161 | "\n", 162 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 163 | "dataiter = iter(cifar10_loader)\n", 164 | "images, labels = next(dataiter)\n", 165 | "\n", 166 | "plt.figure(figsize=(12,12)) # 画像の表示サイズ\n", 167 | "for i in range(n_image):\n", 168 | " ax = plt.subplot(6, 6, i+1)\n", 169 | " ax.imshow(images[i].permute(1, 2, 0))\n", 170 | " label = cifar10_classes[labels[i]]\n", 171 | " ax.set_title(label)\n", 172 | " ax.get_xaxis().set_visible(False)\n", 173 | " ax.get_yaxis().set_visible(False)\n", 174 | " \n", 175 | "plt.show()" 176 | ], 177 | "execution_count": null, 178 | "outputs": [] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": { 183 | "id": "zG7xEjpfU8U-" 184 | }, 185 | "source": [ 186 | "## 反転\n", 187 | "`transforms.RandomHorizontalFlip()`と`transforms.RandomVerticalFlip()`を使って、画像に、水平方向、垂直方向それぞれ0.5の確率(`p=0.5`)で反転をランダムに加えます。 " 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "metadata": { 193 | "id": "foclfneAU8U_" 194 | }, 195 | "source": [ 196 | "transform = transforms.Compose([transforms.RandomHorizontalFlip(p=0.5), # 左右反転\n", 197 | " transforms.RandomVerticalFlip(p=0.5), # 上下反転\n", 198 | " transforms.ToTensor()])\n", 199 | "cifar10_data = CIFAR10(root=\"./data\",\n", 200 | " train=False,download=True,\n", 201 | " transform=transform)\n", 202 | "\n", 203 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 204 | "dataiter = iter(cifar10_loader)\n", 205 | "images, labels = next(dataiter)\n", 206 | "\n", 207 | "plt.figure(figsize=(12,12)) # 画像の表示サイズ\n", 208 | "for i in range(n_image):\n", 209 | " ax = plt.subplot(6, 6, i+1)\n", 210 | " ax.imshow(images[i].permute(1, 2, 0))\n", 211 | " label = cifar10_classes[labels[i]]\n", 212 | " ax.set_title(label)\n", 213 | " ax.get_xaxis().set_visible(False)\n", 214 | " ax.get_yaxis().set_visible(False)\n", 215 | " \n", 216 | "plt.show()" 217 | ], 218 | "execution_count": null, 219 | "outputs": [] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": { 224 | "id": "ERHGGvmqW2fp" 225 | }, 226 | "source": [ 227 | "## 一部を消去\n", 228 | "`transforms.RandomErasing()`を使って、画像の一部を0.5の確率(`p=0.5`)で消去します。 " 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "metadata": { 234 | "id": "KVVyt9-oW2fz" 235 | }, 236 | "source": [ 237 | "transform = transforms.Compose([transforms.ToTensor(),\n", 238 | " transforms.RandomErasing(p=0.5)]) # 一部を消去\n", 239 | "cifar10_data = CIFAR10(root=\"./data\",\n", 240 | " train=False,download=True,\n", 241 | " transform=transform)\n", 242 | "\n", 243 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 244 | "dataiter = iter(cifar10_loader)\n", 245 | "images, labels = next(dataiter)\n", 246 | "\n", 247 | "plt.figure(figsize=(12,12)) # 画像の表示サイズ\n", 248 | "for i in range(n_image):\n", 249 | " ax = plt.subplot(6, 6, i+1)\n", 250 | " ax.imshow(images[i].permute(1, 2, 0))\n", 251 | " label = cifar10_classes[labels[i]]\n", 252 | " ax.set_title(label)\n", 253 | " ax.get_xaxis().set_visible(False)\n", 254 | " ax.get_yaxis().set_visible(False)\n", 255 | " \n", 256 | "plt.show()" 257 | ], 258 | "execution_count": null, 259 | "outputs": [] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "source": [ 264 | "`transforms.RandomErasing()`はTensorにしか適用できないので、`transforms.ToTensor()`以降に記述します。 " 265 | ], 266 | "metadata": { 267 | "id": "qUHxxBSsW2f0" 268 | } 269 | } 270 | ] 271 | } -------------------------------------------------------------------------------- /section_1/01_tensor.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "01_tensor.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyMHdtWgT78bQQ9mNlU7BioR", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "language_info": { 17 | "name": "python" 18 | } 19 | }, 20 | "cells": [ 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "id": "view-in-github", 25 | "colab_type": "text" 26 | }, 27 | "source": [ 28 | "\"Open" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": { 34 | "id": "qBeK8bWc4a_9" 35 | }, 36 | "source": [ 37 | "# Tensor\n", 38 | "TensorはPyTorchにおいて最も基本となるデータ構造です。 \n", 39 | "Tensorを操作するための様々なコードを、Google Colacoratoryで練習しましょう。" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": { 45 | "id": "ztIkOM_N5Bu7" 46 | }, 47 | "source": [ 48 | "## PyTorchの確認\n", 49 | "環境にインストール済みのパッケージを全て表示し、「torch」という名前でPyTorchがインストールされていることを確認します。" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "metadata": { 55 | "id": "SLrzxL39qGie" 56 | }, 57 | "source": [ 58 | "!pip list" 59 | ], 60 | "execution_count": null, 61 | "outputs": [] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": { 66 | "id": "EMC135bx6E3u" 67 | }, 68 | "source": [ 69 | "## Tensorを生成する\n", 70 | "以下のコードは、torchの`tensor()`関数により、PythonのリストからTensorを生成します。 \n", 71 | "type()により型の確認も行います。 " 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "metadata": { 77 | "id": "xCg7mgXPqBc8" 78 | }, 79 | "source": [ 80 | "import torch\n", 81 | "\n", 82 | "a = torch.tensor([12,13,14])\n", 83 | "print(a, type(a))" 84 | ], 85 | "execution_count": null, 86 | "outputs": [] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": { 91 | "id": "6LcfIq4nWfG2" 92 | }, 93 | "source": [ 94 | "以下は、他の生成方法です。" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "metadata": { 100 | "id": "3X2TN2rYtCTO" 101 | }, 102 | "source": [ 103 | "print(\"--- 2次元のリストから生成 ---\")\n", 104 | "b = torch.tensor([[11, 12],\n", 105 | " [13, 14]])\n", 106 | "print(b)\n", 107 | "\n", 108 | "print(\"--- dypeを指定し、倍精度のTensorにする ---\")\n", 109 | "c = torch.tensor([[11, 12],\n", 110 | " [13, 14]], dtype=torch.float64)\n", 111 | "print(c)\n", 112 | "\n", 113 | "print(\"--- 0から19までの数値で初期化 ---\")\n", 114 | "d = torch.arange(0, 20)\n", 115 | "print(d)\n", 116 | "\n", 117 | "print(\"--- すべての値が0の、3×4のTensor ---\")\n", 118 | "e = torch.zeros(3, 4)\n", 119 | "print(e)\n", 120 | "\n", 121 | "print(\"--- すべての値が乱数の、3×4のTensor ---\")\n", 122 | "f = torch.rand(3, 4)\n", 123 | "print(f)\n", 124 | "\n", 125 | "print(\"--- 形状はsizeメソッドで取得 ---\")\n", 126 | "print(f.size())" 127 | ], 128 | "execution_count": null, 129 | "outputs": [] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": { 134 | "id": "b-TrDK5qewJp" 135 | }, 136 | "source": [ 137 | "## TensorとNumPyの配列の相互変換\n", 138 | "機械学習では、数値演算ライブラリNumPyの配列がよく使われます。 \n", 139 | "以下は、TensorとNumPyの相互変換のコードです。 " 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "metadata": { 145 | "id": "VdQc9-L5gBFZ" 146 | }, 147 | "source": [ 148 | "print(\"--- Tensor → NumPy ---\")\n", 149 | "a = torch.tensor([[11, 12],\n", 150 | " [13, 14]])\n", 151 | "b = a.numpy()\n", 152 | "print(b)\n", 153 | "\n", 154 | "print(\"--- NumPy → Tensor ---\")\n", 155 | "c = torch.from_numpy(b)\n", 156 | "print(c)" 157 | ], 158 | "execution_count": null, 159 | "outputs": [] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": { 164 | "id": "CgpWSmhXnas_" 165 | }, 166 | "source": [ 167 | "## 範囲を指定してアクセス\n", 168 | "Tensorの一部に、範囲を指定してアクセスすることができます。" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "metadata": { 174 | "id": "MgWk6RXMoX_l" 175 | }, 176 | "source": [ 177 | "a = torch.tensor([[11, 12, 13],\n", 178 | " [14, 15, 16]])\n", 179 | "\n", 180 | "print(\"--- 2つのインデックスを指定 ---\")\n", 181 | "print(a[0, 1])\n", 182 | "\n", 183 | "print(\"--- 範囲を指定 ---\")\n", 184 | "print(a[1:2, :2])\n", 185 | "\n", 186 | "print(\"--- 3より大きい要素のみを指定 ---\")\n", 187 | "print(a[a>3])\n", 188 | "\n", 189 | "print(\"--- 要素の変更 ---\")\n", 190 | "a[0, 2] = 11\n", 191 | "print(a)\n", 192 | "\n", 193 | "print(\"--- ある次元の要素を一括変更 ---\")\n", 194 | "a[:, 1] = 22\n", 195 | "print(a)" 196 | ], 197 | "execution_count": null, 198 | "outputs": [] 199 | }, 200 | { 201 | "cell_type": "markdown", 202 | "metadata": { 203 | "id": "2HQMM_Fh02of" 204 | }, 205 | "source": [ 206 | "## Tensorの演算\n", 207 | "以下は、Tensor同士の演算の例です。" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "metadata": { 213 | "id": "AQ5IsU0Fz-DJ" 214 | }, 215 | "source": [ 216 | "# ベクトル\n", 217 | "a = torch.tensor([11, 12, 13]) \n", 218 | "b = torch.tensor([14, 15, 16])\n", 219 | "\n", 220 | "# 行列\n", 221 | "c = torch.tensor([[16, 15, 14],\n", 222 | " [13, 12, 11]])\n", 223 | "\n", 224 | "print(\"--- ベクトルとスカラーの演算 ---\")\n", 225 | "print(a + 3)\n", 226 | "\n", 227 | "print(\"--- ベクトル同士の演算 ---\")\n", 228 | "print(a + b) \n", 229 | "\n", 230 | "print(\"--- 行列とスカラーの演算 ---\")\n", 231 | "print(c + 2)\n", 232 | "\n", 233 | "print(\"--- 行列とベクトルの演算(ブロードキャスト) ---\")\n", 234 | "print(c + a)\n", 235 | "\n", 236 | "print(\"--- 行列同士の演算 ---\")\n", 237 | "print(c + c)" 238 | ], 239 | "execution_count": null, 240 | "outputs": [] 241 | }, 242 | { 243 | "cell_type": "markdown", 244 | "source": [ 245 | "ブロードキャストは、条件を満たしていれば形状が異なるTensor同士でも演算が可能になる機能です。" 246 | ], 247 | "metadata": { 248 | "id": "op7j4u0HR8YY" 249 | } 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "metadata": { 254 | "id": "C1otpuXxCb84" 255 | }, 256 | "source": [ 257 | "## Tensorの形状変換\n", 258 | "`view()`を使えば、Tensorの形状を自由に変更することができます。" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "source": [ 264 | "a = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11]) # 1次元のTensor\n", 265 | "b = a.view(3, 4) # (3, 4)の2次元のTensorに変換\n", 266 | "print(b)" 267 | ], 268 | "metadata": { 269 | "id": "-4lOt6alFDfZ" 270 | }, 271 | "execution_count": null, 272 | "outputs": [] 273 | }, 274 | { 275 | "cell_type": "markdown", 276 | "source": [ 277 | "引数のうち1つを-1にすれば、その次元の要素数は自動計算されます。 " 278 | ], 279 | "metadata": { 280 | "id": "UKoNGKogFAW-" 281 | } 282 | }, 283 | { 284 | "cell_type": "code", 285 | "source": [ 286 | "c = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11]) # 1次元のTensor\n", 287 | "d = c.view(3, -1) # (3, 4)の2次元のTensorに変換\n", 288 | "print(d)" 289 | ], 290 | "metadata": { 291 | "id": "zww6M6npGj6D" 292 | }, 293 | "execution_count": null, 294 | "outputs": [] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "source": [ 299 | "`view()`の引数を-1のみにすると、1次元に変換されます。 " 300 | ], 301 | "metadata": { 302 | "id": "aY6BFdhrIhOH" 303 | } 304 | }, 305 | { 306 | "cell_type": "code", 307 | "source": [ 308 | "e = torch.tensor([[[11, 12],\n", 309 | " [13, 14]], \n", 310 | " [[15, 16],\n", 311 | " [17, 18]]]) # 3次元のTensor\n", 312 | "print(e)\n", 313 | "f = e.view(-1) # 1次元のTensorに変換\n", 314 | "print(f)" 315 | ], 316 | "metadata": { 317 | "id": "m2WviA82IhOI" 318 | }, 319 | "execution_count": null, 320 | "outputs": [] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": { 325 | "id": "r0S-nN_c8MKr" 326 | }, 327 | "source": [ 328 | "## 統計値の計算\n", 329 | "Tensorには、様々な統計値を計算する関数とメソッドが用意されています。 \n", 330 | "Tensorから通常の値を取り出すためには、`item()`メソッドを使います。\n" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "metadata": { 336 | "id": "X_LIWIwI59rI" 337 | }, 338 | "source": [ 339 | "a = torch.tensor([[11, 12, 13],\n", 340 | " [14, 15, 16.]])\n", 341 | "\n", 342 | "print(\"--- 平均値(関数) ---\")\n", 343 | "m = torch.mean(a)\n", 344 | "print(m.item()) # item()で値を取り出す\n", 345 | "\n", 346 | "print(\"--- 平均値(メソッド) ---\")\n", 347 | "m = a.mean()\n", 348 | "print(m.item())\n", 349 | "\n", 350 | "print(\"--- 列ごとの平均値 ---\")\n", 351 | "print(a.mean(0))\n", 352 | "\n", 353 | "print(\"--- 合計値 ---\")\n", 354 | "print(torch.sum(a).item())\n", 355 | "\n", 356 | "print(\"--- 最大値 ---\")\n", 357 | "print(torch.max(a).item())\n", 358 | "\n", 359 | "print(\"--- 最小値 ---\")\n", 360 | "print(torch.min(a).item())" 361 | ], 362 | "execution_count": null, 363 | "outputs": [] 364 | }, 365 | { 366 | "cell_type": "markdown", 367 | "source": [ 368 | "今回扱ったTensorの機能はごく一部です。 \n", 369 | "詳しくは、以下の公式ドキュメントを参考にしてください。 \n", 370 | "https://pytorch.org/docs/stable/tensors.html" 371 | ], 372 | "metadata": { 373 | "id": "jYlvxRRcDqTa" 374 | } 375 | } 376 | ] 377 | } -------------------------------------------------------------------------------- /section_2/02_cnn.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "include_colab_link": true 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | }, 13 | "accelerator": "GPU" 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "markdown", 18 | "metadata": { 19 | "id": "view-in-github", 20 | "colab_type": "text" 21 | }, 22 | "source": [ 23 | "\"Open" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": { 29 | "id": "Niaz8_W6OX34" 30 | }, 31 | "source": [ 32 | "# CNNの実装\n", 33 | "PyTorchを使って、畳み込みニューラルネットワーク(CNN)を実装します。 \n", 34 | "CNN自体はCNNの層を追加するのみで実装可能なのですが、今回はデータ拡張とドロップアウトの実装も行います。 \n", 35 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": { 41 | "id": "vsncPqQ-gZJr" 42 | }, 43 | "source": [ 44 | "## データの前処理\n", 45 | "ここからCNNを実装します。 \n", 46 | "データ拡張として、回転とリサイズ、および左右反転を行います。 \n", 47 | "また、学習が効率的になるように入力の平均値を0、標準偏差を1にします(標準化)。 \n", 48 | "DataLoaderは、訓練データ、テストデータそれぞれで設定します。" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "metadata": { 54 | "id": "7t3NRHjhKyC0" 55 | }, 56 | "source": [ 57 | "from torchvision.datasets import CIFAR10\n", 58 | "import torchvision.transforms as transforms\n", 59 | "from torch.utils.data import DataLoader\n", 60 | "\n", 61 | "affine = transforms.RandomAffine([-30, 30], scale=(0.8, 1.2)) # 回転とリサイズ\n", 62 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 63 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 64 | "to_tensor = transforms.ToTensor()\n", 65 | "\n", 66 | "transform_train = transforms.Compose([affine, flip, to_tensor, normalize])\n", 67 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 68 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 69 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 70 | "\n", 71 | "# DataLoaderの設定\n", 72 | "batch_size = 64\n", 73 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 74 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 75 | ], 76 | "execution_count": null, 77 | "outputs": [] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": { 82 | "id": "FalXNYaJPkoE" 83 | }, 84 | "source": [ 85 | "## モデルの構築\n", 86 | "`nn.Module`モジュールを継承したクラスとして、CNNのモデルを構築します。 \n", 87 | "今回は、全結合層にニューロンをランダムに削除する「ドロップアウト」を導入します。 \n", 88 | "ドロップアウトを導入することで、未知のデータに対してより頑強になるようにモデルを訓練することができます。 " 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "metadata": { 94 | "id": "SuqqZmsh_jNK" 95 | }, 96 | "source": [ 97 | "import torch.nn as nn\n", 98 | "\n", 99 | "class Net(nn.Module):\n", 100 | " def __init__(self):\n", 101 | " super().__init__()\n", 102 | " self.conv1 = nn.Conv2d(3, 6, 5) # 畳み込み層:(入力チャンネル数, フィルタ数, フィルタサイズ)\n", 103 | " self.relu = nn.ReLU() # ReLU\n", 104 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, 領域の間隔)\n", 105 | " self.conv2 = nn.Conv2d(6, 16, 5)\n", 106 | " self.fc1 = nn.Linear(16*5*5, 256) # 全結合層\n", 107 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 108 | " self.fc2 = nn.Linear(256, 10)\n", 109 | "\n", 110 | " def forward(self, x):\n", 111 | " x = self.relu(self.conv1(x))\n", 112 | " x = self.pool(x)\n", 113 | " x = self.relu(self.conv2(x))\n", 114 | " x = self.pool(x)\n", 115 | " x = x.view(-1, 16*5*5)\n", 116 | " x = self.relu(self.fc1(x))\n", 117 | " x = self.dropout(x)\n", 118 | " x = self.fc2(x)\n", 119 | " return x\n", 120 | "\n", 121 | "net = Net()\n", 122 | "net.cuda() # GPU対応\n", 123 | "print(net)" 124 | ], 125 | "execution_count": null, 126 | "outputs": [] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "source": [ 131 | "各層で、画像のサイズ(チャンネル数, 画像高さ, 画像幅)\n", 132 | "は以下の通りに変化します。 \n", 133 | " \n", 134 | "入力画像: (3, 32, 32) \n", 135 | "↓ \n", 136 | "nn.Conv2d(3, 6, 5): (6, 28, 28) \n", 137 | "↓ \n", 138 | "nn.MaxPool2d(2, 2): (6, 14, 14) \n", 139 | "↓ \n", 140 | "nn.Conv2d(6, 16, 5): (16, 10, 10) \n", 141 | "↓ \n", 142 | "nn.MaxPool2d(2, 2): (16, 5, 5) \n", 143 | " \n", 144 | "画像の高さおよび幅は、以下の式を使って計算しました。 \n", 145 | "\n", 146 | "$$O_h=\\frac{I_h-F_h+2D}{S}+1$$\n", 147 | "$$O_w=\\frac{I_w-F_w+2D}{S}+1$$\n", 148 | "\n", 149 | "$O_h$、$O_w$: 出力画像の高さ、幅 \n", 150 | "$I_h$、$I_w$: 入力画像の高さ、幅 \n", 151 | "$F_h$、$F_w$: フィルタの高さ、幅 \n", 152 | "$D$: パディング \n", 153 | "$S$: ストライド \n", 154 | " \n", 155 | "今回、全ての畳み込み層でパディングは0、ストライドは1となっています。 " 156 | ], 157 | "metadata": { 158 | "id": "bRrRNmeWoZp_" 159 | } 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": { 164 | "id": "qsW5zCKhQE9p" 165 | }, 166 | "source": [ 167 | "## 学習\n", 168 | "モデルを訓練します。 \n", 169 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 " 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "metadata": { 175 | "id": "u6zwN3nArbGC" 176 | }, 177 | "source": [ 178 | "from torch import optim\n", 179 | "\n", 180 | "# 交差エントロピー誤差関数\n", 181 | "loss_fnc = nn.CrossEntropyLoss()\n", 182 | "\n", 183 | "# 最適化アルゴリズム\n", 184 | "optimizer = optim.Adam(net.parameters())\n", 185 | "\n", 186 | "# 損失のログ\n", 187 | "record_loss_train = []\n", 188 | "record_loss_test = []\n", 189 | "\n", 190 | "# 学習\n", 191 | "for i in range(20): # 20エポック学習\n", 192 | " net.train() # 訓練モード\n", 193 | " loss_train = 0\n", 194 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 195 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 196 | " y = net(x)\n", 197 | " loss = loss_fnc(y, t)\n", 198 | " loss_train += loss.item()\n", 199 | " optimizer.zero_grad()\n", 200 | " loss.backward()\n", 201 | " optimizer.step()\n", 202 | " loss_train /= j+1\n", 203 | " record_loss_train.append(loss_train)\n", 204 | "\n", 205 | " net.eval() # 評価モード\n", 206 | " loss_test = 0\n", 207 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 208 | " x, t = x.cuda(), t.cuda()\n", 209 | " y = net(x)\n", 210 | " loss = loss_fnc(y, t)\n", 211 | " loss_test += loss.item()\n", 212 | " loss_test /= j+1\n", 213 | " record_loss_test.append(loss_test)\n", 214 | "\n", 215 | " if i%1 == 0:\n", 216 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 217 | ], 218 | "execution_count": null, 219 | "outputs": [] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": { 224 | "id": "rJwwrWTw43rx" 225 | }, 226 | "source": [ 227 | "## 誤差の推移\n", 228 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "metadata": { 234 | "id": "OaJx4swE45XI" 235 | }, 236 | "source": [ 237 | "import matplotlib.pyplot as plt\n", 238 | "\n", 239 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 240 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 241 | "plt.legend()\n", 242 | "\n", 243 | "plt.xlabel(\"Epochs\")\n", 244 | "plt.ylabel(\"Error\")\n", 245 | "plt.show()" 246 | ], 247 | "execution_count": null, 248 | "outputs": [] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": { 253 | "id": "iMrpac0m4Nct" 254 | }, 255 | "source": [ 256 | "## 正解率\n", 257 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 258 | ] 259 | }, 260 | { 261 | "cell_type": "code", 262 | "metadata": { 263 | "id": "IRkGCYMM_N35" 264 | }, 265 | "source": [ 266 | "correct = 0\n", 267 | "total = 0\n", 268 | "net.eval() # 評価モード\n", 269 | "for i, (x, t) in enumerate(test_loader):\n", 270 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 271 | " y = net(x)\n", 272 | " correct += (y.argmax(1) == t).sum().item()\n", 273 | " total += len(x)\n", 274 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 275 | ], 276 | "execution_count": null, 277 | "outputs": [] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": { 282 | "id": "LrRAJzwD4zpN" 283 | }, 284 | "source": [ 285 | "## 訓練済みのモデルを使った予測\n", 286 | "訓練済みのモデルを使ってみましょう。 \n", 287 | "画像を入力し、モデルが機能していることを確かめます。" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "metadata": { 293 | "id": "Pdy9nPckTDik" 294 | }, 295 | "source": [ 296 | "cifar10_classes = [\"airplane\", \"automobile\", \"bird\",\n", 297 | " \"cat\", \"deer\", \"dog\", \"frog\",\n", 298 | " \"horse\", \"ship\", \"truck\"]\n", 299 | "\n", 300 | "cifar10_loader = DataLoader(cifar10_test, batch_size=1, shuffle=True)\n", 301 | "dataiter = iter(cifar10_loader)\n", 302 | "images, labels = next(dataiter) # サンプルを1つだけ取り出す\n", 303 | "\n", 304 | "plt.imshow(images[0].permute(1, 2, 0)) # 一番後の次元をチャンネルに\n", 305 | "plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 306 | "plt.show()\n", 307 | "\n", 308 | "net.eval() # 評価モード\n", 309 | "x, t = images.cuda(), labels.cuda() # GPU対応\n", 310 | "y = net(x)\n", 311 | "print(\"正解:\", cifar10_classes[labels[0]],\n", 312 | " \"予測結果:\", cifar10_classes[y.argmax().item()])" 313 | ], 314 | "execution_count": null, 315 | "outputs": [] 316 | } 317 | ] 318 | } -------------------------------------------------------------------------------- /section_3/04_exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "04_exercise.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "GPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34" 32 | }, 33 | "source": [ 34 | "# 演習\n", 35 | "AlexNetをtorchvision.modelsを使わずに実装しましょう。 \n", 36 | "学習に時間がかかるので、「編集」→「ノートブックの設定」の「ハードウェアアクセラレーター」で「GPU」を選択しましょう。 " 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": { 42 | "id": "vsncPqQ-gZJr" 43 | }, 44 | "source": [ 45 | "## データの前処理" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "metadata": { 51 | "id": "7t3NRHjhKyC0" 52 | }, 53 | "source": [ 54 | "from torchvision.datasets import CIFAR10\n", 55 | "import torchvision.transforms as transforms\n", 56 | "from torch.utils.data import DataLoader\n", 57 | "\n", 58 | "transform = transforms.Compose([\n", 59 | " transforms.Resize(256), # 短い方の辺を256に\n", 60 | " transforms.CenterCrop(224), # 辺の長さが224の正方形を中央から切り抜く\n", 61 | " transforms.ToTensor(),\n", 62 | " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n", 63 | "])\n", 64 | "\n", 65 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform)\n", 66 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform)\n", 67 | "\n", 68 | "# DataLoaderの設定\n", 69 | "batch_size = 64\n", 70 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 71 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 72 | ], 73 | "execution_count": null, 74 | "outputs": [] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": { 79 | "id": "FalXNYaJPkoE" 80 | }, 81 | "source": [ 82 | "## AlexNetの構築\n", 83 | "`torch.nn`を使い、torchvision.modelsを使わないで10クラス分類のAlexNetを構築しましょう。 \n", 84 | "以下のセルにコードを追記してください。 \n", 85 | "学習可能なパラメータはデフォルトのままで構いません。 \n", 86 | " \n", 87 | "公式ドキュメントのAlexNet実装を参考にしましょう。 \n", 88 | "SOURCE CODE FOR TORCHVISION.MODELS.ALEXNET: https://pytorch.org/vision/0.12/_modules/torchvision/models/alexnet.html" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "metadata": { 94 | "id": "SuqqZmsh_jNK" 95 | }, 96 | "source": [ 97 | "import torch\n", 98 | "import torch.nn as nn\n", 99 | "\n", 100 | "class AlexNet(nn.Module):\n", 101 | " def __init__(self):\n", 102 | " super().__init__()\n", 103 | " self.features = nn.Sequential(\n", 104 | " # ------- 以下にコードを書く -------\n", 105 | "\n", 106 | "\n", 107 | "\n", 108 | "\n", 109 | "\n", 110 | "\n", 111 | "\n", 112 | "\n", 113 | "\n", 114 | "\n", 115 | "\n", 116 | "\n", 117 | "\n", 118 | " # ------- ここまで -------\n", 119 | " )\n", 120 | " self.avgpool = nn.AdaptiveAvgPool2d((6, 6)) # 画像が6x6のサイズになるようにプーリング\n", 121 | " self.classifier = nn.Sequential(\n", 122 | " # ------- 以下にコードを書く -------\n", 123 | " \n", 124 | "\n", 125 | "\n", 126 | "\n", 127 | "\n", 128 | "\n", 129 | " \n", 130 | " # ------- ここまで -------\n", 131 | " )\n", 132 | "\n", 133 | " def forward(self, x):\n", 134 | " x = self.features(x)\n", 135 | " x = self.avgpool(x)\n", 136 | " x = torch.flatten(x, 1)\n", 137 | " x = self.classifier(x)\n", 138 | " return x\n", 139 | "\n", 140 | "net = AlexNet()\n", 141 | "net.cuda() # GPU対応\n", 142 | "print(net)" 143 | ], 144 | "execution_count": null, 145 | "outputs": [] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": { 150 | "id": "qsW5zCKhQE9p" 151 | }, 152 | "source": [ 153 | "## 学習 " 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "metadata": { 159 | "id": "u6zwN3nArbGC" 160 | }, 161 | "source": [ 162 | "from typing import NewType\n", 163 | "from torch import optim\n", 164 | "\n", 165 | "# 交差エントロピー誤差関数\n", 166 | "loss_fnc = nn.CrossEntropyLoss()\n", 167 | "\n", 168 | "# 最適化アルゴリズム\n", 169 | "optimizer = optim.Adam(net.parameters())\n", 170 | "\n", 171 | "# 損失のログ\n", 172 | "record_loss_train = []\n", 173 | "record_loss_test = []\n", 174 | "\n", 175 | "# 学習\n", 176 | "for i in range(6): # 6エポック学習\n", 177 | " net.train() # 訓練モード\n", 178 | " loss_train = 0\n", 179 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 180 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 181 | " y = net(x)\n", 182 | " loss = loss_fnc(y, t)\n", 183 | " loss_train += loss.item()\n", 184 | " optimizer.zero_grad()\n", 185 | " loss.backward()\n", 186 | " optimizer.step()\n", 187 | " loss_train /= j+1\n", 188 | " record_loss_train.append(loss_train)\n", 189 | "\n", 190 | " net.eval() # 評価モード\n", 191 | " loss_test = 0\n", 192 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 193 | " x, t = x.cuda(), t.cuda()\n", 194 | " y = net(x)\n", 195 | " loss = loss_fnc(y, t)\n", 196 | " loss_test += loss.item()\n", 197 | " loss_test /= j+1\n", 198 | " record_loss_test.append(loss_test)\n", 199 | "\n", 200 | " if i%1 == 0:\n", 201 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 202 | ], 203 | "execution_count": null, 204 | "outputs": [] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": { 209 | "id": "rJwwrWTw43rx" 210 | }, 211 | "source": [ 212 | "## 誤差の推移" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "metadata": { 218 | "id": "OaJx4swE45XI" 219 | }, 220 | "source": [ 221 | "import matplotlib.pyplot as plt\n", 222 | "\n", 223 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 224 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 225 | "plt.legend()\n", 226 | "\n", 227 | "plt.xlabel(\"Epochs\")\n", 228 | "plt.ylabel(\"Error\")\n", 229 | "plt.show()" 230 | ], 231 | "execution_count": null, 232 | "outputs": [] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": { 237 | "id": "iMrpac0m4Nct" 238 | }, 239 | "source": [ 240 | "## 正解率" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "metadata": { 246 | "id": "IRkGCYMM_N35" 247 | }, 248 | "source": [ 249 | "correct = 0\n", 250 | "total = 0\n", 251 | "net.eval() # 評価モード\n", 252 | "for i, (x, t) in enumerate(test_loader):\n", 253 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 254 | " y = net(x)\n", 255 | " correct += (y.argmax(1) == t).sum().item()\n", 256 | " total += len(x)\n", 257 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 258 | ], 259 | "execution_count": null, 260 | "outputs": [] 261 | }, 262 | { 263 | "cell_type": "markdown", 264 | "metadata": { 265 | "id": "VEBDnUbHZ21y" 266 | }, 267 | "source": [ 268 | "# 解答例\n", 269 | "以下は解答例です。" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "source": [ 275 | "import torch\n", 276 | "import torch.nn as nn\n", 277 | "\n", 278 | "class AlexNet(nn.Module):\n", 279 | " def __init__(self):\n", 280 | " super().__init__()\n", 281 | " self.features = nn.Sequential(\n", 282 | " # ------- 以下にコードを書く -------\n", 283 | " nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),\n", 284 | " nn.ReLU(inplace=True),\n", 285 | " nn.MaxPool2d(kernel_size=3, stride=2),\n", 286 | " nn.Conv2d(64, 192, kernel_size=5, padding=2),\n", 287 | " nn.ReLU(inplace=True),\n", 288 | " nn.MaxPool2d(kernel_size=3, stride=2),\n", 289 | " nn.Conv2d(192, 384, kernel_size=3, padding=1),\n", 290 | " nn.ReLU(inplace=True),\n", 291 | " nn.Conv2d(384, 256, kernel_size=3, padding=1),\n", 292 | " nn.ReLU(inplace=True),\n", 293 | " nn.Conv2d(256, 256, kernel_size=3, padding=1),\n", 294 | " nn.ReLU(inplace=True),\n", 295 | " nn.MaxPool2d(kernel_size=3, stride=2)\n", 296 | " # ------- ここまで -------\n", 297 | " )\n", 298 | " self.avgpool = nn.AdaptiveAvgPool2d((6, 6)) # 画像が6x6のサイズになるようにプーリング\n", 299 | " self.classifier = nn.Sequential(\n", 300 | " # ------- 以下にコードを書く -------\n", 301 | " nn.Dropout(p=0.5),\n", 302 | " nn.Linear(256*6*6, 4096),\n", 303 | " nn.ReLU(inplace=True),\n", 304 | " nn.Dropout(p=0.5),\n", 305 | " nn.Linear(4096, 4096),\n", 306 | " nn.ReLU(inplace=True),\n", 307 | " nn.Linear(4096, 10)\n", 308 | " # ------- ここまで -------\n", 309 | " )\n", 310 | "\n", 311 | " def forward(self, x):\n", 312 | " x = self.features(x)\n", 313 | " x = self.avgpool(x)\n", 314 | " x = torch.flatten(x, 1)\n", 315 | " x = self.classifier(x)\n", 316 | " return x\n", 317 | "\n", 318 | "net = AlexNet()\n", 319 | "net.cuda() # GPU対応\n", 320 | "print(net)" 321 | ], 322 | "metadata": { 323 | "id": "-g1BvwSju8Gm" 324 | }, 325 | "execution_count": null, 326 | "outputs": [] 327 | } 328 | ] 329 | } -------------------------------------------------------------------------------- /section_2/03_exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "include_colab_link": true 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | }, 13 | "accelerator": "GPU" 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "markdown", 18 | "metadata": { 19 | "id": "view-in-github", 20 | "colab_type": "text" 21 | }, 22 | "source": [ 23 | "\"Open" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": { 29 | "id": "Niaz8_W6OX34" 30 | }, 31 | "source": [ 32 | "# 演習\n", 33 | "今回の演習では、CNNの実装を練習します。 \n", 34 | "新たなデータ拡張の追加、およびCNNモデルの構築のコードを記述してください。" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": { 40 | "id": "vsncPqQ-gZJr" 41 | }, 42 | "source": [ 43 | "## データの前処理\n", 44 | "以下のセルにコードを追記し、データ拡張に'transforms.RandomErasing()'によるランダムな画像領域の消去を追加しましょう。" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "metadata": { 50 | "id": "7t3NRHjhKyC0" 51 | }, 52 | "source": [ 53 | "from torchvision.datasets import CIFAR10\n", 54 | "import torchvision.transforms as transforms\n", 55 | "from torch.utils.data import DataLoader\n", 56 | "\n", 57 | "affine = transforms.RandomAffine((-30, 30), scale=(0.8, 1.2)) # 回転とリサイズ\n", 58 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 59 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 60 | "to_tensor = transforms.ToTensor()\n", 61 | "erase = # ← ここにコードを追記\n", 62 | "\n", 63 | "transform_train = transforms.Compose( # ←ここにコードを追記\n", 64 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 65 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 66 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 67 | "\n", 68 | "# DataLoaderの設定\n", 69 | "batch_size = 64\n", 70 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 71 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 72 | ], 73 | "execution_count": null, 74 | "outputs": [] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": { 79 | "id": "FalXNYaJPkoE" 80 | }, 81 | "source": [ 82 | "## モデルの構築\n", 83 | "以下のセルで、forwardメソッドの内部にコードを記述して、CNNのモデルを構築しましょう。" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "metadata": { 89 | "id": "SuqqZmsh_jNK" 90 | }, 91 | "source": [ 92 | "import torch.nn as nn\n", 93 | "\n", 94 | "class Net(nn.Module):\n", 95 | " def __init__(self):\n", 96 | " super().__init__()\n", 97 | " self.conv1 = nn.Conv2d(3, 6, 5) # 畳み込み層:(入力チャンネル数, フィルタ数, フィルタサイズ)\n", 98 | " self.relu = nn.ReLU() # ReLU\n", 99 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, 領域の間隔)\n", 100 | " self.conv2 = nn.Conv2d(6, 16, 5)\n", 101 | " self.fc1 = nn.Linear(16*5*5, 256) # 全結合層\n", 102 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 103 | " self.fc2 = nn.Linear(256, 10)\n", 104 | "\n", 105 | " def forward(self, x):\n", 106 | " # ------- 以下にコードを書く -------\n", 107 | "\n", 108 | "\n", 109 | "\n", 110 | "\n", 111 | "\n", 112 | "\n", 113 | "\n", 114 | "\n", 115 | " # ------- ここまで -------\n", 116 | " return x\n", 117 | "\n", 118 | "net = Net()\n", 119 | "net.cuda() # GPU対応\n", 120 | "print(net)" 121 | ], 122 | "execution_count": null, 123 | "outputs": [] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": { 128 | "id": "qsW5zCKhQE9p" 129 | }, 130 | "source": [ 131 | "## 学習\n" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "metadata": { 137 | "id": "u6zwN3nArbGC" 138 | }, 139 | "source": [ 140 | "from torch import optim\n", 141 | "\n", 142 | "# 交差エントロピー誤差関数\n", 143 | "loss_fnc = nn.CrossEntropyLoss()\n", 144 | "\n", 145 | "# 最適化アルゴリズム\n", 146 | "optimizer = optim.Adam(net.parameters())\n", 147 | "\n", 148 | "# 損失のログ\n", 149 | "record_loss_train = []\n", 150 | "record_loss_test = []\n", 151 | "\n", 152 | "# 学習\n", 153 | "for i in range(20): # 20エポック学習\n", 154 | " net.train() # 訓練モード\n", 155 | " loss_train = 0\n", 156 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 157 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 158 | " y = net(x)\n", 159 | " loss = loss_fnc(y, t)\n", 160 | " loss_train += loss.item()\n", 161 | " optimizer.zero_grad()\n", 162 | " loss.backward()\n", 163 | " optimizer.step()\n", 164 | " loss_train /= j+1\n", 165 | " record_loss_train.append(loss_train)\n", 166 | "\n", 167 | " net.eval() # 評価モード\n", 168 | " loss_test = 0\n", 169 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 170 | " x, t = x.cuda(), t.cuda()\n", 171 | " y = net(x)\n", 172 | " loss = loss_fnc(y, t)\n", 173 | " loss_test += loss.item()\n", 174 | " loss_test /= j+1\n", 175 | " record_loss_test.append(loss_test)\n", 176 | "\n", 177 | " if i%1 == 0:\n", 178 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 179 | ], 180 | "execution_count": null, 181 | "outputs": [] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": { 186 | "id": "rJwwrWTw43rx" 187 | }, 188 | "source": [ 189 | "## 誤差の推移" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "metadata": { 195 | "id": "OaJx4swE45XI" 196 | }, 197 | "source": [ 198 | "import matplotlib.pyplot as plt\n", 199 | "\n", 200 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 201 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 202 | "plt.legend()\n", 203 | "\n", 204 | "plt.xlabel(\"Epochs\")\n", 205 | "plt.ylabel(\"Error\")\n", 206 | "plt.show()" 207 | ], 208 | "execution_count": null, 209 | "outputs": [] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": { 214 | "id": "iMrpac0m4Nct" 215 | }, 216 | "source": [ 217 | "## 正解率" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "metadata": { 223 | "id": "IRkGCYMM_N35" 224 | }, 225 | "source": [ 226 | "correct = 0\n", 227 | "total = 0\n", 228 | "net.eval() # 評価モード\n", 229 | "for i, (x, t) in enumerate(test_loader):\n", 230 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 231 | " y = net(x)\n", 232 | " correct += (y.argmax(1) == t).sum().item()\n", 233 | " total += len(x)\n", 234 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 235 | ], 236 | "execution_count": null, 237 | "outputs": [] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": { 242 | "id": "LrRAJzwD4zpN" 243 | }, 244 | "source": [ 245 | "## 訓練済みのモデルを使った予測" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "metadata": { 251 | "id": "Pdy9nPckTDik" 252 | }, 253 | "source": [ 254 | "cifar10_classes = [\"airplane\", \"automobile\", \"bird\",\n", 255 | " \"cat\", \"deer\", \"dog\", \"frog\",\n", 256 | " \"horse\", \"ship\", \"truck\"]\n", 257 | "\n", 258 | "cifar10_loader = DataLoader(cifar10_test, batch_size=1, shuffle=True)\n", 259 | "dataiter = iter(cifar10_loader)\n", 260 | "images, labels = next(dataiter) # サンプルを1つだけ取り出す\n", 261 | "\n", 262 | "plt.imshow(images[0].permute(1, 2, 0)) # 一番後の次元をチャンネルに\n", 263 | "plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 264 | "plt.show()\n", 265 | "\n", 266 | "net.eval() # 評価モード\n", 267 | "x, t = images.cuda(), labels.cuda() # GPU対応\n", 268 | "y = net(x)\n", 269 | "print(\"正解:\", cifar10_classes[labels[0]],\n", 270 | " \"予測結果:\", cifar10_classes[y.argmax().item()])" 271 | ], 272 | "execution_count": null, 273 | "outputs": [] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": { 278 | "id": "VEBDnUbHZ21y" 279 | }, 280 | "source": [ 281 | "# 解答例\n", 282 | "以下は解答例です。" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "metadata": { 288 | "id": "JTHeygFKscPI" 289 | }, 290 | "source": [ 291 | "from torchvision.datasets import CIFAR10\n", 292 | "import torchvision.transforms as transforms\n", 293 | "from torch.utils.data import DataLoader\n", 294 | "\n", 295 | "affine = transforms.RandomAffine((-30, 30), scale=(0.8, 1.2)) # 回転とリサイズ\n", 296 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 297 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 298 | "to_tensor = transforms.ToTensor()\n", 299 | "erase = transforms.RandomErasing(p=0.5) # ← ここにコードを追記\n", 300 | "\n", 301 | "transform_train = transforms.Compose([affine, flip, to_tensor, normalize, erase]) # ←ここにコードを追記\n", 302 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 303 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 304 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 305 | "\n", 306 | "# DataLoaderの設定\n", 307 | "batch_size = 64\n", 308 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 309 | "test_loader = DataLoader(cifar10_test, batch_size=batch_size, shuffle=False)" 310 | ], 311 | "execution_count": null, 312 | "outputs": [] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "metadata": { 317 | "id": "ZbtDEl0GscZK" 318 | }, 319 | "source": [ 320 | "import torch.nn as nn\n", 321 | "\n", 322 | "class Net(nn.Module):\n", 323 | " def __init__(self):\n", 324 | " super().__init__()\n", 325 | " self.conv1 = nn.Conv2d(3, 6, 5) # 畳み込み層:(入力チャンネル数, フィルタ数, フィルタサイズ)\n", 326 | " self.relu = nn.ReLU() # ReLU\n", 327 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, 領域の間隔)\n", 328 | " self.conv2 = nn.Conv2d(6, 16, 5)\n", 329 | " self.fc1 = nn.Linear(16*5*5, 256) # 全結合層\n", 330 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 331 | " self.fc2 = nn.Linear(256, 10)\n", 332 | "\n", 333 | " def forward(self, x):\n", 334 | " # ------- 以下にコードを書く -------\n", 335 | " x = self.relu(self.conv1(x))\n", 336 | " x = self.pool(x)\n", 337 | " x = self.relu(self.conv2(x))\n", 338 | " x = self.pool(x)\n", 339 | " x = x.view(-1, 16*5*5)\n", 340 | " x = self.relu(self.fc1(x))\n", 341 | " x = self.dropout(x)\n", 342 | " x = self.fc2(x)\n", 343 | " # ------- ここまで -------\n", 344 | " return x\n", 345 | "\n", 346 | "net = Net()\n", 347 | "net.cuda() # GPU対応\n", 348 | "print(net)" 349 | ], 350 | "execution_count": null, 351 | "outputs": [] 352 | } 353 | ] 354 | } -------------------------------------------------------------------------------- /python_basic/python_basic_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "python_basic_1.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyN9sAbXgOfuA10FQ+oF1BmI", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "QK1qtAbx7DCH", 32 | "colab_type": "text" 33 | }, 34 | "source": [ 35 | "# Pythonの基礎1\n", 36 | " プログラミング言語Pythonの文法を、手を動かしながら少しずつ学んでいきましょう。 \n", 37 | "解説用のコードセルの下に練習用のコードセルがありますので、コードを書く体験とともに進めていくことをお勧めします。 \n", 38 | "なお、今回の解説がPythonの全てをカバーしているわけではありませんのでご注意ください。" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": { 44 | "id": "vShhk5xk7L6w", 45 | "colab_type": "text" 46 | }, 47 | "source": [ 48 | "## ● 変数\n", 49 | "**変数**には**値**を入れることができます。 \n", 50 | "以下の例では、変数`a`に123という値を入れています。 \n", 51 | "`print(a)`で、変数`a`に入った値を表示することができます。" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "metadata": { 57 | "id": "h7HH2NJB7DCJ", 58 | "colab_type": "code", 59 | "colab": {} 60 | }, 61 | "source": [ 62 | "a = 123\n", 63 | "print(a)" 64 | ], 65 | "execution_count": null, 66 | "outputs": [] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "metadata": { 71 | "id": "G2cA1xc4CZ8_", 72 | "colab_type": "code", 73 | "colab": {} 74 | }, 75 | "source": [ 76 | "# 練習用\n" 77 | ], 78 | "execution_count": null, 79 | "outputs": [] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": { 84 | "id": "PZg4iHpxnAyC", 85 | "colab_type": "text" 86 | }, 87 | "source": [ 88 | "なお、`#`以降の記述はコメントとなり、プログラムとして認識されません。メモなどに活用しましょう。 \n", 89 | "変数には小数の値を入れることもできます。 \n", 90 | "以下では、`b`に123.45という小数の値を入れています。 " 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "metadata": { 96 | "id": "6566lYEEsNJh", 97 | "colab_type": "code", 98 | "colab": {} 99 | }, 100 | "source": [ 101 | "b = 123.45\n", 102 | "print(b)" 103 | ], 104 | "execution_count": null, 105 | "outputs": [] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "metadata": { 110 | "id": "bgMti6leFZn9", 111 | "colab_type": "code", 112 | "colab": {} 113 | }, 114 | "source": [ 115 | "# 練習用\n" 116 | ], 117 | "execution_count": null, 118 | "outputs": [] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": { 123 | "id": "extlg0l1rx2z", 124 | "colab_type": "text" 125 | }, 126 | "source": [ 127 | "変数には文章を入れることもできます。 \n", 128 | "`\"\"`もしくは`''` で囲まれた文章は文字列として認識され、値として変数に入れることができます。 \n" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "metadata": { 134 | "id": "yMwbxO3GLIC6", 135 | "colab_type": "code", 136 | "colab": {} 137 | }, 138 | "source": [ 139 | "c = \"こんにちは、Python!\"\n", 140 | "print(c)" 141 | ], 142 | "execution_count": null, 143 | "outputs": [] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "metadata": { 148 | "id": "p3DojhtkLUYK", 149 | "colab_type": "code", 150 | "colab": {} 151 | }, 152 | "source": [ 153 | "# 練習用\n" 154 | ], 155 | "execution_count": null, 156 | "outputs": [] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": { 161 | "id": "WteivqoSJxEu", 162 | "colab_type": "text" 163 | }, 164 | "source": [ 165 | "変数名には、アルファベットの他に`_`(アンダーバー)や数字を使うこともできます。 \n", 166 | "ただし、変数名の先頭を数字にすることはできません。 " 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "metadata": { 172 | "id": "9-dHbPsYJ_jS", 173 | "colab_type": "code", 174 | "colab": {} 175 | }, 176 | "source": [ 177 | "dog_name = \"Pochi\"\n", 178 | "print(dog_name)\n", 179 | "\n", 180 | "number321 = 321\n", 181 | "print(number321)" 182 | ], 183 | "execution_count": null, 184 | "outputs": [] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "metadata": { 189 | "id": "HYh2U2NKM_GY", 190 | "colab_type": "code", 191 | "colab": {} 192 | }, 193 | "source": [ 194 | "# 練習用\n" 195 | ], 196 | "execution_count": null, 197 | "outputs": [] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": { 202 | "id": "jd_BuH8D7DCM", 203 | "colab_type": "text" 204 | }, 205 | "source": [ 206 | "このような変数の概念は、以降Pythonを学んでいくための基盤となります。" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": { 212 | "id": "AioPKJ3q7DCU", 213 | "colab_type": "text" 214 | }, 215 | "source": [ 216 | "## ● 四則演算\n", 217 | "様々な演算子を使って四則演算を行うことができます。" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "metadata": { 223 | "id": "hYmGSfid7DCU", 224 | "colab_type": "code", 225 | "colab": {} 226 | }, 227 | "source": [ 228 | "a = 7\n", 229 | "b = 3\n", 230 | "\n", 231 | "c = a + b # 足し算\n", 232 | "print(c)\n", 233 | "\n", 234 | "d = a - b # 引き算\n", 235 | "print(d)\n", 236 | "\n", 237 | "e = a * b # 掛け算\n", 238 | "print(e)\n", 239 | "\n", 240 | "f = a / b # 割り算(小数)\n", 241 | "print(f)\n", 242 | "\n", 243 | "g = a // b # 割り算(整数)\n", 244 | "print(g)\n", 245 | "\n", 246 | "h = a % b # 余り\n", 247 | "print(h)" 248 | ], 249 | "execution_count": null, 250 | "outputs": [] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "metadata": { 255 | "id": "QmgKAo4dNlA_", 256 | "colab_type": "code", 257 | "colab": {} 258 | }, 259 | "source": [ 260 | "# 練習用\n" 261 | ], 262 | "execution_count": null, 263 | "outputs": [] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": { 268 | "id": "D4BOaxpW7DCW", 269 | "colab_type": "text" 270 | }, 271 | "source": [ 272 | "上記で使用した演算子を以下にまとめます。\n", 273 | "\n", 274 | "||||\n", 275 | "|:-:|:-:|:--|\n", 276 | "|| \\+ | 足し算 |\n", 277 | "||- | 引き算 |\n", 278 | "|| * | かける |\n", 279 | "|| / | 割る(小数) |\n", 280 | "|| // | 割る(整数) |\n", 281 | "|| % | 余り |\n", 282 | "||||\n", 283 | "\n", 284 | "なお、`+`の演算子は文字列の結合に使うこともできます。" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "metadata": { 290 | "id": "tPQ7XddGQRg1", 291 | "colab_type": "code", 292 | "colab": {} 293 | }, 294 | "source": [ 295 | "a = \"Hello\"\n", 296 | "b = \"World\"\n", 297 | "\n", 298 | "c = a + b\n", 299 | "print(c)" 300 | ], 301 | "execution_count": null, 302 | "outputs": [] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "metadata": { 307 | "id": "5fMSkwA9Qc8F", 308 | "colab_type": "code", 309 | "colab": {} 310 | }, 311 | "source": [ 312 | "# 練習用\n" 313 | ], 314 | "execution_count": null, 315 | "outputs": [] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": { 320 | "id": "Ff52sxFiQ5mG", 321 | "colab_type": "text" 322 | }, 323 | "source": [ 324 | "## ● Bool値と比較演算子\n", 325 | "変数には`True`もしくは`False`の値を入れることができます。 \n", 326 | "これらの値は、**Bool値**と呼ばれます。 \n", 327 | "Bool値は`True`もしくは`False`のどちらかしかとることができません。" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "metadata": { 333 | "id": "sUzagn13Q-WJ", 334 | "colab_type": "code", 335 | "colab": {} 336 | }, 337 | "source": [ 338 | "a = True\n", 339 | "b = False\n", 340 | "\n", 341 | "print(a)\n", 342 | "print(b)" 343 | ], 344 | "execution_count": null, 345 | "outputs": [] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "metadata": { 350 | "id": "0y-SCphVbDPa", 351 | "colab_type": "code", 352 | "colab": {} 353 | }, 354 | "source": [ 355 | "# 練習用\n" 356 | ], 357 | "execution_count": null, 358 | "outputs": [] 359 | }, 360 | { 361 | "cell_type": "markdown", 362 | "metadata": { 363 | "id": "xynAyE7bbIXO", 364 | "colab_type": "text" 365 | }, 366 | "source": [ 367 | "**比較演算子**を使うことで、値を比較した結果をBool値として得ることができます。 \n", 368 | "`>`や`<`などの比較演算子は、左右の値を比較します。 \n" 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "metadata": { 374 | "id": "JPnYBd6675IK", 375 | "colab_type": "code", 376 | "colab": {} 377 | }, 378 | "source": [ 379 | "c = 3\n", 380 | "d = 4\n", 381 | "\n", 382 | "e = c > d # cがdよりも大きいかどうか\n", 383 | "print(e)\n", 384 | "\n", 385 | "f = c < d # cがdよりも小さいかどうか\n", 386 | "print(f)\n", 387 | "\n", 388 | "g = c >= d # cがd以上かどうか\n", 389 | "print(g)\n", 390 | "\n", 391 | "h = c <= d # cがd以下かどうか\n", 392 | "print(h)\n", 393 | "\n", 394 | "i = c == d # cとdが等しいかどうか\n", 395 | "print(i)\n", 396 | "\n", 397 | "j = c != d # cとdが等しくないか\n", 398 | "print(j)" 399 | ], 400 | "execution_count": null, 401 | "outputs": [] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "metadata": { 406 | "id": "74vLCh-THt4B", 407 | "colab_type": "code", 408 | "colab": {} 409 | }, 410 | "source": [ 411 | "# 練習用\n" 412 | ], 413 | "execution_count": null, 414 | "outputs": [] 415 | }, 416 | { 417 | "cell_type": "markdown", 418 | "metadata": { 419 | "id": "leSqs4xJ8g7q", 420 | "colab_type": "text" 421 | }, 422 | "source": [ 423 | "Pythonで使われる比較演算子を以下にまとめます。\n", 424 | "\n", 425 | "||||\n", 426 | "|:-:|:-:|:--|\n", 427 | "|| < | 小さい |\n", 428 | "|| > | 大きい |\n", 429 | "|| <= | 以上 |\n", 430 | "|| >= | 以下 |\n", 431 | "|| == | 等しい |\n", 432 | "|| != | 等しくない |\n", 433 | "||||" 434 | ] 435 | }, 436 | { 437 | "cell_type": "markdown", 438 | "metadata": { 439 | "id": "D6lMp6KNIiGC", 440 | "colab_type": "text" 441 | }, 442 | "source": [ 443 | "## ● 論理演算子\n", 444 | "**論理演算子**を使うと、Bool値の演算を行うことができます。" 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "metadata": { 450 | "id": "lEnQDGY6Jmt1", 451 | "colab_type": "code", 452 | "colab": {} 453 | }, 454 | "source": [ 455 | "a = 3\n", 456 | "b = 4\n", 457 | "c = 5\n", 458 | "\n", 459 | "d = a < b and b < c # 両者がTrueであればTrue\n", 460 | "print(d)\n", 461 | "\n", 462 | "e = a < b or b > c # 片方がTrueであればTrue\n", 463 | "print(e)\n", 464 | "\n", 465 | "f = not a < b # Bool値を反転\n", 466 | "print(f)" 467 | ], 468 | "execution_count": null, 469 | "outputs": [] 470 | }, 471 | { 472 | "cell_type": "code", 473 | "metadata": { 474 | "id": "y0qwm9SnM6GZ", 475 | "colab_type": "code", 476 | "colab": {} 477 | }, 478 | "source": [ 479 | "# 練習用\n" 480 | ], 481 | "execution_count": null, 482 | "outputs": [] 483 | }, 484 | { 485 | "cell_type": "markdown", 486 | "metadata": { 487 | "id": "8cfNnbcoMUS-", 488 | "colab_type": "text" 489 | }, 490 | "source": [ 491 | "Pythonで使われる論理演算子を以下にまとめます。 \n", 492 | "\n", 493 | "||||\n", 494 | "|:-:|:-:|:--|\n", 495 | "|| and | 両者がTrueであればTrue |\n", 496 | "|| or | 片方がTrueであればTrue |\n", 497 | "|| not | Bool値を反転 |\n", 498 | "||||\n", 499 | "\n", 500 | "このような論理演算子を使うことで、複雑な条件をコードで表現することが可能になります。" 501 | ] 502 | } 503 | ] 504 | } -------------------------------------------------------------------------------- /python_basic/python_basic_3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "python_basic_3.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "toc_visible": true, 10 | "authorship_tag": "ABX9TyOQ6B23Ohrb8vjbDOEezdIb", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github", 23 | "colab_type": "text" 24 | }, 25 | "source": [ 26 | "\"Open" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "ewg_pUrO-m3m", 33 | "colab_type": "text" 34 | }, 35 | "source": [ 36 | "# Pythonの基礎3\n", 37 | "関数とクラス、ファイルの保存について解説します。" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "BxlxFRAm-m3o", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "## ●関数\n", 48 | "**関数**を用いることで、処理を一括りにして何度も呼び出すことができます。 \n", 49 | "以下はシンプルな関数の例です。" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "metadata": { 55 | "id": "xftbx6T4-m3p", 56 | "colab_type": "code", 57 | "colab": {} 58 | }, 59 | "source": [ 60 | "def say_hello(): # defの後に関数名を記述\n", 61 | " print(\"Hello world!\") # 行頭にインデントを挿入\n", 62 | "\n", 63 | "say_hello() # 関数の呼び出し" 64 | ], 65 | "execution_count": null, 66 | "outputs": [] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "metadata": { 71 | "id": "wrO8sv-WZHuo", 72 | "colab_type": "code", 73 | "colab": {} 74 | }, 75 | "source": [ 76 | "# 練習用\n" 77 | ], 78 | "execution_count": null, 79 | "outputs": [] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": { 84 | "id": "L8xd1JMv-m3s", 85 | "colab_type": "text" 86 | }, 87 | "source": [ 88 | "一度関数を定義しておけば、あとから何度でも呼び出すことができます。" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "metadata": { 94 | "id": "-Tnd7UjE-m3t", 95 | "colab_type": "code", 96 | "colab": {} 97 | }, 98 | "source": [ 99 | "def say_gm():\n", 100 | " print(\"Good morning!\")\n", 101 | "\n", 102 | "say_gm()\n", 103 | "say_gm()\n", 104 | "say_gm()" 105 | ], 106 | "execution_count": null, 107 | "outputs": [] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "metadata": { 112 | "id": "cAZfsS-vZKeC", 113 | "colab_type": "code", 114 | "colab": {} 115 | }, 116 | "source": [ 117 | "# 練習用\n" 118 | ], 119 | "execution_count": null, 120 | "outputs": [] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": { 125 | "id": "MWyBm7xfaQ1T", 126 | "colab_type": "text" 127 | }, 128 | "source": [ 129 | "## ●引数\n", 130 | "関数は、外部からの値を**引数**として受け取ることができます。 \n", 131 | "以下は、引数を伴うシンプルな関数です。" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "metadata": { 137 | "id": "utV0XhMAafbt", 138 | "colab_type": "code", 139 | "colab": {} 140 | }, 141 | "source": [ 142 | "def say_number(a): # aが引数\n", 143 | " print(a)\n", 144 | "\n", 145 | "say_number(123)" 146 | ], 147 | "execution_count": null, 148 | "outputs": [] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "metadata": { 153 | "id": "RyOkPsNFaR6o", 154 | "colab_type": "code", 155 | "colab": {} 156 | }, 157 | "source": [ 158 | "# 練習用\n" 159 | ], 160 | "execution_count": null, 161 | "outputs": [] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": { 166 | "id": "Z_01jL1ZgIXO", 167 | "colab_type": "text" 168 | }, 169 | "source": [ 170 | "関数を呼び出す際に、( ) 内に値を渡すとそれを関数が受け取ります。 \n", 171 | " \n", 172 | "引数が複数の場合は、`,`(カンマ)で区切ります。" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "metadata": { 178 | "id": "zPN48d8gfq0Z", 179 | "colab_type": "code", 180 | "colab": {} 181 | }, 182 | "source": [ 183 | "def add(a, b, c): # 引数は3つ\n", 184 | " d = a + b + c\n", 185 | " print(d)\n", 186 | "\n", 187 | "add(3, 4, 5)" 188 | ], 189 | "execution_count": null, 190 | "outputs": [] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "metadata": { 195 | "id": "eq9RMuApiHjv", 196 | "colab_type": "code", 197 | "colab": {} 198 | }, 199 | "source": [ 200 | "# 練習用\n" 201 | ], 202 | "execution_count": null, 203 | "outputs": [] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": { 208 | "id": "rmu22GA5hOHQ", 209 | "colab_type": "text" 210 | }, 211 | "source": [ 212 | "## ●返り値\n", 213 | "**返り値**を用いると、関数から外部に値を渡すことができます。 \n", 214 | " \n", 215 | "以下は、返り値のシンプルな例です。 " 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "metadata": { 221 | "id": "PuaerkxqhhnY", 222 | "colab_type": "code", 223 | "colab": {} 224 | }, 225 | "source": [ 226 | "def get_number():\n", 227 | " a = 123\n", 228 | " return a # 返り値\n", 229 | "\n", 230 | "b = get_number()\n", 231 | "print(b)" 232 | ], 233 | "execution_count": null, 234 | "outputs": [] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "metadata": { 239 | "id": "4rKMXPTFmH6S", 240 | "colab_type": "code", 241 | "colab": {} 242 | }, 243 | "source": [ 244 | "# 練習用\n" 245 | ], 246 | "execution_count": null, 247 | "outputs": [] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": { 252 | "id": "FwOzg6qyiBSB", 253 | "colab_type": "text" 254 | }, 255 | "source": [ 256 | "関数の内部にreturnを記述すると、その直後の値を関数の外部に渡します。 \n", 257 | " \n", 258 | "以下は、引数と返り値を組み合わせた例です。" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "metadata": { 264 | "id": "27VGeUNmifwo", 265 | "colab_type": "code", 266 | "colab": {} 267 | }, 268 | "source": [ 269 | "def add(a, b):\n", 270 | " c = a + b\n", 271 | " return c\n", 272 | "\n", 273 | "result1 = add(3, 4)\n", 274 | "print(result1)\n", 275 | "\n", 276 | "result2 = add(7, 8)\n", 277 | "print(result2)" 278 | ], 279 | "execution_count": null, 280 | "outputs": [] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "metadata": { 285 | "id": "dDfU9UZDmwxg", 286 | "colab_type": "code", 287 | "colab": {} 288 | }, 289 | "source": [ 290 | "# 練習用\n" 291 | ], 292 | "execution_count": null, 293 | "outputs": [] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "metadata": { 298 | "id": "ERD55Tt-mrqR", 299 | "colab_type": "text" 300 | }, 301 | "source": [ 302 | "以上のような関数を使うことで、コードの再利用が可能になります。" 303 | ] 304 | }, 305 | { 306 | "cell_type": "markdown", 307 | "metadata": { 308 | "id": "DtAbWNWw-m3y", 309 | "colab_type": "text" 310 | }, 311 | "source": [ 312 | "## ●変数のスコープ\n", 313 | "関数内で定義された変数がローカル変数、関数外で定義された変数がグローバル変数です。 " 314 | ] 315 | }, 316 | { 317 | "cell_type": "code", 318 | "metadata": { 319 | "id": "3pD2XU7t-m3y", 320 | "colab_type": "code", 321 | "colab": {} 322 | }, 323 | "source": [ 324 | "glob_1 = 123 # グローバル変数\n", 325 | "\n", 326 | "def show_number():\n", 327 | " loc_1 = 456 # ローカル変数\n", 328 | " print(glob_1, loc_1)\n", 329 | " \n", 330 | "show_number()" 331 | ], 332 | "execution_count": null, 333 | "outputs": [] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "metadata": { 338 | "id": "39Zt6NeVtHiK", 339 | "colab_type": "code", 340 | "colab": {} 341 | }, 342 | "source": [ 343 | "# 練習用\n" 344 | ], 345 | "execution_count": null, 346 | "outputs": [] 347 | }, 348 | { 349 | "cell_type": "markdown", 350 | "metadata": { 351 | "id": "j4BL7N5d-m30", 352 | "colab_type": "text" 353 | }, 354 | "source": [ 355 | "ローカル変数は同じ関数内からのみアクセスできますが、グローバル変数はどこからでもアクセスできます。 \n", 356 | "\n", 357 | "以下のコードでは、関数の外でローカル変数bにアクセスしようとしているため、エラーが発生します。" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "metadata": { 363 | "id": "7KOGz1gM-m31", 364 | "colab_type": "code", 365 | "colab": {} 366 | }, 367 | "source": [ 368 | "glob_2= 123 # グローバル変数\n", 369 | "\n", 370 | "def setNum():\n", 371 | " loc_2 = 456 # ローカル変数\n", 372 | "\n", 373 | "setNum()\n", 374 | "print(glob_2, loc_2)" 375 | ], 376 | "execution_count": null, 377 | "outputs": [] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "metadata": { 382 | "id": "f5wYs01szjlc", 383 | "colab_type": "code", 384 | "colab": {} 385 | }, 386 | "source": [ 387 | "# 練習用\n" 388 | ], 389 | "execution_count": null, 390 | "outputs": [] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": { 395 | "id": "zG9VcO-6-m35", 396 | "colab_type": "text" 397 | }, 398 | "source": [ 399 | "## ●クラス\n", 400 | "**クラス**を用いると、複数の「関数のようなもの」をまとめることができます。 \n", 401 | "この「関数のようなもの」は、メソッドと呼ばれます。\n", 402 | "\n", 403 | "Pythonでクラスを定義するためには、`class`の表記を用います。 \n", 404 | "メソッドはクラス内で定義するのですが、関数と同様にdefの直後にメソッド名を記述します。 \n", 405 | "\n", 406 | "以下の例では、`Calc`クラス内に`add`メソッドが記述されています。 \n", 407 | "クラスから**インスタンス**を生成し、このインスタンスからメソッドを呼び出すことができます。" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "metadata": { 413 | "id": "h9YW6LdV-m36", 414 | "colab_type": "code", 415 | "colab": {} 416 | }, 417 | "source": [ 418 | "class Calc: # Calcクラス\n", 419 | " def add(self, a, b): # addメソッド\n", 420 | " print(a + b)\n", 421 | "\n", 422 | " def multiply(self, a, b): # multiplyメソッド\n", 423 | " print(a * b)\n", 424 | "\n", 425 | "cl = Calc() # インスタンスclを生成\n", 426 | "cl.add(2, 3)\n", 427 | "cl.multiply(4, 5)" 428 | ], 429 | "execution_count": null, 430 | "outputs": [] 431 | }, 432 | { 433 | "cell_type": "code", 434 | "metadata": { 435 | "id": "s-haa7_RkFGS", 436 | "colab_type": "code", 437 | "colab": {} 438 | }, 439 | "source": [ 440 | "# 練習用\n" 441 | ], 442 | "execution_count": null, 443 | "outputs": [] 444 | }, 445 | { 446 | "cell_type": "markdown", 447 | "metadata": { 448 | "id": "f83MEU1X-m38", 449 | "colab_type": "text" 450 | }, 451 | "source": [ 452 | "関数とは異なり、メソッドの最初の引数はselfと書く必要があります。 \n", 453 | " \n", 454 | "このselfを用いて、インスタンスは値を保持することができます。 \n", 455 | "インスタンス内で値を保持する変数を、**インスタンス変数**といいます。 \n", 456 | "以下の例では、`set_number`メソッドの中でインスタンス変数を設定しています。" 457 | ] 458 | }, 459 | { 460 | "cell_type": "code", 461 | "metadata": { 462 | "id": "9le-T7MT-m39", 463 | "colab_type": "code", 464 | "colab": {} 465 | }, 466 | "source": [ 467 | "class Box:\n", 468 | " def set_number(self, n1, n2):\n", 469 | " self.num1 = n1 # num1がインスタンス変数\n", 470 | " self.num2 = n2\n", 471 | " \n", 472 | "bx = Box()\n", 473 | "bx.set_number(123, 456)\n", 474 | "\n", 475 | "print(bx.num1) # インスタンス変数の値を表示\n", 476 | "print(bx.num2)\n", 477 | "\n", 478 | "bx.num1 = 999 # 値を変更\n", 479 | "print(bx.num1)" 480 | ], 481 | "execution_count": null, 482 | "outputs": [] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "metadata": { 487 | "id": "jHLWfjHLnefH", 488 | "colab_type": "code", 489 | "colab": {} 490 | }, 491 | "source": [ 492 | "# 練習用\n" 493 | ], 494 | "execution_count": null, 495 | "outputs": [] 496 | }, 497 | { 498 | "cell_type": "markdown", 499 | "metadata": { 500 | "id": "ZHSv1Cbd-m3-", 501 | "colab_type": "text" 502 | }, 503 | "source": [ 504 | "インスタンス変数は、インスタンスごとに異なる値を設定することができます。 \n", 505 | "以下の例では、`Dog`クラスから`dog1`、`dog2`、2つのインスタンスを生成し、インスタンス変数にそれぞれ異なる値を設定しています。 \n", 506 | "その上で、これらのインスタンスをリストに格納し、ループ内で値を表示します。" 507 | ] 508 | }, 509 | { 510 | "cell_type": "code", 511 | "metadata": { 512 | "id": "b-oYXKYp-m3_", 513 | "colab_type": "code", 514 | "colab": {} 515 | }, 516 | "source": [ 517 | "class Dog:\n", 518 | " def set_dog(self, n, a):\n", 519 | " self.name = n\n", 520 | " self.age = a\n", 521 | " \n", 522 | "dog1 = Dog()\n", 523 | "dog1.set_dog(\"Pochi\", 5)\n", 524 | "\n", 525 | "dog2 = Dog()\n", 526 | "dog2.set_dog(\"Hachi\", 12)\n", 527 | "\n", 528 | "dogs = [dog1, dog2] # リストに格納\n", 529 | "for d in dogs:\n", 530 | " print(d.name, d.age)" 531 | ], 532 | "execution_count": null, 533 | "outputs": [] 534 | }, 535 | { 536 | "cell_type": "code", 537 | "metadata": { 538 | "id": "oLVA4jq1tCM2", 539 | "colab_type": "code", 540 | "colab": {} 541 | }, 542 | "source": [ 543 | "# 練習用\n" 544 | ], 545 | "execution_count": null, 546 | "outputs": [] 547 | }, 548 | { 549 | "cell_type": "markdown", 550 | "metadata": { 551 | "id": "VWXp1IvK7e45", 552 | "colab_type": "text" 553 | }, 554 | "source": [ 555 | "クラスを使うことで、複雑な構造を持つ処理を簡潔に記述することが可能になります。" 556 | ] 557 | }, 558 | { 559 | "cell_type": "markdown", 560 | "metadata": { 561 | "id": "iI06xAN-W94U", 562 | "colab_type": "text" 563 | }, 564 | "source": [ 565 | "## ●ファイルの保存と読み込み\n", 566 | "with構文を用いて、ファイルの読み込みや保存を簡潔に記述することができます。 \n", 567 | "以下は、文字列をファイルに保存する例です。 \n", 568 | "保存されたファイルは、サイドバーで確認することができます。" 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "metadata": { 574 | "id": "vC8DP5nV93TP", 575 | "colab_type": "code", 576 | "colab": {} 577 | }, 578 | "source": [ 579 | "greetings = \"Good morning! Good night!\"\n", 580 | "\n", 581 | "with open(\"greetings.txt\", \"w\") as f:\n", 582 | " f.write(greetings) # ファイルに保存" 583 | ], 584 | "execution_count": null, 585 | "outputs": [] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "metadata": { 590 | "id": "FwhBtEkI_OBl", 591 | "colab_type": "code", 592 | "colab": {} 593 | }, 594 | "source": [ 595 | "# 練習用\n" 596 | ], 597 | "execution_count": null, 598 | "outputs": [] 599 | }, 600 | { 601 | "cell_type": "markdown", 602 | "metadata": { 603 | "id": "Tjp3EXIBXsXc", 604 | "colab_type": "text" 605 | }, 606 | "source": [ 607 | "以下は、上記で保存されたファイルを読み込んで表示する例です。" 608 | ] 609 | }, 610 | { 611 | "cell_type": "code", 612 | "metadata": { 613 | "id": "APsIqyhbVXZb", 614 | "colab_type": "code", 615 | "colab": {} 616 | }, 617 | "source": [ 618 | "with open(\"greetings.txt\", \"r\") as f:\n", 619 | " print(f.read()) # ファイルの読み込み" 620 | ], 621 | "execution_count": null, 622 | "outputs": [] 623 | }, 624 | { 625 | "cell_type": "code", 626 | "metadata": { 627 | "id": "EEvkDyzO_SXP", 628 | "colab_type": "code", 629 | "colab": {} 630 | }, 631 | "source": [ 632 | "# 練習用\n" 633 | ], 634 | "execution_count": null, 635 | "outputs": [] 636 | } 637 | ] 638 | } -------------------------------------------------------------------------------- /python_basic/python_basic_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "python_basic_2.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyPdjxknDZNDHdnEKg4+DwZF", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "QK1qtAbx7DCH", 32 | "colab_type": "text" 33 | }, 34 | "source": [ 35 | "# Pythonの基礎2\n", 36 | "リストや分岐、ループなどについて学んでいきます。" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": { 42 | "id": "BBT3UlBN7DCX", 43 | "colab_type": "text" 44 | }, 45 | "source": [ 46 | "## ●リスト\n", 47 | "**リスト**は、複数の値をまとめて扱う場合に使用します。 \n", 48 | "リストは全体を`[]`で囲み、各要素は`,`で区切ります。 " 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "metadata": { 54 | "id": "Qi_hyR077DCY", 55 | "colab_type": "code", 56 | "colab": {} 57 | }, 58 | "source": [ 59 | "a = [2011, 2012, 2013, 2014, 2015] # リストの作成\n", 60 | "\n", 61 | "print(a[0]) # 先頭から0番目の要素\n", 62 | "print(a[1]) # 先頭から1番目の要素\n", 63 | "print(a[2]) # 先頭から2番目の要素" 64 | ], 65 | "execution_count": null, 66 | "outputs": [] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "metadata": { 71 | "id": "8uCyuQHR_4M0", 72 | "colab_type": "code", 73 | "colab": {} 74 | }, 75 | "source": [ 76 | "# 練習用\n" 77 | ], 78 | "execution_count": null, 79 | "outputs": [] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": { 84 | "id": "FsL7GD6p_xL7", 85 | "colab_type": "text" 86 | }, 87 | "source": [ 88 | "リストでは、変数名の直後に`[ ]`を記述することで各要素を取り出すことができます。 \n", 89 | "Pythonのリストはどのような値でも格納することができます。" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "metadata": { 95 | "id": "eQyRokhrCutm", 96 | "colab_type": "code", 97 | "colab": {} 98 | }, 99 | "source": [ 100 | "b = 2016\n", 101 | "c = [b, 2017, 20.1, \"Hello\", \"Hi\"]\n", 102 | "print(c[1:4]) # 先頭から1番目以上、4番目未満の範囲" 103 | ], 104 | "execution_count": null, 105 | "outputs": [] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "metadata": { 110 | "id": "GCqOwdJPFAb8", 111 | "colab_type": "code", 112 | "colab": {} 113 | }, 114 | "source": [ 115 | "# 練習用\n" 116 | ], 117 | "execution_count": null, 118 | "outputs": [] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": { 123 | "id": "xTCNxy9IESfE", 124 | "colab_type": "text" 125 | }, 126 | "source": [ 127 | "リストの中にリストを格納することもできます。" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "metadata": { 133 | "id": "T1cpxD79GBcu", 134 | "colab_type": "code", 135 | "colab": {} 136 | }, 137 | "source": [ 138 | "d =[[2012, 2013, 2014], [2015, 2016, 2017]]\n", 139 | "print(d[0]) # 先頭から0番目の要素" 140 | ], 141 | "execution_count": null, 142 | "outputs": [] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "metadata": { 147 | "id": "ScUcc8ycGXrW", 148 | "colab_type": "code", 149 | "colab": {} 150 | }, 151 | "source": [ 152 | "# 練習用\n" 153 | ], 154 | "execution_count": null, 155 | "outputs": [] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": { 160 | "id": "eF1dmMxzQK0-", 161 | "colab_type": "text" 162 | }, 163 | "source": [ 164 | "リストは、作成後に要素を変更することができます。 \n", 165 | "また、appendにより要素を追加することができます。" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "metadata": { 171 | "id": "QqTepYh6QuMa", 172 | "colab_type": "code", 173 | "colab": {} 174 | }, 175 | "source": [ 176 | "e = [\"Py\", 543.21, 79, \"thon\", [2018, 2019, 2020]]\n", 177 | "print(e)\n", 178 | "\n", 179 | "# 要素の変更\n", 180 | "e[2] = 99\n", 181 | "print(e)\n", 182 | "\n", 183 | "# 要素の追加\n", 184 | "e.append(2021)\n", 185 | "print(e)" 186 | ], 187 | "execution_count": null, 188 | "outputs": [] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "metadata": { 193 | "id": "XqeoFPxMqNwb", 194 | "colab_type": "code", 195 | "colab": {} 196 | }, 197 | "source": [ 198 | "# 練習用\n" 199 | ], 200 | "execution_count": null, 201 | "outputs": [] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": { 206 | "id": "GeQVpswkLLvU", 207 | "colab_type": "text" 208 | }, 209 | "source": [ 210 | "リストにより、多くの値を効率よく扱うことが可能になります。" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": { 216 | "id": "33Tx-KRc7DCZ", 217 | "colab_type": "text" 218 | }, 219 | "source": [ 220 | "## ●タプル\n", 221 | "**タプル**はリストと同じく複数の値をまとめて扱いたいときに利用しますが、要素の追加や削除、入れ替えなどはできません。 \n", 222 | "タプルは全体を`()`で囲み、各要素は`,`で区切ります。 \n", 223 | "要素を変更する予定が無い場合は、リストよりもタプルを使用する方がベターです。 \n", 224 | "以下では、リストとタプルを比較しています。 " 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "metadata": { 230 | "id": "uMW9UFiP7DCa", 231 | "colab_type": "code", 232 | "colab": {} 233 | }, 234 | "source": [ 235 | "a = [2012, 2013, 2014] # リスト\n", 236 | "b = (2012, 2013, 2014) # タプル\n", 237 | "\n", 238 | "print(a)\n", 239 | "print(b)\n", 240 | "\n", 241 | "print(a[1])\n", 242 | "print(b[1])\n", 243 | "\n", 244 | "a[1] = 2016\n", 245 | "print(a)\n", 246 | "\n", 247 | "# b[1] = 2016 # エラーが発生\n", 248 | "# print(b)\n", 249 | "\n", 250 | "a.append(2015)\n", 251 | "print(a)\n", 252 | "\n", 253 | "# b.append(2015) # エラーが発生\n", 254 | "# print(b)" 255 | ], 256 | "execution_count": null, 257 | "outputs": [] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "metadata": { 262 | "id": "htyvMHuSqsEf", 263 | "colab_type": "code", 264 | "colab": {} 265 | }, 266 | "source": [ 267 | "# 練習用\n" 268 | ], 269 | "execution_count": null, 270 | "outputs": [] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": { 275 | "id": "KrLdlqyL7DCc", 276 | "colab_type": "text" 277 | }, 278 | "source": [ 279 | "タプルの要素を変更したり、タプルに要素を追加しようとするとエラーが発生します。" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": { 285 | "id": "NkynT8abLLvF", 286 | "colab_type": "text" 287 | }, 288 | "source": [ 289 | "## ●辞書\n", 290 | "**辞書**は、キーと値の組合せでデータを格納します。  \n", 291 | "以下は、Pythonの辞書を扱う例です。 \n", 292 | "文字列をキーとして辞書を作成し、値の取得や入れ替え、要素の追加を行なっています。" 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "metadata": { 298 | "id": "_Mrxui8mLQ5P", 299 | "colab_type": "code", 300 | "colab": {} 301 | }, 302 | "source": [ 303 | "a = {\"Taro\":1985, \"Hanako\":1986} # 辞書の作成\n", 304 | "print(a[\"Taro\"]) # \"Taro\"のキーを持つ値を取得\n", 305 | "\n", 306 | "a[\"Hanako\"] = 1987 # 要素の入れ替え\n", 307 | "print(a)\n", 308 | "\n", 309 | "a[\"Jiro\"] = 1989 # 要素の追加\n", 310 | "print(a)" 311 | ], 312 | "execution_count": null, 313 | "outputs": [] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "metadata": { 318 | "id": "srGuibNYsDrJ", 319 | "colab_type": "code", 320 | "colab": {} 321 | }, 322 | "source": [ 323 | "# 練習用\n" 324 | ], 325 | "execution_count": null, 326 | "outputs": [] 327 | }, 328 | { 329 | "cell_type": "markdown", 330 | "metadata": { 331 | "id": "uEXLmC08sxOD", 332 | "colab_type": "text" 333 | }, 334 | "source": [ 335 | "辞書は、キーを使って多数の値を管理したい際に使用します。" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": { 341 | "id": "vOkphdpi7DCh", 342 | "colab_type": "text" 343 | }, 344 | "source": [ 345 | "## ●if文 \n", 346 | "**if**文により条件分岐を行うことができます。 \n", 347 | "ifの右側が`True`であればその次の処理が、`False`であればelseの次の処理が実行されます。 \n", 348 | "以下のコードは、`a`の値が5であれば足し算を行い、5でなければ掛け算を行います。 \n" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "metadata": { 354 | "id": "tubP_tFRzohW", 355 | "colab_type": "code", 356 | "colab": {} 357 | }, 358 | "source": [ 359 | "a = 5\n", 360 | "\n", 361 | "if a == 5: # aと5は等しいのでifの右はTrue\n", 362 | " print(\"3+4=\")\n", 363 | " print(3+4)\n", 364 | "else:\n", 365 | " print(\"3×4=\")\n", 366 | " print(3*4)" 367 | ], 368 | "execution_count": null, 369 | "outputs": [] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "metadata": { 374 | "id": "DEzLifnOsXl9", 375 | "colab_type": "code", 376 | "colab": {} 377 | }, 378 | "source": [ 379 | "# 練習用\n" 380 | ], 381 | "execution_count": null, 382 | "outputs": [] 383 | }, 384 | { 385 | "cell_type": "markdown", 386 | "metadata": { 387 | "id": "rr_1KJ0r2Os5", 388 | "colab_type": "text" 389 | }, 390 | "source": [ 391 | "分岐後の処理の行頭には、複数のスペースからなる「インデント」を挿入します。 \n", 392 | "インデントは通常半角スペース4つを使用します。 \n", 393 | " \n", 394 | "3つ以上の分岐を行う際には、`elif`を使用します。 \n" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "metadata": { 400 | "id": "fod0Q-CY1k-8", 401 | "colab_type": "code", 402 | "colab": {} 403 | }, 404 | "source": [ 405 | "b = 4\n", 406 | "\n", 407 | "if b < 3:\n", 408 | " print(\"Hello!\")\n", 409 | "elif b < 5: # ifの右側がFalseの場合\n", 410 | " print(\"Hi!\")\n", 411 | "else: # if、elifの右側がFalseの場合\n", 412 | " print(\"Yeah!\")" 413 | ], 414 | "execution_count": null, 415 | "outputs": [] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "metadata": { 420 | "id": "NzpzGvXBsnoC", 421 | "colab_type": "code", 422 | "colab": {} 423 | }, 424 | "source": [ 425 | "# 練習用\n" 426 | ], 427 | "execution_count": null, 428 | "outputs": [] 429 | }, 430 | { 431 | "cell_type": "markdown", 432 | "metadata": { 433 | "id": "6bf9rfImsqRl", 434 | "colab_type": "text" 435 | }, 436 | "source": [ 437 | "`elif`を並べることで、さらに多くの分岐を行うことが可能になります。" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "metadata": { 443 | "id": "mgzqzezO7DCh", 444 | "colab_type": "code", 445 | "colab": {} 446 | }, 447 | "source": [ 448 | "time = 20\n", 449 | "\n", 450 | "if time < 12:\n", 451 | " print(\"Good morning!\")\n", 452 | "elif time < 17:\n", 453 | " print(\"Good afternoon!\")\n", 454 | "elif time < 21:\n", 455 | " print(\"Good evening!\")\n", 456 | "else:\n", 457 | " print(\"Good night!\")" 458 | ], 459 | "execution_count": null, 460 | "outputs": [] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "metadata": { 465 | "id": "MajMrIr6uYFj", 466 | "colab_type": "code", 467 | "colab": {} 468 | }, 469 | "source": [ 470 | "# 練習用\n" 471 | ], 472 | "execution_count": null, 473 | "outputs": [] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": { 478 | "id": "4ikn14Eq7DCj", 479 | "colab_type": "text" 480 | }, 481 | "source": [ 482 | "## ●for文\n", 483 | "**for**文を使えば、同じ処理を繰り返し実行することができます。 \n", 484 | "以下の例は、リストをとfor文を使ったループ処理です。 " 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "metadata": { 490 | "id": "qf8iaf9V7DCj", 491 | "colab_type": "code", 492 | "colab": {} 493 | }, 494 | "source": [ 495 | "a = [2001, 2002, 2003, 2004, 2005]\n", 496 | "for i in a: # iにはリストaの各要素が入る\n", 497 | " print(i + 10) # 行頭にインデントを入れる" 498 | ], 499 | "execution_count": null, 500 | "outputs": [] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "metadata": { 505 | "id": "ydtFlmi62SFw", 506 | "colab_type": "code", 507 | "colab": {} 508 | }, 509 | "source": [ 510 | "# 練習用\n" 511 | ], 512 | "execution_count": null, 513 | "outputs": [] 514 | }, 515 | { 516 | "cell_type": "markdown", 517 | "metadata": { 518 | "id": "QhR-cy3d2T83", 519 | "colab_type": "text" 520 | }, 521 | "source": [ 522 | "繰り返し行う処理には行頭にインデントを挿入します。 \n", 523 | " \n", 524 | "ループ内で連番の整数を使う場合は、`range`を使用します。 \n", 525 | "以下の例では、`i`に0から5までの整数が入ります。 " 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "metadata": { 531 | "id": "BS44zQjq2cLy", 532 | "colab_type": "code", 533 | "colab": {} 534 | }, 535 | "source": [ 536 | "for i in range(0, 6): # iには0以上6未満の整数が入る\n", 537 | " print(i * 2)" 538 | ], 539 | "execution_count": null, 540 | "outputs": [] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "metadata": { 545 | "id": "d38PRmcY4C-B", 546 | "colab_type": "code", 547 | "colab": {} 548 | }, 549 | "source": [ 550 | "# 練習用\n" 551 | ], 552 | "execution_count": null, 553 | "outputs": [] 554 | }, 555 | { 556 | "cell_type": "markdown", 557 | "metadata": { 558 | "id": "0vD9S7yM4Ova", 559 | "colab_type": "text" 560 | }, 561 | "source": [ 562 | "for文によるループを使うことで、冗長なコードを簡潔にまとめることが可能になります。" 563 | ] 564 | }, 565 | { 566 | "cell_type": "markdown", 567 | "metadata": { 568 | "id": "FKQ9lg_NFEoJ", 569 | "colab_type": "text" 570 | }, 571 | "source": [ 572 | "## ●while文\n", 573 | "ある条件が満たされている間ループするためには、**while**文を用います。" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "metadata": { 579 | "id": "vFVOuNokFKV3", 580 | "colab_type": "code", 581 | "colab": {} 582 | }, 583 | "source": [ 584 | "print(\"--- 10未満 ---\")\n", 585 | "a = 0\n", 586 | "while a < 10: # aが10未満である間ループ\n", 587 | " print(a)\n", 588 | " a += 1 # aに1を加える\n", 589 | "\n", 590 | "print(\"--- 10と等しくない ---\")\n", 591 | "b = 0\n", 592 | "while b != 10: # bが10と等しくない限りループ\n", 593 | " print(b)\n", 594 | " b += 1" 595 | ], 596 | "execution_count": null, 597 | "outputs": [] 598 | }, 599 | { 600 | "cell_type": "code", 601 | "metadata": { 602 | "id": "W94f0JFR9p3p", 603 | "colab_type": "code", 604 | "colab": {} 605 | }, 606 | "source": [ 607 | "# 練習用\n" 608 | ], 609 | "execution_count": null, 610 | "outputs": [] 611 | }, 612 | { 613 | "cell_type": "markdown", 614 | "metadata": { 615 | "id": "jdyK90d_GJzn", 616 | "colab_type": "text" 617 | }, 618 | "source": [ 619 | "## ●分岐とループの組み合わせ\n", 620 | "分岐とループを組み合わせることで、条件が満たされた処理のみをループ内で実行することが可能になります。" 621 | ] 622 | }, 623 | { 624 | "cell_type": "code", 625 | "metadata": { 626 | "id": "qncEVtHrHNkM", 627 | "colab_type": "code", 628 | "colab": {} 629 | }, 630 | "source": [ 631 | "a = [] # 空のリスト\n", 632 | "for i in range(0, 10):\n", 633 | " if i%2 == 0: # 偶数であれば\n", 634 | " a.append(i)\n", 635 | "\n", 636 | "print (a)" 637 | ], 638 | "execution_count": null, 639 | "outputs": [] 640 | }, 641 | { 642 | "cell_type": "code", 643 | "metadata": { 644 | "id": "bwW7OyfbBiKR", 645 | "colab_type": "code", 646 | "colab": {} 647 | }, 648 | "source": [ 649 | "# 練習用\n" 650 | ], 651 | "execution_count": null, 652 | "outputs": [] 653 | } 654 | ] 655 | } --------------------------------------------------------------------------------