是否可以在用于更传统数据集 (CIFAR-10/MNIST) 的 CNN 模型中使用高光谱 1x1 像素集合?

Luk*_*dge 7 machine-learning deep-learning conv-neural-network keras tensorflow

我在 Keras/Tensorflow 中创建了一个可用的 CNN 模型,并成功使用 CIFAR-10 和 MNIST 数据集来测试该模型。功能代码如下所示:

import keras
from keras.datasets import cifar10
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout, Conv2D, Flatten, MaxPooling2D
from keras.layers.normalization import BatchNormalization

(X_train, y_train), (X_test, y_test) = cifar10.load_data()

#reshape data to fit model
X_train = X_train.reshape(50000,32,32,3)
X_test = X_test.reshape(10000,32,32,3)

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)


# Building the model 

#1st Convolutional Layer
model.add(Conv2D(filters=64, input_shape=(32,32,3), kernel_size=(11,11), strides=(4,4), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'))

#2nd Convolutional Layer
model.add(Conv2D(filters=224, kernel_size=(5, 5), strides=(1,1), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'))

#3rd Convolutional Layer
model.add(Conv2D(filters=288, kernel_size=(3,3), strides=(1,1), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))

#4th Convolutional Layer
model.add(Conv2D(filters=288, kernel_size=(3,3), strides=(1,1), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))

#5th Convolutional Layer
model.add(Conv2D(filters=160, kernel_size=(3,3), strides=(1,1), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'))

model.add(Flatten())

# 1st Fully Connected Layer
model.add(Dense(4096, input_shape=(32,32,3,)))
model.add(BatchNormalization())
model.add(Activation('relu'))
# Add Dropout to prevent overfitting
model.add(Dropout(0.4))

#2nd Fully Connected Layer
model.add(Dense(4096))
model.add(BatchNormalization())
model.add(Activation('relu'))
#Add Dropout
model.add(Dropout(0.4))

#3rd Fully Connected Layer
model.add(Dense(1000))
model.add(BatchNormalization())
model.add(Activation('relu'))
#Add Dropout
model.add(Dropout(0.4))

#Output Layer
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('softmax'))


#compile model using accuracy to measure model performance
opt = keras.optimizers.Adam(learning_rate = 0.0001)
model.compile(optimizer=opt, loss='categorical_crossentropy', 
              metrics=['accuracy'])


#train the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=30)
Run Code Online (Sandbox Code Playgroud)

从这一点来看,在利用上述数据集之后,我想更进一步,使用比灰度或 RGB 提供的通道更多的数据集,因此包含高光谱数据集。在寻找高光谱数据集时,我遇到了这个

此阶段的问题是认识到该高光谱数据集是一张图像,地面实况中的每个值都与每个像素相关。在这个阶段,我将数据重新格式化为高光谱数据/像素的集合。

代码重新格式化 x_train 和 x_test 的更正数据集:

import keras
import scipy
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import to_categorical
from scipy import io

mydict = scipy.io.loadmat('Indian_pines_corrected.mat')
dataset = np.array(mydict.get('indian_pines_corrected'))


#This is creating the split between x_train and x_test from the original dataset 
# x_train after this code runs will have a shape of (121, 145, 200) 
# x_test after this code runs will have a shape of (24, 145, 200)
x_train = np.zeros((121,145,200), dtype=np.int)
x_test = np.zeros((24,145,200), dtype=np.int)    

xtemp = np.array_split(dataset, [121])
x_train = np.array(xtemp[0])
x_test = np.array(xtemp[1])

# x_train will have a shape of (17545, 200) 
# x_test will have a shape of (3480, 200)
x_train = x_train.reshape(-1, x_train.shape[-1])
x_test = x_test.reshape(-1, x_test.shape[-1])
Run Code Online (Sandbox Code Playgroud)

为 Y_train 和 Y_test 重新格式化地面实况数据集的代码:

truthDataset = scipy.io.loadmat('Indian_pines_gt.mat')
gTruth = truthDataset.get('indian_pines_gt')

#This is creating the split between Y_train and Y_test from the original dataset 
# Y_train after this code runs will have a shape of (121, 145) 
# Y_test after this code runs will have a shape of (24, 145)

Y_train = np.zeros((121,145), dtype=np.int)
Y_test = np.zeros((24,145), dtype=np.int)    

ytemp = np.array_split(gTruth, [121])
Y_train = np.array(ytemp[0])
Y_test = np.array(ytemp[1])

# Y_train will have a shape of (17545) 
# Y_test will have a shape of (3480)
Y_train = Y_train.reshape(-1)
Y_test = Y_test.reshape(-1)


#17 binary categories ranging from 0-16

#Y_train one-hot encode target column
Y_train = to_categorical(Y_train)

#Y_test one-hot encode target column
Y_test = to_categorical(Y_test, num_classes = 17)
Run Code Online (Sandbox Code Playgroud)

我的思考过程是,尽管初始图像被分解为 1x1 的块,但每个块拥有的大量通道及其各自的值将有助于数据集的分类。

本质上,我想将这些重新格式化的数据输入到我的模型中(在本文的第一个代码片段中看到),但是由于我在这一专业领域缺乏经验,我不确定我是否采取了错误的方法。我期望输入形状为 (1,1,200),即 x_train 和 x_test 的形状分别为 (17545,1,1,200) 和 (3480,1,1,200)。

Les*_*rel 2

首先,假设您使用的高光谱图像是针对语义分割问题而不是分类问题。


如果我们看看什么是神经网络中的卷积层,它不太可能工作得很好。它可能有效,但可能有更好的方法。

让我们看一下这个 2D 卷积动画(由 Michael Plotke 获得CC-BY-SA 3.0许可):2D 卷积动画

我们可以看到,2D 卷积运算的核心就像是对图像的某个区域应用一定大小的滤波器,然后对图像的所有区域重复此操作。当尝试学习/查找空间特征(即相邻像素之间的关系)时,2D 卷积通常在神经网络中使用。

摘自CS231n - 卷积网络

当我们在输入体积的宽度和高度上滑动过滤器时,我们将生成一个二维激活图,该图给出该过滤器在每个空间位置的响应。直观地说,网络将学习当看到某种类型的视觉特征时激活的过滤器,例如第一层上某种方向的边缘或某种颜色的斑点,或者最终网络较高层上的整个蜂窝或轮状图案。

通过使用大小为 1x1 的小块,您实际上剥离了数据的空间维度。在这种情况下应用 2D 卷积没有太大意义。(特别是考虑到该架构中使用的过滤器的大小,例如第一层中的 11x11)。


建议的方法:

  • 寻找一个更大的数据集,其中包含多个专为分类而设计的图像:这可能是正确的方法。在数据驱动的问题中,最重要的部分是数据。
  • 如果对该图像的区域进行分类对您来说很重要,您可以对光谱数据像素使用更简单的网络架构和/或机器学习技术。这可能有效,但您仍然会丢失相邻像素之间的空间关系。