Ho ripreso il filone di questa prova per provare i Decision Tree con le firme spettrali di Sentinel 2
Per la prova ho preso l'immagine S2B_MSIL2A_20230826T100559_N0509_R022_T32TPP_20230826T134424.SAFE
del periodo estivo del Mugello (Toscana) in modo da avere suolo nudo disponibile.
Visto che volevo estrarre tutte le bande tramite SNAP ho campionato tutte le bande a 10 m (altrimenti come visto nel precedente post lo Spectral Viewer estrae solo le bande native a 10 m)...e qui c'e' un problema...ho dovuto fare il resampling spaziale di tutta l'immagine e dopo fare il subset della mia sola area di interesse altrimenti, invertendo le due operazioni, SNAP entrava continuamente in errore
Usando gli OpenData della Regione Toscana
https://dati.toscana.it/dataset/dbped
ho usato il dataset per selezionare il parametro contenuto in argilla del suolo categorizzandolo a passi del 5%. Usando i Pin e la vista sincronizzata tra la mappe del suolo e l'immagine telerilevata sono selezionati 153 punti appartenenti a 4 classi di contenuto in argilla
Classe/Nr spettri
3 44
2 41
0 34
1 34
Il contenuto in argille delle classi e'
classe 1 (amaranto) : 45-50%
classe 2 (arancione) : 30-35%
classe 3 (rosso) :40-45%
classe 4 (verde) : 20-25%
il file dati in CSV e' formato nel seguente modo
443,490,560,665,705,740,783,842,865,945,1610,2190,Classe
0.0711,0.1056,0.1548,0.2046,0.2335,0.2442,0.2617,0.2624,0.2801,0.2813,0.3556,0.2868,1
0.0777,0.1052,0.157,0.2032,0.2311,0.2415,0.2611,0.2562,0.2741,0.2841,0.3473,0.2829,1
Come si vede dall'esempio la variabilita' spettrale in ogni classe e' molto elevata (in rosso lo spettro medio)
Lo spettro medio per ogni classe di contenuto in argilla e' visualizzato negl grafico sottostante
Usando una rete neurale tradizionale l'accuratezza e ' prossima al 77%
import pandas as pd
import numpy as np
import tensorflow as tf
import seaborn as sns
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Dropout
from sklearn.preprocessing import LabelEncoder , StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
df = pd.read_csv('/content/totale2.csv')
print(df.head())
le = LabelEncoder()
df['Classe'] = le.fit_transform(df['Classe'])
X = df.drop(columns=['Classe'])
y = df['Classe']
print(y.head())
print(y.value_counts())
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.25,shuffle=True,random_state=7)
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
print(X_train.size)
print(y_train)
y_train = tf.keras.utils.to_categorical(y_train,num_classes=4)
def get_models():
model = Sequential([
Dense(units=32,input_shape=(12,),activation='relu'),
Dense(units=32,activation='relu'),
Dropout(0.5),
Dense(units=4,activation='softmax')
])
return model
model = get_models()
model.compile(optimizer='Adam',loss='categorical_crossentropy',metrics=['accuracy'])
model.summary()
model.fit(X_train,y_train,epochs=100, verbose=2)
prediction = model.predict(X_test)
prediction = np.argmax(prediction,axis=-1)
acury = accuracy_score(y_test,prediction)
print(acury)
cm = confusion_matrix(y_test,prediction)
print(cm)
0.7692307692307693
Con la seguente matrice di confusione
[[ 4 1 0 0]
[ 4 7 0 0]
[ 0 0 9 0]
[ 1 2 1 10]]
Utilizzando i decision tree
!pip install -q -U tensorflow_decision_forests
!pip install -q -U dtreeviz
import tensorflow_decision_forests as tfdf
import tensorflow as tf
import os
import numpy as np
import pandas as pd
import tensorflow as tf
import math
import dtreeviz
from matplotlib import pyplot as plt
from IPython import display
import logging
logging.getLogger('matplotlib.font_manager').setLevel(level=logging.CRITICAL)
display.set_matplotlib_formats('retina') # generate hires plots
np.random.seed(1234)
def split_dataset(dataset, test_ratio=0.30, seed=1234):
np.random.seed(seed)
test_indices = np.random.rand(len(dataset)) < test_ratio
return dataset[~test_indices], dataset[test_indices]
df_spettri = pd.read_csv("/content/totale2.csv")
df_spettri.head(3)
spettri_label = "Classe" # Name of the classification target label
classes = list(df_spettri[spettri_label].unique())
df_spettri[spettri_label] = df_spettri[spettri_label].map(classes.index)
print(f"Target '{spettri_label}'' classes: {classes}")
df_spettri.head(3)
# Split into training and test sets
train_ds_pd, test_ds_pd = split_dataset(df_spettri)
print(f"{len(train_ds_pd)} examples in training, {len(test_ds_pd)} examples for testing.")
# Convert to tensorflow data sets
train_ds = tfdf.keras.pd_dataframe_to_tf_dataset(train_ds_pd, label=spettri_label)
test_ds = tfdf.keras.pd_dataframe_to_tf_dataset(test_ds_pd, label=spettri_label)
cmodel = tfdf.keras.RandomForestModel(verbose=0, random_seed=1234)
cmodel.fit(train_ds)
cmodel.compile(metrics=["accuracy"])
cmodel.evaluate(test_ds, return_dict=True, verbose=0)
# Tell dtreeviz about training data and model
spettri_features = [f.name for f in cmodel.make_inspector().features()]
viz_cmodel = dtreeviz.model(cmodel,
tree_index=3,
X_train=train_ds_pd[spettri_features],
y_train=train_ds_pd[spettri_label],
feature_names=spettri_features,
target_name=spettri_label,
class_names=classes)
viz_cmodel.view(scale=1.75)
si ha una accuracy di circa 0.7