{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![](https://i.typlog.com/tanxy/8331661530_1720295.jpg)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import scipy.io as sio\n", "import numpy as np\n", "from sklearn import preprocessing\n", "import torch\n", "import torch.nn as nn\n", "import math\n", "from torch.utils.data import Dataset,DataLoader\n", "import torch.optim as optim\n", "from torch.autograd import Variable\n", "import torch.nn.functional as F\n", "import logging" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Spectral Residual Learning 模块的输入\n", "class SPCModuleIN(nn.Module):\n", " def __init__(self, in_channels, out_channels, bias=True):\n", " super(SPCModuleIN, self).__init__()\n", " \n", " self.s1 = nn.Conv3d(in_channels, out_channels, kernel_size=(7,1,1), stride=(2,1,1), bias=False)\n", " #self.bn = nn.BatchNorm3d(out_channels)\n", "\n", " def forward(self, input):\n", " \n", " input = input.unsqueeze(1)\n", " \n", " out = self.s1(input)\n", " \n", " return out.squeeze(1) " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Spectral Residual Leaning 部分\n", "class ResSPC(nn.Module):\n", " def __init__(self, in_channels, out_channels, bias=True):\n", " super(ResSPC, self).__init__()\n", " \n", " self.spc1 = nn.Sequential(nn.Conv3d(in_channels, in_channels, kernel_size=(7,1,1), padding=(3,0,0), bias=False),\n", " nn.LeakyReLU(inplace=True),\n", " nn.BatchNorm3d(in_channels),)\n", " \n", " self.spc2 = nn.Sequential(nn.Conv3d(in_channels, in_channels, kernel_size=(7,1,1), padding=(3,0,0), bias=False),\n", " nn.LeakyReLU(inplace=True),)\n", " \n", " self.bn2 = nn.BatchNorm3d(out_channels)\n", "\n", " def forward(self, input):\n", " \n", " out = self.spc1(input)\n", " out = self.bn2(self.spc2(out))\n", " \n", " return F.leaky_relu(out + input)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Spatial Residual Learning 输入部分\n", "class SPAModuleIN(nn.Module):\n", " def __init__(self, in_channels, out_channels, k=97, bias=True):\n", " super(SPAModuleIN, self).__init__()\n", " \n", " # print('k=',k)\n", " self.s1 = nn.Conv3d(in_channels, out_channels, kernel_size=(k,3,3), bias=False)\n", " #self.bn = nn.BatchNorm2d(out_channels)\n", "\n", " def forward(self, input):\n", " \n", " # print(input.size())\n", " out = self.s1(input)\n", " out = out.squeeze(2)\n", " # print(out.size)\n", " \n", " return out" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Spatial Residual Learning 部分\n", "class ResSPA(nn.Module):\n", " def __init__(self, in_channels, out_channels, bias=True):\n", " super(ResSPA, self).__init__()\n", " \n", " self.spa1 = nn.Sequential(nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1),\n", " nn.LeakyReLU(inplace=True),\n", " nn.BatchNorm2d(in_channels),)\n", " \n", " self.spa2 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),\n", " nn.LeakyReLU(inplace=True),)\n", " self.bn2 = nn.BatchNorm2d(out_channels)\n", "\n", " def forward(self, input):\n", " \n", " out = self.spa1(input)\n", " out = self.bn2(self.spa2(out))\n", " \n", " return F.leaky_relu(out + input)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# 整个 SSRN 的网络\n", "# 由 SPCModuleIN + ResSPC + SPAModuleI + ResSPA 组成\n", "class SSRN(nn.Module):\n", " def __init__(self, num_classes=9, k=97):\n", " super(SSRN, self).__init__()\n", " \n", " # 第一层输入,经过第一个卷积层\n", " self.layer1 = SPCModuleIN(1, 24)\n", " #self.bn1 = nn.BatchNorm3d(28)\n", " \n", " # 第二层,经过第一个光谱卷积块\n", " self.layer2 = ResSPC(24,24)\n", " \n", " # 第三层进入第二个光谱卷积块\n", " self.layer3 = ResSPC(24,24)\n", " \n", " # 第四层,经过空间残差块的输入部分的第一个卷积层\n", " self.layer4 = SPAModuleIN(24, 24, k=k)\n", " \n", " # \n", " self.bn4 = nn.BatchNorm2d(24)\n", " \n", " self.layer5 = ResSPA(24, 24)\n", " self.layer6 = ResSPA(24, 24)\n", "\n", " self.fc = nn.Linear(24, num_classes)\n", "\n", " def forward(self, x):\n", "\n", " x = F.leaky_relu(self.layer1(x)) #self.bn1(F.leaky_relu(self.layer1(x)))\n", "# print(x.shape)\n", " #print(x.size())\n", " x = self.layer2(x)\n", "# print(x.shape)\n", " x = self.layer3(x)\n", "# print(x.shape)\n", " #x = self.layer31(x)\n", "\n", " x = self.bn4(F.leaky_relu(self.layer4(x)))\n", "# print(x.shape)\n", " x = self.layer5(x)\n", "# print(x.shape)\n", " x = self.layer6(x)\n", "# print(x.shape)\n", "\n", " x = F.avg_pool2d(x, x.size()[-1])\n", "# print(x.shape)\n", " x = self.fc(x.squeeze())\n", "# print(x.shape)\n", " \n", " return x" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SSRN(\n", " (layer1): SPCModuleIN(\n", " (s1): Conv3d(1, 24, kernel_size=(7, 1, 1), stride=(2, 1, 1), bias=False)\n", " )\n", " (layer2): ResSPC(\n", " (spc1): Sequential(\n", " (0): Conv3d(24, 24, kernel_size=(7, 1, 1), stride=(1, 1, 1), padding=(3, 0, 0), bias=False)\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " (2): BatchNorm3d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (spc2): Sequential(\n", " (0): Conv3d(24, 24, kernel_size=(7, 1, 1), stride=(1, 1, 1), padding=(3, 0, 0), bias=False)\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " )\n", " (bn2): BatchNorm3d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (layer3): ResSPC(\n", " (spc1): Sequential(\n", " (0): Conv3d(24, 24, kernel_size=(7, 1, 1), stride=(1, 1, 1), padding=(3, 0, 0), bias=False)\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " (2): BatchNorm3d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (spc2): Sequential(\n", " (0): Conv3d(24, 24, kernel_size=(7, 1, 1), stride=(1, 1, 1), padding=(3, 0, 0), bias=False)\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " )\n", " (bn2): BatchNorm3d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (layer4): SPAModuleIN(\n", " (s1): Conv3d(24, 24, kernel_size=(97, 3, 3), stride=(1, 1, 1), bias=False)\n", " )\n", " (bn4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " (layer5): ResSPA(\n", " (spa1): Sequential(\n", " (0): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " (2): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (spa2): Sequential(\n", " (0): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " )\n", " (bn2): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (layer6): ResSPA(\n", " (spa1): Sequential(\n", " (0): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " (2): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (spa2): Sequential(\n", " (0): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", " (1): LeakyReLU(negative_slope=0.01, inplace=True)\n", " )\n", " (bn2): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (fc): Linear(in_features=24, out_features=16, bias=True)\n", ")\n", "torch.Size([16])\n" ] } ], "source": [ "# 测试一下定义的 SSRN 网络通不通 (batch_size, frames, height, width, channels)\n", "x = torch.randn(1, 200, 7, 7)\n", "net = SSRN(num_classes=16, k=97)\n", "print(net)\n", "y = net(x)\n", "print(y.shape)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# 一些预处理函数\n", "def indexToAssignment(index_, pad_length, Row, Col):\n", " new_assign = {}\n", " for counter, value in enumerate(index_):\n", " assign_0 = value // Col + pad_length\n", " assign_1 = value % Col + pad_length\n", " new_assign[counter] = [assign_0, assign_1]\n", " return new_assign\n", "\n", "def assignmentToIndex(assign_0, assign_1, Row, Col):\n", " new_index = assign_0 * Col + assign_1\n", " return new_index\n", "\n", "def selectNeighboringPatch(matrix, ex_len, pos_row, pos_col):\n", " # print(matrix.shape)\n", " selected_rows = matrix[:,range(pos_row-ex_len,pos_row+ex_len+1), :]\n", " selected_patch = selected_rows[:, :, range(pos_col-ex_len, pos_col+ex_len+1)]\n", " return selected_patch\n", "\n", "def sampling(proptionVal, groundTruth): #divide dataset into train and test datasets\n", " labels_loc = {}\n", " train = {}\n", " test = {}\n", " m = max(groundTruth)\n", " for i in range(m):\n", " indices = [j for j, x in enumerate(groundTruth.ravel().tolist()) if x == i + 1]\n", " np.random.shuffle(indices)\n", " labels_loc[i] = indices\n", " nb_val = int(proptionVal * len(indices))\n", " train[i] = indices[:-nb_val]\n", " test[i] = indices[-nb_val:]\n", " whole_indices = []\n", " train_indices = []\n", " test_indices = []\n", " for i in range(m):\n", " whole_indices += labels_loc[i]\n", " train_indices += train[i]\n", " test_indices += test[i]\n", " np.random.shuffle(train_indices)\n", " np.random.shuffle(test_indices)\n", " return whole_indices, train_indices, test_indices\n", "\n", "\n", "\n", "sample_200 = [2, 27, 19, 4, 9, 14, 2, 10, 3, 24, 41, 14, 4, 18, 7, 2]\n", "rsample_200 = [1, 28, 16, 5, 9, 14, 1, 9, 1, 19, 47, 12, 4, 24, 8, 2]\n", "\n", "def rsampling(groundTruth, sample_num = sample_200, rsample_num = rsample_200): #divide dataset into train and test datasets\n", " labels_loc = {}\n", " labeled = {}\n", " train2 = {}\n", " val = {}\n", " test = {}\n", " m = np.max(groundTruth)\n", " for i in range(m):\n", " indices = [j for j, x in enumerate(groundTruth.ravel().tolist()) if x == i + 1]\n", " np.random.shuffle(indices)\n", " labels_loc[i] = indices\n", " labeled[i] = indices[:sample_num[i]]\n", " train2[i] = indices[sample_num[i]:sample_num[i]+rsample_num[i]]\n", " val[i] = indices[-(sample_num[i]+rsample_num[i]):]\n", " test[i] = indices[sample_num[i]+rsample_num[i]:-(sample_num[i]+rsample_num[i])]\n", " whole_indices = []\n", " labeled_indices = []\n", " train2_indices = []\n", " val_indices = []\n", " test_indices = []\n", " for i in range(m):\n", " whole_indices += labels_loc[i]\n", " labeled_indices += labeled[i]\n", " train2_indices += train2[i]\n", " val_indices += val[i]\n", " test_indices += test[i]\n", " np.random.shuffle(labeled_indices)\n", " np.random.shuffle(train2_indices) \n", " np.random.shuffle(val_indices) \n", " np.random.shuffle(test_indices)\n", " return whole_indices, labeled_indices, train2_indices, val_indices, test_indices\n", "\n", "\n", "def zeroPadding_3D(old_matrix, pad_length, pad_depth = 0):\n", " new_matrix = np.lib.pad(old_matrix, ((pad_depth, pad_depth), (pad_length, pad_length), (pad_length, pad_length)), 'constant', constant_values=0)\n", " return new_matrix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 预处理" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# 读取 Indian Pines 数据集\n", "mat_data = sio.loadmat('../data/Indian_pines_corrected.mat')\n", "data_IN = mat_data['indian_pines_corrected']\n", "mat_gt = sio.loadmat('../data/Indian_pines_gt.mat')\n", "gt_IN = mat_gt['indian_pines_gt']\n", "# print(data_IN.shape, gt_IN.shape) → (145, 145, 200) (145, 145)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TEST_SIZE= 9449\n" ] } ], "source": [ "# Input dataset configuration to generate 103×7×7 HSI samples\n", "new_gt_IN = gt_IN\n", "# the number of land-cover categories in Indian Pines\n", "nb_classes = 16\n", "\n", "INPUT_DIMENSION_CONV = 200\n", "INPUT_DIMENSION = 200\n", "\n", "# 20%:10%:70% data for training, validation and testing\n", "\n", "TOTAL_SIZE = 10249 # Indian Pines 的有效像素是 10249\n", "\n", "TRAIN_SIZE = 200\n", "DEV_SIZE = 200\n", "VAL_SIZE = 400\n", "TEST_SIZE = TOTAL_SIZE - TRAIN_SIZE - DEV_SIZE - VAL_SIZE # 10249-200-200-400\n", "print('TEST_SIZE=', TEST_SIZE) # TEST_SIZE= 9449\n", "\n", "# Indian Pines 数据集的有效光谱通道数\n", "img_channels = 200\n", "PATCH_LENGTH = 4" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# 进行了减去均值除以方差的预处理\n", "MAX = data_IN.max()\n", "data_IN = np.transpose(data_IN, (2,0,1))\n", "\n", "data_IN = data_IN - np.mean(data_IN, axis=(1,2), keepdims=True)\n", "data_IN = data_IN / MAX" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----- Some Shapes For details ----\n", "data.shape = (200, 21025)\n", "gt.shape = (21025,)\n", "whole_data.shape = (200, 145, 145)\n", "padded_data.shape = (200, 153, 153)\n", "train_data.shape = (200, 200, 9, 9)\n", "test_data.shape = (9449, 200, 9, 9)\n", "all_data.shape = (10249, 200, 9, 9)\n" ] } ], "source": [ "# np.prod 返回指定轴上的乘积,不指定轴默认是所有元素的乘积\n", "# 这里其实就是将 data_IN.shape=(145, 145, 200) reshap 为 (200, 145×145),即将前两个维度堆叠\n", "# 还有就是将 data_IN.shape=(145, 145) reshape 为 (21025, ),也是将前两个维度堆叠\n", "data = data_IN.reshape(np.prod(data_IN.shape[:1]),np.prod(data_IN.shape[1:]))\n", "print('----- Some Shapes For details ----')\n", "print('data.shape =', data.shape)\n", "gt = new_gt_IN.reshape(np.prod(new_gt_IN.shape[:2]),)\n", "print('gt.shape =', gt.shape)\n", "\n", "whole_data = data.reshape(data_IN.shape[0], data_IN.shape[1],data_IN.shape[2])\n", "print('whole_data.shape =', whole_data.shape)\n", "#whole_data = whole_data - np.mean(whole_data, axis=(1,2), keepdims=True)\n", "# 对 whole_data 进行 PATCH_LENGTH = 4 的填充,其实就是 145 × 145 的 size 每边都增加 4,最后就是 145 + 4 + 4 = 153\n", "padded_data = zeroPadding_3D(whole_data, PATCH_LENGTH)\n", "print('padded_data.shape =', padded_data.shape)\n", "\n", "#CATEGORY = 9\n", "\n", "train_data = np.zeros((TRAIN_SIZE, INPUT_DIMENSION_CONV, 2*PATCH_LENGTH + 1, 2*PATCH_LENGTH + 1))\n", "print('train_data.shape =', train_data.shape)\n", "test_data = np.zeros((TEST_SIZE, INPUT_DIMENSION_CONV, 2*PATCH_LENGTH + 1, 2*PATCH_LENGTH + 1))\n", "print('test_data.shape =', test_data.shape)\n", "all_data = np.zeros((TOTAL_SIZE, INPUT_DIMENSION_CONV, 2*PATCH_LENGTH + 1, 2*PATCH_LENGTH + 1))\n", "print('all_data.shape =', all_data.shape)\n", "\n", "\n", "all_indices, train_indices, dev_indices, val_indices, test_indices = rsampling(gt)\n", "\n", "y_train = gt[train_indices] - 1\n", "y_test = gt[test_indices] - 1\n", "y_all = gt[all_indices] - 1\n", "\n", "train_assign = indexToAssignment(train_indices, PATCH_LENGTH, whole_data.shape[1], whole_data.shape[2])\n", "for i in range(len(train_assign)):\n", " train_data[i] = selectNeighboringPatch(padded_data, PATCH_LENGTH, train_assign[i][0], train_assign[i][1])\n", " \n", "test_assign = indexToAssignment(test_indices, PATCH_LENGTH, whole_data.shape[1], whole_data.shape[2])\n", "for i in range(len(test_assign)):\n", " test_data[i] = selectNeighboringPatch(padded_data, PATCH_LENGTH, test_assign[i][0], test_assign[i][1])\n", " \n", "all_assign = indexToAssignment(all_indices, PATCH_LENGTH, whole_data.shape[1], whole_data.shape[2])\n", "for i in range(len(all_assign)):\n", " all_data[i] = selectNeighboringPatch(padded_data, PATCH_LENGTH, all_assign[i][0], all_assign[i][1])" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([3, 8])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.prod([[1, 2], [3, 4]], axis=0)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "import torch\n", "from torch.utils import data\n", "\n", "class HSIDataset(data.Dataset):\n", " def __init__(self, list_IDs, samples, labels):\n", " \n", " self.list_IDs = list_IDs\n", " self.samples = samples\n", " self.labels = labels\n", "\n", " def __len__(self):\n", " return len(self.list_IDs)\n", "\n", " def __getitem__(self, index):\n", " # Select sample\n", " ID = self.list_IDs[index]\n", "\n", " # Load data and get label\n", " X = self.samples[ID]\n", " y = self.labels[ID]\n", "\n", " return X, y" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# CUDA for PyTorch\n", "# 选择 GPU 进行训练\n", "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n", "\n", "# Parameters\n", "params = {'batch_size': 50,\n", " 'shuffle': True,\n", " 'num_workers': 8}\n", "\n", "# Generators\n", "training_set = HSIDataset(range(len(train_indices)), train_data, y_train)\n", "training_generator = data.DataLoader(training_set, **params)\n", "\n", "validation_set = HSIDataset(range(len(test_indices)), test_data, y_test)\n", "validation_generator = data.DataLoader(validation_set, **params)\n", "\n", "all_set = HSIDataset(range(len(all_indices)), all_data, y_all)\n", "all_generator = data.DataLoader(all_set, **params)\n", "\n", "\n", "trainloader = torch.utils.data.DataLoader(training_set, batch_size=50, shuffle=True, num_workers=8)\n", "\n", "validationloader = torch.utils.data.DataLoader(validation_set, batch_size=50, shuffle=False, num_workers=8)\n", "\n", "allloader = torch.utils.data.DataLoader(all_set, batch_size=50, shuffle=False, num_workers=8)\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 4] loss: 2.7162\n", "Accuracy of the network on the validation set: 24.11895 %\n", "[2, 4] loss: 2.0227\n", "Accuracy of the network on the validation set: 24.11895 %\n", "[3, 4] loss: 1.7701\n", "Accuracy of the network on the validation set: 0.12700 %\n", "[4, 4] loss: 1.5836\n", "Accuracy of the network on the validation set: 5.72547 %\n", "[5, 4] loss: 1.4111\n", "Accuracy of the network on the validation set: 9.37665 %\n", "[6, 4] loss: 1.3106\n", "Accuracy of the network on the validation set: 9.37665 %\n", "[7, 4] loss: 1.2268\n", "Accuracy of the network on the validation set: 9.37665 %\n", "[8, 4] loss: 1.0714\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[9, 4] loss: 0.9874\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[10, 4] loss: 0.9272\n", "Accuracy of the network on the validation set: 10.06456 %\n", "[11, 4] loss: 0.8138\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[12, 4] loss: 0.7358\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[13, 4] loss: 0.6966\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[14, 4] loss: 0.6242\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[15, 4] loss: 0.5519\n", "Accuracy of the network on the validation set: 8.04318 %\n", "[16, 4] loss: 0.4973\n", "Accuracy of the network on the validation set: 8.05376 %\n", "[17, 4] loss: 0.4350\n", "Accuracy of the network on the validation set: 9.14382 %\n", "[18, 4] loss: 0.4468\n", "Accuracy of the network on the validation set: 7.83152 %\n", "[19, 4] loss: 0.4053\n", "Accuracy of the network on the validation set: 7.09070 %\n", "[20, 4] loss: 0.3519\n", "Accuracy of the network on the validation set: 9.04858 %\n", "[21, 4] loss: 0.3069\n", "Accuracy of the network on the validation set: 12.86909 %\n", "[22, 4] loss: 0.3460\n", "Accuracy of the network on the validation set: 38.69193 %\n", "[23, 4] loss: 0.3244\n", "Accuracy of the network on the validation set: 44.45973 %\n", "[24, 4] loss: 0.3181\n", "Accuracy of the network on the validation set: 59.91110 %\n", "[25, 4] loss: 0.2651\n", "Accuracy of the network on the validation set: 60.32384 %\n", "[26, 4] loss: 0.2398\n", "Accuracy of the network on the validation set: 61.40332 %\n", "[27, 4] loss: 0.2439\n", "Accuracy of the network on the validation set: 74.31474 %\n", "[28, 4] loss: 0.1928\n", "Accuracy of the network on the validation set: 84.12530 %\n", "[29, 4] loss: 0.1847\n", "Accuracy of the network on the validation set: 87.05683 %\n", "[30, 4] loss: 0.1567\n", "Accuracy of the network on the validation set: 85.49053 %\n", "[31, 4] loss: 0.1418\n", "Accuracy of the network on the validation set: 79.54281 %\n", "[32, 4] loss: 0.1176\n", "Accuracy of the network on the validation set: 87.00392 %\n", "[33, 4] loss: 0.1178\n", "Accuracy of the network on the validation set: 85.43761 %\n", "[34, 4] loss: 0.0870\n", "Accuracy of the network on the validation set: 84.85554 %\n", "[35, 4] loss: 0.0871\n", "Accuracy of the network on the validation set: 85.50111 %\n", "[36, 4] loss: 0.0721\n", "Accuracy of the network on the validation set: 87.64949 %\n", "[37, 4] loss: 0.0771\n", "Accuracy of the network on the validation set: 86.54884 %\n", "[38, 4] loss: 0.0801\n", "Accuracy of the network on the validation set: 84.33697 %\n", "[39, 4] loss: 0.0545\n", "Accuracy of the network on the validation set: 81.76527 %\n", "[40, 4] loss: 0.0690\n", "Accuracy of the network on the validation set: 88.71838 %\n", "[41, 4] loss: 0.0667\n", "Accuracy of the network on the validation set: 86.18901 %\n", "[42, 4] loss: 0.0838\n", "Accuracy of the network on the validation set: 77.74368 %\n", "[43, 4] loss: 0.0986\n", "Accuracy of the network on the validation set: 81.44777 %\n", "[44, 4] loss: 0.0815\n", "Accuracy of the network on the validation set: 80.92920 %\n", "[45, 4] loss: 0.0761\n", "Accuracy of the network on the validation set: 76.42079 %\n", "[46, 4] loss: 0.1073\n", "Accuracy of the network on the validation set: 84.24172 %\n", "[47, 4] loss: 0.0947\n", "Accuracy of the network on the validation set: 75.99746 %\n", "[48, 4] loss: 0.1019\n", "Accuracy of the network on the validation set: 75.96571 %\n", "[49, 4] loss: 0.0650\n", "Accuracy of the network on the validation set: 77.75426 %\n", "[50, 4] loss: 0.0534\n", "Accuracy of the network on the validation set: 81.90285 %\n", "[51, 4] loss: 0.0517\n", "Accuracy of the network on the validation set: 85.18362 %\n", "[52, 4] loss: 0.0547\n", "Accuracy of the network on the validation set: 74.71690 %\n", "[53, 4] loss: 0.0423\n", "Accuracy of the network on the validation set: 83.75489 %\n", "[54, 4] loss: 0.0448\n", "Accuracy of the network on the validation set: 87.30024 %\n", "[55, 4] loss: 0.0419\n", "Accuracy of the network on the validation set: 88.31622 %\n", "[56, 4] loss: 0.0571\n", "Accuracy of the network on the validation set: 70.70589 %\n", "[57, 4] loss: 0.0555\n", "Accuracy of the network on the validation set: 88.04106 %\n", "[58, 4] loss: 0.0805\n", "Accuracy of the network on the validation set: 70.98106 %\n", "[59, 4] loss: 0.1174\n", "Accuracy of the network on the validation set: 78.04000 %\n", "[60, 4] loss: 0.1034\n", "Accuracy of the network on the validation set: 77.39443 %\n", "[61, 4] loss: 0.0609\n", "Accuracy of the network on the validation set: 78.30458 %\n", "[62, 4] loss: 0.0595\n", "Accuracy of the network on the validation set: 80.74929 %\n", "[63, 4] loss: 0.0719\n", "Accuracy of the network on the validation set: 84.88729 %\n", "[64, 4] loss: 0.0696\n", "Accuracy of the network on the validation set: 78.89724 %\n", "[65, 4] loss: 0.0566\n", "Accuracy of the network on the validation set: 84.66504 %\n", "[66, 4] loss: 0.1038\n", "Accuracy of the network on the validation set: 81.42661 %\n", "[67, 4] loss: 0.0988\n", "Accuracy of the network on the validation set: 63.66811 %\n", "[68, 4] loss: 0.1816\n", "Accuracy of the network on the validation set: 65.44608 %\n", "[69, 4] loss: 0.1896\n", "Accuracy of the network on the validation set: 72.94952 %\n", "[70, 4] loss: 0.1280\n", "Accuracy of the network on the validation set: 61.19166 %\n", "[71, 4] loss: 0.2858\n", "Accuracy of the network on the validation set: 69.97566 %\n", "[72, 4] loss: 0.1813\n", "Accuracy of the network on the validation set: 66.67372 %\n", "[73, 4] loss: 0.1547\n", "Accuracy of the network on the validation set: 50.84136 %\n", "[74, 4] loss: 0.1030\n", "Accuracy of the network on the validation set: 74.43116 %\n", "[75, 4] loss: 0.0767\n", "Accuracy of the network on the validation set: 77.20394 %\n", "[76, 4] loss: 0.1155\n", "Accuracy of the network on the validation set: 75.90221 %\n", "[77, 4] loss: 0.0701\n", "Accuracy of the network on the validation set: 73.80675 %\n", "[78, 4] loss: 0.1133\n", "Accuracy of the network on the validation set: 77.22510 %\n", "[79, 4] loss: 0.0995\n", "Accuracy of the network on the validation set: 77.70134 %\n", "[80, 4] loss: 0.0996\n", "Accuracy of the network on the validation set: 78.95015 %\n", "[81, 4] loss: 0.0716\n", "Accuracy of the network on the validation set: 84.00889 %\n", "[82, 4] loss: 0.0912\n", "Accuracy of the network on the validation set: 82.98233 %\n", "[83, 4] loss: 0.1056\n", "Accuracy of the network on the validation set: 75.91280 %\n", "[84, 4] loss: 0.0839\n", "Accuracy of the network on the validation set: 75.38364 %\n", "[85, 4] loss: 0.0483\n", "Accuracy of the network on the validation set: 75.98688 %\n", "[86, 4] loss: 0.0384\n", "Accuracy of the network on the validation set: 77.87067 %\n", "[87, 4] loss: 0.0483\n", "Accuracy of the network on the validation set: 85.15187 %\n", "[88, 4] loss: 0.0378\n", "Accuracy of the network on the validation set: 85.86094 %\n", "[89, 4] loss: 0.0398\n", "Accuracy of the network on the validation set: 87.22616 %\n", "[90, 4] loss: 0.0416\n", "Accuracy of the network on the validation set: 87.17325 %\n", "[91, 4] loss: 0.0288\n", "Accuracy of the network on the validation set: 85.42703 %\n", "[92, 4] loss: 0.0315\n", "Accuracy of the network on the validation set: 86.25251 %\n", "[93, 4] loss: 0.0273\n", "Accuracy of the network on the validation set: 81.34194 %\n", "[94, 4] loss: 0.0281\n", "Accuracy of the network on the validation set: 82.66483 %\n", "[95, 4] loss: 0.0197\n", "Accuracy of the network on the validation set: 86.15727 %\n", "[96, 4] loss: 0.0170\n", "Accuracy of the network on the validation set: 88.18923 %\n", "[97, 4] loss: 0.0221\n", "Accuracy of the network on the validation set: 88.77130 %\n", "[98, 4] loss: 0.0214\n", "Accuracy of the network on the validation set: 89.38512 %\n", "[99, 4] loss: 0.0099\n", "Accuracy of the network on the validation set: 89.88253 %\n", "[100, 4] loss: 0.0117\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Accuracy of the network on the validation set: 90.26352 %\n", "[101, 4] loss: 0.0108\n", "Accuracy of the network on the validation set: 90.55985 %\n", "[102, 4] loss: 0.0090\n", "Accuracy of the network on the validation set: 90.53868 %\n", "[103, 4] loss: 0.0105\n", "Accuracy of the network on the validation set: 90.29527 %\n", "[104, 4] loss: 0.0091\n", "Accuracy of the network on the validation set: 90.07302 %\n", "[105, 4] loss: 0.0109\n", "Accuracy of the network on the validation set: 90.03069 %\n", "[106, 4] loss: 0.0081\n", "Accuracy of the network on the validation set: 90.15769 %\n", "[107, 4] loss: 0.0094\n", "Accuracy of the network on the validation set: 90.30585 %\n", "[108, 4] loss: 0.0056\n", "Accuracy of the network on the validation set: 90.35877 %\n", "[109, 4] loss: 0.0073\n", "Accuracy of the network on the validation set: 90.39052 %\n", "[110, 4] loss: 0.0060\n", "Accuracy of the network on the validation set: 90.46460 %\n", "[111, 4] loss: 0.0071\n", "Accuracy of the network on the validation set: 90.60218 %\n", "[112, 4] loss: 0.0061\n", "Accuracy of the network on the validation set: 90.65510 %\n", "[113, 4] loss: 0.0096\n", "Accuracy of the network on the validation set: 90.59160 %\n", "[114, 4] loss: 0.0092\n", "Accuracy of the network on the validation set: 89.78728 %\n", "[115, 4] loss: 0.0068\n", "Accuracy of the network on the validation set: 89.44862 %\n", "[116, 4] loss: 0.0072\n", "Accuracy of the network on the validation set: 89.58620 %\n", "[117, 4] loss: 0.0152\n", "Accuracy of the network on the validation set: 88.81363 %\n", "[118, 4] loss: 0.0093\n", "Accuracy of the network on the validation set: 88.88771 %\n", "[119, 4] loss: 0.0138\n", "Accuracy of the network on the validation set: 89.22637 %\n", "[120, 4] loss: 0.0070\n", "Accuracy of the network on the validation set: 86.52767 %\n", "[121, 4] loss: 0.0152\n", "Accuracy of the network on the validation set: 85.87152 %\n", "[122, 4] loss: 0.0101\n", "Accuracy of the network on the validation set: 89.01471 %\n", "[123, 4] loss: 0.0089\n", "Accuracy of the network on the validation set: 89.80845 %\n", "[124, 4] loss: 0.0065\n", "Accuracy of the network on the validation set: 89.77670 %\n", "[125, 4] loss: 0.0056\n", "Accuracy of the network on the validation set: 89.89311 %\n", "[126, 4] loss: 0.0089\n", "Accuracy of the network on the validation set: 90.30585 %\n", "[127, 4] loss: 0.0063\n", "Accuracy of the network on the validation set: 90.10477 %\n", "[128, 4] loss: 0.0067\n", "Accuracy of the network on the validation set: 90.09419 %\n", "[129, 4] loss: 0.0057\n", "Accuracy of the network on the validation set: 90.16827 %\n", "[130, 4] loss: 0.0053\n", "Accuracy of the network on the validation set: 89.98836 %\n", "[131, 4] loss: 0.0061\n", "Accuracy of the network on the validation set: 90.33760 %\n", "[132, 4] loss: 0.0071\n", "Accuracy of the network on the validation set: 90.35877 %\n", "[133, 4] loss: 0.0046\n", "Accuracy of the network on the validation set: 90.49635 %\n", "[134, 4] loss: 0.0043\n", "Accuracy of the network on the validation set: 90.59160 %\n", "[135, 4] loss: 0.0034\n", "Accuracy of the network on the validation set: 90.62335 %\n", "[136, 4] loss: 0.0049\n", "Accuracy of the network on the validation set: 90.63393 %\n", "[137, 4] loss: 0.0034\n", "Accuracy of the network on the validation set: 89.73436 %\n", "[138, 4] loss: 0.0042\n", "Accuracy of the network on the validation set: 88.93005 %\n", "[139, 4] loss: 0.0045\n", "Accuracy of the network on the validation set: 89.15229 %\n", "[140, 4] loss: 0.0079\n", "Accuracy of the network on the validation set: 90.46460 %\n", "[141, 4] loss: 0.0046\n", "Accuracy of the network on the validation set: 90.75034 %\n", "[142, 4] loss: 0.0053\n", "Accuracy of the network on the validation set: 90.75034 %\n", "[143, 4] loss: 0.0057\n", "Accuracy of the network on the validation set: 90.77151 %\n", "[144, 4] loss: 0.0034\n", "Accuracy of the network on the validation set: 90.63393 %\n", "[145, 4] loss: 0.0058\n", "Accuracy of the network on the validation set: 90.81384 %\n", "[146, 4] loss: 0.0042\n", "Accuracy of the network on the validation set: 90.69743 %\n", "[147, 4] loss: 0.0057\n", "Accuracy of the network on the validation set: 90.82443 %\n", "[148, 4] loss: 0.0038\n", "Accuracy of the network on the validation set: 90.77151 %\n", "[149, 4] loss: 0.0052\n", "Accuracy of the network on the validation set: 90.63393 %\n", "[150, 4] loss: 0.0046\n", "Accuracy of the network on the validation set: 90.48577 %\n", "[151, 4] loss: 0.0027\n", "Accuracy of the network on the validation set: 90.32702 %\n", "[152, 4] loss: 0.0045\n", "Accuracy of the network on the validation set: 90.43285 %\n", "[153, 4] loss: 0.0034\n", "Accuracy of the network on the validation set: 90.35877 %\n", "[154, 4] loss: 0.0035\n", "Accuracy of the network on the validation set: 90.34818 %\n", "[155, 4] loss: 0.0038\n", "Accuracy of the network on the validation set: 90.36935 %\n", "[156, 4] loss: 0.0028\n", "Accuracy of the network on the validation set: 90.27410 %\n", "[157, 4] loss: 0.0032\n", "Accuracy of the network on the validation set: 90.21060 %\n", "[158, 4] loss: 0.0065\n", "Accuracy of the network on the validation set: 82.49550 %\n", "[159, 4] loss: 0.0110\n", "Accuracy of the network on the validation set: 88.66547 %\n", "[160, 4] loss: 0.0144\n", "Accuracy of the network on the validation set: 83.75489 %\n", "[161, 4] loss: 0.0189\n", "Accuracy of the network on the validation set: 87.48016 %\n", "[162, 4] loss: 0.0049\n", "Accuracy of the network on the validation set: 87.98815 %\n", "[163, 4] loss: 0.0083\n", "Accuracy of the network on the validation set: 87.89290 %\n", "[164, 4] loss: 0.0062\n", "Accuracy of the network on the validation set: 88.96179 %\n", "[165, 4] loss: 0.0037\n", "Accuracy of the network on the validation set: 89.00413 %\n", "[166, 4] loss: 0.0046\n", "Accuracy of the network on the validation set: 89.30046 %\n", "[167, 4] loss: 0.0054\n", "Accuracy of the network on the validation set: 89.63912 %\n", "[168, 4] loss: 0.0050\n", "Accuracy of the network on the validation set: 90.66568 %\n", "[169, 4] loss: 0.0033\n", "Accuracy of the network on the validation set: 91.09959 %\n", "[170, 4] loss: 0.0037\n", "Accuracy of the network on the validation set: 91.13134 %\n", "[171, 4] loss: 0.0037\n", "Accuracy of the network on the validation set: 91.07842 %\n", "[172, 4] loss: 0.0030\n", "Accuracy of the network on the validation set: 90.90909 %\n", "[173, 4] loss: 0.0038\n", "Accuracy of the network on the validation set: 90.57043 %\n", "[174, 4] loss: 0.0030\n", "Accuracy of the network on the validation set: 90.57043 %\n", "[175, 4] loss: 0.0033\n", "Accuracy of the network on the validation set: 90.73976 %\n", "[176, 4] loss: 0.0023\n", "Accuracy of the network on the validation set: 90.87734 %\n", "[177, 4] loss: 0.0023\n", "Accuracy of the network on the validation set: 90.98317 %\n", "[178, 4] loss: 0.0029\n", "Accuracy of the network on the validation set: 90.94084 %\n", "[179, 4] loss: 0.0040\n", "Accuracy of the network on the validation set: 90.83501 %\n", "[180, 4] loss: 0.0049\n", "Accuracy of the network on the validation set: 90.70801 %\n", "[181, 4] loss: 0.0036\n", "Accuracy of the network on the validation set: 90.59160 %\n", "[182, 4] loss: 0.0029\n", "Accuracy of the network on the validation set: 90.52810 %\n", "[183, 4] loss: 0.0025\n", "Accuracy of the network on the validation set: 90.78209 %\n", "[184, 4] loss: 0.0032\n", "Accuracy of the network on the validation set: 91.06784 %\n", "[185, 4] loss: 0.0035\n", "Accuracy of the network on the validation set: 91.39591 %\n", "[186, 4] loss: 0.0029\n", "Accuracy of the network on the validation set: 91.19484 %\n", "[187, 4] loss: 0.0041\n", "Accuracy of the network on the validation set: 91.07842 %\n", "[188, 4] loss: 0.0042\n", "Accuracy of the network on the validation set: 90.72918 %\n", "[189, 4] loss: 0.0017\n", "Accuracy of the network on the validation set: 90.26352 %\n", "[190, 4] loss: 0.0023\n", "Accuracy of the network on the validation set: 90.14711 %\n", "[191, 4] loss: 0.0021\n", "Accuracy of the network on the validation set: 90.34818 %\n", "[192, 4] loss: 0.0019\n", "Accuracy of the network on the validation set: 90.50693 %\n", "[193, 4] loss: 0.0027\n", "Accuracy of the network on the validation set: 90.59160 %\n", "[194, 4] loss: 0.0028\n", "Accuracy of the network on the validation set: 91.13134 %\n", "[195, 4] loss: 0.0027\n", "Accuracy of the network on the validation set: 91.29008 %\n", "[196, 4] loss: 0.0024\n", "Accuracy of the network on the validation set: 91.35358 %\n", "[197, 4] loss: 0.0026\n", "Accuracy of the network on the validation set: 91.17367 %\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[198, 4] loss: 0.0022\n", "Accuracy of the network on the validation set: 90.49635 %\n", "[199, 4] loss: 0.0026\n", "Accuracy of the network on the validation set: 90.25294 %\n", "[200, 4] loss: 0.0024\n", "Accuracy of the network on the validation set: 90.20002 %\n", "Finished Training\n" ] } ], "source": [ "# 实例化网络,准备放到 GPU 上训练\n", "net = SSRN(num_classes=16, k=97)\n", "net.to(device)\n", "\n", "import torch\n", "import torch.optim as optim\n", "# 引入时间模块格式化时间生成唯一训练文件\n", "import time\n", "unique_time = time.strftime(\"%Y%m%d-%H%M%S\")\n", "\n", "criterion = nn.CrossEntropyLoss()\n", "#optimizer = optim.RMSprop(net.parameters())\n", "# 论文中使用的是 RMSprop 优化器,但是最后作者还是使用了 Adam,估计优化效果更好吧\n", "optimizer = optim.Adam(net.parameters(), lr=0.002)\n", "\n", "best_pred = 0\n", "#SAVE_PATH3 = './saved_models/ssnet_best3_up_seed' + str(args.seed) + '.pth' \n", "SSRN_TRAIN_SAVE_PATH = 'SSRN-Train-' + unique_time + '.pth' \n", "#torch.save(net.state_dict(), SAVE_PATH)\n", "\n", "for epoch in range(200): # loop over the dataset multiple times\n", " \n", " running_loss = 0.0\n", " #iters = len(trainloader)\n", " net = net.train()\n", " for i, data in enumerate(trainloader, 0):\n", " # get the inputs\n", " inputs, labels = data\n", " inputs, labels = inputs.to(device), labels.to(device)\n", "\n", " # zero the parameter gradients\n", " optimizer.zero_grad()\n", "\n", " # forward + backward + optimize\n", " outputs = net(inputs.float())\n", " loss = criterion(outputs, labels.long())\n", " loss.backward()\n", " optimizer.step()\n", "\n", " # print statistics\n", " running_loss += loss.item()\n", " if i % 4 == 3: # print every 2000 mini-batches\n", " print('[%d, %5d] loss: %.4f' %\n", " (epoch + 1, i + 1, running_loss / 4))\n", " running_loss = 0.0\n", " #schedular.step()\n", " \n", " correct = 0\n", " total = 0\n", " net = net.eval()\n", " counter = 0 \n", " with torch.no_grad():\n", " for data in validationloader:\n", "# if counter <= 10:\n", "# counter += 1\n", " images, labels = data\n", " images, labels = images.to(device), labels.to(device)\n", " outputs = net(images.float())\n", " _, predicted = torch.max(outputs.data, 1)\n", " total += labels.size(0)\n", " correct += (predicted == labels.long()).sum().item()\n", "\n", " new_pred = correct / total\n", " print('Accuracy of the network on the validation set: %.5f %%' % (\n", " 100 * new_pred))\n", " \n", " if new_pred > best_pred:\n", " logging.info('new_pred %f', new_pred)\n", " logging.info('best_pred %f', best_pred)\n", " torch.save(net.state_dict(), SSRN_TRAIN_SAVE_PATH)\n", " best_pred=new_pred\n", " \n", "print('Finished Training')" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "## Validation Stage Functions\n", "def cal_results(matrix):\n", " shape = np.shape(matrix)\n", " number = 0\n", " sum = 0\n", " AA = np.zeros([shape[0]], dtype=np.float)\n", " for i in range(shape[0]):\n", " number += matrix[i, i]\n", " AA[i] = matrix[i, i] / np.sum(matrix[i, :])\n", " sum += np.sum(matrix[i, :]) * np.sum(matrix[:, i])\n", " OA = number / np.sum(matrix)\n", " AA_mean = np.mean(AA)\n", " pe = sum / (np.sum(matrix) ** 2)\n", " Kappa = (OA - pe) / (1 - pe)\n", " return OA, AA_mean, Kappa, AA\n", "\n", "\n", "def predVisIN(indices, pred, size1, size2):\n", " \n", " if pred.ndim > 1:\n", " pred = np.ravel(pred)\n", " \n", " x = np.zeros(size1*size2)\n", " x[indices] = pred\n", " \n", " y = np.ones((x.shape[0], 3))\n", "\n", " for index, item in enumerate(x):\n", " if item == 0:\n", " y[index] = np.array([230, 230, 230]) / 255. # np.array([255, 255, 255]) / 255.\n", " if item == 1:\n", " y[index] = np.array([255, 0, 0]) / 255.\n", " if item == 2:\n", " y[index] = np.array([0, 255, 0]) / 255.\n", " if item == 3:\n", " y[index] = np.array([0, 0, 255]) / 255.\n", " if item == 4:\n", " y[index] = np.array([255, 255, 0]) / 255.\n", " if item == 5:\n", " y[index] = np.array([0, 255, 255]) / 255.\n", " if item == 6:\n", " y[index] = np.array([255, 0, 255]) / 255.\n", " if item == 7:\n", " y[index] = np.array([192, 192, 192]) / 255.\n", " if item == 8:\n", " y[index] = np.array([128, 128, 128]) / 255.\n", " if item == 9:\n", " y[index] = np.array([128, 0, 0]) / 255.\n", " if item == 10: \n", " y[index] = np.array([128, 128, 0]) / 255.\n", " if item == 11:\n", " y[index] = np.array([0, 128, 0]) / 255.\n", " if item == 12:\n", " y[index] = np.array([128, 0, 128]) / 255.\n", " if item == 13:\n", " y[index] = np.array([0, 128, 128]) / 255.\n", " if item == 14:\n", " y[index] = np.array([0, 0, 128]) / 255.\n", " if item == 15:\n", " y[index] = np.array([255, 165, 0]) / 255.\n", " if item == 16:\n", " y[index] = np.array([255, 215, 0]) / 255.\n", " \n", " y_rgb = np.reshape(y, (size1, size2, 3))\n", " \n", " return y_rgb" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "OA, AA_Mean, Kappa: %f, %f, %f, 0.9139591491163086 0.932226390035374 0.9019106981267497\n", "('AA for each class: ', array([0.975 , 0.90743551, 0.88289474, 0.88127854, 0.9082774 ,\n", " 0.99703264, 1. , 0.98863636, 1. , 0.88148984,\n", " 0.89863975, 0.84473198, 1. , 0.9703641 , 0.80337079,\n", " 0.97647059]))\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/tmp/ipykernel_5205/1516455691.py:6: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", " AA = np.zeros([shape[0]], dtype=np.float)\n" ] } ], "source": [ "# Validation Stage \n", "\n", "from sklearn import metrics, preprocessing\n", "\n", "trained_net = SSRN(num_classes=16, k=97)\n", "\n", "trained_net.load_state_dict(torch.load(SSRN_TRAIN_SAVE_PATH))\n", "trained_net.eval()\n", "trained_net = trained_net.cuda()\n", "\n", "label_val = []\n", "pred_val = []\n", "\n", "with torch.no_grad():\n", " for data in validationloader:\n", " images, labels = data\n", " #label_val = torch.stack([label_val.type_as(labels), labels])\n", " label_val.append(labels)\n", " \n", " images, labels = images.to(device), labels.to(device)\n", " outputs = trained_net(images.float())\n", " _, predicted = torch.max(outputs.data, 1)\n", " #pred_val = torch.stack([pred_val.type_as(predicted), predicted])\n", " pred_val.append(predicted)\n", " \n", "label_val_cpu = [x.cpu() for x in label_val]\n", "pred_val_cpu = [x.cpu() for x in pred_val]\n", "\n", "label_cat = np.concatenate(label_val_cpu)\n", "pred_cat = np.concatenate(pred_val_cpu)\n", "\n", "matrix = metrics.confusion_matrix(label_cat, pred_cat)\n", "\n", "OA, AA_mean, Kappa, AA = cal_results(matrix)\n", "\n", "print('OA, AA_Mean, Kappa: %f, %f, %f, ', OA, AA_mean, Kappa)\n", "print(str((\"AA for each class: \", AA)))" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# generate classification maps\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "all_pred = []\n", "\n", "with torch.no_grad():\n", " for data in allloader:\n", " images, _ = data\n", " images, _ = images.to(device), labels.to(device)\n", " outputs = trained_net(images.float())\n", " _, predicted = torch.max(outputs.data, 1)\n", " all_pred.append(predicted)\n", "\n", "all_pred = torch.cat(all_pred)\n", "all_pred = all_pred.cpu().numpy() + 1\n", "\n", "y_pred = predVisIN(all_indices, all_pred, 145, 145)\n", "\n", "\n", "#plt.plot(x, y)\n", "plt.imshow(y_pred)\n", "plt.axis('off')\n", "fig_path = 'SSRN-Train-' + unique_time + '.png'\n", "plt.savefig(fig_path, bbox_inches=0)\n", "#plt.savefig(fig_path, bbox_inches='tight')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "BBP", "language": "python", "name": "bbp" }, "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.9.13" } }, "nbformat": 4, "nbformat_minor": 2 }