From 1f3dce9e912214e5d8c67367ce3923cadf9e2261 Mon Sep 17 00:00:00 2001 From: Aishwarya Muttineni <66995746+aishwarya756@users.noreply.github.com> Date: Tue, 24 Aug 2021 08:38:17 +0530 Subject: [PATCH] Adding Hyperspectral Image Classification --- Hyperspectral Image Classification/HSI.ipynb | 1501 +++++++++++++++++ Hyperspectral Image Classification/HSI.py | 502 ++++++ .../HSI_Confusion Matrix.png | Bin 0 -> 21746 bytes .../HSI_cmap.png | Bin 0 -> 18463 bytes Hyperspectral Image Classification/HSI_gt.png | Bin 0 -> 15803 bytes 5 files changed, 2003 insertions(+) create mode 100644 Hyperspectral Image Classification/HSI.ipynb create mode 100644 Hyperspectral Image Classification/HSI.py create mode 100644 Hyperspectral Image Classification/HSI_Confusion Matrix.png create mode 100644 Hyperspectral Image Classification/HSI_cmap.png create mode 100644 Hyperspectral Image Classification/HSI_gt.png diff --git a/Hyperspectral Image Classification/HSI.ipynb b/Hyperspectral Image Classification/HSI.ipynb new file mode 100644 index 0000000..6e82396 --- /dev/null +++ b/Hyperspectral Image Classification/HSI.ipynb @@ -0,0 +1,1501 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "KSC_PCA.ipynb", + "provenance": [], + "collapsed_sections": [], + "machine_shape": "hm" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "code", + "metadata": { + "id": "cJTVxOQGz-cw" + }, + "source": [ + "import numpy as np\n", + "from sklearn.decomposition import PCA\n", + "import scipy.io as sio\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn import preprocessing\n", + "import os\n", + "import random\n", + "from random import shuffle\n", + "from skimage.transform import rotate\n", + "import scipy.ndimage\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline" + ], + "execution_count": 60, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "pQrsee9I0Qaa" + }, + "source": [ + "import torch" + ], + "execution_count": 61, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "n3f-2cIx0USV" + }, + "source": [ + "from torch.utils.data import Dataset, DataLoader" + ], + "execution_count": 62, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "8YegeH3I0YAk" + }, + "source": [ + "hsi_data= sio.loadmat('KSC.mat')['KSC']\n", + "labels = sio.loadmat('KSC_gt.mat')['KSC_gt']" + ], + "execution_count": 63, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "X9RGVlN30YW4" + }, + "source": [ + "[height,width,depth]=hsi_data.shape" + ], + "execution_count": 64, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "_u36Tv-i0YkC" + }, + "source": [ + "def splitTrainTestSet(X, y, testRatio=0.10):\n", + " X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=testRatio, random_state=345,\n", + " stratify=y)\n", + " return X_train, X_test, y_train, y_test\n", + "\n", + "def oversampleWeakClasses(X, y):\n", + " uniqueLabels, labelCounts = np.unique(y, return_counts=True)\n", + " maxCount = np.max(labelCounts)\n", + " labelInverseRatios = maxCount / labelCounts \n", + " # repeat for every label and concat\n", + " newX = X[y == uniqueLabels[0], :, :, :].repeat(round(labelInverseRatios[0]), axis=0)\n", + " newY = y[y == uniqueLabels[0]].repeat(round(labelInverseRatios[0]), axis=0)\n", + " for label, labelInverseRatio in zip(uniqueLabels[1:], labelInverseRatios[1:]):\n", + " cX = X[y== label,:,:,:].repeat(round(labelInverseRatio), axis=0)\n", + " cY = y[y == label].repeat(round(labelInverseRatio), axis=0)\n", + " newX = np.concatenate((newX, cX))\n", + " newY = np.concatenate((newY, cY))\n", + " np.random.seed(seed=42)\n", + " rand_perm = np.random.permutation(newY.shape[0])\n", + " newX = newX[rand_perm, :, :, :]\n", + " newY = newY[rand_perm]\n", + " return newX, newY" + ], + "execution_count": 65, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "C-2VJDlm0Yns" + }, + "source": [ + "def standartizeData(X):\n", + " newX = np.reshape(X, (-1, X.shape[2]))\n", + " scaler = preprocessing.StandardScaler().fit(newX) \n", + " newX = scaler.transform(newX)\n", + " newX = np.reshape(newX, (X.shape[0],X.shape[1],X.shape[2]))\n", + " return newX, scaler\n", + "\n", + "def applyPCA(X, numComponents=75):\n", + " newX = np.reshape(X, (-1, X.shape[2]))\n", + " pca = PCA(n_components=numComponents, whiten=True)\n", + " newX = pca.fit_transform(newX)\n", + " newX = np.reshape(newX, (X.shape[0],X.shape[1], numComponents))\n", + " return newX, pca\n", + "\n", + "def padWithZeros(X, margin=2):\n", + " newX = np.zeros((X.shape[0] + 2 * margin, X.shape[1] + 2* margin, X.shape[2]))\n", + " x_offset = margin\n", + " y_offset = margin\n", + " newX[x_offset:X.shape[0] + x_offset, y_offset:X.shape[1] + y_offset, :] = X\n", + " return newX\n", + "\n", + "def createPatches(X, y, windowSize=11, removeZeroLabels = True):\n", + " margin = int((windowSize - 1) / 2)\n", + " zeroPaddedX = padWithZeros(X, margin=margin)\n", + " # split patches\n", + " patchesData = np.zeros((X.shape[0] * X.shape[1], windowSize, windowSize, X.shape[2]))\n", + " patchesLabels = np.zeros((X.shape[0] * X.shape[1]))\n", + " patchIndex = 0\n", + " for r in range(margin, zeroPaddedX.shape[0] - margin):\n", + " for c in range(margin, zeroPaddedX.shape[1] - margin):\n", + " patch = zeroPaddedX[r - margin:r + margin + 1, c - margin:c + margin + 1] \n", + " patchesData[patchIndex, :, :, :] = patch\n", + " patchesLabels[patchIndex] = y[r-margin, c-margin]\n", + " patchIndex = patchIndex + 1\n", + " if removeZeroLabels:\n", + " patchesData = patchesData[patchesLabels>0,:,:,:]\n", + " patchesLabels = patchesLabels[patchesLabels>0]\n", + " patchesLabels -= 1\n", + " return patchesData, patchesLabels\n", + "\n", + "\n", + "def AugmentData(X_train):\n", + " for i in range(int(X_train.shape[0]/2)):\n", + " patch = X_train[i,:,:,:]\n", + " num = random.randint(0,2)\n", + " if (num == 0):\n", + " \n", + " flipped_patch = np.flipud(patch)\n", + " if (num == 1):\n", + " \n", + " flipped_patch = np.fliplr(patch)\n", + " if (num == 2):\n", + " \n", + " no = random.randrange(-180,180,30)\n", + " flipped_patch = scipy.ndimage.interpolation.rotate(patch, no,axes=(1, 0),\n", + " reshape=False, output=None, order=3, mode='constant', cval=0.0, prefilter=False)\n", + " \n", + " \n", + " patch2 = flipped_patch\n", + " X_train[i,:,:,:] = patch2\n", + " \n", + " return X_train" + ], + "execution_count": 66, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ufC7Yw8O0Yqk" + }, + "source": [ + "import numpy as np\n", + "import scipy\n", + "import os\n", + "from keras.models import Sequential\n", + "from keras.layers import Dense, Dropout, Flatten\n", + "from keras.layers import Conv2D, MaxPooling2D,BatchNormalization\n", + "from tensorflow.keras.callbacks import EarlyStopping\n", + "from tensorflow.keras.optimizers import SGD\n", + "from keras import backend as K\n", + "from keras.utils import np_utils\n", + "from keras.utils.vis_utils import plot_model" + ], + "execution_count": 67, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "StGbOjVp0Yt1" + }, + "source": [ + "weight_of_size=10" + ], + "execution_count": 68, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "p7ZWKFn80-VW" + }, + "source": [ + "X=hsi_data\n", + "y=labels" + ], + "execution_count": 69, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ePFCJRgs1AvN" + }, + "source": [ + "X,pca = applyPCA(X,30)" + ], + "execution_count": 70, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Qz9K49eR1Ay8", + "outputId": "c0e55591-90e8-430a-d6be-47a04c5abba5" + }, + "source": [ + "X.shape" + ], + "execution_count": 71, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(512, 614, 30)" + ] + }, + "metadata": {}, + "execution_count": 71 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "V3F5oORe1A2R" + }, + "source": [ + "XPatches, yPatches = createPatches(X, y, windowSize=15)" + ], + "execution_count": 72, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PuYf0Pct1A5D", + "outputId": "e36ac328-6780-4845-f337-af2edc6b2f7b" + }, + "source": [ + "XPatches.shape" + ], + "execution_count": 73, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(5211, 15, 15, 30)" + ] + }, + "metadata": {}, + "execution_count": 73 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "kuYNa7oB1A8M" + }, + "source": [ + "X_train, X_test, y_train, y_test = splitTrainTestSet(XPatches, yPatches, testRatio=0.2)" + ], + "execution_count": 74, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "fiFb0Wb51A_T" + }, + "source": [ + "X_train=np.reshape(X_train,(X_train.shape[0],X_train.shape[3],X_train.shape[1],X_train.shape[1]))" + ], + "execution_count": 75, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "_qUQQRem1hRf" + }, + "source": [ + "X_test=np.reshape(X_test,(X_test.shape[0],X_test.shape[3],X_test.shape[1],X_test.shape[1]))" + ], + "execution_count": 76, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "TetR8MOG1BCa", + "outputId": "c2d73dfa-a822-4a09-c432-cbaf37e38da6" + }, + "source": [ + "X_train.shape" + ], + "execution_count": 77, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(4168, 30, 15, 15)" + ] + }, + "metadata": {}, + "execution_count": 77 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1BimoC6S1SUu", + "outputId": "86a83c53-0e00-45b2-906f-1bef8afd2a0b" + }, + "source": [ + "X_train.shape" + ], + "execution_count": 78, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(4168, 30, 15, 15)" + ] + }, + "metadata": {}, + "execution_count": 78 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WIoAFbJQ1SZN", + "outputId": "b1ad25a7-6a54-40b7-cf28-0a5e5a6f8bb9" + }, + "source": [ + "y_train" + ], + "execution_count": 79, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([ 0., 12., 3., ..., 0., 5., 9.])" + ] + }, + "metadata": {}, + "execution_count": 79 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "QYvfhO4a1Sc7" + }, + "source": [ + "class MyDataset(Dataset):\n", + " def __init__(self, data, target, transform=None):\n", + " self.data = torch.from_numpy(data).float()\n", + " self.target = torch.from_numpy(target).int()\n", + " self.transform = transform\n", + " \n", + " def __getitem__(self, index):\n", + " x = self.data[index]\n", + " y = self.target[index]\n", + " \n", + " if self.transform:\n", + " x = self.transform(x)\n", + " \n", + " return x, y\n", + " \n", + " def __len__(self):\n", + " return len(self.data)" + ], + "execution_count": 80, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "pNLLxJ5-1Sgt" + }, + "source": [ + "data_train = MyDataset(X_train, y_train)" + ], + "execution_count": 81, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "SokuQpZd1SnS", + "outputId": "e3c84f6b-5b31-45d7-d4e3-f3b200b41f1d" + }, + "source": [ + "input_shape= X_train[0].shape\n", + "print(input_shape)" + ], + "execution_count": 82, + "outputs": [ + { + "output_type": "stream", + "text": [ + "(30, 15, 15)\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "SS1OdXZ81e8D", + "outputId": "51518c03-877d-44e5-d84a-a4a3d65d56a5" + }, + "source": [ + "data_train.__getitem__(0)[0].shape" + ], + "execution_count": 83, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "torch.Size([30, 15, 15])" + ] + }, + "metadata": {}, + "execution_count": 83 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "8voUJFUk1hGU" + }, + "source": [ + "n_epochs = 8\n", + "batch_size_train = 16\n", + "batch_size_test = 10\n", + "learning_rate = 0.01\n", + "momentum = 0.5\n", + "log_interval = 100\n", + "first_HL = 8" + ], + "execution_count": 84, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "y--iqOXK1hKI", + "outputId": "c4db170c-2d60-4835-f138-69646cd4cd4e" + }, + "source": [ + "import torch\n", + "import torchvision\n", + "\n", + "## Call the Dataset Class \n", + "#data_train = torchvision.datasets.IndianPines('./data',download=True,PATCH_LENGTH=2)\n", + "\n", + "## Check the shapes\n", + "print(data_train.__getitem__(0)[0].shape)\n", + "print(data_train.__len__())\n", + "\n", + "\n", + "## Wrap it around a Torch Dataloader\n", + "train_loader = torch.utils.data.DataLoader(data_train,batch_size=16,shuffle=True, num_workers=2)" + ], + "execution_count": 85, + "outputs": [ + { + "output_type": "stream", + "text": [ + "torch.Size([30, 15, 15])\n", + "4168\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "el20l7Ny1hN0", + "outputId": "cb2c8148-096d-4119-b1ee-d6a40a54fc01" + }, + "source": [ + "len(data_train)" + ], + "execution_count": 86, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "4168" + ] + }, + "metadata": {}, + "execution_count": 86 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "3XrPc66T1hU_" + }, + "source": [ + "data_test=MyDataset(X_test, y_test)" + ], + "execution_count": 87, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "iFIxbEZM1uxr", + "outputId": "22252246-ed62-4f5d-9697-90581ed25149" + }, + "source": [ + "import torch\n", + "import torchvision\n", + "\n", + "## Call the Dataset Class \n", + "#data_test = torchvision.datasets.IndianPines('./data',download=True,PATCH_LENGTH=2)\n", + "\n", + "## Check the shapes\n", + "print(data_test.__getitem__(0)[0].shape)\n", + "print(data_test.__len__())" + ], + "execution_count": 88, + "outputs": [ + { + "output_type": "stream", + "text": [ + "torch.Size([30, 15, 15])\n", + "1043\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "q3QXolwr1u05" + }, + "source": [ + "test_loader = torch.utils.data.DataLoader(data_test,batch_size=10,shuffle=False, num_workers=2)" + ], + "execution_count": 89, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 568 + }, + "id": "GGroI38H1u3_", + "outputId": "532d0011-bf95-406c-bc42-ef2a329d68d1" + }, + "source": [ + "examples = enumerate(test_loader)\n", + "batch_idx, (example_data, example_targets) = next(examples)\n", + "\n", + "print(example_data.shape)\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "fig = plt.figure()\n", + "for i in range(6):\n", + " plt.subplot(2,3,i+1)\n", + " plt.tight_layout()\n", + " plt.imshow(example_data[i][0], interpolation='none')\n", + " plt.title(\"Ground Truth: {}\".format(example_targets[i]))\n", + " plt.xticks([])\n", + " plt.yticks([])\n", + "fig" + ], + "execution_count": 90, + "outputs": [ + { + "output_type": "stream", + "text": [ + "torch.Size([10, 30, 15, 15])\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "execution_count": 90 + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "oVSa9KkH1u7E" + }, + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torchvision\n", + "import torchvision.transforms as transforms\n", + "\n", + "import random" + ], + "execution_count": 91, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "nNd9tITQ1u-F" + }, + "source": [ + "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", + "\n", + "# Hyper-parameters\n", + "num_epochs = 16\n", + "learning_rate = 0.001\n", + "\n", + "torch.manual_seed(0)\n", + "random.seed(0)" + ], + "execution_count": 111, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ait2YKMs1vEZ" + }, + "source": [ + "Half_width =60\n", + "layer_width = 20" + ], + "execution_count": 112, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "JXPg_kE-1vHB" + }, + "source": [ + "class SpinalCNN(nn.Module):\n", + " \"\"\"CNN.\"\"\"\n", + "\n", + " def __init__(self):\n", + " \"\"\"CNN Builder.\"\"\"\n", + " super(SpinalCNN, self).__init__()\n", + "\n", + " self.conv_layer = nn.Sequential(\n", + "\n", + " # Conv Layer block 1\n", + " nn.Conv2d(in_channels=30, out_channels=15, kernel_size=3, padding=1),\n", + " nn.BatchNorm2d(15),\n", + " nn.ReLU(inplace=True),\n", + " nn.Conv2d(in_channels=15, out_channels=30, kernel_size=3, padding=1),\n", + " nn.ReLU(inplace=True),\n", + " nn.MaxPool2d(kernel_size=2, stride=2),\n", + "\n", + " # Conv Layer block 2\n", + " nn.Conv2d(in_channels=30, out_channels=60, kernel_size=3, padding=1),\n", + " nn.BatchNorm2d(60),\n", + " nn.ReLU(inplace=True),\n", + " nn.Conv2d(in_channels=60, out_channels=60, kernel_size=3, padding=1),\n", + " nn.ReLU(inplace=True),\n", + " nn.MaxPool2d(kernel_size=2, stride=2),\n", + " nn.Dropout2d(p=0.05),\n", + "\n", + " # Conv Layer block 3\n", + " nn.Conv2d(in_channels=60, out_channels=120, kernel_size=3, padding=1),\n", + " nn.BatchNorm2d(120),\n", + " nn.ReLU(inplace=True),\n", + " nn.Conv2d(in_channels=120, out_channels=120, kernel_size=3, padding=1),\n", + " nn.ReLU(inplace=True),\n", + " nn.MaxPool2d(kernel_size=2, stride=2),\n", + " )\n", + " \n", + " self.fc_spinal_layer1 = nn.Sequential(\n", + " nn.Dropout(p=0.1), nn.Linear(Half_width, layer_width),\n", + " nn.ReLU(inplace=True),\n", + " )\n", + " self.fc_spinal_layer2 = nn.Sequential(\n", + " nn.Dropout(p=0.1), nn.Linear(Half_width + layer_width, layer_width),\n", + " nn.ReLU(inplace=True),\n", + " )\n", + " self.fc_spinal_layer3 = nn.Sequential(\n", + " nn.Dropout(p=0.1), nn.Linear(Half_width + layer_width, layer_width),\n", + " nn.ReLU(inplace=True),\n", + " )\n", + " self.fc_spinal_layer4 = nn.Sequential(\n", + " nn.Dropout(p=0.1), nn.Linear(Half_width + layer_width, layer_width),\n", + " nn.ReLU(inplace=True),\n", + " )\n", + " self.fc_out = nn.Sequential(\n", + " nn.Dropout(p=0.1), nn.Linear(layer_width*4, 16) \n", + " )\n", + "\n", + "\n", + " def forward(self, x):\n", + " \"\"\"Perform forward.\"\"\"\n", + " \n", + " # conv layers\n", + " x = self.conv_layer(x)\n", + " \n", + " # flatten\n", + " x = x.view(x.size(0), -1)\n", + " \n", + " x1 = self.fc_spinal_layer1(x[:, 0:Half_width])\n", + " x2 = self.fc_spinal_layer2(torch.cat([ x[:,Half_width:2*Half_width], x1], dim=1))\n", + " x3 = self.fc_spinal_layer3(torch.cat([ x[:,0:Half_width], x2], dim=1))\n", + " x4 = self.fc_spinal_layer4(torch.cat([ x[:,Half_width:2*Half_width], x3], dim=1))\n", + " \n", + " x = torch.cat([x1, x2], dim=1)\n", + " x = torch.cat([x, x3], dim=1)\n", + " x = torch.cat([x, x4], dim=1)\n", + "\n", + " x = self.fc_out(x)\n", + "\n", + " return x" + ], + "execution_count": 113, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WQzxIEJp2LKl", + "outputId": "dff13971-7d7e-460d-8679-7eb412d50632" + }, + "source": [ + "from tensorflow.keras.optimizers import Adam\n", + "model = SpinalCNN().to(device)\n", + "# defining the optimizer\n", + "optimizer = Adam(model.parameters(), lr=0.07)\n", + "# defining the loss function\n", + "criterion = nn.CrossEntropyLoss()\n", + "# checking if GPU is available\n", + "if torch.cuda.is_available():\n", + " model = model.cuda()\n", + " criterion = criterion.cuda()\n", + " \n", + "print(model)" + ], + "execution_count": 114, + "outputs": [ + { + "output_type": "stream", + "text": [ + "SpinalCNN(\n", + " (conv_layer): Sequential(\n", + " (0): Conv2d(30, 15, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (1): BatchNorm2d(15, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (2): ReLU(inplace=True)\n", + " (3): Conv2d(15, 30, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (4): ReLU(inplace=True)\n", + " (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n", + " (6): Conv2d(30, 60, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (7): BatchNorm2d(60, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (8): ReLU(inplace=True)\n", + " (9): Conv2d(60, 60, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (10): ReLU(inplace=True)\n", + " (11): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n", + " (12): Dropout2d(p=0.05, inplace=False)\n", + " (13): Conv2d(60, 120, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (14): BatchNorm2d(120, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (15): ReLU(inplace=True)\n", + " (16): Conv2d(120, 120, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n", + " (17): ReLU(inplace=True)\n", + " (18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n", + " )\n", + " (fc_spinal_layer1): Sequential(\n", + " (0): Dropout(p=0.1, inplace=False)\n", + " (1): Linear(in_features=60, out_features=20, bias=True)\n", + " (2): ReLU(inplace=True)\n", + " )\n", + " (fc_spinal_layer2): Sequential(\n", + " (0): Dropout(p=0.1, inplace=False)\n", + " (1): Linear(in_features=80, out_features=20, bias=True)\n", + " (2): ReLU(inplace=True)\n", + " )\n", + " (fc_spinal_layer3): Sequential(\n", + " (0): Dropout(p=0.1, inplace=False)\n", + " (1): Linear(in_features=80, out_features=20, bias=True)\n", + " (2): ReLU(inplace=True)\n", + " )\n", + " (fc_spinal_layer4): Sequential(\n", + " (0): Dropout(p=0.1, inplace=False)\n", + " (1): Linear(in_features=80, out_features=20, bias=True)\n", + " (2): ReLU(inplace=True)\n", + " )\n", + " (fc_out): Sequential(\n", + " (0): Dropout(p=0.1, inplace=False)\n", + " (1): Linear(in_features=80, out_features=16, bias=True)\n", + " )\n", + ")\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.7/dist-packages/keras/optimizer_v2/optimizer_v2.py:356: UserWarning: The `lr` argument is deprecated, use `learning_rate` instead.\n", + " \"The `lr` argument is deprecated, use `learning_rate` instead.\")\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Bajf_H5MII9l", + "outputId": "8235c2cc-1963-433c-84e3-502a13342051" + }, + "source": [ + "from torchvision import models\n", + "from torchsummary import summary\n", + "model = SpinalCNN().to(device)\n", + "summary(model, (30, 15, 15))" + ], + "execution_count": 115, + "outputs": [ + { + "output_type": "stream", + "text": [ + "----------------------------------------------------------------\n", + " Layer (type) Output Shape Param #\n", + "================================================================\n", + " Conv2d-1 [-1, 15, 15, 15] 4,065\n", + " BatchNorm2d-2 [-1, 15, 15, 15] 30\n", + " ReLU-3 [-1, 15, 15, 15] 0\n", + " Conv2d-4 [-1, 30, 15, 15] 4,080\n", + " ReLU-5 [-1, 30, 15, 15] 0\n", + " MaxPool2d-6 [-1, 30, 7, 7] 0\n", + " Conv2d-7 [-1, 60, 7, 7] 16,260\n", + " BatchNorm2d-8 [-1, 60, 7, 7] 120\n", + " ReLU-9 [-1, 60, 7, 7] 0\n", + " Conv2d-10 [-1, 60, 7, 7] 32,460\n", + " ReLU-11 [-1, 60, 7, 7] 0\n", + " MaxPool2d-12 [-1, 60, 3, 3] 0\n", + " Dropout2d-13 [-1, 60, 3, 3] 0\n", + " Conv2d-14 [-1, 120, 3, 3] 64,920\n", + " BatchNorm2d-15 [-1, 120, 3, 3] 240\n", + " ReLU-16 [-1, 120, 3, 3] 0\n", + " Conv2d-17 [-1, 120, 3, 3] 129,720\n", + " ReLU-18 [-1, 120, 3, 3] 0\n", + " MaxPool2d-19 [-1, 120, 1, 1] 0\n", + " Dropout-20 [-1, 60] 0\n", + " Linear-21 [-1, 20] 1,220\n", + " ReLU-22 [-1, 20] 0\n", + " Dropout-23 [-1, 80] 0\n", + " Linear-24 [-1, 20] 1,620\n", + " ReLU-25 [-1, 20] 0\n", + " Dropout-26 [-1, 80] 0\n", + " Linear-27 [-1, 20] 1,620\n", + " ReLU-28 [-1, 20] 0\n", + " Dropout-29 [-1, 80] 0\n", + " Linear-30 [-1, 20] 1,620\n", + " ReLU-31 [-1, 20] 0\n", + " Dropout-32 [-1, 80] 0\n", + " Linear-33 [-1, 16] 1,296\n", + "================================================================\n", + "Total params: 259,271\n", + "Trainable params: 259,271\n", + "Non-trainable params: 0\n", + "----------------------------------------------------------------\n", + "Input size (MB): 0.03\n", + "Forward/backward pass size (MB): 0.36\n", + "Params size (MB): 0.99\n", + "Estimated Total Size (MB): 1.37\n", + "----------------------------------------------------------------\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "SXlcqkeD2OhL", + "outputId": "2c08ecdb-04fd-4485-93a7-5ff1cd99ee9e" + }, + "source": [ + "model = SpinalCNN().to(device)\n", + "\n", + "\n", + "\n", + "# Loss and optimizer\n", + "criterion = nn.CrossEntropyLoss()\n", + "optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n", + "\n", + "# For updating learning rate\n", + "def update_lr(optimizer, lr): \n", + " for param_group in optimizer.param_groups:\n", + " param_group['lr'] = lr\n", + "\n", + "# Train the model\n", + "total_step = len(train_loader)\n", + "curr_lr = learning_rate\n", + "for epoch in range(num_epochs):\n", + " for i, (images, labels) in enumerate(train_loader):\n", + " images = images.to(device)\n", + " labels = labels.to(device)\n", + " \n", + " #print(images.shape)\n", + " # Forward pass\n", + " outputs = model(images)\n", + " labels = torch.tensor(labels, dtype=torch.long, device=device)\n", + " loss = criterion(outputs, labels)\n", + "\n", + " # Backward and optimize\n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + "\n", + " if (i+1) % 500 == 0:\n", + " print(\"Epoch [{}/{}], Step [{}/{}] Loss: {:.4f}\"\n", + " .format(epoch+1, num_epochs, i+1, total_step, loss.item()))\n", + " \n", + "\n", + " # Decay learning rate\n", + " if (epoch) == 1 or epoch>20:\n", + " curr_lr /= 3\n", + " update_lr(optimizer, curr_lr)\n", + " \n", + " # Test the model\n", + " model.eval()\n", + " with torch.no_grad():\n", + " correct = 0\n", + " total = 0\n", + " predicted_numpy=[]\n", + " for images, labels in test_loader:\n", + "\n", + " images = images.to(device)\n", + " labels = labels.to(device)\n", + " outputs = model(images)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " predicted_numpy.append(predicted.cpu().numpy())\n", + "\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + " \n", + " print('Accuracy of the model on the test images: {} %'.format(100 * correct / total))\n", + " \n", + " model.train()" + ], + "execution_count": 116, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:25: 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": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Accuracy of the model on the test images: 65.29242569511025 %\n", + "Accuracy of the model on the test images: 74.97603068072867 %\n", + "Accuracy of the model on the test images: 85.0431447746884 %\n", + "Accuracy of the model on the test images: 74.59252157238734 %\n", + "Accuracy of the model on the test images: 88.68648130393098 %\n", + "Accuracy of the model on the test images: 87.91946308724832 %\n", + "Accuracy of the model on the test images: 90.12464046021093 %\n", + "Accuracy of the model on the test images: 88.20709491850431 %\n", + "Accuracy of the model on the test images: 89.83700862895493 %\n", + "Accuracy of the model on the test images: 89.74113135186961 %\n", + "Accuracy of the model on the test images: 91.46692233940556 %\n", + "Accuracy of the model on the test images: 89.26174496644295 %\n", + "Accuracy of the model on the test images: 93.28859060402685 %\n", + "Accuracy of the model on the test images: 93.7679769894535 %\n", + "Accuracy of the model on the test images: 95.11025886864813 %\n", + "Accuracy of the model on the test images: 95.39789069990412 %\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "An_Q8lsCIwND", + "outputId": "056998bd-4f87-40be-c432-32a08f327793" + }, + "source": [ + "len(predicted_numpy)" + ], + "execution_count": 117, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "105" + ] + }, + "metadata": {}, + "execution_count": 117 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "euZAgKaHIxCz" + }, + "source": [ + "predicted_numpy = np.concatenate(predicted_numpy)" + ], + "execution_count": 118, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mycKQHlLIzxD", + "outputId": "d23d2b85-659c-479d-9436-40beaef57e01" + }, + "source": [ + "predicted_numpy.shape" + ], + "execution_count": 119, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(1043,)" + ] + }, + "metadata": {}, + "execution_count": 119 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "NTOvc63PI2QV", + "outputId": "7332a4f9-aac7-43dc-b96c-540458e9dcd4" + }, + "source": [ + "from sklearn.metrics import confusion_matrix\n", + "from sklearn.metrics import plot_confusion_matrix\n", + "y_true = y_test\n", + "y_pred = predicted_numpy\n", + "print(confusion_matrix(y_true, y_pred), end='\\n')" + ], + "execution_count": 120, + "outputs": [ + { + "output_type": "stream", + "text": [ + "[[150 0 0 1 1 0 0 0 0 0 0 0 0]\n", + " [ 0 42 0 4 2 1 0 0 0 0 0 0 0]\n", + " [ 0 0 48 2 1 0 0 0 0 0 0 0 0]\n", + " [ 1 0 7 42 0 0 0 0 0 0 0 0 0]\n", + " [ 0 0 6 1 25 0 0 0 0 0 0 0 0]\n", + " [ 0 1 0 0 0 45 0 0 0 0 0 0 0]\n", + " [ 0 0 0 0 0 0 21 0 0 0 0 0 0]\n", + " [ 0 0 0 1 0 0 0 80 5 0 0 0 0]\n", + " [ 0 0 0 0 0 0 0 8 96 0 0 0 0]\n", + " [ 0 0 0 0 0 0 0 2 0 78 0 1 0]\n", + " [ 0 0 0 0 0 0 0 0 0 0 84 0 0]\n", + " [ 0 0 1 0 1 0 0 0 0 0 0 99 0]\n", + " [ 0 0 0 0 0 0 0 1 0 0 0 0 185]]\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 445 + }, + "id": "vyFGKcL2DqtK", + "outputId": "6ad145a1-059f-4a91-bb21-d340ae4e44cd" + }, + "source": [ + "from sklearn.metrics import confusion_matrix\n", + "from sklearn.metrics import plot_confusion_matrix\n", + "import seaborn as sn\n", + "y_true = y_test\n", + "y_pred = predicted_numpy\n", + "plt.figure(figsize = (10,7))\n", + "print(sn.heatmap(confusion_matrix(y_true, y_pred),annot=True,cmap=\"OrRd\",fmt='d'))\n", + "plt.savefig('KSC_pca_Confusion Matrix')" + ], + "execution_count": 135, + "outputs": [ + { + "output_type": "stream", + "text": [ + "AxesSubplot(0.125,0.125;0.62x0.755)\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "YN04vF05da6u", + "outputId": "1b7e24c3-a9bc-4cee-c0f5-e47341d851b4" + }, + "source": [ + "from sklearn.metrics import cohen_kappa_score\n", + "print(cohen_kappa_score(y_true, y_pred, labels=None, weights=None, sample_weight=None))" + ], + "execution_count": 122, + "outputs": [ + { + "output_type": "stream", + "text": [ + "0.9487756139835698\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Q-Jm_Xf3I6Gb" + }, + "source": [ + "from sklearn.metrics import classification_report" + ], + "execution_count": 123, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "uza4cL23I8sU", + "outputId": "45326f14-5d91-4a03-997f-2812045a21de" + }, + "source": [ + "from sklearn.metrics import confusion_matrix\n", + "from sklearn.metrics import plot_confusion_matrix\n", + "y_true = y_test\n", + "y_pred = predicted_numpy\n", + "target_names = ['class 0', 'class 1', 'class 2', 'class 3', 'class 4', 'class 5', 'class 6', 'class 7', 'class 8', 'class 9', 'class 10', 'class 11', 'class 12']\n", + "print(classification_report(y_true, y_pred, target_names=target_names, digits=4))" + ], + "execution_count": 124, + "outputs": [ + { + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " class 0 0.9934 0.9868 0.9901 152\n", + " class 1 0.9767 0.8571 0.9130 49\n", + " class 2 0.7742 0.9412 0.8496 51\n", + " class 3 0.8235 0.8400 0.8317 50\n", + " class 4 0.8333 0.7812 0.8065 32\n", + " class 5 0.9783 0.9783 0.9783 46\n", + " class 6 1.0000 1.0000 1.0000 21\n", + " class 7 0.8791 0.9302 0.9040 86\n", + " class 8 0.9505 0.9231 0.9366 104\n", + " class 9 1.0000 0.9630 0.9811 81\n", + " class 10 1.0000 1.0000 1.0000 84\n", + " class 11 0.9900 0.9802 0.9851 101\n", + " class 12 1.0000 0.9946 0.9973 186\n", + "\n", + " accuracy 0.9540 1043\n", + " macro avg 0.9384 0.9366 0.9364 1043\n", + "weighted avg 0.9565 0.9540 0.9545 1043\n", + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "2x7ipmMdaM41" + }, + "source": [ + "f = sio.loadmat('KSC.mat')['KSC']\n", + "g = sio.loadmat('KSC_gt.mat')['KSC_gt']" + ], + "execution_count": 125, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "px_1RS-CaYMm" + }, + "source": [ + "F,pca = applyPCA(f,30)" + ], + "execution_count": 126, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "eSKEsR-aagxO" + }, + "source": [ + "FPatches, gPatches = createPatches(F,g, windowSize=15)" + ], + "execution_count": 127, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ZlOxKP8Ga3-e" + }, + "source": [ + "import itertools" + ], + "execution_count": 130, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ms0BA6OBah21" + }, + "source": [ + "def classified_pixels(FPatches,gPatches,g):\n", + " FPatches=np.reshape(FPatches,(FPatches.shape[0],FPatches.shape[3],FPatches.shape[1],FPatches.shape[2]))\n", + " data_test=MyDataset(FPatches, gPatches)\n", + " test_loader = torch.utils.data.DataLoader(data_test,batch_size=10,shuffle=False, num_workers=2)\n", + " with torch.no_grad():\n", + " correct = 0\n", + " total = 0\n", + " predicted_numpy=[]\n", + " for images, labels in test_loader:\n", + " images = images.to(device)\n", + " labels = labels.to(device)\n", + " outputs = model(images)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " predicted_numpy.append(predicted.cpu().numpy())\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + " classification_map=np.array(predicted_numpy)\n", + " cm=[]\n", + " for arr in classification_map:\n", + " cm.append(arr.tolist())\n", + " cm=list(itertools.chain.from_iterable(cm))\n", + " classification_map=np.array(cm)\n", + "\n", + " height=g.shape[0]\n", + " width=g.shape[1]\n", + " outputs = np.zeros((height,width))\n", + " k=0\n", + " for i in range(height):\n", + " for j in range(width):\n", + " target = g[i][j]\n", + " if target == 0 :\n", + " continue\n", + " else :\n", + " outputs[i][j]=classification_map[k]\n", + " k=k+1\n", + " return classification_map,outputs" + ], + "execution_count": 131, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UWG5PNKCap0H", + "outputId": "ddb78580-ac25-4849-cf03-4ee7dbd81528" + }, + "source": [ + "cma,out=classified_pixels(FPatches,gPatches,g)" + ], + "execution_count": 132, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:17: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 377 + }, + "id": "FY7dB4Jiatq7", + "outputId": "f1939d53-a171-4cb0-f406-69b173ce3cf7" + }, + "source": [ + "plt.figure(figsize=(7,7))\n", + "a=plt.imshow(out)\n", + "plt.savefig('KSC_pca_cmap')" + ], + "execution_count": 133, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 377 + }, + "id": "IU2Z8ja6bEBM", + "outputId": "bd2a1e56-ce2b-4153-f260-b4e209cfe458" + }, + "source": [ + "plt.figure(figsize=(7,7))\n", + "plt.imshow(g)\n", + "plt.savefig('KSC_pca_gt')" + ], + "execution_count": 134, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/Hyperspectral Image Classification/HSI.py b/Hyperspectral Image Classification/HSI.py new file mode 100644 index 0000000..f612d6a --- /dev/null +++ b/Hyperspectral Image Classification/HSI.py @@ -0,0 +1,502 @@ +# -*- coding: utf-8 -*- +"""KSC_PCA.ipynb + +Automatically generated by Colaboratory. + +Original file is located at + https://colab.research.google.com/drive/13bVyVdv-yBFo30C4Ce_Q4eKjwpb5Sm8y +""" + +# Commented out IPython magic to ensure Python compatibility. +import numpy as np +from sklearn.decomposition import PCA +import scipy.io as sio +from sklearn.model_selection import train_test_split +from sklearn import preprocessing +import os +import random +from random import shuffle +from skimage.transform import rotate +import scipy.ndimage +import matplotlib.pyplot as plt +# %matplotlib inline + +import torch + +from torch.utils.data import Dataset, DataLoader + +hsi_data= sio.loadmat('KSC.mat')['KSC'] +labels = sio.loadmat('KSC_gt.mat')['KSC_gt'] + +[height,width,depth]=hsi_data.shape + +def splitTrainTestSet(X, y, testRatio=0.10): + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=testRatio, random_state=345, + stratify=y) + return X_train, X_test, y_train, y_test + +def oversampleWeakClasses(X, y): + uniqueLabels, labelCounts = np.unique(y, return_counts=True) + maxCount = np.max(labelCounts) + labelInverseRatios = maxCount / labelCounts + # repeat for every label and concat + newX = X[y == uniqueLabels[0], :, :, :].repeat(round(labelInverseRatios[0]), axis=0) + newY = y[y == uniqueLabels[0]].repeat(round(labelInverseRatios[0]), axis=0) + for label, labelInverseRatio in zip(uniqueLabels[1:], labelInverseRatios[1:]): + cX = X[y== label,:,:,:].repeat(round(labelInverseRatio), axis=0) + cY = y[y == label].repeat(round(labelInverseRatio), axis=0) + newX = np.concatenate((newX, cX)) + newY = np.concatenate((newY, cY)) + np.random.seed(seed=42) + rand_perm = np.random.permutation(newY.shape[0]) + newX = newX[rand_perm, :, :, :] + newY = newY[rand_perm] + return newX, newY + +def standartizeData(X): + newX = np.reshape(X, (-1, X.shape[2])) + scaler = preprocessing.StandardScaler().fit(newX) + newX = scaler.transform(newX) + newX = np.reshape(newX, (X.shape[0],X.shape[1],X.shape[2])) + return newX, scaler + +def applyPCA(X, numComponents=75): + newX = np.reshape(X, (-1, X.shape[2])) + pca = PCA(n_components=numComponents, whiten=True) + newX = pca.fit_transform(newX) + newX = np.reshape(newX, (X.shape[0],X.shape[1], numComponents)) + return newX, pca + +def padWithZeros(X, margin=2): + newX = np.zeros((X.shape[0] + 2 * margin, X.shape[1] + 2* margin, X.shape[2])) + x_offset = margin + y_offset = margin + newX[x_offset:X.shape[0] + x_offset, y_offset:X.shape[1] + y_offset, :] = X + return newX + +def createPatches(X, y, windowSize=11, removeZeroLabels = True): + margin = int((windowSize - 1) / 2) + zeroPaddedX = padWithZeros(X, margin=margin) + # split patches + patchesData = np.zeros((X.shape[0] * X.shape[1], windowSize, windowSize, X.shape[2])) + patchesLabels = np.zeros((X.shape[0] * X.shape[1])) + patchIndex = 0 + for r in range(margin, zeroPaddedX.shape[0] - margin): + for c in range(margin, zeroPaddedX.shape[1] - margin): + patch = zeroPaddedX[r - margin:r + margin + 1, c - margin:c + margin + 1] + patchesData[patchIndex, :, :, :] = patch + patchesLabels[patchIndex] = y[r-margin, c-margin] + patchIndex = patchIndex + 1 + if removeZeroLabels: + patchesData = patchesData[patchesLabels>0,:,:,:] + patchesLabels = patchesLabels[patchesLabels>0] + patchesLabels -= 1 + return patchesData, patchesLabels + + +def AugmentData(X_train): + for i in range(int(X_train.shape[0]/2)): + patch = X_train[i,:,:,:] + num = random.randint(0,2) + if (num == 0): + + flipped_patch = np.flipud(patch) + if (num == 1): + + flipped_patch = np.fliplr(patch) + if (num == 2): + + no = random.randrange(-180,180,30) + flipped_patch = scipy.ndimage.interpolation.rotate(patch, no,axes=(1, 0), + reshape=False, output=None, order=3, mode='constant', cval=0.0, prefilter=False) + + + patch2 = flipped_patch + X_train[i,:,:,:] = patch2 + + return X_train + +import numpy as np +import scipy +import os +from keras.models import Sequential +from keras.layers import Dense, Dropout, Flatten +from keras.layers import Conv2D, MaxPooling2D,BatchNormalization +from tensorflow.keras.callbacks import EarlyStopping +from tensorflow.keras.optimizers import SGD +from keras import backend as K +from keras.utils import np_utils +from keras.utils.vis_utils import plot_model + +weight_of_size=10 + +X=hsi_data +y=labels + +X,pca = applyPCA(X,30) + +X.shape + +XPatches, yPatches = createPatches(X, y, windowSize=15) + +XPatches.shape + +X_train, X_test, y_train, y_test = splitTrainTestSet(XPatches, yPatches, testRatio=0.2) + +X_train=np.reshape(X_train,(X_train.shape[0],X_train.shape[3],X_train.shape[1],X_train.shape[1])) + +X_test=np.reshape(X_test,(X_test.shape[0],X_test.shape[3],X_test.shape[1],X_test.shape[1])) + +X_train.shape + +X_train.shape + +y_train + +class MyDataset(Dataset): + def __init__(self, data, target, transform=None): + self.data = torch.from_numpy(data).float() + self.target = torch.from_numpy(target).int() + self.transform = transform + + def __getitem__(self, index): + x = self.data[index] + y = self.target[index] + + if self.transform: + x = self.transform(x) + + return x, y + + def __len__(self): + return len(self.data) + +data_train = MyDataset(X_train, y_train) + +input_shape= X_train[0].shape +print(input_shape) + +data_train.__getitem__(0)[0].shape + +n_epochs = 8 +batch_size_train = 16 +batch_size_test = 10 +learning_rate = 0.01 +momentum = 0.5 +log_interval = 100 +first_HL = 8 + +import torch +import torchvision + +## Call the Dataset Class +#data_train = torchvision.datasets.IndianPines('./data',download=True,PATCH_LENGTH=2) + +## Check the shapes +print(data_train.__getitem__(0)[0].shape) +print(data_train.__len__()) + + +## Wrap it around a Torch Dataloader +train_loader = torch.utils.data.DataLoader(data_train,batch_size=16,shuffle=True, num_workers=2) + +len(data_train) + +data_test=MyDataset(X_test, y_test) + +import torch +import torchvision + +## Call the Dataset Class +#data_test = torchvision.datasets.IndianPines('./data',download=True,PATCH_LENGTH=2) + +## Check the shapes +print(data_test.__getitem__(0)[0].shape) +print(data_test.__len__()) + +test_loader = torch.utils.data.DataLoader(data_test,batch_size=10,shuffle=False, num_workers=2) + +examples = enumerate(test_loader) +batch_idx, (example_data, example_targets) = next(examples) + +print(example_data.shape) + +import matplotlib.pyplot as plt + +fig = plt.figure() +for i in range(6): + plt.subplot(2,3,i+1) + plt.tight_layout() + plt.imshow(example_data[i][0], interpolation='none') + plt.title("Ground Truth: {}".format(example_targets[i])) + plt.xticks([]) + plt.yticks([]) +fig + +import torch +import torch.nn as nn +import torchvision +import torchvision.transforms as transforms + +import random + +device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + +# Hyper-parameters +num_epochs = 16 +learning_rate = 0.001 + +torch.manual_seed(0) +random.seed(0) + +Half_width =60 +layer_width = 20 + +class SpinalCNN(nn.Module): + """CNN.""" + + def __init__(self): + """CNN Builder.""" + super(SpinalCNN, self).__init__() + + self.conv_layer = nn.Sequential( + + # Conv Layer block 1 + nn.Conv2d(in_channels=30, out_channels=15, kernel_size=3, padding=1), + nn.BatchNorm2d(15), + nn.ReLU(inplace=True), + nn.Conv2d(in_channels=15, out_channels=30, kernel_size=3, padding=1), + nn.ReLU(inplace=True), + nn.MaxPool2d(kernel_size=2, stride=2), + + # Conv Layer block 2 + nn.Conv2d(in_channels=30, out_channels=60, kernel_size=3, padding=1), + nn.BatchNorm2d(60), + nn.ReLU(inplace=True), + nn.Conv2d(in_channels=60, out_channels=60, kernel_size=3, padding=1), + nn.ReLU(inplace=True), + nn.MaxPool2d(kernel_size=2, stride=2), + nn.Dropout2d(p=0.05), + + # Conv Layer block 3 + nn.Conv2d(in_channels=60, out_channels=120, kernel_size=3, padding=1), + nn.BatchNorm2d(120), + nn.ReLU(inplace=True), + nn.Conv2d(in_channels=120, out_channels=120, kernel_size=3, padding=1), + nn.ReLU(inplace=True), + nn.MaxPool2d(kernel_size=2, stride=2), + ) + + self.fc_spinal_layer1 = nn.Sequential( + nn.Dropout(p=0.1), nn.Linear(Half_width, layer_width), + nn.ReLU(inplace=True), + ) + self.fc_spinal_layer2 = nn.Sequential( + nn.Dropout(p=0.1), nn.Linear(Half_width + layer_width, layer_width), + nn.ReLU(inplace=True), + ) + self.fc_spinal_layer3 = nn.Sequential( + nn.Dropout(p=0.1), nn.Linear(Half_width + layer_width, layer_width), + nn.ReLU(inplace=True), + ) + self.fc_spinal_layer4 = nn.Sequential( + nn.Dropout(p=0.1), nn.Linear(Half_width + layer_width, layer_width), + nn.ReLU(inplace=True), + ) + self.fc_out = nn.Sequential( + nn.Dropout(p=0.1), nn.Linear(layer_width*4, 16) + ) + + + def forward(self, x): + """Perform forward.""" + + # conv layers + x = self.conv_layer(x) + + # flatten + x = x.view(x.size(0), -1) + + x1 = self.fc_spinal_layer1(x[:, 0:Half_width]) + x2 = self.fc_spinal_layer2(torch.cat([ x[:,Half_width:2*Half_width], x1], dim=1)) + x3 = self.fc_spinal_layer3(torch.cat([ x[:,0:Half_width], x2], dim=1)) + x4 = self.fc_spinal_layer4(torch.cat([ x[:,Half_width:2*Half_width], x3], dim=1)) + + x = torch.cat([x1, x2], dim=1) + x = torch.cat([x, x3], dim=1) + x = torch.cat([x, x4], dim=1) + + x = self.fc_out(x) + + return x + +from tensorflow.keras.optimizers import Adam +model = SpinalCNN().to(device) +# defining the optimizer +optimizer = Adam(model.parameters(), lr=0.07) +# defining the loss function +criterion = nn.CrossEntropyLoss() +# checking if GPU is available +if torch.cuda.is_available(): + model = model.cuda() + criterion = criterion.cuda() + +print(model) + +from torchvision import models +from torchsummary import summary +model = SpinalCNN().to(device) +summary(model, (30, 15, 15)) + +model = SpinalCNN().to(device) + + + +# Loss and optimizer +criterion = nn.CrossEntropyLoss() +optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) + +# For updating learning rate +def update_lr(optimizer, lr): + for param_group in optimizer.param_groups: + param_group['lr'] = lr + +# Train the model +total_step = len(train_loader) +curr_lr = learning_rate +for epoch in range(num_epochs): + for i, (images, labels) in enumerate(train_loader): + images = images.to(device) + labels = labels.to(device) + + #print(images.shape) + # Forward pass + outputs = model(images) + labels = torch.tensor(labels, dtype=torch.long, device=device) + loss = criterion(outputs, labels) + + # Backward and optimize + optimizer.zero_grad() + loss.backward() + optimizer.step() + + + if (i+1) % 500 == 0: + print("Epoch [{}/{}], Step [{}/{}] Loss: {:.4f}" + .format(epoch+1, num_epochs, i+1, total_step, loss.item())) + + + # Decay learning rate + if (epoch) == 1 or epoch>20: + curr_lr /= 3 + update_lr(optimizer, curr_lr) + + # Test the model + model.eval() + with torch.no_grad(): + correct = 0 + total = 0 + predicted_numpy=[] + for images, labels in test_loader: + + images = images.to(device) + labels = labels.to(device) + outputs = model(images) + _, predicted = torch.max(outputs.data, 1) + predicted_numpy.append(predicted.cpu().numpy()) + + total += labels.size(0) + correct += (predicted == labels).sum().item() + + print('Accuracy of the model on the test images: {} %'.format(100 * correct / total)) + + model.train() + +len(predicted_numpy) + +predicted_numpy = np.concatenate(predicted_numpy) + +predicted_numpy.shape + +from sklearn.metrics import confusion_matrix +from sklearn.metrics import plot_confusion_matrix +y_true = y_test +y_pred = predicted_numpy +print(confusion_matrix(y_true, y_pred), end='\n') + +from sklearn.metrics import confusion_matrix +from sklearn.metrics import plot_confusion_matrix +import seaborn as sn +y_true = y_test +y_pred = predicted_numpy +plt.figure(figsize = (10,7)) +print(sn.heatmap(confusion_matrix(y_true, y_pred),annot=True,cmap="OrRd",fmt='d')) +plt.savefig('KSC_pca_Confusion Matrix') + +from sklearn.metrics import cohen_kappa_score +print(cohen_kappa_score(y_true, y_pred, labels=None, weights=None, sample_weight=None)) + +from sklearn.metrics import classification_report + +from sklearn.metrics import confusion_matrix +from sklearn.metrics import plot_confusion_matrix +y_true = y_test +y_pred = predicted_numpy +target_names = ['class 0', 'class 1', 'class 2', 'class 3', 'class 4', 'class 5', 'class 6', 'class 7', 'class 8', 'class 9', 'class 10', 'class 11', 'class 12'] +print(classification_report(y_true, y_pred, target_names=target_names, digits=4)) + +f = sio.loadmat('KSC.mat')['KSC'] +g = sio.loadmat('KSC_gt.mat')['KSC_gt'] + +F,pca = applyPCA(f,30) + +FPatches, gPatches = createPatches(F,g, windowSize=15) + +import itertools + +def classified_pixels(FPatches,gPatches,g): + FPatches=np.reshape(FPatches,(FPatches.shape[0],FPatches.shape[3],FPatches.shape[1],FPatches.shape[2])) + data_test=MyDataset(FPatches, gPatches) + test_loader = torch.utils.data.DataLoader(data_test,batch_size=10,shuffle=False, num_workers=2) + with torch.no_grad(): + correct = 0 + total = 0 + predicted_numpy=[] + for images, labels in test_loader: + images = images.to(device) + labels = labels.to(device) + outputs = model(images) + _, predicted = torch.max(outputs.data, 1) + predicted_numpy.append(predicted.cpu().numpy()) + total += labels.size(0) + correct += (predicted == labels).sum().item() + classification_map=np.array(predicted_numpy) + cm=[] + for arr in classification_map: + cm.append(arr.tolist()) + cm=list(itertools.chain.from_iterable(cm)) + classification_map=np.array(cm) + + height=g.shape[0] + width=g.shape[1] + outputs = np.zeros((height,width)) + k=0 + for i in range(height): + for j in range(width): + target = g[i][j] + if target == 0 : + continue + else : + outputs[i][j]=classification_map[k] + k=k+1 + return classification_map,outputs + +cma,out=classified_pixels(FPatches,gPatches,g) + +plt.figure(figsize=(7,7)) +a=plt.imshow(out) +plt.savefig('KSC_pca_cmap') + +plt.figure(figsize=(7,7)) +plt.imshow(g) +plt.savefig('KSC_pca_gt') \ No newline at end of file diff --git a/Hyperspectral Image Classification/HSI_Confusion Matrix.png b/Hyperspectral Image Classification/HSI_Confusion Matrix.png new file mode 100644 index 0000000000000000000000000000000000000000..9137ce4569a85e23ed1f2cb69216f6a5ce65ece7 GIT binary patch literal 21746 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 Qer*U$TwbjBtzp3b1zcQ&o&W#< literal 0 HcmV?d00001