Matheus Schmitz
LinkedIn
Github Portfolio
Artificial Intelligence for Satellite Image Classification
Every minute, the world loses an area of forest the size of 48 football fields. And deforestation in the Amazon Basin accounts for the largest share, contributing to reduced biodiversity, habitat loss, climate change and other devastating effects. However, better data on the location of deforestation and human encroachment on forests can help governments and stakeholders respond more quickly and effectively.
Planet, the designer and builder of the Earth's largest constellation of imaging satellites, will soon be collecting daily images of the entire Earth's surface at a resolution of 3-5 meters. Although considerable research has been devoted to tracking changes in forests, it typically relies on Landsat (30 meters) or MODIS (250 meters) resolution images. This limits its effectiveness in areas where small-scale deforestation or forest degradation predominates.
Furthermore, these existing methods generally cannot differentiate forest degradation between human causes and natural causes. Higher resolution images are exceptionally good at this, but robust methods have not yet been developed for Planet imaging.
In this work, the goal is to classify satellite images with different atmospheric conditions and land cover/land use classes.
Datasets with satellite images are available for free on Kaggle:
https://www.kaggle.com/c/planet-understanding-the-amazon-from-space/data
Images are provided in two formats: .tif and .jpg
The .tif files offer better resolution quality, but the final dataset is almost 40 GB. Therefore, for the purpose of this project (which is to study CNNs) we will use images in .jpg format totaling just over 1 GB.
Although images can be extracted from the link above, we've already made it for you and organized it on Titan (DSA server). More details when we upload the images.
Below is a description of the format of the images.
The images have been split into chips, like this one below.
The chips were derived from full-frame analysis performed by Planet, using the 4-band satellites in synchronous orbit to the sun (SSO) and the International Space Station (ISS). The chipset uses the GeoTiff format and each one contains four bands of data: red, green, blue and infrared. The satellites' specific spectral response can be found in Planet's documentation. Each of these channels is in 16-bit digital number format and meets Planet four-band orthoanalytic scene product specifications.
The chips are also available in JPG format, which we will use here in the project.
Dataset Creation
In order to assemble this dataset, an initial specification of the phenomena to be found and included in the final dataset was established. From this initial specification, a "wish list" of scenes was created in which an approximate number of scenes needed to obtain a sufficient number of chips to demonstrate the phenomenon were included.
This initial set of scenes was painstakingly collected by the Planet Berlin team using Planet Explorer. In total, this initial set of scenes was approximately 1600 and covered an area of thirty million hectares.
This initial set of scenes was processed using a custom processor to create the 4-band jpg and tiff chips. Any chip that did not have a full four-band product was omitted. This initial set of over 150,000 chips was divided into two sets, a "hard" and an "easy".
The easy set contained scenes that the Berlin team identified as having easier-to-identify labels, such as primary forest, agriculture, housing, roads, water and cloud conditions. The most difficult set of data was derived from scenes in which the Berlin team had selected for cultivation, slash and burn cropland, deforestation, mining and other phenomena.
The chips were labeled using the Crowd Flower platform and a mix of collective labor and teams from Berlin and San Francisco. While the utmost care has been taken to obtain a large, well-labeled dataset, not all of the labels in our dataset are correct. Governments around the world have a large number of highly trained analysts to review images and cannot always agree on what is present in a given satellite image.
Also, the commonly prescribed approach to tagging data in the GIS community is to use real data to tag scenes, which is expensive and time-consuming. With that in mind, the data has a reasonably high signal to noise ratio and is sufficient for training. Given the ease and convenience of labeling multiple files, a large, relatively inexpensive, and quickly labeled dataset is believed to be better than a small, more definitive, but less diverse dataset.
The company SCCON also participated in the project.
Class Tags
The class labels for this task were chosen in collaboration with the Planet team and represent a reasonable subset of phenomena of interest in the Amazon basin. The labels can be divided into three groups: atmospheric conditions, common land cover/land use phenomena and rare land cover/land use phenomena.
Each chip (patch) will have one and potentially more than one atmospheric label and zero or more common and rare labels.
Chips labeled as cloudy must not have other labels, but there may be labeling errors.
!nvidia-smi
Sun May 3 22:00:11 2020 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 440.64.00 Driver Version: 440.64.00 CUDA Version: 10.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 TITAN X (Pascal) On | 00000000:05:00.0 Off | N/A | | 23% 38C P8 9W / 250W | 114MiB / 12194MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 1 GeForce GTX 108... On | 00000000:09:00.0 Off | N/A | | 23% 34C P8 9W / 250W | 2MiB / 11178MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 2 TITAN RTX On | 00000000:0B:00.0 Off | N/A | | 40% 39C P0 84W / 280W | 1MiB / 24220MiB | 31% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | 0 1596 G /usr/lib/xorg/Xorg 39MiB | | 0 1633 G /usr/bin/gnome-shell 72MiB | +-----------------------------------------------------------------------------+
# Imports para manipulação e visualização de dados
import os
import sys
import cv2
import csv
import math
import time
import pickle
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from os import listdir
from tqdm import tqdm
from PIL import Image
from mpl_toolkits.axes_grid1 import ImageGrid
# Deep Learning
import tensorflow as tf
import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.backend import clear_session
from keras import backend as K
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPool2D
from keras.optimizers import Adam
from keras.callbacks import ModelCheckpoint, Callback, ReduceLROnPlateau
# Evaluate metrics
import sklearn
from sklearn.utils import shuffle
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
# Disable warnings
import sys
import warnings
import matplotlib.cbook
if not sys.warnoptions:
warnings.simplefilter("ignore")
warnings.simplefilter(action='ignore', category=FutureWarning)
warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=matplotlib.cbook.mplDeprecation)
%matplotlib inline
Using TensorFlow backend.
# Package versions
# Using Python 3.7.6
%reload_ext watermark
%watermark --iversions
pandas 1.0.3 PIL.Image 7.0.0 cv2.cv2 4.2.0 seaborn 0.10.0 sklearn 0.22.2 keras 2.3.1 matplotlib 3.2.1 csv 1.0 numpy 1.18.2 tensorflow 2.1.0 Data Science Academy
# Lista todos os dispositivos disponiveis
from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
[name: "/device:CPU:0" device_type: "CPU" memory_limit: 268435456 locality { } incarnation: 8763216327050890134 , name: "/device:XLA_CPU:0" device_type: "XLA_CPU" memory_limit: 17179869184 locality { } incarnation: 1473671902246478259 physical_device_desc: "device: XLA_CPU device" , name: "/device:XLA_GPU:0" device_type: "XLA_GPU" memory_limit: 17179869184 locality { } incarnation: 16491048179918758946 physical_device_desc: "device: XLA_GPU device" , name: "/device:XLA_GPU:1" device_type: "XLA_GPU" memory_limit: 17179869184 locality { } incarnation: 4122107778021623223 physical_device_desc: "device: XLA_GPU device" , name: "/device:XLA_GPU:2" device_type: "XLA_GPU" memory_limit: 17179869184 locality { } incarnation: 28995238231739062 physical_device_desc: "device: XLA_GPU device" , name: "/device:GPU:0" device_type: "GPU" memory_limit: 23824914842 locality { bus_id: 1 links { } } incarnation: 15714529720384447878 physical_device_desc: "device: 0, name: TITAN RTX, pci bus id: 0000:0b:00.0, compute capability: 7.5" , name: "/device:GPU:1" device_type: "GPU" memory_limit: 11810943796 locality { bus_id: 1 links { link { device_id: 2 type: "StreamExecutor" strength: 1 } } } incarnation: 2337761275895557007 physical_device_desc: "device: 1, name: TITAN X (Pascal), pci bus id: 0000:05:00.0, compute capability: 6.1" , name: "/device:GPU:2" device_type: "GPU" memory_limit: 10910800282 locality { bus_id: 1 links { link { device_id: 1 type: "StreamExecutor" strength: 1 } } } incarnation: 12991201856458469678 physical_device_desc: "device: 2, name: GeForce GTX 1080 Ti, pci bus id: 0000:09:00.0, compute capability: 6.1" ]
import tensorflow as tf
print("Número Disponível de GPUs: ", len(tf.config.experimental.list_physical_devices('GPU')))
Número Disponível de GPUs: 3
# List the code for each GPU
tf.config.list_physical_devices('GPU')
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU'), PhysicalDevice(name='/physical_device:GPU:1', device_type='GPU'), PhysicalDevice(name='/physical_device:GPU:2', device_type='GPU')]
# Directory with images
imagens_treino = '/media/datasets/DeepLearningI/Cap08/CNN02/train-jpg'
imagens_teste = '/media/datasets/DeepLearningI/Cap08/CNN02/test-jpg'
# Directory with labels
etiquetas_treino = '/media/datasets/DeepLearningI/Cap08/CNN02/labels/train_v2.csv'
# Output directory
classificacao_etiquetas_teste = 'arquivos/resultado.csv'
# Load csvs to DataFrames
dados_treino = pd.read_csv(etiquetas_treino)
dados_teste = pd.read_csv(classificacao_etiquetas_teste)
# Inspect DataFrames
dados_treino.head()
image_name | tags | |
---|---|---|
0 | train_0 | haze primary |
1 | train_1 | agriculture clear primary water |
2 | train_2 | clear primary |
3 | train_3 | clear primary |
4 | train_4 | agriculture clear habitation primary road |
# Shape
dados_treino.shape
(40479, 2)
# Inspect DataFrames
dados_teste.head()
image_name | tags | |
---|---|---|
0 | test_0 | primary clear agriculture road water |
1 | test_1 | primary clear agriculture road water |
2 | test_2 | primary clear agriculture road water |
3 | test_3 | primary clear agriculture road water |
4 | test_4 | primary clear agriculture road water |
# Shape
dados_teste.shape
(61191, 2)
# Add the .jpg extension to image names
dados_treino['image_name'] = dados_treino['image_name'].astype(str) + '.jpg'
dados_teste['image_name'] = dados_teste['image_name'].astype(str) + '.jpg'
# Convert labels from string to list of strings
dados_teste['tags'] = dados_teste['tags'].apply(lambda x: x.split(' '))
# View DataFrame
print("\nImagens de Treino:\n")
dados_treino.head()
Imagens de Treino:
image_name | tags | |
---|---|---|
0 | train_0.jpg | haze primary |
1 | train_1.jpg | agriculture clear primary water |
2 | train_2.jpg | clear primary |
3 | train_3.jpg | clear primary |
4 | train_4.jpg | agriculture clear habitation primary road |
# View DataFrame
print("\nImagens de Teste (começo do arquivo):\n")
dados_teste.head()
Imagens de Teste (começo do arquivo):
image_name | tags | |
---|---|---|
0 | test_0.jpg | [primary, clear, agriculture, road, water] |
1 | test_1.jpg | [primary, clear, agriculture, road, water] |
2 | test_2.jpg | [primary, clear, agriculture, road, water] |
3 | test_3.jpg | [primary, clear, agriculture, road, water] |
4 | test_4.jpg | [primary, clear, agriculture, road, water] |
# View DataFrame
print("\nImagens de Teste (final do arquivo):\n")
dados_teste.tail()
Imagens de Teste (final do arquivo):
image_name | tags | |
---|---|---|
61186 | file_9995.jpg | [primary, clear, agriculture, road, water] |
61187 | file_9996.jpg | [primary, clear, agriculture, road, water] |
61188 | file_9997.jpg | [primary, clear, agriculture, road, water] |
61189 | file_9998.jpg | [primary, clear, agriculture, road, water] |
61190 | file_9999.jpg | [primary, clear, agriculture, road, water] |
# Shrink the test dataset size
dados_teste_final = dados_teste.iloc[:40479,]
# Store the remaining test files apart
dados_teste_restante = dados_teste.iloc[40479:,]
# Shape
dados_teste_final.shape
(40479, 2)
# Shape
dados_teste_restante.shape
(20712, 2)
# Delete the original dataset to reduce RAM usage
del dados_teste
# Train-test split and convert to np.array
X_imagens_treino = np.array(dados_treino['image_name'].tolist())
X_imagens_treino.reshape((X_imagens_treino.shape[0], 1))
y_labels_treino = np.array(dados_treino['tags'].tolist())
# X
X_imagens_treino
array(['train_0.jpg', 'train_1.jpg', 'train_2.jpg', ..., 'train_40476.jpg', 'train_40477.jpg', 'train_40478.jpg'], dtype='<U15')
# Shape
X_imagens_treino.shape
(40479,)
# y
y_labels_treino
array(['haze primary', 'agriculture clear primary water', 'clear primary', ..., 'agriculture clear primary', 'agriculture clear primary road', 'agriculture cultivation partly_cloudy primary'], dtype='<U92')
# Shape
y_labels_treino.shape
(40479,)
# There are 17 labels and each image has multiple labels
# Labels list
labels = []
# Loop through the labels and get all unique labels
for tag in dados_treino['tags'].values:
labels_in_tag = tag.split(' ')
for label in labels_in_tag:
if label not in labels:
labels.append(label)
# Sort the labels
labels.sort()
# Print
print('\nClasses Únicas:', len(labels))
print('\nNomes das Classes:', labels)
Classes Únicas: 17 Nomes das Classes: ['agriculture', 'artisinal_mine', 'bare_ground', 'blooming', 'blow_down', 'clear', 'cloudy', 'conventional_mine', 'cultivation', 'habitation', 'haze', 'partly_cloudy', 'primary', 'road', 'selective_logging', 'slash_burn', 'water']
# Loop through the images to check the quality of each resolution
# Figure size
plt.figure(figsize = (20, 20))
# List of resolutions
res = [32, 64, 128, 256]
# Number of images
num_imagens = 5
# All images have the same size. Resizing with OpenCV to evaluate resolutions.
for i in range(len(res)):
for j in range(num_imagens):
img = cv2.imread(os.path.join(imagens_treino, dados_treino['image_name'][j + 1]))
img = cv2.resize(img, (res[i], res[i]))
plt.subplot(len(res), num_imagens, i * num_imagens + j + 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title(dados_treino['tags'][j + 1] + "\n" + str(res[i]) + "x" + str(res[i]))
plt.axis('off')
plt.show()
The 128x128 images have good resolution and faster processing than the 256x256 images.
# Loop through train labels
# Dict to count label instances
labels_count = {}
# Loop
for tag in dados_treino['tags'].values:
labels_in_tag = tag.split(' ')
for label in labels_in_tag:
if label in labels_count:
labels_count[label] += 1
else:
labels_count[label] = 0
# Extract min and max
min_label = min(labels_count, key = labels_count.get)
max_label = max(labels_count, key = labels_count.get)
# Print
print(min_label + " é a classe com menor número de imagens: " + str(labels_count[min_label]))
print(max_label + " é a classe com maior número de imagens: " + str(labels_count[max_label]))
conventional_mine é a classe com menor número de imagens: 99 primary é a classe com maior número de imagens: 37512
# Figure size
plt.figure(figsize = (18, 8))
# Plot
plt.bar(range(len(labels_count)), list(labels_count.values()), align = 'center', color = 'green')
plt.xticks(range(len(labels_count)), list(labels_count.keys()), rotation = 30)
plt.show()
# Function to extract the model's learning curve
def curva_aprendizado(modelo, key = 'accuracy', ylim = (0.8, 1.01)):
plt.figure(figsize = (15,6))
plt.plot(modelo.history[key])
plt.plot(modelo.history['val_' + key])
plt.title('Curva de Aprendizado do Modelo')
plt.ylabel(key.title())
plt.xlabel('Epoch')
plt.ylim(ylim)
plt.legend(['Treino', 'Teste'], loc = 'best')
plt.show()
The F-beta score is the weighted harmonic mean of accuracy and recall, reaching its optimal value at 1 and its worst value at 0.
The beta parameter determines the weight of recall in the combined score, with beta < 1 giving more weight to accuracy, while beta > 1 favors recall (beta -> 0 considers only accuracy, beta -> + inf only recall).
Let's create a function for the F-beta score and use it as a metric in validating our model. Scikit-learn has a function for this metric, but the idea is for you to understand what is being done and that's why we're creating ours. Here's the link to Scikit-learn:
https://scikit-learn.org/stable/modules/generated/sklearn.metrics.fbeta_score.html
# F-Beta Score function
def fbeta_score(y_true, y_pred):
beta_squared = 4
tp = K.sum(y_true * y_pred) + K.epsilon()
fp = K.sum(y_pred) - tp
fn = K.sum(y_true) - tp
precision = tp / (tp + fp)
recall = tp / (tp + fn)
result = (beta_squared + 1) * (precision * recall) / (beta_squared * precision + recall + K.epsilon())
return result
# Model hyperparameters
# Image dimensions
INPUT_SHAPE = (128, 128, 3)
# Batch Size
BATCH_SIZE = 128
# Dropout
DROPOUT_RATE = 0.1
# Number of epochs
EPOCHS = 25
# Learning rate
LR = 0.0001
# Decay rate
DECAY = 0.0001
# Number of folds for cross validation
NFOLDS = 5
# Number of each fold during training
# We start with 1 because the variable will be incremented inside the training loop
NUM_FOLD = 1
# Image classification threshold
# The sigmoid function delivers probabilities and we set the limit for one class or another
THRES = [0.2] * 17
# Directory to save models
PATH_MODELOS = 'modelos/'
# Directory to save files
PATH_ARQUIVOS = 'arquivos/'
# CNN model architecture
def cria_modelo():
model = Sequential([
# First convolutional layer, with two sequential convolutions
Conv2D(32, kernel_size = (3, 3), activation = 'relu', padding = 'same', input_shape = INPUT_SHAPE),
Conv2D(32, kernel_size = (3, 3), activation = 'relu'),
MaxPool2D(pool_size = (2, 2)),
Dropout(DROPOUT_RATE),
# Second convolutional layer, with two sequential convolutions
Conv2D(64, kernel_size = (3, 3), activation = 'relu', padding = 'same'),
Conv2D(64, kernel_size = (3, 3), activation = 'relu'),
MaxPool2D(pool_size = (2, 2)),
Dropout(DROPOUT_RATE),
# Third convolutional layer, with two sequential convolutions
Conv2D(128, kernel_size = (3, 3), activation = 'relu', padding = 'same'),
Conv2D(128, kernel_size = (3, 3), activation = 'relu'),
Conv2D(128, kernel_size = (3, 3), activation = 'relu'),
MaxPool2D(pool_size = (2, 2)),
Dropout(DROPOUT_RATE),
# Fourth convolutional layer, with two sequential convolutions
Conv2D(256, kernel_size = (3, 3), activation = 'relu', padding = 'same'),
Conv2D(256, kernel_size = (3, 3), activation = 'relu'),
Conv2D(256, kernel_size = (3, 3), activation = 'relu'),
MaxPool2D(pool_size = (2, 2)),
Dropout(DROPOUT_RATE),
Flatten(),
Dense(17, activation = 'sigmoid')
])
# Adam optimizer
optimizer = Adam(LR, decay = DECAY)
return model
# Create model
modelo = cria_modelo()
# Clears the session and prints the model summary
clear_session()
modelo.summary()
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 128, 128, 32) 896 _________________________________________________________________ conv2d_2 (Conv2D) (None, 126, 126, 32) 9248 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 63, 63, 32) 0 _________________________________________________________________ dropout_1 (Dropout) (None, 63, 63, 32) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 63, 63, 64) 18496 _________________________________________________________________ conv2d_4 (Conv2D) (None, 61, 61, 64) 36928 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 30, 30, 64) 0 _________________________________________________________________ dropout_2 (Dropout) (None, 30, 30, 64) 0 _________________________________________________________________ conv2d_5 (Conv2D) (None, 30, 30, 128) 73856 _________________________________________________________________ conv2d_6 (Conv2D) (None, 28, 28, 128) 147584 _________________________________________________________________ conv2d_7 (Conv2D) (None, 26, 26, 128) 147584 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 13, 13, 128) 0 _________________________________________________________________ dropout_3 (Dropout) (None, 13, 13, 128) 0 _________________________________________________________________ conv2d_8 (Conv2D) (None, 13, 13, 256) 295168 _________________________________________________________________ conv2d_9 (Conv2D) (None, 11, 11, 256) 590080 _________________________________________________________________ conv2d_10 (Conv2D) (None, 9, 9, 256) 590080 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 4, 4, 256) 0 _________________________________________________________________ dropout_4 (Dropout) (None, 4, 4, 256) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 4096) 0 _________________________________________________________________ dense_1 (Dense) (None, 17) 69649 ================================================================= Total params: 1,979,569 Trainable params: 1,979,569 Non-trainable params: 0 _________________________________________________________________
# Empty list for the test predictions
y_teste = []
# Number of folds
folds = KFold(n_splits = NFOLDS, shuffle = True, random_state = 1).split(X_imagens_treino, y_labels_treino)
%%time
# Training loop with cross-validation
for train_index, val_index in folds:
print("\nIniciando o Treinamento do Fold", NUM_FOLD)
# Prepare train data
X_train_files_fold = X_imagens_treino[train_index]
y_train_fold = y_labels_treino[train_index]
# Prepare validation data
X_val_files_fold = X_imagens_treino[val_index]
y_val_fold = y_labels_treino[val_index]
# Convert to DataFrame
train_df = pd.DataFrame(list(zip(X_train_files_fold, y_train_fold)), columns = ['image_name', 'tags'])
val_df = pd.DataFrame(list(zip(X_val_files_fold, y_val_fold)), columns = ['image_name', 'tags'])
# Get the labels
train_df['tags'] = train_df['tags'].apply(lambda x: x.split(' '))
val_df['tags'] = val_df['tags'].apply(lambda x: x.split(' '))
print("\nDimensões dos Dados de Treino:", len(train_df))
# Adjust train images
# Based on: https://keras.io/preprocessing/image/
train_datagen = ImageDataGenerator(rescale = 1./255,
width_shift_range = 0.2,
height_shift_range = 0.2,
horizontal_flip = True,
vertical_flip = True)
# Adjust test images
train_generator = train_datagen.flow_from_dataframe(train_df,
directory = imagens_treino,
x_col = 'image_name',
y_col = 'tags',
target_size = (INPUT_SHAPE[0], INPUT_SHAPE[1]), # 128 x 128
class_mode = 'categorical',
batch_size = BATCH_SIZE,
classes = labels,)
print("\nDimensões dos Dados de Validação:", len(val_df))
# Adjust valid images
val_datagen = ImageDataGenerator(rescale = 1./255)
# Prepare validation dataset
val_generator = val_datagen.flow_from_dataframe(val_df,
directory = imagens_treino,
x_col = 'image_name',
y_col = 'tags',
target_size = (INPUT_SHAPE[0], INPUT_SHAPE[1]), # 128 x 128
class_mode = 'categorical',
batch_size = BATCH_SIZE,
classes = labels,)
print("\nDimensões dos Dados de Teste:", len(dados_teste_final))
# Adjust test images
test_datagen = ImageDataGenerator(rescale = 1./255)
# Prepare test dataset
test_generator = test_datagen.flow_from_dataframe(dados_teste_final,
directory = imagens_teste,
x_col = 'image_name',
y_col = 'tags',
target_size = (INPUT_SHAPE[0], INPUT_SHAPE[1]), # 128 x 128
class_mode = 'categorical',
batch_size = BATCH_SIZE,
classes = labels,
shuffle = False,)
# Clear session (free GPU memory)
clear_session()
# Create model
modelo_cnn_satelite = cria_modelo()
# Learning Rate and Adam Optinmizer
adam = Adam(learning_rate = LR)
# Loss functions
func_loss = 'binary_crossentropy'
# Compile model
modelo_cnn_satelite.compile(optimizer = adam, loss = func_loss, metrics = [fbeta_score, 'accuracy'])
# Path to save the model after each fold
modelo_fold_salvo = os.path.join(PATH_MODELOS, 'pesos_fold_' + str(NUM_FOLD) + '.h5')
# Callbacks to checkpoint the model and reduce learning rate on plateau
# https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/ReduceLROnPlateau
callbacks = [ModelCheckpoint(modelo_fold_salvo,
monitor = 'fbeta_score',
save_best_only = True,
mode = 'max'),
ReduceLROnPlateau(monitor = 'loss',
factor = 0.1,
patience = 3,
mode = 'min',
min_lr = 0.000001,
verbose = 1)]
# Trein model
modelo_cnn_satelite.fit_generator(train_generator,
epochs = EPOCHS,
validation_data = val_generator,
callbacks = callbacks)
# Load model from disk
modelo_cnn_satelite.load_weights(modelo_fold_salvo)
# Predict
print("\nModelo fazendo a classificação nos dados de teste. Seja paciente e aguarde...")
previsao_teste = modelo_cnn_satelite.predict_generator(test_generator)
# Store results
y_teste.append(previsao_teste)
# Go to next cross-validation fold
print("\nTérmino do Fold ", NUM_FOLD, " da Validação Cruzada.")
NUM_FOLD += 1
print("\nTreinamento Concluído.")
Iniciando o Treinamento do Fold 1 Dimensões dos Dados de Treino: 32383 Found 32383 validated image filenames belonging to 17 classes. Dimensões dos Dados de Validação: 8096 Found 8096 validated image filenames belonging to 17 classes. Dimensões dos Dados de Teste: 40479 Found 40479 validated image filenames belonging to 17 classes. Epoch 1/25 253/253 [==============================] - 152s 602ms/step - loss: 0.2766 - fbeta_score: 0.5452 - accuracy: 0.9030 - val_loss: 0.2300 - val_fbeta_score: 0.5863 - val_accuracy: 0.9122 Epoch 2/25 253/253 [==============================] - 146s 576ms/step - loss: 0.2177 - fbeta_score: 0.6129 - accuracy: 0.9143 - val_loss: 0.1973 - val_fbeta_score: 0.6298 - val_accuracy: 0.9183 Epoch 3/25 253/253 [==============================] - 147s 581ms/step - loss: 0.2022 - fbeta_score: 0.6426 - accuracy: 0.9200 - val_loss: 0.1943 - val_fbeta_score: 0.6615 - val_accuracy: 0.9249 Epoch 4/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1890 - fbeta_score: 0.6686 - accuracy: 0.9254 - val_loss: 0.2025 - val_fbeta_score: 0.6881 - val_accuracy: 0.9277 Epoch 5/25 253/253 [==============================] - 147s 583ms/step - loss: 0.1767 - fbeta_score: 0.6930 - accuracy: 0.9307 - val_loss: 0.2211 - val_fbeta_score: 0.7129 - val_accuracy: 0.9354 Epoch 6/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1680 - fbeta_score: 0.7102 - accuracy: 0.9344 - val_loss: 0.2049 - val_fbeta_score: 0.7093 - val_accuracy: 0.9363 Epoch 7/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1618 - fbeta_score: 0.7213 - accuracy: 0.9370 - val_loss: 0.1628 - val_fbeta_score: 0.7267 - val_accuracy: 0.9390 Epoch 8/25 253/253 [==============================] - 145s 575ms/step - loss: 0.1586 - fbeta_score: 0.7272 - accuracy: 0.9382 - val_loss: 0.1622 - val_fbeta_score: 0.7401 - val_accuracy: 0.9420 Epoch 9/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1555 - fbeta_score: 0.7326 - accuracy: 0.9395 - val_loss: 0.1630 - val_fbeta_score: 0.7333 - val_accuracy: 0.9407 Epoch 10/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1523 - fbeta_score: 0.7385 - accuracy: 0.9407 - val_loss: 0.1389 - val_fbeta_score: 0.7365 - val_accuracy: 0.9417 Epoch 11/25 253/253 [==============================] - 145s 575ms/step - loss: 0.1502 - fbeta_score: 0.7413 - accuracy: 0.9411 - val_loss: 0.1641 - val_fbeta_score: 0.7595 - val_accuracy: 0.9426 Epoch 12/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1490 - fbeta_score: 0.7440 - accuracy: 0.9418 - val_loss: 0.1328 - val_fbeta_score: 0.7510 - val_accuracy: 0.9435 Epoch 13/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1467 - fbeta_score: 0.7476 - accuracy: 0.9425 - val_loss: 0.1447 - val_fbeta_score: 0.7510 - val_accuracy: 0.9428 Epoch 14/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1449 - fbeta_score: 0.7501 - accuracy: 0.9431 - val_loss: 0.1546 - val_fbeta_score: 0.7704 - val_accuracy: 0.9453 Epoch 15/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1434 - fbeta_score: 0.7535 - accuracy: 0.9439 - val_loss: 0.1645 - val_fbeta_score: 0.7705 - val_accuracy: 0.9446 Epoch 16/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1417 - fbeta_score: 0.7560 - accuracy: 0.9440 - val_loss: 0.1345 - val_fbeta_score: 0.7612 - val_accuracy: 0.9445 Epoch 17/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1404 - fbeta_score: 0.7581 - accuracy: 0.9449 - val_loss: 0.1495 - val_fbeta_score: 0.7692 - val_accuracy: 0.9458 Epoch 18/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1390 - fbeta_score: 0.7608 - accuracy: 0.9454 - val_loss: 0.1086 - val_fbeta_score: 0.7810 - val_accuracy: 0.9467 Epoch 19/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1374 - fbeta_score: 0.7635 - accuracy: 0.9460 - val_loss: 0.1208 - val_fbeta_score: 0.7765 - val_accuracy: 0.9487 Epoch 20/25 253/253 [==============================] - 145s 571ms/step - loss: 0.1374 - fbeta_score: 0.7635 - accuracy: 0.9460 - val_loss: 0.1183 - val_fbeta_score: 0.7837 - val_accuracy: 0.9485 Epoch 21/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1367 - fbeta_score: 0.7649 - accuracy: 0.9463 - val_loss: 0.1377 - val_fbeta_score: 0.7619 - val_accuracy: 0.9475 Epoch 22/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1349 - fbeta_score: 0.7680 - accuracy: 0.9471 - val_loss: 0.1591 - val_fbeta_score: 0.7751 - val_accuracy: 0.9473 Epoch 23/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1336 - fbeta_score: 0.7707 - accuracy: 0.9478 - val_loss: 0.0882 - val_fbeta_score: 0.7795 - val_accuracy: 0.9491 Epoch 24/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1334 - fbeta_score: 0.7706 - accuracy: 0.9479 - val_loss: 0.1252 - val_fbeta_score: 0.7851 - val_accuracy: 0.9484 Epoch 25/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1322 - fbeta_score: 0.7731 - accuracy: 0.9481 - val_loss: 0.1083 - val_fbeta_score: 0.7899 - val_accuracy: 0.9494 Modelo fazendo a classificação nos dados de teste. Seja paciente e aguarde... Término do Fold 1 da Validação Cruzada. Iniciando o Treinamento do Fold 2 Dimensões dos Dados de Treino: 32383 Found 32383 validated image filenames belonging to 17 classes. Dimensões dos Dados de Validação: 8096 Found 8096 validated image filenames belonging to 17 classes. Dimensões dos Dados de Teste: 40479 Found 40479 validated image filenames belonging to 17 classes. Epoch 1/25 253/253 [==============================] - 152s 601ms/step - loss: 0.2777 - fbeta_score: 0.5462 - accuracy: 0.9020 - val_loss: 0.2567 - val_fbeta_score: 0.5752 - val_accuracy: 0.9102 Epoch 2/25 253/253 [==============================] - 145s 575ms/step - loss: 0.2220 - fbeta_score: 0.6041 - accuracy: 0.9118 - val_loss: 0.2268 - val_fbeta_score: 0.6008 - val_accuracy: 0.9129 Epoch 3/25 253/253 [==============================] - 145s 575ms/step - loss: 0.2075 - fbeta_score: 0.6335 - accuracy: 0.9185 - val_loss: 0.2014 - val_fbeta_score: 0.6205 - val_accuracy: 0.9181 Epoch 4/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1965 - fbeta_score: 0.6531 - accuracy: 0.9221 - val_loss: 0.2377 - val_fbeta_score: 0.6625 - val_accuracy: 0.9262 Epoch 5/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1843 - fbeta_score: 0.6776 - accuracy: 0.9273 - val_loss: 0.1797 - val_fbeta_score: 0.6925 - val_accuracy: 0.9309 Epoch 6/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1722 - fbeta_score: 0.7011 - accuracy: 0.9325 - val_loss: 0.1445 - val_fbeta_score: 0.6981 - val_accuracy: 0.9327 Epoch 7/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1648 - fbeta_score: 0.7154 - accuracy: 0.9358 - val_loss: 0.1755 - val_fbeta_score: 0.7327 - val_accuracy: 0.9343 Epoch 8/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1594 - fbeta_score: 0.7259 - accuracy: 0.9381 - val_loss: 0.1627 - val_fbeta_score: 0.7353 - val_accuracy: 0.9399 Epoch 9/25 253/253 [==============================] - 148s 583ms/step - loss: 0.1563 - fbeta_score: 0.7318 - accuracy: 0.9393 - val_loss: 0.1186 - val_fbeta_score: 0.7451 - val_accuracy: 0.9398 Epoch 10/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1522 - fbeta_score: 0.7387 - accuracy: 0.9409 - val_loss: 0.1003 - val_fbeta_score: 0.7557 - val_accuracy: 0.9411 Epoch 11/25 253/253 [==============================] - 145s 575ms/step - loss: 0.1493 - fbeta_score: 0.7434 - accuracy: 0.9417 - val_loss: 0.1512 - val_fbeta_score: 0.7514 - val_accuracy: 0.9434 Epoch 12/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1477 - fbeta_score: 0.7467 - accuracy: 0.9421 - val_loss: 0.1477 - val_fbeta_score: 0.7567 - val_accuracy: 0.9436 Epoch 13/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1461 - fbeta_score: 0.7492 - accuracy: 0.9428 - val_loss: 0.1895 - val_fbeta_score: 0.7670 - val_accuracy: 0.9407 Epoch 14/25 253/253 [==============================] - 147s 580ms/step - loss: 0.1442 - fbeta_score: 0.7527 - accuracy: 0.9435 - val_loss: 0.1587 - val_fbeta_score: 0.7735 - val_accuracy: 0.9445 Epoch 15/25 253/253 [==============================] - 146s 575ms/step - loss: 0.1432 - fbeta_score: 0.7541 - accuracy: 0.9440 - val_loss: 0.1339 - val_fbeta_score: 0.7739 - val_accuracy: 0.9451 Epoch 16/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1418 - fbeta_score: 0.7569 - accuracy: 0.9446 - val_loss: 0.1293 - val_fbeta_score: 0.7700 - val_accuracy: 0.9462 Epoch 17/25 253/253 [==============================] - 147s 581ms/step - loss: 0.1405 - fbeta_score: 0.7587 - accuracy: 0.9450 - val_loss: 0.0942 - val_fbeta_score: 0.7727 - val_accuracy: 0.9436 Epoch 18/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1388 - fbeta_score: 0.7617 - accuracy: 0.9458 - val_loss: 0.0982 - val_fbeta_score: 0.7714 - val_accuracy: 0.9485 Epoch 19/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1367 - fbeta_score: 0.7656 - accuracy: 0.9466 - val_loss: 0.1025 - val_fbeta_score: 0.7776 - val_accuracy: 0.9474 Epoch 20/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1362 - fbeta_score: 0.7667 - accuracy: 0.9470 - val_loss: 0.1500 - val_fbeta_score: 0.7840 - val_accuracy: 0.9475 Epoch 21/25 253/253 [==============================] - 145s 572ms/step - loss: 0.1354 - fbeta_score: 0.7680 - accuracy: 0.9472 - val_loss: 0.1277 - val_fbeta_score: 0.7810 - val_accuracy: 0.9491 Epoch 22/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1344 - fbeta_score: 0.7701 - accuracy: 0.9479 - val_loss: 0.1337 - val_fbeta_score: 0.7839 - val_accuracy: 0.9504 Epoch 23/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1329 - fbeta_score: 0.7725 - accuracy: 0.9481 - val_loss: 0.1010 - val_fbeta_score: 0.7800 - val_accuracy: 0.9486 Epoch 24/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1323 - fbeta_score: 0.7738 - accuracy: 0.9486 - val_loss: 0.1064 - val_fbeta_score: 0.7843 - val_accuracy: 0.9484 Epoch 25/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1316 - fbeta_score: 0.7746 - accuracy: 0.9489 - val_loss: 0.1202 - val_fbeta_score: 0.7870 - val_accuracy: 0.9496 Modelo fazendo a classificação nos dados de teste. Seja paciente e aguarde... Término do Fold 2 da Validação Cruzada. Iniciando o Treinamento do Fold 3 Dimensões dos Dados de Treino: 32383 Found 32383 validated image filenames belonging to 17 classes. Dimensões dos Dados de Validação: 8096 Found 8096 validated image filenames belonging to 17 classes. Dimensões dos Dados de Teste: 40479 Found 40479 validated image filenames belonging to 17 classes. Epoch 1/25 253/253 [==============================] - 152s 600ms/step - loss: 0.2708 - fbeta_score: 0.5518 - accuracy: 0.9043 - val_loss: 0.2716 - val_fbeta_score: 0.5613 - val_accuracy: 0.9045 Epoch 2/25 253/253 [==============================] - 147s 580ms/step - loss: 0.2185 - fbeta_score: 0.6116 - accuracy: 0.9137 - val_loss: 0.2327 - val_fbeta_score: 0.5864 - val_accuracy: 0.9142 Epoch 3/25 253/253 [==============================] - 146s 578ms/step - loss: 0.2057 - fbeta_score: 0.6366 - accuracy: 0.9192 - val_loss: 0.2413 - val_fbeta_score: 0.6509 - val_accuracy: 0.9198 Epoch 4/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1929 - fbeta_score: 0.6615 - accuracy: 0.9242 - val_loss: 0.1781 - val_fbeta_score: 0.6756 - val_accuracy: 0.9273 Epoch 5/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1809 - fbeta_score: 0.6849 - accuracy: 0.9292 - val_loss: 0.2149 - val_fbeta_score: 0.6999 - val_accuracy: 0.9313 Epoch 6/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1724 - fbeta_score: 0.7016 - accuracy: 0.9326 - val_loss: 0.1883 - val_fbeta_score: 0.7129 - val_accuracy: 0.9333 Epoch 7/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1669 - fbeta_score: 0.7123 - accuracy: 0.9351 - val_loss: 0.1389 - val_fbeta_score: 0.7213 - val_accuracy: 0.9356 Epoch 8/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1614 - fbeta_score: 0.7221 - accuracy: 0.9371 - val_loss: 0.1585 - val_fbeta_score: 0.7201 - val_accuracy: 0.9386 Epoch 9/25 253/253 [==============================] - 145s 572ms/step - loss: 0.1587 - fbeta_score: 0.7269 - accuracy: 0.9381 - val_loss: 0.1479 - val_fbeta_score: 0.7243 - val_accuracy: 0.9392 Epoch 10/25 253/253 [==============================] - 147s 582ms/step - loss: 0.1553 - fbeta_score: 0.7328 - accuracy: 0.9395 - val_loss: 0.1281 - val_fbeta_score: 0.7506 - val_accuracy: 0.9401 Epoch 11/25 253/253 [==============================] - 145s 575ms/step - loss: 0.1532 - fbeta_score: 0.7370 - accuracy: 0.9401 - val_loss: 0.1308 - val_fbeta_score: 0.7413 - val_accuracy: 0.9424 Epoch 12/25 253/253 [==============================] - 145s 575ms/step - loss: 0.1506 - fbeta_score: 0.7411 - accuracy: 0.9409 - val_loss: 0.1171 - val_fbeta_score: 0.7444 - val_accuracy: 0.9427 Epoch 13/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1494 - fbeta_score: 0.7426 - accuracy: 0.9415 - val_loss: 0.1106 - val_fbeta_score: 0.7635 - val_accuracy: 0.9430 Epoch 14/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1469 - fbeta_score: 0.7469 - accuracy: 0.9424 - val_loss: 0.1599 - val_fbeta_score: 0.7603 - val_accuracy: 0.9450 Epoch 15/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1451 - fbeta_score: 0.7505 - accuracy: 0.9432 - val_loss: 0.2192 - val_fbeta_score: 0.7515 - val_accuracy: 0.9462 Epoch 16/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1436 - fbeta_score: 0.7525 - accuracy: 0.9438 - val_loss: 0.0913 - val_fbeta_score: 0.7662 - val_accuracy: 0.9430 Epoch 17/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1416 - fbeta_score: 0.7565 - accuracy: 0.9446 - val_loss: 0.1277 - val_fbeta_score: 0.7566 - val_accuracy: 0.9452 Epoch 18/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1403 - fbeta_score: 0.7585 - accuracy: 0.9448 - val_loss: 0.1682 - val_fbeta_score: 0.7593 - val_accuracy: 0.9462 Epoch 19/25 253/253 [==============================] - 146s 575ms/step - loss: 0.1398 - fbeta_score: 0.7594 - accuracy: 0.9451 - val_loss: 0.1388 - val_fbeta_score: 0.7717 - val_accuracy: 0.9483 Epoch 20/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1380 - fbeta_score: 0.7628 - accuracy: 0.9462 - val_loss: 0.1300 - val_fbeta_score: 0.7679 - val_accuracy: 0.9460 Epoch 21/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1365 - fbeta_score: 0.7657 - accuracy: 0.9467 - val_loss: 0.1508 - val_fbeta_score: 0.7723 - val_accuracy: 0.9487 Epoch 22/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1359 - fbeta_score: 0.7665 - accuracy: 0.9468 - val_loss: 0.1578 - val_fbeta_score: 0.7815 - val_accuracy: 0.9472 Epoch 23/25 253/253 [==============================] - 144s 568ms/step - loss: 0.1346 - fbeta_score: 0.7690 - accuracy: 0.9475 - val_loss: 0.1014 - val_fbeta_score: 0.7762 - val_accuracy: 0.9481 Epoch 24/25 253/253 [==============================] - 146s 575ms/step - loss: 0.1339 - fbeta_score: 0.7703 - accuracy: 0.9478 - val_loss: 0.1097 - val_fbeta_score: 0.7821 - val_accuracy: 0.9499 Epoch 25/25 253/253 [==============================] - 145s 571ms/step - loss: 0.1339 - fbeta_score: 0.7701 - accuracy: 0.9478 - val_loss: 0.1253 - val_fbeta_score: 0.7768 - val_accuracy: 0.9503 Modelo fazendo a classificação nos dados de teste. Seja paciente e aguarde... Término do Fold 3 da Validação Cruzada. Iniciando o Treinamento do Fold 4 Dimensões dos Dados de Treino: 32383 Found 32383 validated image filenames belonging to 17 classes. Dimensões dos Dados de Validação: 8096 Found 8096 validated image filenames belonging to 17 classes. Dimensões dos Dados de Teste: 40479 Found 40479 validated image filenames belonging to 17 classes. Epoch 1/25 253/253 [==============================] - 151s 598ms/step - loss: 0.2732 - fbeta_score: 0.5512 - accuracy: 0.9047 - val_loss: 0.2206 - val_fbeta_score: 0.5700 - val_accuracy: 0.9035 Epoch 2/25 253/253 [==============================] - 146s 575ms/step - loss: 0.2198 - fbeta_score: 0.6088 - accuracy: 0.9134 - val_loss: 0.2312 - val_fbeta_score: 0.5970 - val_accuracy: 0.9137 Epoch 3/25 253/253 [==============================] - 147s 580ms/step - loss: 0.2098 - fbeta_score: 0.6290 - accuracy: 0.9177 - val_loss: 0.1696 - val_fbeta_score: 0.6268 - val_accuracy: 0.9190 Epoch 4/25 253/253 [==============================] - 145s 572ms/step - loss: 0.1985 - fbeta_score: 0.6492 - accuracy: 0.9209 - val_loss: 0.1950 - val_fbeta_score: 0.6461 - val_accuracy: 0.9218 Epoch 5/25 253/253 [==============================] - 147s 583ms/step - loss: 0.1836 - fbeta_score: 0.6782 - accuracy: 0.9274 - val_loss: 0.2005 - val_fbeta_score: 0.6788 - val_accuracy: 0.9303 Epoch 6/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1736 - fbeta_score: 0.6982 - accuracy: 0.9318 - val_loss: 0.1900 - val_fbeta_score: 0.6992 - val_accuracy: 0.9353 Epoch 7/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1670 - fbeta_score: 0.7110 - accuracy: 0.9346 - val_loss: 0.1471 - val_fbeta_score: 0.7283 - val_accuracy: 0.9362 Epoch 8/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1614 - fbeta_score: 0.7219 - accuracy: 0.9371 - val_loss: 0.1270 - val_fbeta_score: 0.7402 - val_accuracy: 0.9379 Epoch 9/25 253/253 [==============================] - 147s 582ms/step - loss: 0.1573 - fbeta_score: 0.7290 - accuracy: 0.9387 - val_loss: 0.1837 - val_fbeta_score: 0.7290 - val_accuracy: 0.9406 Epoch 10/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1528 - fbeta_score: 0.7367 - accuracy: 0.9401 - val_loss: 0.0832 - val_fbeta_score: 0.7483 - val_accuracy: 0.9405 Epoch 11/25 253/253 [==============================] - 147s 582ms/step - loss: 0.1503 - fbeta_score: 0.7413 - accuracy: 0.9411 - val_loss: 0.1397 - val_fbeta_score: 0.7419 - val_accuracy: 0.9428 Epoch 12/25 253/253 [==============================] - 148s 584ms/step - loss: 0.1478 - fbeta_score: 0.7450 - accuracy: 0.9420 - val_loss: 0.1768 - val_fbeta_score: 0.7621 - val_accuracy: 0.9405 Epoch 13/25 253/253 [==============================] - 147s 582ms/step - loss: 0.1457 - fbeta_score: 0.7489 - accuracy: 0.9427 - val_loss: 0.1257 - val_fbeta_score: 0.7530 - val_accuracy: 0.9447 Epoch 14/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1442 - fbeta_score: 0.7514 - accuracy: 0.9431 - val_loss: 0.1282 - val_fbeta_score: 0.7744 - val_accuracy: 0.9433 Epoch 15/25 253/253 [==============================] - 147s 580ms/step - loss: 0.1420 - fbeta_score: 0.7553 - accuracy: 0.9444 - val_loss: 0.0902 - val_fbeta_score: 0.7634 - val_accuracy: 0.9455 Epoch 16/25 253/253 [==============================] - 147s 580ms/step - loss: 0.1417 - fbeta_score: 0.7565 - accuracy: 0.9444 - val_loss: 0.1477 - val_fbeta_score: 0.7614 - val_accuracy: 0.9465 Epoch 17/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1408 - fbeta_score: 0.7577 - accuracy: 0.9448 - val_loss: 0.1759 - val_fbeta_score: 0.7640 - val_accuracy: 0.9454 Epoch 18/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1385 - fbeta_score: 0.7617 - accuracy: 0.9454 - val_loss: 0.1548 - val_fbeta_score: 0.7763 - val_accuracy: 0.9468 Epoch 19/25 253/253 [==============================] - 145s 573ms/step - loss: 0.1380 - fbeta_score: 0.7632 - accuracy: 0.9461 - val_loss: 0.1193 - val_fbeta_score: 0.7690 - val_accuracy: 0.9484 Epoch 20/25 253/253 [==============================] - 147s 581ms/step - loss: 0.1362 - fbeta_score: 0.7655 - accuracy: 0.9466 - val_loss: 0.1316 - val_fbeta_score: 0.7785 - val_accuracy: 0.9458 Epoch 21/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1356 - fbeta_score: 0.7673 - accuracy: 0.9471 - val_loss: 0.0925 - val_fbeta_score: 0.7770 - val_accuracy: 0.9488 Epoch 22/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1335 - fbeta_score: 0.7707 - accuracy: 0.9476 - val_loss: 0.1034 - val_fbeta_score: 0.7883 - val_accuracy: 0.9496 Epoch 23/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1326 - fbeta_score: 0.7724 - accuracy: 0.9483 - val_loss: 0.0823 - val_fbeta_score: 0.7807 - val_accuracy: 0.9485 Epoch 24/25 253/253 [==============================] - 144s 570ms/step - loss: 0.1317 - fbeta_score: 0.7740 - accuracy: 0.9484 - val_loss: 0.1295 - val_fbeta_score: 0.7923 - val_accuracy: 0.9508 Epoch 25/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1303 - fbeta_score: 0.7771 - accuracy: 0.9492 - val_loss: 0.1078 - val_fbeta_score: 0.7826 - val_accuracy: 0.9457 Modelo fazendo a classificação nos dados de teste. Seja paciente e aguarde... Término do Fold 4 da Validação Cruzada. Iniciando o Treinamento do Fold 5 Dimensões dos Dados de Treino: 32384 Found 32384 validated image filenames belonging to 17 classes. Dimensões dos Dados de Validação: 8095 Found 8095 validated image filenames belonging to 17 classes. Dimensões dos Dados de Teste: 40479 Found 40479 validated image filenames belonging to 17 classes. Epoch 1/25 253/253 [==============================] - 152s 599ms/step - loss: 0.2753 - fbeta_score: 0.5466 - accuracy: 0.9013 - val_loss: 0.2264 - val_fbeta_score: 0.5667 - val_accuracy: 0.9116 Epoch 2/25 253/253 [==============================] - 145s 575ms/step - loss: 0.2213 - fbeta_score: 0.6058 - accuracy: 0.9130 - val_loss: 0.2295 - val_fbeta_score: 0.6052 - val_accuracy: 0.9158 Epoch 3/25 253/253 [==============================] - 147s 583ms/step - loss: 0.2069 - fbeta_score: 0.6352 - accuracy: 0.9187 - val_loss: 0.2025 - val_fbeta_score: 0.6370 - val_accuracy: 0.9207 Epoch 4/25 253/253 [==============================] - 147s 580ms/step - loss: 0.1940 - fbeta_score: 0.6585 - accuracy: 0.9228 - val_loss: 0.1936 - val_fbeta_score: 0.6646 - val_accuracy: 0.9272 Epoch 5/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1794 - fbeta_score: 0.6873 - accuracy: 0.9294 - val_loss: 0.2690 - val_fbeta_score: 0.6927 - val_accuracy: 0.9287 Epoch 6/25 253/253 [==============================] - 147s 580ms/step - loss: 0.1688 - fbeta_score: 0.7087 - accuracy: 0.9341 - val_loss: 0.1892 - val_fbeta_score: 0.7084 - val_accuracy: 0.9381 Epoch 7/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1624 - fbeta_score: 0.7211 - accuracy: 0.9370 - val_loss: 0.1867 - val_fbeta_score: 0.7232 - val_accuracy: 0.9390 Epoch 8/25 253/253 [==============================] - 147s 581ms/step - loss: 0.1573 - fbeta_score: 0.7300 - accuracy: 0.9385 - val_loss: 0.1405 - val_fbeta_score: 0.7413 - val_accuracy: 0.9404 Epoch 9/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1555 - fbeta_score: 0.7329 - accuracy: 0.9395 - val_loss: 0.1963 - val_fbeta_score: 0.7433 - val_accuracy: 0.9420 Epoch 10/25 253/253 [==============================] - 146s 579ms/step - loss: 0.1508 - fbeta_score: 0.7411 - accuracy: 0.9411 - val_loss: 0.1383 - val_fbeta_score: 0.7441 - val_accuracy: 0.9442 Epoch 11/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1484 - fbeta_score: 0.7454 - accuracy: 0.9418 - val_loss: 0.1601 - val_fbeta_score: 0.7433 - val_accuracy: 0.9429 Epoch 12/25 253/253 [==============================] - 146s 575ms/step - loss: 0.1479 - fbeta_score: 0.7457 - accuracy: 0.9422 - val_loss: 0.1565 - val_fbeta_score: 0.7586 - val_accuracy: 0.9456 Epoch 13/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1447 - fbeta_score: 0.7517 - accuracy: 0.9435 - val_loss: 0.1563 - val_fbeta_score: 0.7626 - val_accuracy: 0.9459 Epoch 14/25 253/253 [==============================] - 147s 579ms/step - loss: 0.1425 - fbeta_score: 0.7554 - accuracy: 0.9443 - val_loss: 0.1274 - val_fbeta_score: 0.7650 - val_accuracy: 0.9466 Epoch 15/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1407 - fbeta_score: 0.7580 - accuracy: 0.9449 - val_loss: 0.1201 - val_fbeta_score: 0.7750 - val_accuracy: 0.9458 Epoch 16/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1396 - fbeta_score: 0.7597 - accuracy: 0.9447 - val_loss: 0.1447 - val_fbeta_score: 0.7641 - val_accuracy: 0.9462 Epoch 17/25 253/253 [==============================] - 147s 581ms/step - loss: 0.1387 - fbeta_score: 0.7613 - accuracy: 0.9457 - val_loss: 0.1385 - val_fbeta_score: 0.7715 - val_accuracy: 0.9471 Epoch 18/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1373 - fbeta_score: 0.7640 - accuracy: 0.9458 - val_loss: 0.1304 - val_fbeta_score: 0.7856 - val_accuracy: 0.9477 Epoch 19/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1355 - fbeta_score: 0.7671 - accuracy: 0.9468 - val_loss: 0.1494 - val_fbeta_score: 0.7920 - val_accuracy: 0.9486 Epoch 20/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1342 - fbeta_score: 0.7694 - accuracy: 0.9471 - val_loss: 0.1256 - val_fbeta_score: 0.7891 - val_accuracy: 0.9497 Epoch 21/25 253/253 [==============================] - 146s 577ms/step - loss: 0.1334 - fbeta_score: 0.7713 - accuracy: 0.9477 - val_loss: 0.1153 - val_fbeta_score: 0.7730 - val_accuracy: 0.9500 Epoch 22/25 253/253 [==============================] - 146s 578ms/step - loss: 0.1323 - fbeta_score: 0.7728 - accuracy: 0.9479 - val_loss: 0.1466 - val_fbeta_score: 0.7890 - val_accuracy: 0.9501 Epoch 23/25 253/253 [==============================] - 146s 576ms/step - loss: 0.1320 - fbeta_score: 0.7738 - accuracy: 0.9482 - val_loss: 0.1478 - val_fbeta_score: 0.7870 - val_accuracy: 0.9497 Epoch 24/25 253/253 [==============================] - 145s 574ms/step - loss: 0.1308 - fbeta_score: 0.7757 - accuracy: 0.9486 - val_loss: 0.1182 - val_fbeta_score: 0.7847 - val_accuracy: 0.9488 Epoch 25/25 253/253 [==============================] - 145s 571ms/step - loss: 0.1300 - fbeta_score: 0.7767 - accuracy: 0.9489 - val_loss: 0.1419 - val_fbeta_score: 0.7938 - val_accuracy: 0.9516 Modelo fazendo a classificação nos dados de teste. Seja paciente e aguarde... Término do Fold 5 da Validação Cruzada. Treinamento Concluído. CPU times: user 5h 56min 52s, sys: 9min 14s, total: 6h 6min 6s Wall time: 5h 10min 5s
# Saved model path
model_path_of_fold = os.path.join(PATH_MODELOS, 'pesos_fold_' + str(NUM_FOLD - 1) + '.h5')
# Create model
modelo_final = cria_modelo()
# Load saved model
modelo_final.load_weights(model_path_of_fold)
# Plot model performance
curva_aprendizado(modelo_cnn_satelite.history)
The model has great performance and learning was slow. We could increase the learning rate a little bit and train longer in order to increase the accuracy even more.
# The y_test item has all the predictions in the test data for each fold of the cross validation
len(y_teste)
5
# Create an array for results of one CV fold
resultado = np.array(y_teste[0])
# View fold results
resultado
array([[3.58537026e-02, 1.15087430e-03, 2.74071121e-03, ..., 1.06197447e-02, 1.62826444e-03, 4.93933558e-02], [6.93802312e-02, 1.10839121e-03, 1.89726776e-03, ..., 1.71465091e-02, 1.46847568e-03, 4.84707914e-02], [1.15033634e-01, 1.32205756e-03, 2.07197107e-03, ..., 7.18102601e-05, 1.11096841e-03, 9.87202600e-02], ..., [1.28187209e-01, 3.08408635e-04, 5.84577210e-04, ..., 1.44266465e-04, 6.78103126e-04, 9.32235867e-02], [9.32165861e-01, 1.80980866e-03, 2.02542841e-02, ..., 5.01354458e-03, 1.23906862e-02, 1.58686966e-01], [5.99018559e-02, 6.51527080e-04, 3.68372235e-03, ..., 6.84326887e-03, 1.73138711e-03, 9.66413543e-02]], dtype=float32)
# Convert array to dataframe and preview result
resultado_df = pd.DataFrame(resultado, columns = labels)
resultado_df.head()
agriculture | artisinal_mine | bare_ground | blooming | blow_down | clear | cloudy | conventional_mine | cultivation | habitation | haze | partly_cloudy | primary | road | selective_logging | slash_burn | water | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.035854 | 0.001151 | 0.002741 | 3.312169e-02 | 0.004185 | 0.982465 | 0.000044 | 0.000278 | 0.023750 | 0.005646 | 0.000627 | 0.013735 | 0.999645 | 0.023195 | 0.010620 | 0.001628 | 0.049393 |
1 | 0.069380 | 0.001108 | 0.001897 | 2.924577e-02 | 0.007014 | 0.902134 | 0.000004 | 0.000149 | 0.065861 | 0.009277 | 0.000077 | 0.106229 | 0.999982 | 0.030755 | 0.017147 | 0.001468 | 0.048471 |
2 | 0.115034 | 0.001322 | 0.002072 | 1.965914e-05 | 0.000094 | 0.001064 | 0.016263 | 0.000399 | 0.030340 | 0.010436 | 0.000264 | 0.976215 | 0.983666 | 0.075785 | 0.000072 | 0.001111 | 0.098720 |
3 | 0.017205 | 0.000190 | 0.000708 | 1.400888e-02 | 0.000946 | 0.980363 | 0.000010 | 0.000054 | 0.012234 | 0.002051 | 0.000106 | 0.016535 | 0.999901 | 0.010341 | 0.003278 | 0.000325 | 0.023448 |
4 | 0.054526 | 0.000048 | 0.000135 | 9.120800e-08 | 0.000002 | 0.000796 | 0.420501 | 0.000011 | 0.005659 | 0.007255 | 0.000865 | 0.568739 | 0.532211 | 0.034072 | 0.000003 | 0.000026 | 0.078662 |
# Shape
resultado_df.shape
(40479, 17)
In the table above, each row is an image and each column is a class. Each column represents the class score for that image. All this for 1 single fold.
Let's calculate the average of the results obtained from the cross validation with k (5) folds.
# Loop to fill the array
for i in range(1, NFOLDS):
resultado += np.array(y_teste[i])
resultado /= NFOLDS
# Convert array to dataframe
resultado_df_final = pd.DataFrame(resultado, columns = labels)
resultado_df_final.head()
agriculture | artisinal_mine | bare_ground | blooming | blow_down | clear | cloudy | conventional_mine | cultivation | habitation | haze | partly_cloudy | primary | road | selective_logging | slash_burn | water | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.017726 | 0.000241 | 0.001418 | 0.007395 | 0.002265 | 0.245403 | 0.000015 | 0.000047 | 0.013692 | 0.001906 | 0.000832 | 0.004331 | 0.251142 | 0.006566 | 0.002542 | 0.000602 | 0.021365 |
1 | 0.025142 | 0.000216 | 0.000907 | 0.015320 | 0.006049 | 0.243286 | 0.000001 | 0.000024 | 0.037599 | 0.003390 | 0.000075 | 0.010230 | 0.251197 | 0.006217 | 0.006709 | 0.001237 | 0.018200 |
2 | 0.049017 | 0.000511 | 0.001105 | 0.000022 | 0.000167 | 0.000125 | 0.000939 | 0.000391 | 0.034046 | 0.002138 | 0.000080 | 0.249998 | 0.249673 | 0.015629 | 0.000184 | 0.000667 | 0.039647 |
3 | 0.020377 | 0.000238 | 0.000840 | 0.009568 | 0.001577 | 0.188609 | 0.000002 | 0.000036 | 0.017641 | 0.001785 | 0.000045 | 0.081648 | 0.251196 | 0.008114 | 0.003946 | 0.000404 | 0.016709 |
4 | 0.031166 | 0.000176 | 0.000720 | 0.000010 | 0.000020 | 0.001138 | 0.109564 | 0.000060 | 0.009219 | 0.003895 | 0.001106 | 0.164217 | 0.146160 | 0.014621 | 0.000057 | 0.000089 | 0.025342 |
# Saving the predictions
resultado_df_final.to_csv(PATH_ARQUIVOS + 'resultado_previsoes.csv')
# Recording predictions and suggested classes in testing
# List for predictions
preds = []
# Loop to extract predictions
for i in range(resultado_df_final.shape[0]):
a = resultado_df_final.iloc[[i]]
a = a.apply(lambda x: x > THRES, axis = 1)
a = a.transpose()
a = a.loc[a[i] == True]
' '.join(list(a.index))
preds.append(' '.join(list(a.index)))
# Recording the original labels and model predictions in csv format
# This is the file I'll submit to Kaggle
dados_teste_final['preds'] = preds
dados_teste_final.to_csv(PATH_ARQUIVOS + 'resultado_final.csv', index = False)
# Viewing 20 model predictions
dados_teste_final.head(20)
image_name | tags | preds | |
---|---|---|---|
0 | test_0.jpg | [primary, clear, agriculture, road, water] | clear primary |
1 | test_1.jpg | [primary, clear, agriculture, road, water] | clear primary |
2 | test_2.jpg | [primary, clear, agriculture, road, water] | partly_cloudy primary |
3 | test_3.jpg | [primary, clear, agriculture, road, water] | primary |
4 | test_4.jpg | [primary, clear, agriculture, road, water] | |
5 | test_5.jpg | [primary, clear, agriculture, road, water] | clear primary |
6 | test_6.jpg | [primary, clear, agriculture, road, water] | primary |
7 | test_7.jpg | [primary, clear, agriculture, road, water] | clear habitation road |
8 | test_8.jpg | [primary, clear, agriculture, road, water] | clear primary |
9 | test_9.jpg | [primary, clear, agriculture, road, water] | primary |
10 | test_10.jpg | [primary, clear, agriculture, road, water] | partly_cloudy primary |
11 | test_11.jpg | [primary, clear, agriculture, road, water] | clear primary |
12 | test_12.jpg | [primary, clear, agriculture, road, water] | cloudy |
13 | test_13.jpg | [primary, clear, agriculture, road, water] | clear primary |
14 | test_14.jpg | [primary, clear, agriculture, road, water] | clear primary |
15 | test_15.jpg | [primary, clear, agriculture, road, water] | clear primary |
16 | test_16.jpg | [primary, clear, agriculture, road, water] | agriculture clear primary road |
17 | test_17.jpg | [primary, clear, agriculture, road, water] | primary |
18 | test_18.jpg | [primary, clear, agriculture, road, water] | primary |
19 | test_19.jpg | [primary, clear, agriculture, road, water] | clear primary |
Matheus Schmitz
LinkedIn
Github Portfolio