Visto lo scarso successo del metodo analitico visto qui ho provato un metodo alternativo citato spesso il letteratura che prevede la determinazione della batimetria da dati ottici usando la rete neurale decision tree
Per cambiare ho preso i dati Landsat sulla Laguna di Venezia (la batimetria della Laguna di Venezia e' molto piu' variabile rispetto a quella della lagunan di Orbetello) usando come dato di verita' a terra questo geotiff http://cigno.ve.ismar.cnr.it/layers/geonode%3Alag02_okart_export
Su Qgis sono stati importate le bande RGB,NIR di Landsat8 e dopo avere creato una griglia regolare di punti spaziati di 30 m e' stata estratta una tabella con i valori di riflettanza per ogni banda e la profondita'
Una volta ottenuto il file CSV i dati di batimetria sono stati divisi in classi di 0.5 m per rendere possibile la successiva elaborazione tramite un semplice script in GO
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"math"
"os"
"strconv"
)
func main() {
f, err := os.Open("tree.csv")
if err != nil {
log.Fatal(err)
}
defer f.Close()
csvReader := csv.NewReader(f)
for {
rec, err := csvReader.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
tt, _ := strconv.ParseFloat(rec[0], 'f')
t := math.Abs(tt)
fmt.Print(math.Floor(t / 0.5))
fmt.Println("," + rec[1] + "," + rec[2] + "," + rec[3] + "," + rec[4])
}
}
il file finale ha un formato del tipo
classe,red,nir,gren,blue
3,6707,5566,8241,9397
3,6714,5575,8221,9375
3,6696,5573,8184,9369
3,6665,5577,8144,9331
3,6638,5584,8089,9287
3,6636,5568,8080,9281
In totale sono emerse 23 classi per un totale di 16000 punti
Come si vede la distribuzione e' fondamentalmentre asimmetrica con le prima 4 classi che rappresentano la gran parte dei dati. E' stato effettuato un taglio dei dati alle prime 6 classi
Il file CSV e' stato utilizzato all'interno dello script seguente in Colab (si tratta di un semplice adattamento del programma di esempio di Tensorflow per la rete decision tree)
# -*- coding: utf-8 -*-
"""decisiontree_venezia.ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/drive/1f8HLdjHiDNvpplKzNOVrXuIXrKTay0TS
"""
!pip install tensorflow_decision_forests
import numpy as np
import pandas as pd
import tensorflow_decision_forests as tfdf
path = "/content/classi_nobat_ridotto.csv"
pandas_dataset = pd.read_csv(path)
# Display the first 3 examples.
pandas_dataset.head(3)
np.random.seed(1)
# Use the ~10% of the examples as the testing set
# and the remaining ~90% of the examples as the training set.
test_indices = np.random.rand(len(pandas_dataset)) < 0.1
pandas_train_dataset = pandas_dataset[~test_indices]
pandas_test_dataset = pandas_dataset[test_indices]
print("Training examples: ", len(pandas_train_dataset))
print("Testing examples: ", len(pandas_test_dataset))
tf_train_dataset = tfdf.keras.pd_dataframe_to_tf_dataset(pandas_train_dataset, label='classe')
model = tfdf.keras.CartModel()
model.fit(tf_train_dataset)
tfdf.model_plotter.plot_model_in_colab(model, max_depth=10)
model.compile("accuracy")
print("Train evaluation: ", model.evaluate(tf_train_dataset, return_dict=True))
tf_test_dataset = tfdf.keras.pd_dataframe_to_tf_dataset(pandas_test_dataset, label='classe')
print("Test evaluation: ", model.evaluate(tf_test_dataset, return_dict=True))
from keras.utils import plot_model
plot_model(
model,
to_file='model.png',
show_shapes=False,
show_dtype=False,
show_layer_names=True,
rankdir='TB',
expand_nested=False,
dpi=96,
layer_range=None,
show_layer_activations=False,
show_trainable=False
)
!pip install keras-tuner
import keras_tuner as kt
def build_model(hp):
model = tfdf.keras.CartModel(
min_examples=hp.Choice("min_examples",
# Try four possible values for "min_examples" hyperparameter.
# min_examples=10 would limit the growth of the decision tree,
# while min_examples=1 would lead to deeper decision trees.
[1, 2, 5, 10]),
validation_ratio=hp.Choice("validation_ratio",
# Three possible values for the "validation_ratio" hyperparameter.
[0.0, 0.05, 0.10]),
)
model.compile("accuracy")
return model
tuner = kt.RandomSearch(
build_model,
objective="val_accuracy",
max_trials=10,
directory="/tmp/tuner",
project_name="tune_cart")
tuner.search(x=tf_train_dataset, validation_data=tf_test_dataset)
best_model = tuner.get_best_models()[0]
print("Best hyperparameters: ", tuner.get_best_hyperparameters()[0].values)
# >> Best hyperparameters: {'min_examples': 2, 'validation_ratio': 0.0}
model = tfdf.keras.CartModel(min_examples=2, validation_ratio=0.0)
model.fit(tf_train_dataset)
model.compile("accuracy")
print("Test evaluation: ", model.evaluate(tf_test_dataset, return_dict=True))
tfdf.model_plotter.plot_model_in_colab(model, max_depth=10)
Training examples: 13463
Testing examples: 1520
al termine si ha una accuracy della porzione di dati di test superiore al 70%
14/14 [==============================] - 1s 8ms/step - loss: 0.0000e+00 - accuracy: 0.7761
Train evaluation: {'loss': 0.0, 'accuracy': 0.7761271595954895}
2/2 [==============================] - 0s 19ms/step - loss: 0.0000e+00 - accuracy: 0.7388
Test evaluation: {'loss': 0.0, 'accuracy': 0.7388157844543457}
In generale la rete nel caso di incertezza di una classe seleziona sempre classi contingue