diff --git a/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/Model.pkl b/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/Model.pkl new file mode 100644 index 0000000..7f79350 Binary files /dev/null and b/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/Model.pkl differ diff --git a/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/cnn服装分类.ipynb b/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/cnn服装分类.ipynb new file mode 100644 index 0000000..bf53de7 --- /dev/null +++ b/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/cnn服装分类.ipynb @@ -0,0 +1,638 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import numpy as np\n", + "import pandas as pd\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.optim as optim\n", + "import torch.nn.functional as F\n", + "from torch.utils.data import Dataset, DataLoader" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "device(type='cpu')" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "device=torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n", + "device" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "batch_size = 256\n", + "lr=1e-4\n", + "epochs=20\n", + "# 设置好超参数\n", + "# 因为不是linux系统上跑,所以num_workers就不写,默认0\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "下载Fashion-MNIST数据集" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision import transforms\n", + "image_size = 28\n", + "data_transforms = transforms.Compose([\n", + " # transforms.ToPILImage(),\n", + " transforms.Resize(image_size),\n", + " transforms.ToTensor()\n", + "])\n", + "# 如果你使用的内置的dataset,那么ToPILImage这一句可以不要" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz\n", + "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to ./FashionMNIST\\raw\\train-images-idx3-ubyte.gz\n" + ] + }, + { + "data": { + "text/plain": [ + " 0%| | 0/26421880 [00:00" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy89olMNAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAgrklEQVR4nO3df3CU5d3v8c/ukmz4kQRCyC8JNOAPWoG0pZLmUSmWDBCf8YgyHX+dOeB4YLTBKVKrk46K2s6kxTnW0aE480wLdUZEOUfg0dOHjqIJRxvoAWUYjjUP0FjCAwmaNgkEkiy71/mDY3pWEvG62Oy12bxfM/dMsnt/c31z504+u9k73wSMMUYAACRZ0HcDAICRiQACAHhBAAEAvCCAAABeEEAAAC8IIACAFwQQAMALAggA4MUo3w18USwW04kTJ5Sdna1AIOC7HQCAJWOMTp8+rZKSEgWDgz/PSbkAOnHihEpLS323AQC4TC0tLZo8efKg96dcAGVnZ0uSbtDNGqUMz90gJQRD1iWR781yWirzvY+sa0ykz2mtZAiOHeNUFygpsq6JHv6L01opzeW3MEw303lF9J5+3//zfDBDFkDr16/XM888o9bWVpWXl+uFF17Q3LlzL1n3+a/dRilDowIEECQF7APIjMpyWsrlnDOB1P2BEwxkOtUFQmH7mnT8fnV6GSB1z4ek+X+H4FIvowzJRQivvvqq1qxZo7Vr1+qDDz5QeXm5Fi1apFOnTg3FcgCAYWhIAujZZ5/VihUrdO+99+ob3/iGXnzxRY0ZM0a//e1vh2I5AMAwlPAA6uvr0/79+1VVVfWPRYJBVVVVqbGx8aL9e3t71dXVFbcBANJfwgPos88+UzQaVWFhYdzthYWFam1tvWj/uro65ebm9m9cAQcAI4P3P0Stra1VZ2dn/9bS0uK7JQBAEiT8Krj8/HyFQiG1tbXF3d7W1qaioosv7QyHwwqH7a+4AQAMbwl/BpSZmak5c+Zo165d/bfFYjHt2rVLlZWViV4OADBMDcnfAa1Zs0bLli3Td77zHc2dO1fPPfecuru7de+99w7FcgCAYWhIAuiOO+7Qp59+qieeeEKtra365je/qZ07d150YQIAYOQKGJNacyO6urqUm5ur+bqVSQgprnX1P1nXfO8//2/rmudL7GtcnYp2W9dsPT3DuuZfT5Zb12y5+jXrmtaodYkk6euZ9iN8oiZmXXPzx//JuqbrN4PPFhtMzuY91jVwd95EVK8d6uzsVE5OzqD7eb8KDgAwMhFAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADAC4aRppnef77Ouqb+X/7Faa0zsR7rmk+j561rTkTtB2NGjNug9x5jf871mZB1TczhsV/pqL9Z17Scz7OukaRJoS7rmqyA/de2JNTnsI79sTvtMChVku6f/c/WNdGOTqe10gnDSAEAKY0AAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAv3EYGI2W5TLY+dv6M01p7eq6wrskKRKxrxgZ7rWtcZQfPWde4TIGOKmBd020yrWvyQm5f29Ox0dY1EYev7f+KTLKucTmHbsz6zLpGkp788G3rmsfL7CfSj1Q8AwIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALxhGmsLO3l5hXfP36B+taw70FljXSNLXMuwHPPaYDOuaiAlZ14RkrGskqTsWtq+RfY2LmMPjxQyHQamS21BWlwGmBaHT1jUug1z39k6wrpGkmZnt1jXB2TOsa2IHP7auSQc8AwIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALxhGmsJOVqbf44OQYtY1LkM4XQZWSlJmIGpdEwzYf04uUn0oa+moDuuaT6NjrWuygz3WNadjWdY1kpQXzLSuaf+W/eDTCQetS9JC+v2EAwAMCwQQAMCLhAfQk08+qUAgELfNmGH//zEAAOltSF4Duvbaa/X222//Y5FRvNQEAIg3JMkwatQoFRUVDcWHBgCkiSF5Dejw4cMqKSnRtGnTdM899+jYsWOD7tvb26uurq64DQCQ/hIeQBUVFdq0aZN27typDRs2qLm5WTfeeKNOnx74f7/X1dUpNze3fystLU10SwCAFJTwAKqurtYPfvADzZ49W4sWLdLvf/97dXR06LXXXhtw/9raWnV2dvZvLS0tiW4JAJCChvzqgPHjx+vqq6/WkSNHBrw/HA4rHLb/ozcAwPA25H8HdObMGR09elTFxcVDvRQAYBhJeAA9/PDDamho0CeffKI//vGPuu222xQKhXTXXXcleikAwDCW8F/BHT9+XHfddZfa29s1adIk3XDDDdqzZ48mTZqU6KUAAMNYwgNoy5Ytif6QI1b+tZ8mZZ2C0MBXKF5KzNg/gY6Y5PxRsusQThcux8FlWKrL5+Q6lLXmv/9X65p7b37HuubWnAPWNa3RcdY1UYevkauu6fY19uNL0wOz4AAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADAi+RMhoST7xZ+kpR1goGYU13EhBLcycBc+nMZECq5D+9Mhj6H450T7HFa61/v/G/WNZ0x+38s2R4bbV2TFYhY1/Qow7pGkmKyP/d6S+z7G6l4BgQA8IIAAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAvmIadwubnfGxd02Psp/eODZy3rpGkbqeqJHEdau04RTspHKaCd8WynJbqMfbTo8cEe61rzkbHWNd8I7PduqY1aj+pW5KiMtY1JZP/5rTWSJTC320AgHRGAAEAvCCAAABeEEAAAC8IIACAFwQQAMALAggA4AUBBADwggACAHhBAAEAvCCAAABeEEAAAC8YRprCrsk4ZV3TYz87UVmBqH2RpB4Tsi9yWCvmNCDUfnCnJPchpsngchwcBphKUobDgNqIw/mQFYhY1xSG7AeLfnLefrjqBfbH4YpxndY19hXpgWdAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFw0hT2NUZWdY1H0d6rWvygo7DSB0Gi3Yb+1OuT/ZDLkOuw0hTWNBhsKjrI8wMh69tj7Ef+NkeHeewTrd1TZbjkNmzMfvjUDr679Y1DCMFACCJCCAAgBfWAbR7927dcsstKikpUSAQ0Pbt2+PuN8boiSeeUHFxsUaPHq2qqiodPnw4Uf0CANKEdQB1d3ervLxc69evH/D+devW6fnnn9eLL76ovXv3auzYsVq0aJF6enouu1kAQPqwfkW4urpa1dXVA95njNFzzz2nxx57TLfeeqsk6aWXXlJhYaG2b9+uO++88/K6BQCkjYS+BtTc3KzW1lZVVVX135abm6uKigo1NjYOWNPb26uurq64DQCQ/hIaQK2trZKkwsLCuNsLCwv77/uiuro65ebm9m+lpaWJbAkAkKK8XwVXW1urzs7O/q2lpcV3SwCAJEhoABUVFUmS2tra4m5va2vrv++LwuGwcnJy4jYAQPpLaACVlZWpqKhIu3bt6r+tq6tLe/fuVWVlZSKXAgAMc9ZXwZ05c0ZHjhzpf7+5uVkHDhxQXl6epkyZotWrV+vnP/+5rrrqKpWVlenxxx9XSUmJlixZksi+AQDDnHUA7du3TzfddFP/+2vWrJEkLVu2TJs2bdIjjzyi7u5urVy5Uh0dHbrhhhu0c+dOZWXZzzUDAKQv6wCaP3++jDGD3h8IBPT000/r6aefvqzGIIUC9r8hzXAYWOkqqMHPg8FEjP1g0ZixPw6ZDsM0JcmtKv24DBbNCkSGoJOLhWQ/WTTTcTity/nw/dyPrGsOaYbDSsOf96vgAAAjEwEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF5YT8NGavtb1P7fXozP6HFaa3zQfsLwpzH7xzxRh+nHSD6XqeWTRnVZ14wOZFrXZAfPWtdI0lljf+79U/hv1jXPW1ekB54BAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALwggAIAXDCNNklBOTlLWcRncOSFoP8BUkv7Ua79WViBiXROS/dBTVy4DNYOB5PVnK1PRpK3VYzKsa7KD9oNwt54ptK6pGnPOukaSTkRD1jUTQm7fTyMRz4AAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAuGkSZJdMZU3y0MKugwwFSSVn90p3XNv5VvtK451JdtXaPAefsauQ0WdRmWGuWxnyQpL9hnXbOlda51zW1XnrKukaRQ1O08wlfDdwEAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeMEw0iTpKRydlHUyAlHrmlAgw2mts+/nW9dM+Jb9cegzIesal6Gikttg0ZCMdU3EJOmxn8P5ILkdv6ixH2qbHbSvaTpVYF0TvsrtHJcYRjqUeAYEAPCCAAIAeGEdQLt379Ytt9yikpISBQIBbd++Pe7+5cuXKxAIxG2LFy9OVL8AgDRhHUDd3d0qLy/X+vXrB91n8eLFOnnyZP/2yiuvXFaTAID0Y30RQnV1taqrq790n3A4rKKiIuemAADpb0heA6qvr1dBQYGuueYaPfDAA2pvbx90397eXnV1dcVtAID0l/AAWrx4sV566SXt2rVLv/zlL9XQ0KDq6mpFowNfDlpXV6fc3Nz+rbS0NNEtAQBSUML/DujOO+/sf3vWrFmaPXu2pk+frvr6ei1YsOCi/Wtra7VmzZr+97u6ugghABgBhvwy7GnTpik/P19HjhwZ8P5wOKycnJy4DQCQ/oY8gI4fP6729nYVFxcP9VIAgGHE+ldwZ86ciXs209zcrAMHDigvL095eXl66qmntHTpUhUVFeno0aN65JFHdOWVV2rRokUJbRwAMLxZB9C+fft000039b//+es3y5Yt04YNG3Tw4EH97ne/U0dHh0pKSrRw4UL97Gc/UzgcTlzXAIBhzzqA5s+fL2MGH774hz/84bIaSlenr7AfqOnia6P6rGv+3BdxWmvin+0HNYYC9r/1jcj+2I1Vr3WN5DZY1IXLsE+XQamuknUcsgL2X9vIsbH2C11vXyJJwSQdh1D+ROua6GeD/3nLcMEsOACAFwQQAMALAggA4AUBBADwggACAHhBAAEAvCCAAABeEEAAAC8IIACAFwQQAMALAggA4AUBBADwggACAHiR8H/JjYH1TAwkZZ2JwdHWNXt6xjmtFf7MfvK2i4ixP02TNc1ZkqKy/9q6TLZO/c/Jvr+gw2PgcHsaPm52mBKfDkbmZw0A8I4AAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXjCMNEnOZ9sPaowah4GVDkMN3z9ztXWNJGUcPuFUh9QXM/bnkcsA03DA/kdQZqd1ibOYw+fkJJikdVIMz4AAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAuGkSZJJD/iu4VBvd82zalubNtfEtzJwHpiGfZFocT3gS8XdRhg6jI8N9RjP9i3M3bOukaSMgL2A4FdBEaNzB/FPAMCAHhBAAEAvCCAAABeEEAAAC8IIACAFwQQAMALAggA4AUBBADwggACAHhBAAEAvCCAAABeEEAAAC9G5gQ8DwIZyRlq6OI/WiY61X396oBD1QHriqDDQMioXHqTQrIfdJksLp+T6+fjslbEaQKs/ZDegMOn9O65SfZFkr4TbnWqs2XOn0/KOqmGZ0AAAC8IIACAF1YBVFdXp+uuu07Z2dkqKCjQkiVL1NTUFLdPT0+PampqNHHiRI0bN05Lly5VW1tbQpsGAAx/VgHU0NCgmpoa7dmzR2+99ZYikYgWLlyo7u7u/n0eeughvfHGG9q6dasaGhp04sQJ3X777QlvHAAwvFldhLBz58649zdt2qSCggLt379f8+bNU2dnp37zm99o8+bN+v73vy9J2rhxo77+9a9rz549+u53v5u4zgEAw9plvQbU2dkpScrLy5Mk7d+/X5FIRFVVVf37zJgxQ1OmTFFjY+OAH6O3t1ddXV1xGwAg/TkHUCwW0+rVq3X99ddr5syZkqTW1lZlZmZq/PjxcfsWFhaqtXXgyxnr6uqUm5vbv5WWlrq2BAAYRpwDqKamRocOHdKWLVsuq4Ha2lp1dnb2by0tLZf18QAAw4PTH6KuWrVKb775pnbv3q3Jkyf3315UVKS+vj51dHTEPQtqa2tTUVHRgB8rHA4rHA67tAEAGMasngEZY7Rq1Spt27ZN77zzjsrKyuLunzNnjjIyMrRr167+25qamnTs2DFVVlYmpmMAQFqwegZUU1OjzZs3a8eOHcrOzu5/XSc3N1ejR49Wbm6u7rvvPq1Zs0Z5eXnKycnRgw8+qMrKSq6AAwDEsQqgDRs2SJLmz58fd/vGjRu1fPlySdKvfvUrBYNBLV26VL29vVq0aJF+/etfJ6RZAED6sAogYy49BTArK0vr16/X+vXrnZtKRybmNhwzGcb8JcOpruPbbgMebbkM1MwIRIegk4G5XMkTM8mZguUyyFWS5NBfhuyPedTY99eTZ/+99B+RCdY1klSRpGGk6u1NzjophllwAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8MLpP6IivYT63OoCUfsp1S7GBu0nBZ+Nuf2X3TEOa7lwmdYdlf0UaJdJ4pJ01thPSA85TN4OBewfA4/qsS7R4XOF9kWSxuT8u1OdrWhHZ1LWSTU8AwIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALxhGmiTBUfaDGo+dP2tdU5YxzrrGOD4MGb+/za3QUl7ojHXNtFFuE1Yjxn54Z0bAZUiofU0yRXXauub4eZcfJ/ZDYwsb7Qd39i1z+1E3LmDfX/05Htd/VRwpAIAXBBAAwAsCCADgBQEEAPCCAAIAeEEAAQC8IIAAAF4QQAAALwggAIAXBBAAwAsCCADgBQEEAPCCYaRJEjufulkfy3CrO/+XT6xrbp4xz7om2tVlXSOHAaGSFBjlcDCCDmvF7IeepjxjP3A3ELYf9mm6/491zX+ZuN+6RpL+HuuxrhkTzHRaayRK3Z+KAIC0RgABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXhBAAAAvGEaaJJPq7QcUZi2wX6fXRKxrJvx71H4hR06DRV0Yt2GfJtKX4EbwZcz580lZ5390fMep7pmiD61rft+d77TWSMQzIACAFwQQAMALqwCqq6vTddddp+zsbBUUFGjJkiVqamqK22f+/PkKBAJx2/3335/QpgEAw59VADU0NKimpkZ79uzRW2+9pUgkooULF6q7uztuvxUrVujkyZP927p16xLaNABg+LO6CGHnzp1x72/atEkFBQXav3+/5s37x3+6HDNmjIqKihLTIQAgLV3Wa0CdnZ2SpLy8vLjbX375ZeXn52vmzJmqra3V2bNnB/0Yvb296urqitsAAOnP+TLsWCym1atX6/rrr9fMmTP7b7/77rs1depUlZSU6ODBg3r00UfV1NSk119/fcCPU1dXp6eeesq1DQDAMOUcQDU1NTp06JDee++9uNtXrlzZ//asWbNUXFysBQsW6OjRo5o+ffpFH6e2tlZr1qzpf7+rq0ulpaWubQEAhgmnAFq1apXefPNN7d69W5MnT/7SfSsqKiRJR44cGTCAwuGwwuGwSxsAgGHMKoCMMXrwwQe1bds21dfXq6ys7JI1Bw4ckCQVFxc7NQgASE9WAVRTU6PNmzdrx44dys7OVmtrqyQpNzdXo0eP1tGjR7V582bdfPPNmjhxog4ePKiHHnpI8+bN0+zZs4fkEwAADE9WAbRhwwZJF/7Y9P+3ceNGLV++XJmZmXr77bf13HPPqbu7W6WlpVq6dKkee+yxhDUMAEgP1r+C+zKlpaVqaGi4rIYAACMD07CTZMLvGq1r/lA7zbqmNKPduibn3cPWNZLkMkM7kGE/FdxE7VcKBAPWNfAgFLIuMb291jX/8/VK6xpJeuaH9tOwX2+b47BSm0PN8McwUgCAFwQQAMALAggA4AUBBADwggACAHhBAAEAvCCAAABeEEAAAC8IIACAFwQQAMALAggA4AUBBADwgmGkKeyp+iX2RWH7wZ1Xt++3X8eRy2BRxexrTMx+GXjgcj44mPJvnU51137rHuuasW/kWNdMYBgpAADJQwABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXqTcLDhjjCTpvCKS8dyMZ7FzPQ5F9rO1zpuI/TquXIa0meTMC4MPAfsSY/+DIRDttV9HUvSsQ02f/fdtUr8Hk+C8Lnw+5hJfq4C51B5Jdvz4cZWWlvpuAwBwmVpaWjR58uRB70+5AIrFYjpx4oSys7MVCMQ/Ourq6lJpaalaWlqUk2M/cTZdcBwu4DhcwHG4gONwQSocB2OMTp8+rZKSEgWDg7/Sk3K/ggsGg1+amJKUk5Mzok+wz3EcLuA4XMBxuIDjcIHv45Cbm3vJfbgIAQDgBQEEAPBiWAVQOBzW2rVrFQ6HfbfiFcfhAo7DBRyHCzgOFwyn45ByFyEAAEaGYfUMCACQPgggAIAXBBAAwAsCCADgxbAJoPXr1+trX/uasrKyVFFRoT/96U++W0q6J598UoFAIG6bMWOG77aG3O7du3XLLbeopKREgUBA27dvj7vfGKMnnnhCxcXFGj16tKqqqnT48GE/zQ6hSx2H5cuXX3R+LF682E+zQ6Surk7XXXedsrOzVVBQoCVLlqipqSlun56eHtXU1GjixIkaN26cli5dqra2Nk8dD42vchzmz59/0flw//33e+p4YMMigF599VWtWbNGa9eu1QcffKDy8nItWrRIp06d8t1a0l177bU6efJk//bee+/5bmnIdXd3q7y8XOvXrx/w/nXr1un555/Xiy++qL1792rs2LFatGiRenochrmmsEsdB0lavHhx3PnxyiuvJLHDodfQ0KCamhrt2bNHb731liKRiBYuXKju7u7+fR566CG98cYb2rp1qxoaGnTixAndfvvtHrtOvK9yHCRpxYoVcefDunXrPHU8CDMMzJ0719TU1PS/H41GTUlJiamrq/PYVfKtXbvWlJeX+27DK0lm27Zt/e/HYjFTVFRknnnmmf7bOjo6TDgcNq+88oqHDpPji8fBGGOWLVtmbr31Vi/9+HLq1CkjyTQ0NBhjLnztMzIyzNatW/v3+fOf/2wkmcbGRl9tDrkvHgdjjPne975nfvSjH/lr6itI+WdAfX192r9/v6qqqvpvCwaDqqqqUmNjo8fO/Dh8+LBKSko0bdo03XPPPTp27Jjvlrxqbm5Wa2tr3PmRm5urioqKEXl+1NfXq6CgQNdcc40eeOABtbe3+25pSHV2dkqS8vLyJEn79+9XJBKJOx9mzJihKVOmpPX58MXj8LmXX35Z+fn5mjlzpmpra3X2rMP/lxhCKTeM9Is+++wzRaNRFRYWxt1eWFiojz/+2FNXflRUVGjTpk265pprdPLkST311FO68cYbdejQIWVnZ/tuz4vW1lZJGvD8+Py+kWLx4sW6/fbbVVZWpqNHj+qnP/2pqqur1djYqFAo5Lu9hIvFYlq9erWuv/56zZw5U9KF8yEzM1Pjx4+P2zedz4eBjoMk3X333Zo6dapKSkp08OBBPfroo2pqatLrr7/usdt4KR9A+Ifq6ur+t2fPnq2KigpNnTpVr732mu677z6PnSEV3Hnnnf1vz5o1S7Nnz9b06dNVX1+vBQsWeOxsaNTU1OjQoUMj4nXQLzPYcVi5cmX/27NmzVJxcbEWLFigo0ePavr06cluc0Ap/yu4/Px8hUKhi65iaWtrU1FRkaeuUsP48eN19dVX68iRI75b8ebzc4Dz42LTpk1Tfn5+Wp4fq1at0ptvvql333037t+3FBUVqa+vTx0dHXH7p+v5MNhxGEhFRYUkpdT5kPIBlJmZqTlz5mjXrl39t8ViMe3atUuVlZUeO/PvzJkzOnr0qIqLi3234k1ZWZmKiorizo+uri7t3bt3xJ8fx48fV3t7e1qdH8YYrVq1Stu2bdM777yjsrKyuPvnzJmjjIyMuPOhqalJx44dS6vz4VLHYSAHDhyQpNQ6H3xfBfFVbNmyxYTDYbNp0ybz0UcfmZUrV5rx48eb1tZW360l1Y9//GNTX19vmpubzfvvv2+qqqpMfn6+OXXqlO/WhtTp06fNhx9+aD788EMjyTz77LPmww8/NH/961+NMcb84he/MOPHjzc7duwwBw8eNLfeeqspKysz586d89x5Yn3ZcTh9+rR5+OGHTWNjo2lubjZvv/22+fa3v22uuuoq09PT47v1hHnggQdMbm6uqa+vNydPnuzfzp4927/P/fffb6ZMmWLeeecds2/fPlNZWWkqKys9dp14lzoOR44cMU8//bTZt2+faW5uNjt27DDTpk0z8+bN89x5vGERQMYY88ILL5gpU6aYzMxMM3fuXLNnzx7fLSXdHXfcYYqLi01mZqa54oorzB133GGOHDniu60h9+677xpJF23Lli0zxly4FPvxxx83hYWFJhwOmwULFpimpia/TQ+BLzsOZ8+eNQsXLjSTJk0yGRkZZurUqWbFihVp9yBtoM9fktm4cWP/PufOnTM//OEPzYQJE8yYMWPMbbfdZk6ePOmv6SFwqeNw7NgxM2/ePJOXl2fC4bC58sorzU9+8hPT2dnpt/Ev4N8xAAC8SPnXgAAA6YkAAgB4QQABALwggAAAXhBAAAAvCCAAgBcEEADACwIIAOAFAQQA8IIAAgB4QQABALwggAAAXvxf+rkIFE0QvyMAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.imshow(image[0][0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "打印随机一张图" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "下面开始搭建模型" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class CNNnet(nn.Module):\n", + " def __init__(self):\n", + " super(CNNnet, self).__init__()\n", + " self.conv = nn.Sequential(\n", + " # 黑白图片的in_channels = 1\n", + " nn.Conv2d(1, 32, 5),\n", + " nn.ReLU(),\n", + " nn.MaxPool2d(2, stride = 2),\n", + " # 防止过拟合\n", + " nn.Dropout(0.3),\n", + " nn.Conv2d(32, 64, 5),\n", + " nn.ReLU(),\n", + " # 下面第一个2为kernel_size的大小\n", + " nn.MaxPool2d(2, stride = 2),\n", + " nn.Dropout(0.3)\n", + " )\n", + " self.fc = nn.Sequential(\n", + " nn.Linear(64 * 4 * 4, 512),\n", + " nn.ReLU(),\n", + " nn.Linear(512, 10)\n", + " )\n", + " def forward(self, x):\n", + " x = self.conv(x)\n", + " x = x.view(-1, 64 * 4 * 4)\n", + " x = self.fc(x)\n", + " # x = nn.functional.normalize(x)\n", + " return x\n", + "\n", + "model=CNNnet()\n", + "print(model)\n", + "\n", + "\n", + "import torchvision.models as models\n", + "from torchinfo import summary\n", + "summary(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "这么看我们这个CNN的结构,还是比较一目了然的。" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "from tensorboardX import SummaryWriter\n", + "\n", + "writer = SummaryWriter('./runs')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "writer.add_graph(model,input_to_model = torch.rand(32, 1, 224, 224))\n", + "writer.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "尝试用Tensorboard交互性界面进一步可视化一下CNN的结构" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "model = CNNnet()\n", + "# 建立模型\n", + "criterion = nn.CrossEntropyLoss()\n", + "# 交叉熵为loss function\n", + "optimizer = optim.Adam(model.parameters(),lr = 0.001)\n", + "# Adam作为优化算法" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "def train(epoch):\n", + " model.train()\n", + " running_loss = 0.0\n", + " for batch_idx, data in enumerate(train_loader, 0):\n", + " # 1.准备数据\n", + " inputs, target = data \n", + " inputs, target = inputs.to(device), target.to(device)\n", + " # 2.Forward\n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, target)\n", + " # 3.Backward\n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " # 4.Update parameters\n", + " optimizer.step()\n", + " \n", + " running_loss += loss.item()\n", + " if batch_idx % 30 == 29:\n", + " print('[%d, %5d] loss: %.3f'%(\n", + " epoch + 1,\n", + " batch_idx + 1,\n", + " running_loss / 30))\n", + " running_loss = 0.0\n", + " # 每30 batch 输出一次\n", + " print('Finished epoch %d, loss: %.3f'%(epoch + 1, running_loss))\n", + "# 训练整个CNN" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def test():\n", + " correct = 0\n", + " total = 0\n", + " with torch.no_grad():\n", + " for data in test_loader:\n", + " images, labels = data\n", + " images, labels = images.to(device), labels.to(device)\n", + " outputs = model(images)\n", + " # 求出每一行(样本)的最大值的下标,dim=1即行的维度\n", + " # 返回最大值和最大值所在的下标\n", + " _, predicted = torch.max(outputs.data, dim = 1)\n", + " # label矩阵为N × 1\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + " print('accuracy on test set :%d %% ' % (100 * correct / total))\n", + " return correct / total\n", + "# 测试" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 30] loss: 1.198\n", + "[1, 60] loss: 0.718\n", + "[1, 90] loss: 0.631\n", + "[1, 120] loss: 0.592\n", + "[1, 150] loss: 0.558\n", + "[1, 180] loss: 0.532\n", + "[1, 210] loss: 0.491\n", + "Finished epoch 1, loss: 11.346\n", + "accuracy on test set :82 % \n", + "[2, 30] loss: 0.458\n", + "[2, 60] loss: 0.442\n", + "[2, 90] loss: 0.435\n", + "[2, 120] loss: 0.417\n", + "[2, 150] loss: 0.410\n", + "[2, 180] loss: 0.384\n", + "[2, 210] loss: 0.399\n", + "Finished epoch 2, loss: 9.113\n", + "accuracy on test set :85 % \n", + "[3, 30] loss: 0.371\n", + "[3, 60] loss: 0.368\n", + "[3, 90] loss: 0.371\n", + "[3, 120] loss: 0.362\n", + "[3, 150] loss: 0.362\n", + "[3, 180] loss: 0.361\n", + "[3, 210] loss: 0.331\n", + "Finished epoch 3, loss: 8.068\n", + "accuracy on test set :87 % \n", + "[4, 30] loss: 0.317\n", + "[4, 60] loss: 0.331\n", + "[4, 90] loss: 0.324\n", + "[4, 120] loss: 0.331\n", + "[4, 150] loss: 0.320\n", + "[4, 180] loss: 0.306\n", + "[4, 210] loss: 0.335\n", + "Finished epoch 4, loss: 7.704\n", + "accuracy on test set :88 % \n", + "[5, 30] loss: 0.310\n", + "[5, 60] loss: 0.284\n", + "[5, 90] loss: 0.300\n", + "[5, 120] loss: 0.304\n", + "[5, 150] loss: 0.294\n", + "[5, 180] loss: 0.302\n", + "[5, 210] loss: 0.296\n", + "Finished epoch 5, loss: 7.099\n", + "accuracy on test set :89 % \n", + "[6, 30] loss: 0.284\n", + "[6, 60] loss: 0.274\n", + "[6, 90] loss: 0.286\n", + "[6, 120] loss: 0.299\n", + "[6, 150] loss: 0.282\n", + "[6, 180] loss: 0.289\n", + "[6, 210] loss: 0.268\n", + "Finished epoch 6, loss: 6.700\n", + "accuracy on test set :90 % \n", + "[7, 30] loss: 0.275\n", + "[7, 60] loss: 0.254\n", + "[7, 90] loss: 0.271\n", + "[7, 120] loss: 0.284\n", + "[7, 150] loss: 0.257\n", + "[7, 180] loss: 0.260\n", + "[7, 210] loss: 0.278\n", + "Finished epoch 7, loss: 6.579\n", + "accuracy on test set :90 % \n", + "[8, 30] loss: 0.259\n", + "[8, 60] loss: 0.265\n", + "[8, 90] loss: 0.241\n", + "[8, 120] loss: 0.262\n", + "[8, 150] loss: 0.261\n", + "[8, 180] loss: 0.252\n", + "[8, 210] loss: 0.249\n", + "Finished epoch 8, loss: 6.139\n", + "accuracy on test set :90 % \n", + "[9, 30] loss: 0.250\n", + "[9, 60] loss: 0.251\n", + "[9, 90] loss: 0.245\n", + "[9, 120] loss: 0.255\n", + "[9, 150] loss: 0.242\n", + "[9, 180] loss: 0.248\n", + "[9, 210] loss: 0.246\n", + "Finished epoch 9, loss: 5.539\n", + "accuracy on test set :91 % \n", + "[10, 30] loss: 0.227\n", + "[10, 60] loss: 0.241\n", + "[10, 90] loss: 0.255\n", + "[10, 120] loss: 0.237\n", + "[10, 150] loss: 0.237\n", + "[10, 180] loss: 0.236\n", + "[10, 210] loss: 0.234\n", + "Finished epoch 10, loss: 5.765\n", + "accuracy on test set :91 % \n" + ] + } + ], + "source": [ + "if __name__ == '__main__':\n", + " epoch_list = []\n", + " acc_list = []\n", + " \n", + " for epoch in range(10):\n", + " train(epoch)\n", + " acc = test()\n", + " epoch_list.append(epoch)\n", + " acc_list.append(acc)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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F4XGa9m2kzp8Jk9+3u4MPgMADFOrAHTo0CH179//su39+vXToUOHrrsoNE7Z+ZcMPnPFZwCAgWoVgDw9PZWZmXnZ9jNnzsjNrdZjRWjkLh18vp/BZwCAgWoVgG6//XbNmjVLubm5tm0XLlzQ7Nmzddttt9VZcWg8dv5wTu/vqrziM4PPAACD1apd88ILL+imm25Su3bt1K9fP0nSnj17FBQUpP/85z91WiAc36WDz/cNDFM/Bp8BAAarVQAKCQnRvn37tGzZMu3du1fe3t6aPHmy7r//frm7u9d1jXBw73x34pLB565GlwMAQO2vA9S0aVMNGzZMbdu2VWlpqSTp008/lST9+te/rpvq4PCy80v04udHJFUMPrdsevk95AAAaGi1CkCpqam6++67tX//fplMJlmtVplMP850mM3mOisQju3ZT5OVX1KuXiF+DD4DAOxGrYagp0+frvDwcGVlZalJkyY6cOCANm7cqMjISG3YsKGOS4Sj2lE5+GwySfNHM/gMALAfteoAbd26VV999ZX8/f3l4uIiV1dXDRs2TAkJCXriiSe0e/fuuq4TDqbcbFH8BwckVVzxuW9Yc2MLAgDgErXqAJnNZvn4+EiS/P39dfr0aUlSu3btlJKSUnfVwWH957sTSs7IZ/AZAGCXatUB6tmzp/bu3avw8HBFRUXp+eefl4eHh15//XV16NChrmuEg8nOL9GiysHnP/yKwWcAgP2pVQdo7ty5slgskqRnnnlGx48f14033qh169bppZdeuqb3evnll9W+fXt5eXkpKipK27dvv+L+ixcvVkREhLy9vRUWFqaZM2equLi42j7p6en67W9/q1atWsnb21u9evXiJq0NKOHTw8ovKVfvUD/dN5DBZwCA/alVB2jkyJG25506dVJycrLOnTunFi1aVFsN9ktWrlyp2NhYLV26VFFRUVq8eLFGjhyplJQUBQYGXrb/8uXLFRcXp7feektDhgzRkSNH9OCDD8pkMmnRokWSpPPnz2vo0KG65ZZb9OmnnyogIEBHjx5VixZcfK8hbD9+Tqt3pctkkp7his8AADtlslqtVqP+8KioKA0cOFBLliyRJFksFoWFhWnatGmKi4u7bP+pU6fq8OHDSkxMtG178skntW3bNm3evFmSFBcXpy1btuibb7656jpKSkpUUlJi+zkvL09hYWHKzc2Vr69v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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(epoch_list, acc_list)\n", + "plt.ylabel('accuracy')\n", + "plt.xlabel('epoch')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "绘制出每次epoch的准确率的曲线" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "save_path = \"./Model.pkl\"\n", + "torch.save(model, save_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "最后保存模型" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.7" + }, + "orig_nbformat": 4.0 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/cnn网络.ipynb b/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/cnn网络.ipynb new file mode 100644 index 0000000..b5c1312 --- /dev/null +++ b/共享单车数据分析/十三组平时作业(实战)/torch实现cnn服饰分类/cnn网络.ipynb @@ -0,0 +1,273 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "from torch.utils.data import Dataset, DataLoader, random_split\n", + "from torchvision import transforms, datasets, models\n", + "\n", + "torch.manual_seed(1) # 设置随机种子, 用于复现\n", + "\n", + "image_size = 28\n", + "# 超参数\n", + "EPOCH = 100 # 前向后向传播迭代次数\n", + "LR = 0.001 # 学习率 learning rate\n", + "BATCH_SIZE = 50 # 批量训练时候一次送入数据的size\n", + "DOWNLOAD_MNIST = True\n", + "\n", + "mean = [0.485, 0.456, 0.406]\n", + "std = [0.229, 0.224, 0.225]\n", + "# 训练集\n", + "data_path = \"images\"\n", + "\n", + "train_augs = transforms.Compose([\n", + " transforms.Resize([256, 256]),\n", + " transforms.ToTensor(),\n", + " transforms.Normalize(mean, std)\n", + "])\n", + "full_data = datasets.ImageFolder(root=data_path, transform=train_augs)\n", + "train_size = int(len(full_data) * 0.8) # 这里train_size是一个长度矢量,并非是比例,我们将训练和测试进行8/2划分\n", + "test_size = len(full_data) - train_size\n", + "\n", + "train_dataset, test_dataset = random_split(full_data, [train_size, test_size])\n", + "\n", + "train_loader = DataLoader(train_dataset, batch_size=4, num_workers=0, shuffle=True, )\n", + "test_loader = DataLoader(test_dataset, batch_size=4, num_workers=0, shuffle=False)\n", + "print(train_loader)\n", + "\n", + "\n", + "class CNN(nn.Module):\n", + " def __init__(self):\n", + " super(CNN, self).__init__()\n", + " self.len = 256\n", + " self.conv1 = nn.Sequential(\n", + " nn.Conv2d( # 输入的图片 (1,28,28)\n", + " in_channels=3,\n", + " out_channels=16, # 经过一个卷积层之后 (16,28,28)\n", + " kernel_size=5,\n", + " stride=1, # 如果想要 con2d 出来的图片长宽没有变化, padding=(kernel_size-1)/2 当 stride=1\n", + " padding=2\n", + " ),\n", + " nn.ReLU(),\n", + " nn.MaxPool2d(kernel_size=2) # 经过池化层处理,维度为(16,14,14)\n", + " )\n", + "\n", + " self.conv2 = nn.Sequential(\n", + " nn.Conv2d( # 输入(16,14,14)\n", + " in_channels=16,\n", + " out_channels=32,\n", + " kernel_size=5,\n", + " stride=1,\n", + " padding=2\n", + " ), # 输出(32,14,14)\n", + " nn.ReLU(),\n", + " nn.MaxPool2d(kernel_size=2) # 输出(32,7,7)\n", + " )\n", + "\n", + " self.fc1 = nn.Linear(32 * 64 * 64, 120)\n", + " self.fc2 = nn.Linear(120, 40)\n", + " self.fc3 = nn.Linear(40, 5)\n", + "\n", + " def forward(self, x):\n", + " x = self.conv1(x) # (batch_size,16,14,14)\n", + " x = self.conv2(x) # 输出(batch_size,32,7,7)\n", + " x = x.view(x.size(0), -1) # (batch_size,32*7*7)\n", + " x = F.relu(self.fc1(x))\n", + " x = F.relu(self.fc2(x))\n", + " x = self.fc3(x)\n", + " return x\n", + "\n", + "\n", + "cnn = CNN()\n", + "optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) # 定义优化器\n", + "loss_func = nn.CrossEntropyLoss() # 定义损失函数\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Finished Training! Total cost time: 167.14745330810547\n" + ] + } + ], + "source": [ + "import time\n", + "import matplotlib.pyplot as plt\n", + "start = time.time()\n", + "running_loss_list=[]\n", + "test_loss_list=[]\n", + "for epoch in range(10):\n", + "\n", + " running_loss = 0.0\n", + " test_loss=0.0\n", + " for i, data in enumerate(train_loader, 0):\n", + " # 获取输入数据\n", + " inputs, labels = data\n", + " # 清空梯度缓存\n", + " optimizer.zero_grad()\n", + "\n", + " outputs = cnn(inputs)\n", + " loss = loss_func(outputs, labels)\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " # 打印统计信息\n", + " running_loss += loss.item()\n", + " for i, data in enumerate(test_loader, 0):\n", + " # 获取输入数据\n", + " inputs, labels = data\n", + " # 清空梯度缓存\n", + " optimizer.zero_grad()\n", + "\n", + " outputs = cnn(inputs)\n", + " loss = loss_func(outputs, labels)\n", + " # 打印统计信息\n", + " test_loss += loss.item()\n", + " running_loss_list.append(running_loss)\n", + " test_loss_list.append(test_loss)\n", + "\n", + "print('Finished Training! Total cost time: ', time.time() - start)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYEAAAEaCAYAAAD3+OukAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAxCUlEQVR4nO3deVxU9f7H8df3MKwqyOYCiLvmbi65lppkKmZqLum1e82WW1aWNy0rFSsrTMmlNG3RfrapZWGZueDa5pZpimuFqde8iIA74HC+vz+o0UlURJgDM5/n49FD58w5c97zfRBvz6601hohhBAeybA6gBBCCOtICQghhAeTEhBCCA8mJSCEEB5MSkAIITyYlIAQQngwKQFRpIYMGUJMTIzVMYpNtWrVmDBhgtUxhCgyUgJCCOHBpASE8AA5OTlWRxAllJSAKFZaayZPnkyNGjXw8fGhZs2aTJ061WmexYsXc+ONNxIQEED58uW56aab+OmnnwA4f/48//nPf4iKisLX15fKlStz9913X3Gd06ZNo2nTppQtW5ZKlSpx991388cffzjeX7t2LUopVq5cyS233EJAQAD169fn66+/dvqc7du307ZtW3x9falduzYLFy686vfNyMhg8ODBREdH4+/vT926dUlISODvF+YvWLCA5s2b4+fnR2hoKN26dSMjI8Px/owZM6hfvz6+vr5UqFCBu+66y/Fefruk7r//fjp27Oh43bFjR+677z7Gjh1L5cqViY6OBuCjjz6iVatWBAUFERYWRmxsLPv27XP6rNTUVO69914qVqyIn58fdevWZc6cOWitqVGjBi+//LLT/GfOnCEwMJD333//quMjSh4pAVGsZs6cydixYxk9ejTJycmMGjWK0aNH8+677wJw9OhR+vXrx8CBA0lOTuaHH37giSeewGazAfD666+zcOFCPvjgA/bv388XX3xB69atr7reyZMns2PHDj7//HMOHjyYb3GMHDmSZ599lu3bt9OqVSsGDBjg+EV87tw5unfvTvny5dm0aRPz5s1j0qRJpKamXnG92dnZNGzYkMTERHbt2sXYsWOJi4vjvffec8wzd+5cBg8eTK9evdi6dStr1qyha9eu5ObmAhAXF8fTTz/NsGHD2LFjB8uWLaNZs2YFGu+LLVy4kGPHjrFq1SpWrlzpyDdmzBi2bt3KypUr8fLyIjY21rGlcO7cOTp06MD27dv58MMP2bVrF6+//joBAQEopXjggQd49913nUpt/vz52Gw2+vXrd80ZRQmghShC//rXv3Tnzp0dr6OiovSoUaOc5nniiSd09erVtdZab926VQM6JSUl388bPny47tSpkzZNs9CZ/lrH4cOHtdZar1mzRgN60aJFjnmOHj2qAb1s2TKttdZvv/22LlOmjE5PT3fMs2PHDg3oF1988ZrWP3z4cB0TE+N4XaVKFf3II4/kO+/p06e1n5+fnjRp0mU/r2rVqpdkuO+++3SHDh0crzt06KBr166tc3Nzr5jt+PHjGtDffvut1lrrd955R/v6+upDhw7lO//Ro0e1t7e3XrlypWNa69at9fDhw6+4HlFyyZaAKDYnT57k8OHD3HLLLU7TO3TowIEDBzh79iyNGzfm9ttvp2HDhvTu3Ztp06Zx6NAhx7z33nsvO3bsoFatWjz00EMsWrToqvu3165dy+23306VKlUoV64c7du3B+D33393mq9p06aOv1esWBEvLy/+97//AbBr1y7q1atHcHCwY56GDRsSFBR0xXWbpkl8fDxNmzYlLCyMsmXLMmvWLMe6U1NTOXToEF26dMl3+eTkZLKysi77/rVo3rw5huH8v/i2bdvo3bs31atXp1y5co7dRH/l+/HHH6lfvz5RUVH5fmbFihW58847efvttwHYuXMnGzZs4IEHHrjuvMIaUgLCUl5eXnz99desXr2ali1bsmjRIurUqcOSJUuAvF/UKSkpTJ48GR8fHx5//HGaNm3KyZMn8/28gwcP0r17d6pVq8b8+fPZsmULX3zxBXDpwVEfH59LljdN87q+T0JCAq+88grDhw9n5cqVbNu2jfvvv79ID8wahnHJMYbz589fMl+ZMmWcXp89e5YuXbqglGLu3Lls2rSJzZs3o5S6pnwPPfQQiYmJpKWl8c4779CmTRsaNmxYuC8jLCclIIpNYGAgUVFRrF+/3mn6unXrqF69OgEBAQAopbjpppt49tlnWb9+PR06dGDu3LmO+cuWLUvv3r2ZPn06W7ZsYffu3axbty7fdW7evJlz584xdepU2rVrR926dR3/ur8W9evXZ/fu3WRmZjqmJScnc+LEiSsut379erp27crQoUO58cYbqVWrFvv373e8X6FCBaKiolixYsVl1+vn53fZ9//6jCNHjjhN++tA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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.style.use(\"ggplot\") # matplotlib的美化样式\n", + "plt.figure()\n", + "plt.title(\"loss and accuracy\")\n", + "plt.xlabel(\"epoch\")\n", + "plt.ylabel(\"loss\")\n", + "\n", + "plt.plot(running_loss_list,label='train')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy of the network on the test images: 84 %\n" + ] + } + ], + "source": [ + "correct = 0\n", + "total = 0\n", + "with torch.no_grad():\n", + " for data in test_loader:\n", + " images, labels = data\n", + " outputs = cnn(images)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + "\n", + "print('Accuracy of the network on the test images: %d %%' % (100 * correct / total))" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy of the network on the train images: 96 %\n" + ] + } + ], + "source": [ + "with torch.no_grad():\n", + " for data in train_loader:\n", + " images, labels = data\n", + " outputs = cnn(images)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + "\n", + "print('Accuracy of the network on the train images: %d %%' % (100 * correct / total))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}