train and test a basic MLP¶
The code block directly below will train an MLP (or dense) autoencoder on the Pavia Uni hyperspectral dataset. Make sure you have a folder in your directory called ‘models’. Once trained, look at the next code block to test out the trained autoencoder. If you have already downloaded the Pavia Uni dataset (e.g. from another example) you can comment out that step.
The network has three encoder and three decoder layers, with 50 neurons in the first layer, 30 in the second and 10 in the third (the latent layer). A model is trained with 200,000 spectral samples and 100 validation samples with a batch size of 1000 samples. Training lasts for 100 epochs, with a learning rate of 0.001, the Adam optimiser and cosine spectral angle (CSA) reconstruction loss function. The train loss and validation loss are displayed every 10 epochs. Models are saved at 50 and 100 epochs. The models are saved in the models/test_ae_mlp folder.
import deephyp.data
import deephyp.autoencoder
import scipy.io
import os
import shutil
try:
from urllib import urlretrieve # python2
except:
from urllib.request import urlretrieve # python3
# download dataset (if already downloaded, comment this out)
urlretrieve( 'http://www.ehu.eus/ccwintco/uploads/e/ee/PaviaU.mat', os.path.join(os.getcwd(),'PaviaU.mat') )
# read data into numpy array
mat = scipy.io.loadmat( 'PaviaU.mat' )
img = mat[ 'paviaU' ]
# create a hyperspectral dataset object from the numpy array
hypData = deephyp.data.HypImg( img )
# pre-process data to make the model easier to train
hypData.pre_process( 'minmax' )
# create data iterator objects for training and validation using the pre-processed data
trainSamples = 200000
valSamples = 100
dataTrain = deephyp.data.Iterator( dataSamples=hypData.spectraPrep[:trainSamples, :],
targets=hypData.spectraPrep[:trainSamples, :], batchSize=1000 )
dataVal = deephyp.data.Iterator( dataSamples=hypData.spectraPrep[trainSamples:trainSamples+valSamples, :],
targets=hypData.spectraPrep[trainSamples:trainSamples+valSamples, :] )
# shuffle training data
dataTrain.shuffle()
# setup a fully-connected autoencoder neural network with 3 encoder layers
net = deephyp.autoencoder.mlp_1D_network( inputSize=hypData.numBands, encoderSize=[50,30,10], activationFunc='relu',
weightInitOpt='truncated_normal', tiedWeights=None, skipConnect=False )
# setup a training operation for the network
net.add_train_op( name='csa', lossFunc='CSA', learning_rate=1e-3, decay_steps=None, decay_rate=None,
method='Adam', wd_lambda=0.0 )
# create a directory to save the learnt model
model_dir = os.path.join('models','test_ae_mlp')
if os.path.exists(model_dir):
# if directory already exists, delete it
shutil.rmtree(model_dir)
os.mkdir(model_dir)
# train the network for 100 epochs, saving the model at epoch 50 and 100
net.train(dataTrain=dataTrain, dataVal=dataVal, train_op_name='csa', n_epochs=100, save_addr=model_dir,
visualiseRateTrain=10, visualiseRateVal=10, save_epochs=[50,100])
The code below will test a trained MLP (or dense) autoencoder on the Pavia Uni hyperspectral dataset. Make sure you have a folder in your directory called ‘results’. The network can be trained using the above code block. Run the testing code block as a separate script to the training code block.
The network is setup using the config file output during training. Then the 100 epoch model is added (named ‘csa_100’). The model is used to encode a latent representation of the Pavia Uni data, and reconstruct it from the latent representation. A figure of the latent vector for a ‘meadow’ spectral sample and the reconstruction is saved in the results folder.
import deephyp.data
import deephyp.autoencoder
import scipy.io
import matplotlib.pyplot as plt
import os
import numpy as np
# read data into numpy array
mat = scipy.io.loadmat( 'PaviaU.mat' )
img = mat[ 'paviaU' ]
# create a hyperspectral dataset object from the numpy array
hypData = deephyp.data.HypImg( img )
# pre-process data to make the model easier to train
hypData.pre_process( 'minmax' )
# setup a network from a config file
net = deephyp.autoencoder.mlp_1D_network( configFile=os.path.join('models','test_ae_mlp','config.json') )
# assign previously trained parameters to the network, and name model
net.add_model( addr=os.path.join('models','test_ae_mlp','epoch_100'), modelName='csa_100' )
# feed forward hyperspectral dataset through encoder (get latent encoding)
dataZ = net.encoder( modelName='csa_100', dataSamples=hypData.spectraPrep )
# feed forward latent encoding through decoder (get reconstruction)
dataY = net.decoder(modelName='csa_100', dataZ=dataZ)
#--------- visualisation ----------------------------------------
# reshape latent encoding to original image dimensions
imgZ = np.reshape(dataZ, (hypData.numRows, hypData.numCols, -1))
# reshape reconstructed output of decoder
imgY = np.reshape(dataY, (hypData.numRows, hypData.numCols, -1))
# reshape pre-processed input
imgX = np.reshape(hypData.spectraPrep, (hypData.numRows, hypData.numCols, -1))
# visualise latent image using 3 out of the 10 dimensions
colourImg = imgZ.copy()
colourImg = colourImg[ :,:,np.argsort(-np.std(np.std(colourImg, axis=0), axis=0))[:3] ]
colourImg /= np.max(np.max(colourImg, axis=0), axis=0)
# save a latent image (using 3 out of the 10 dimensions)
plt.imsave(os.path.join('results', 'test_mlp_latentImg.png'), colourImg)
# save plot of latent vector of 'meadow' spectra
fig = plt.figure()
plt.plot(imgZ[576, 210, :])
plt.xlabel('latent dimension')
plt.ylabel('latent value')
plt.title('meadow spectra')
plt.savefig(os.path.join('results', 'test_mlp_latentVector.png'))
# save plot comparing pre-processed 'meadow' spectra input with decoder reconstruction
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(range(hypData.numBands),imgX[576, 210, :],label='pre-processed input')
ax.plot(range(hypData.numBands),imgY[576, 210, :],label='reconstruction')
plt.xlabel('band')
plt.ylabel('value')
plt.title('meadow spectra')
ax.legend()
plt.savefig(os.path.join('results', 'test_mlp_InputVsReconstruct.png'))