diff --git a/2、幸福感数据分析/第2组--王瑞恒/fnn(1).ipynb b/2、幸福感数据分析/第2组--王瑞恒/fnn(1).ipynb new file mode 100644 index 0000000..7b4ddab --- /dev/null +++ b/2、幸福感数据分析/第2组--王瑞恒/fnn(1).ipynb @@ -0,0 +1,393 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "collapsed": true + }, + "outputs": [], + "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", + "import pandas as pd\n", + "import sklearn\n", + "df=pd.read_csv(\"result.csv\").drop(\"Unnamed: 0\",axis=1)\n", + "df=df.values" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running on the GPU\n" + ] + } + ], + "source": [ + " # 设置随机种子, 用于复现\n", + "torch.cuda.is_available()\n", + "# 超参数\n", + "EPOCH = 100 # 前向后向传播迭代次数\n", + "LR = 0.01 # 学习率 learning rate\n", + "BATCH_SIZE = 50 # 批量训练时候一次送入数据的size\n", + "if torch.cuda.is_available():\n", + " device = torch.device(\"cuda:0\") # you can continue going on here, like cuda:1 cuda:2....etc.\n", + " print(\"Running on the GPU\")\n", + "else:\n", + " device = torch.device(\"cpu\")\n", + " print(\"Running on the CPU\")\n", + "train_size = int(len(df) * 0.8) # 这里按照8:2进行训练和测试\n", + "test_size = len(df) - train_size\n", + "train_dataset, test_dataset = random_split(df, [train_size, test_size])\n", + "train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\n", + "test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)\n" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 88, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "from torch.nn import functional as F\n", + "\n", + "\n", + "class focal_loss_multi(nn.Module):\n", + " def __init__(self, alpha=[0.3, 0.3, 0.2,0.05,0.2], gamma=2, num_classes=5, size_average=True):\n", + " super(focal_loss_multi, self).__init__()\n", + " self.size_average = size_average\n", + " if isinstance(alpha, (float, int)): # 只设置第一类别的权重\n", + " self.alpha = torch.zeros(num_classes)\n", + " self.alpha[0] += alpha\n", + " self.alpha[1:] += (1 - alpha) # self.alpha = [0.25,0.75,0.75,0.75,0.75]\n", + " if isinstance(alpha, list): # 全部权重自己设置\n", + " self.alpha = torch.Tensor(alpha)\n", + " self.gamma = gamma\n", + "\n", + " def forward(self, inputs, targets):\n", + " alpha = torch.tensor(self.alpha).cuda()\n", + " N = inputs.size(0)\n", + " C = inputs.size(1)\n", + " # 下面这些只是为了获取四个样本的概率probs\n", + " # 如模型中有softmax,则不需要下一行代码\n", + " P = F.softmax(inputs, dim=1)\n", + "\n", + " class_mask = inputs.data.new(N, C).fill_(0) # 生成和input一样shape的tensor\n", + " class_mask = class_mask.requires_grad_() # 加入梯度计算\n", + " ids = targets.view(-1, 1) # 获取目标的索引\n", + " alpha = alpha.gather(0, ids.view(-1))\n", + " # one hot\n", + " class_mask.data.scatter_(1, ids.data, 1.) # 利用scatter将索引丢给mask\n", + " probs = (P * class_mask).sum(1).view(-1, 1)\n", + " # focal loss公式\n", + " log_p = probs.log()\n", + " loss = torch.pow((1 - probs), self.gamma) * log_p\n", + " batch_loss = (-alpha * loss).t()\n", + "\n", + " # batch loss求平均\n", + " if self.size_average:\n", + " loss = batch_loss.mean()\n", + " else:\n", + " loss = batch_loss.sum()\n", + " return loss" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 89, + "outputs": [], + "source": [ + "class FNN(nn.Module):\n", + " def __init__(self):\n", + " super(FNN, self).__init__()\n", + " self.len = 256\n", + " channel_list = [35, 20, 10, 5]\n", + " self.fc1 = nn.Linear(channel_list[0], channel_list[1])\n", + " self.fc2 = nn.Linear(channel_list[1], channel_list[2])\n", + " self.fc3 = nn.Linear(channel_list[2], channel_list[3])\n", + "\n", + " def forward(self, x):\n", + " x = x.to(torch.float32)\n", + " x = F.relu(self.fc1(x))\n", + " x = F.relu(self.fc2(x))\n", + " x = self.fc3(x)\n", + "\n", + " return x\n", + "\n", + "\n", + "device = torch.device(\"cuda:0\")\n", + "fnn = FNN()\n", + "fnn = fnn.to(device)\n", + "optimizer = torch.optim.Adam(fnn.parameters(), lr=LR) # 定义优化器\n", + "loss_func = focal_loss_multi() # 定义损失函数" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 90, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "E:\\anaconda\\envs\\OD\\lib\\site-packages\\ipykernel_launcher.py:19: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "epoch:0,loss: 3.317510150372982\n", + "epoch:1,loss: 2.452270571142435\n", + "epoch:2,loss: 2.4119314439594746\n", + "epoch:3,loss: 2.3866591453552246\n", + "epoch:4,loss: 2.3689726442098618\n", + "epoch:5,loss: 2.347518652677536\n", + "epoch:6,loss: 2.3187698423862457\n", + "epoch:7,loss: 2.271201703697443\n", + "epoch:8,loss: 2.2221206203103065\n", + "epoch:9,loss: 2.1982677318155766\n", + "epoch:10,loss: 2.1672453321516514\n", + "epoch:11,loss: 2.1174759529531\n", + "epoch:12,loss: 2.0535657703876495\n", + "epoch:13,loss: 2.0038397684693336\n", + "epoch:14,loss: 1.9795553460717201\n", + "epoch:15,loss: 1.9287250824272633\n", + "epoch:16,loss: 1.929360631853342\n", + "epoch:17,loss: 1.9060515873134136\n", + "epoch:18,loss: 1.895568199455738\n", + "epoch:19,loss: 1.89094128459692\n", + "epoch:20,loss: 1.8567495830357075\n", + "epoch:21,loss: 1.8590333499014378\n", + "epoch:22,loss: 1.8468697294592857\n", + "epoch:23,loss: 1.8296680003404617\n", + "epoch:24,loss: 1.8331830948591232\n", + "epoch:25,loss: 1.8214774802327156\n", + "epoch:26,loss: 1.8323743417859077\n", + "epoch:27,loss: 1.8189895488321781\n", + "epoch:28,loss: 1.8023353908210993\n", + "epoch:29,loss: 1.815315444022417\n", + "epoch:30,loss: 1.793947871774435\n", + "epoch:31,loss: 1.7978992387652397\n", + "epoch:32,loss: 1.797480572015047\n", + "epoch:33,loss: 1.8008490167558193\n", + "epoch:34,loss: 1.787273570895195\n", + "epoch:35,loss: 1.7938106134533882\n", + "epoch:36,loss: 1.7855671420693398\n", + "epoch:37,loss: 1.7853158228099346\n", + "epoch:38,loss: 1.779071794822812\n", + "epoch:39,loss: 1.7772890888154507\n", + "epoch:40,loss: 1.7805412858724594\n", + "epoch:41,loss: 1.7821214124560356\n", + "epoch:42,loss: 1.778700441122055\n", + "epoch:43,loss: 1.7772935274988413\n", + "epoch:44,loss: 1.7692392878234386\n", + "epoch:45,loss: 1.7684272415935993\n", + "epoch:46,loss: 1.764982808381319\n", + "epoch:47,loss: 1.7638895623385906\n", + "epoch:48,loss: 1.764635469764471\n", + "epoch:49,loss: 1.7732038386166096\n", + "epoch:50,loss: 1.7635880578309298\n", + "epoch:51,loss: 1.7605439126491547\n", + "epoch:52,loss: 1.7595937848091125\n", + "epoch:53,loss: 1.764160642400384\n", + "epoch:54,loss: 1.7587832789868116\n", + "epoch:55,loss: 1.7608645055443048\n", + "epoch:56,loss: 1.7657096441835165\n", + "epoch:57,loss: 1.7644518110901117\n", + "epoch:58,loss: 1.7554370928555727\n", + "epoch:59,loss: 1.7590856924653053\n", + "epoch:60,loss: 1.754825972020626\n", + "epoch:61,loss: 1.7519988380372524\n", + "epoch:62,loss: 1.7458938676863909\n", + "epoch:63,loss: 1.7428808901458979\n", + "epoch:64,loss: 1.7531350925564766\n", + "epoch:65,loss: 1.7495515011250973\n", + "epoch:66,loss: 1.7374108117073774\n", + "epoch:67,loss: 1.7384705375880003\n", + "epoch:68,loss: 1.7429211493581533\n", + "epoch:69,loss: 1.7501412313431501\n", + "epoch:70,loss: 1.7402582298964262\n", + "epoch:71,loss: 1.7597463615238667\n", + "epoch:72,loss: 1.7596425581723452\n", + "epoch:73,loss: 1.7574352715164423\n", + "epoch:74,loss: 1.7475287541747093\n", + "epoch:75,loss: 1.749899910762906\n", + "epoch:76,loss: 1.7449354715645313\n", + "epoch:77,loss: 1.740980226546526\n", + "epoch:78,loss: 1.7242713905870914\n", + "epoch:79,loss: 1.7329185511916876\n", + "epoch:80,loss: 1.7370264008641243\n", + "epoch:81,loss: 1.7353635840117931\n", + "epoch:82,loss: 1.7412365172058344\n", + "epoch:83,loss: 1.738460123538971\n", + "epoch:84,loss: 1.72850570268929\n", + "epoch:85,loss: 1.7325993571430445\n", + "epoch:86,loss: 1.7321137189865112\n", + "epoch:87,loss: 1.7326700314879417\n", + "epoch:88,loss: 1.734771229326725\n", + "epoch:89,loss: 1.7349314503371716\n", + "epoch:90,loss: 1.732768315821886\n", + "epoch:91,loss: 1.7245301865041256\n", + "epoch:92,loss: 1.7301282286643982\n", + "epoch:93,loss: 1.7266905568540096\n", + "epoch:94,loss: 1.7192118503153324\n", + "epoch:95,loss: 1.725474501028657\n", + "epoch:96,loss: 1.7465850282460451\n", + "epoch:97,loss: 1.7176410257816315\n", + "epoch:98,loss: 1.7161648757755756\n", + "epoch:99,loss: 1.7235474828630686\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import time\n", + "import matplotlib.pyplot as plt\n", + "\n", + "start = time.time()\n", + "running_loss_list = []\n", + "test_loss_list = []\n", + "\n", + "for epoch in range(100):\n", + "\n", + " running_loss = 0.0\n", + " test_loss = 0.0\n", + " for data in test_loader:\n", + " # 获取输入数据\n", + " inputs = data[:, 1:].to(device)\n", + " labels = (data[:, 0]-1).to(device)\n", + " # 清空梯度缓存\n", + " optimizer.zero_grad()\n", + "\n", + " outputs = fnn(inputs)\n", + "\n", + " loss = loss_func(outputs, labels.long())\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " # 打印统计信息\n", + " running_loss += loss.item()\n", + " running_loss_list.append(running_loss)\n", + " #test_loss_list.append(test_loss)\n", + " for data in test_loader:\n", + " # 获取输入数据\n", + " inputs = data[:, 1:].to(device)\n", + " labels = (data[:, 0]-1).to(device)\n", + "\n", + " # 清空梯度缓存\n", + " outputs = fnn(inputs)\n", + " loss = loss_func(outputs, labels.long())\n", + " # 打印统计信息\n", + " test_loss += loss.item()\n", + " test_loss_list.append(test_loss*4)\n", + " print(f\"epoch:{epoch},loss: {running_loss}\")\n", + "plt.style.use(\"ggplot\") # matplotlib的美化样式\n", + "plt.figure()\n", + "plt.title(\"loss and accuracy\")\n", + "plt.xlabel(\"epoch\")\n", + "plt.ylabel(\"loss\")\n", + "plt.plot(test_loss_list,label='train',color='b')\n", + "plt.plot(running_loss_list,label='test')\n", + "plt.show()" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 91, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy of the network on the test: 61 %\n", + "Accuracy of the network on the train: 60 %\n" + ] + } + ], + "source": [ + "correct = 0\n", + "total = 0\n", + "with torch.no_grad():\n", + " for data in test_loader:\n", + " inputs = data[:, 1:].to(device)\n", + " labels = (data[:, 0]-1).to(device)\n", + " outputs = fnn(inputs)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + "print('Accuracy of the network on the test: %d %%' % (100 * correct / total))\n", + "with torch.no_grad():\n", + " for data in train_loader:\n", + " inputs = data[:, 1:].to(device)\n", + " labels = (data[:, 0]-1).to(device)\n", + " outputs = fnn(inputs)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + "print('Accuracy of the network on the train: %d %%' % (100 * correct / total))" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [], + "metadata": { + "collapsed": false + } + } + ], + "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 +} diff --git a/2、幸福感数据分析/第2组--王瑞恒/fnn.ipynb b/2、幸福感数据分析/第2组--王瑞恒/fnn.ipynb deleted file mode 100644 index 50b452e..0000000 --- a/2、幸福感数据分析/第2组--王瑞恒/fnn.ipynb +++ /dev/null @@ -1,330 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "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", - "import pandas as pd\n", - "import sklearn\n", - "df=pd.read_csv(\"Analysis.csv\").drop(\"Unnamed: 0\",axis=1)\n", - "df=df.values" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running on the GPU\n" - ] - } - ], - "source": [ - "torch.manual_seed(0) # 设置随机种子, 用于复现\n", - "torch.cuda.is_available()\n", - "# 超参数\n", - "EPOCH = 100 # 前向后向传播迭代次数\n", - "LR = 0.001 # 学习率 learning rate\n", - "BATCH_SIZE = 50 # 批量训练时候一次送入数据的size\n", - "DOWNLOAD_MNIST = True\n", - "if torch.cuda.is_available():\n", - " device = torch.device(\"cuda:0\") # you can continue going on here, like cuda:1 cuda:2....etc.\n", - " print(\"Running on the GPU\")\n", - "else:\n", - " device = torch.device(\"cpu\")\n", - " print(\"Running on the CPU\")\n", - "train_size = int(len(df) * 0.8) # 这里按照8:2进行训练和测试\n", - "test_size = len(df) - train_size\n", - "train_dataset, test_dataset = random_split(df, [train_size, test_size])\n", - "train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True)\n", - "test_loader = DataLoader(test_dataset, batch_size=128, shuffle=False)" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 4, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from torch.nn import functional as F\n", - "\n", - "\n", - "class focal_loss_multi(nn.Module):\n", - " def __init__(self, alpha=[0.3, 0.3, 0.15,0.05,0.15], gamma=2, num_classes=5, size_average=True):\n", - " super(focal_loss_multi, self).__init__()\n", - " self.size_average = size_average\n", - " if isinstance(alpha, (float, int)): # 只设置第一类别的权重\n", - " self.alpha = torch.zeros(num_classes)\n", - " self.alpha[0] += alpha\n", - " self.alpha[1:] += (1 - alpha) # self.alpha = [0.25,0.75,0.75,0.75,0.75]\n", - " if isinstance(alpha, list): # 全部权重自己设置\n", - " self.alpha = torch.Tensor(alpha)\n", - " self.gamma = gamma\n", - "\n", - " def forward(self, inputs, targets):\n", - " alpha = torch.tensor(self.alpha).cuda()\n", - " N = inputs.size(0)\n", - " C = inputs.size(1)\n", - " # 下面这些只是为了获取四个样本的概率probs\n", - " # 如模型中有softmax,则不需要下一行代码\n", - " P = F.softmax(inputs, dim=1)\n", - "\n", - " class_mask = inputs.data.new(N, C).fill_(0) # 生成和input一样shape的tensor\n", - " class_mask = class_mask.requires_grad_() # 加入梯度计算\n", - " ids = targets.view(-1, 1) # 获取目标的索引\n", - " alpha = alpha.gather(0, ids.view(-1))\n", - " # one hot\n", - " class_mask.data.scatter_(1, ids.data, 1.) # 利用scatter将索引丢给mask\n", - " probs = (P * class_mask).sum(1).view(-1, 1)\n", - " # focal loss公式\n", - " log_p = probs.log()\n", - " loss = torch.pow((1 - probs), self.gamma) * log_p\n", - " batch_loss = (-alpha * loss).t()\n", - "\n", - " # batch loss求平均\n", - " if self.size_average:\n", - " loss = batch_loss.mean()\n", - " else:\n", - " loss = batch_loss.sum()\n", - " return loss" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 7, - "outputs": [], - "source": [ - "class FNN(nn.Module):\n", - " def __init__(self):\n", - " super(FNN, self).__init__()\n", - " self.len = 256\n", - " channel_list = [35, 20, 10, 5]\n", - " self.fc1 = nn.Linear(319, 100)\n", - " self.fc2 = nn.Linear(100, 50)\n", - " self.fc3 = nn.Linear(50, 5)\n", - "\n", - " def forward(self, x):\n", - " x = x.to(torch.float32)\n", - " x = F.relu(self.fc1(x))\n", - " x = F.relu(self.fc2(x))\n", - " x = self.fc3(x)\n", - "\n", - " return x\n", - "\n", - "\n", - "device = torch.device(\"cuda:0\")\n", - "fnn = FNN()\n", - "fnn = fnn.to(device)\n", - "optimizer = torch.optim.Adam(fnn.parameters(), lr=LR) # 定义优化器\n", - "loss_func = nn.CrossEntropyLoss() # 定义损失函数" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 8, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "epoch:0,loss: 3151.320207595825\n", - "epoch:1,loss: 2321.903450489044\n", - "epoch:2,loss: 2256.9100246429443\n", - "epoch:3,loss: 1298.6741995811462\n", - "epoch:4,loss: 1091.3950700759888\n", - "epoch:5,loss: 1104.776943206787\n", - "epoch:6,loss: 1231.5100865364075\n", - "epoch:7,loss: 804.4745910167694\n", - "epoch:8,loss: 658.784494638443\n", - "epoch:9,loss: 557.0827589035034\n", - "epoch:10,loss: 738.1325252056122\n", - "epoch:11,loss: 769.6880600452423\n", - "epoch:12,loss: 458.10057759284973\n", - "epoch:13,loss: 497.0901508331299\n", - "epoch:14,loss: 411.6603829860687\n", - "epoch:15,loss: 250.5609985589981\n", - "epoch:16,loss: 387.088232755661\n", - "epoch:17,loss: 308.30130994319916\n", - "epoch:18,loss: 314.35631680488586\n", - "epoch:19,loss: 375.5763142108917\n", - "epoch:20,loss: 569.8007245063782\n", - "epoch:21,loss: 272.95087587833405\n", - "epoch:22,loss: 232.02807366847992\n", - "epoch:23,loss: 272.6717760562897\n", - "epoch:24,loss: 282.62205362319946\n", - "epoch:25,loss: 370.58508718013763\n", - "epoch:26,loss: 238.88684809207916\n", - "epoch:27,loss: 218.5786339044571\n", - "epoch:28,loss: 188.61170387268066\n", - "epoch:29,loss: 221.02100276947021\n", - "epoch:30,loss: 179.70251786708832\n", - "epoch:31,loss: 156.12333726882935\n", - "epoch:32,loss: 122.91987252235413\n", - "epoch:33,loss: 153.1979397535324\n", - "epoch:34,loss: 224.07494640350342\n", - "epoch:35,loss: 139.0951155424118\n", - "epoch:36,loss: 123.49365735054016\n", - "epoch:37,loss: 97.87656390666962\n", - "epoch:38,loss: 78.64693450927734\n", - "epoch:39,loss: 105.379523396492\n", - "epoch:40,loss: 95.40038180351257\n", - "epoch:41,loss: 118.63325464725494\n", - "epoch:42,loss: 101.8169903755188\n", - "epoch:43,loss: 88.45156133174896\n", - "epoch:44,loss: 84.13636815547943\n", - "epoch:45,loss: 117.95539236068726\n", - "epoch:46,loss: 70.38489985466003\n", - "epoch:47,loss: 67.91977047920227\n", - "epoch:48,loss: 66.15549075603485\n", - "epoch:49,loss: 64.69176268577576\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import time\n", - "import matplotlib.pyplot as plt\n", - "\n", - "start = time.time()\n", - "running_loss_list = []\n", - "test_loss_list = []\n", - "\n", - "for epoch in range(50):\n", - "\n", - " running_loss = 0.0\n", - " test_loss = 0.0\n", - " for data in train_loader:\n", - " # 获取输入数据\n", - " inputs = data[:, 1:].to(device)\n", - " labels = (data[:, 0]-1).to(device)\n", - " # 清空梯度缓存\n", - " optimizer.zero_grad()\n", - "\n", - " outputs = fnn(inputs)\n", - "\n", - " loss = loss_func(outputs, labels.long())\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # 打印统计信息\n", - " running_loss += loss.item()\n", - "\n", - " running_loss_list.append(running_loss)\n", - " test_loss_list.append(test_loss)\n", - " for i, data in enumerate(test_loader, 0):\n", - " # 获取输入数据\n", - " inputs = data[:, 1:].to(device)\n", - " labels = (data[:, 0]-1).to(device)\n", - "\n", - " # 清空梯度缓存\n", - " outputs = fnn(inputs)\n", - " loss = loss_func(outputs, labels.long())\n", - " # 打印统计信息\n", - " test_loss += loss.item()\n", - " running_loss_list.append(running_loss)\n", - " test_loss_list.append(test_loss)\n", - " print(f\"epoch:{epoch},loss: {running_loss}\")\n", - "plt.style.use(\"ggplot\") # matplotlib的美化样式\n", - "plt.figure()\n", - "plt.title(\"loss and accuracy\")\n", - "plt.xlabel(\"epoch\")\n", - "plt.ylabel(\"loss\")\n", - "plt.plot(test_loss_list,label='train')\n", - "plt.plot(running_loss_list,label='train')\n", - "plt.show()" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 9, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Accuracy of the network on the test images: 60 %\n" - ] - } - ], - "source": [ - "correct = 0\n", - "total = 0\n", - "with torch.no_grad():\n", - " for data in test_loader:\n", - " inputs = data[:, 1:].to(device)\n", - " labels = (data[:, 0]-1).to(device)\n", - " outputs = fnn(inputs)\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))" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": null, - "outputs": [], - "source": [], - "metadata": { - "collapsed": false - } - } - ], - "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 -}