mercoledì 31 maggio 2023

Batimetria Venezia da Landsat con Decision Tree

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

 

Nessun commento:

Posta un commento

Dockerizza Flask

Un esempio semplice per inserire in un container Docker una applicazione Flask Partiamo da una semplice applicazione che ha un file app.py ...