Skip to content

Instantly share code, notes, and snippets.

@leng-yue
Created June 3, 2020 01:18
Show Gist options
  • Save leng-yue/d0c949df2ed18d1891afa127a301b5a3 to your computer and use it in GitHub Desktop.
Save leng-yue/d0c949df2ed18d1891afa127a301b5a3 to your computer and use it in GitHub Desktop.
MNIST与三种网络结构.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "MNIST与三种网络结构.ipynb",
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyPWnbL6aYWk8bkr8wlkmrLo",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/leng-yue/d0c949df2ed18d1891afa127a301b5a3/mnist.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HdYBr76ZfN1y",
"colab_type": "text"
},
"source": [
"# MNIST与三种网络结构"
]
},
{
"cell_type": "code",
"metadata": {
"id": "5QWD7_ojfIJb",
"colab_type": "code",
"colab": {}
},
"source": [
"import torch\n",
"import torchvision\n",
"from torch import nn\n",
"from torch.utils.data import DataLoader\n",
"import torchvision.transforms as T\n",
"import matplotlib.pyplot as plt"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "bt_gW6OSkHew",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "ca8e58de-5797-4890-cb3d-3bf4a552c0e5"
},
"source": [
"# 超参数\n",
"BATCH_SIZE = 128\n",
"DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
"print(\"Current Device\", DEVICE.type)"
],
"execution_count": 41,
"outputs": [
{
"output_type": "stream",
"text": [
"Current Device cuda\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "9ecD7D8lka9P",
"colab_type": "code",
"colab": {}
},
"source": [
"trans = T.Compose([T.ToTensor(), T.Normalize((0.5,), (1.0,))])\n",
"\n",
"train_set = torchvision.datasets.MNIST(root='./', train=True, transform=trans, download=True)\n",
"test_set = torchvision.datasets.MNIST(root='./', train=False, transform=trans)\n",
"\n",
"train_loader = DataLoader(dataset=train_set, batch_size=BATCH_SIZE, shuffle=True)\n",
"test_loader = DataLoader(dataset=test_set, batch_size=BATCH_SIZE, shuffle=False)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "j2lrLgcEktRb",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 248
},
"outputId": "4d04a7ad-12b4-4f1e-e208-1ccc8a44dd61"
},
"source": [
"for i in range(16):\n",
" plt.subplot(4, 4, i + 1)\n",
" plt.imshow(train_set.__getitem__(i)[0].squeeze().numpy(), cmap='Greys_r')\n",
" plt.axis('off')\n",
"plt.show()"
],
"execution_count": 43,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 16 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "DNxTUY-ckt4U",
"colab_type": "code",
"colab": {}
},
"source": [
"# Full Connected\n",
"# FullConnectedNet = nn.Sequential(\n",
"# nn.Linear(28 * 28, 512),\n",
"# nn.ReLU(),\n",
"# nn.Linear(512, 256),\n",
"# nn.ReLU(),\n",
"# nn.Linear(256, 10)\n",
"# )"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "rTnPk5pfpm-x",
"colab_type": "code",
"colab": {}
},
"source": [
"# CNN\n",
"# class LeNet(nn.Module):\n",
"# def __init__(self):\n",
"# super(LeNet, self).__init__()\n",
"# self.conv1 = nn.Sequential(\n",
"# nn.Conv2d(1, 20, 5, 1), # (28 + 2 * 0 - 5) / 1 + 1 = 24\n",
"# nn.ReLU(),\n",
"# nn.MaxPool2d(2, 2) # (24 + 2 * 0 - 2) / 2 + 1 = 12\n",
"# )\n",
"# self.conv2 = nn.Sequential(\n",
"# nn.Conv2d(20, 50, 5, 1), # (12 + 2 * 0 - 5) / 1 + 1 = 8\n",
"# nn.ReLU(),\n",
"# nn.MaxPool2d(2, 2) # (8 + 2 * 0 - 2) / 2 + 1 = 4\n",
"# )\n",
"# self.linear = nn.Sequential(\n",
"# nn.Linear(4 * 4 * 50, 500),\n",
"# nn.ReLU(),\n",
"# nn.Linear(500, 10)\n",
"# )\n",
"\n",
"# def forward(self, x):\n",
"# x = self.conv1(x)\n",
"# x = self.conv2(x)\n",
"# x = x.view(x.shape[0], -1)\n",
"# x = self.linear(x)\n",
"# return x"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "YRrqK67FrE14",
"colab_type": "code",
"colab": {}
},
"source": [
"# RNN\n",
"class GRUNet(nn.Module):\n",
" def __init__(self):\n",
" super(GRUNet, self).__init__()\n",
" self.gru = nn.GRU(28, 100, batch_first=True)\n",
" self.linear = nn.Linear(100, 10)\n",
"\n",
" def forward(self, x):\n",
" x = x.squeeze()\n",
" # x: [batch, 28, 28] [batch, timestamp, input]\n",
" out, _ = self.gru(x)\n",
" # out: [batch, 28, 100] [batch, timestamp, hidden]\n",
" x = self.linear(out[:, -1, :])\n",
" return x"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "Zs0PiWprlbyt",
"colab_type": "code",
"colab": {}
},
"source": [
"model = GRUNet()\n",
"model = model.to(DEVICE)\n",
"optimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n",
"loss_func = nn.CrossEntropyLoss() # 交叉熵 0,1,2...9 [0-1,0-1,....]"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "6uey98EylcHo",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 341
},
"outputId": "9c49679f-c13c-42ac-a951-586eceab6f88"
},
"source": [
"for epoch in range(3):\n",
" for index, (x, label) in enumerate(train_loader):\n",
" x, label = x.to(DEVICE), label.to(DEVICE)\n",
" # x = x.view(-1, 28 * 28) # 全连接\n",
" out = model(x)\n",
" loss = loss_func(out, label)\n",
"\n",
" # 快乐三步曲\n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" if (index + 1) % 100 == 0 or (index + 1) == len(train_loader):\n",
" print('TRAIN', 'epoch', epoch, 'batch index', index + 1, 'loss', float(loss))\n",
" \n",
" correct = count = 0\n",
" for index, (x, label) in enumerate(test_loader):\n",
" x, label = x.to(DEVICE), label.to(DEVICE)\n",
" # x = x.view(-1, 28 * 28) # 全连接\n",
" out = model(x) # [batch_size, 10]\n",
" loss = loss_func(out, label)\n",
" _, predict = torch.max(out, 1)\n",
" count += x.shape[0]\n",
" correct += (predict == label).sum()\n",
"\n",
" if (index + 1) % 100 == 0 or (index + 1) == len(test_loader):\n",
" print('TRAIN', 'epoch', epoch, 'batch index', index + 1, 'loss', float(loss), 'acc', correct * 1.0 / count)\n"
],
"execution_count": 50,
"outputs": [
{
"output_type": "stream",
"text": [
"TRAIN epoch 0 batch index 100 loss 0.1101863831281662\n",
"TRAIN epoch 0 batch index 200 loss 0.13605506718158722\n",
"TRAIN epoch 0 batch index 300 loss 0.10176292061805725\n",
"TRAIN epoch 0 batch index 400 loss 0.09847277402877808\n",
"TRAIN epoch 0 batch index 469 loss 0.03433843329548836\n",
"TRAIN epoch 0 batch index 79 loss 0.005884051322937012 acc tensor(0.9750, device='cuda:0')\n",
"TRAIN epoch 1 batch index 100 loss 0.029632315039634705\n",
"TRAIN epoch 1 batch index 200 loss 0.032762497663497925\n",
"TRAIN epoch 1 batch index 300 loss 0.058894962072372437\n",
"TRAIN epoch 1 batch index 400 loss 0.07496350258588791\n",
"TRAIN epoch 1 batch index 469 loss 0.01914743334054947\n",
"TRAIN epoch 1 batch index 79 loss 0.0012041926383972168 acc tensor(0.9715, device='cuda:0')\n",
"TRAIN epoch 2 batch index 100 loss 0.05023415759205818\n",
"TRAIN epoch 2 batch index 200 loss 0.09404107928276062\n",
"TRAIN epoch 2 batch index 300 loss 0.1221444308757782\n",
"TRAIN epoch 2 batch index 400 loss 0.11949461698532104\n",
"TRAIN epoch 2 batch index 469 loss 0.07262753695249557\n",
"TRAIN epoch 2 batch index 79 loss 0.0014670491218566895 acc tensor(0.9725, device='cuda:0')\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "ndZVQqvvlcKE",
"colab_type": "code",
"colab": {}
},
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment