satellite_image_classification.py
# -*- coding: utf-8 -*-"""Satellite-Image-Classification-with-TensorFlow_PythonCode.ipynbAutomatically generated by Colaboratory.Original file is located at https://colab.research.google.com/drive/1SVpaW9HSebpHNYf6LXTm7elnHOSdQA5i"""!pip install tensorflow tensorflow_addons tensorflow_datasets tensorflow_hub numpy matplotlib seabornimport osimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsimport tensorflow as tfimport tensorflow_datasets as tfdsimport tensorflow_hub as hubimport tensorflow_addons as tfa# load the whole dataset, for data infoall_ds = tfds.load("eurosat", with_info=True)# load training, testing & validation sets, splitting by 60%, 20% and 20% respectivelytrain_ds = tfds.load("eurosat", split="train[:60%]")test_ds = tfds.load("eurosat", split="train[60%:80%]")valid_ds = tfds.load("eurosat", split="train[80%:]")# the class namesclass_names = all_ds[1].features["label"].names# total number of classes (10)num_classes = len(class_names)num_examples = all_ds[1].splits["train"].num_examples# make a plot for number of samples on each classfig, ax = plt.subplots(1, 1, figsize=(14,10))labels, counts = np.unique(np.fromiter(all_ds[0]["train"].map(lambda x: x["label"]), np.int32), return_counts=True)plt.ylabel('Counts')plt.xlabel('Labels')sns.barplot(x = [class_names[l] for l in labels], y = counts, ax=ax) for i, x_ in enumerate(labels): ax.text(x_-0.2, counts[i]+5, counts[i])# set the titleax.set_title("Bar Plot showing Number of Samples on Each Class")# save the image# plt.savefig("class_samples.png")def prepare_for_training(ds, cache=True, batch_size=64, shuffle_buffer_size=1000): if cache: if isinstance(cache, str): ds = ds.cache(cache) else: ds = ds.cache() ds = ds.map(lambda d: (d["image"], tf.one_hot(d["label"], num_classes))) # shuffle the dataset ds = ds.shuffle(buffer_size=shuffle_buffer_size) # Repeat forever ds = ds.repeat() # split to batches ds = ds.batch(batch_size) # `prefetch` lets the dataset fetch batches in the background while the model # is training. ds = ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE) return dsbatch_size = 64# preprocess training & validation setstrain_ds = prepare_for_training(train_ds, batch_size=batch_size)valid_ds = prepare_for_training(valid_ds, batch_size=batch_size)# validating shapesfor el in valid_ds.take(1): print(el[0].shape, el[1].shape)for el in train_ds.take(1): print(el[0].shape, el[1].shape)# take the first batch of the training setbatch = next(iter(train_ds))def show_batch(batch): plt.figure(figsize=(16, 16)) for n in range(min(32, batch_size)): ax = plt.subplot(batch_size//8, 8, n + 1) # show the image plt.imshow(batch[0][n]) # and put the corresponding label as title upper to the image plt.title(class_names[tf.argmax(batch[1][n].numpy())]) plt.axis('off') plt.savefig("sample-images.png")# showing a batch of images along with labelsshow_batch(batch)model_url = "https://tfhub.dev/google/imagenet/efficientnet_v2_imagenet1k_l/feature_vector/2"# download & load the layer as a feature vectorkeras_layer = hub.KerasLayer(model_url, output_shape=[1280], trainable=True)m = tf.keras.Sequential([ keras_layer, tf.keras.layers.Dense(num_classes, activation="softmax")])# build the model with input image shape as (64, 64, 3)m.build([None, 64, 64, 3])m.compile( loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy", tfa.metrics.F1Score(num_classes)])m.summary()model_name = "satellite-classification"model_path = os.path.join("results", model_name + ".h5")model_checkpoint = tf.keras.callbacks.ModelCheckpoint(model_path, save_best_only=True, verbose=1)n_training_steps = int(num_examples * 0.6) // batch_sizen_validation_steps = int(num_examples * 0.2) // batch_sizehistory = m.fit( train_ds, validation_data=valid_ds, steps_per_epoch=n_training_steps, validation_steps=n_validation_steps, verbose=1, epochs=5, callbacks=[model_checkpoint])# number of testing stepsn_testing_steps = int(all_ds[1].splits["train"].num_examples * 0.2)m.load_weights(model_path)# get all testing images as NumPy arrayimages = np.array([ d["image"] for d in test_ds.take(n_testing_steps) ])print("images.shape:", images.shape)# get all testing labels as NumPy arraylabels = np.array([ d["label"] for d in test_ds.take(n_testing_steps) ])print("labels.shape:", labels.shape)# feed the images to get predictionspredictions = m.predict(images)# perform argmax to get class indexpredictions = np.argmax(predictions, axis=1)print("predictions.shape:", predictions.shape)from sklearn.metrics import f1_scoreaccuracy = tf.keras.metrics.Accuracy()accuracy.update_state(labels, predictions)print("Accuracy:", accuracy.result().numpy())print("F1 Score:", f1_score(labels, predictions, average="macro"))# compute the confusion matrixcmn = tf.math.confusion_matrix(labels, predictions).numpy()# normalize the matrix to be in percentagescmn = cmn.astype('float') / cmn.sum(axis=0)[:, np.newaxis]# make a plot for the confusion matrixfig, ax = plt.subplots(figsize=(10,10))sns.heatmap(cmn, annot=True, fmt='.2f', xticklabels=[f"pred_{c}" for c in class_names], yticklabels=[f"true_{c}" for c in class_names], # cmap="Blues" cmap="rocket_r" )plt.ylabel('Actual')plt.xlabel('Predicted')# plot the resulting confusion matrixplt.savefig("confusion-matrix.png")# plt.show()def show_predicted_samples(): plt.figure(figsize=(14, 14)) for n in range(64): ax = plt.subplot(8, 8, n + 1) # show the image plt.imshow(images[n]) # and put the corresponding label as title upper to the image if predictions[n] == labels[n]: # correct prediction ax.set_title(class_names[predictions[n]], color="green") else: # wrong prediction ax.set_title(f"{class_names[predictions[n]]}/T:{class_names[labels[n]]}", color="red") plt.axis('off') plt.savefig("predicted-sample-images.png")# showing a batch of images along with predictions labelsshow_predicted_samples()