wip
This commit is contained in:
1 parent
c0081cf86e
commit
1da59d68df
6 files changed
+13163
-170
No files matched your search
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+62
-168
@@ -299,51 +299,6 @@ scaler_temporal = joblib.load('./models/oli_transformer/scaler_temporal.joblib')
|
|||||||
scaler_static = joblib.load('./models/oli_transformer/scaler_static.joblib')
|
scaler_static = joblib.load('./models/oli_transformer/scaler_static.joblib')
|
||||||
scaler_y = joblib.load('./models/oli_transformer/scaler_y.joblib')
|
scaler_y = joblib.load('./models/oli_transformer/scaler_y.joblib')
|
||||||
|
|
||||||
def prepare_monthly_weather_stats(weather_data):
|
|
||||||
"""Prepara le statistiche mensili dal weather_data."""
|
|
||||||
monthly_stats = weather_data.groupby(['year', 'month']).agg({
|
|
||||||
'temp': 'mean',
|
|
||||||
'precip': 'sum',
|
|
||||||
'solarradiation': 'sum' # useremo questo come proxy per solar_energy_sum
|
|
||||||
}).reset_index()
|
|
||||||
|
|
||||||
monthly_stats.columns = ['year', 'month', 'temp_mean', 'precip_sum', 'solar_energy_sum']
|
|
||||||
return monthly_stats
|
|
||||||
|
|
||||||
def prepare_static_features(variety_info, hectares):
|
|
||||||
"""Prepara le feature statiche nello stesso formato usato durante il training."""
|
|
||||||
# Inizializza un array con il numero di ettari
|
|
||||||
static_features = [hectares]
|
|
||||||
|
|
||||||
# Aggiungi le feature della varietà
|
|
||||||
variety_name = variety_info['Varietà di Olive'].lower().replace(" ", "_").replace("'", "")
|
|
||||||
technique = variety_info['Tecnica di Coltivazione'].lower()
|
|
||||||
|
|
||||||
# Feature di base della varietà
|
|
||||||
variety_features = {
|
|
||||||
f'{variety_name}_prod_t_ha': variety_info['Produzione (tonnellate/ettaro)'],
|
|
||||||
f'{variety_name}_oil_prod_t_ha': variety_info['Produzione Olio (tonnellate/ettaro)'],
|
|
||||||
f'{variety_name}_oil_prod_l_ha': variety_info['Produzione Olio (litri/ettaro)'],
|
|
||||||
f'{variety_name}_min_yield_pct': variety_info['Min % Resa'],
|
|
||||||
f'{variety_name}_max_yield_pct': variety_info['Max % Resa'],
|
|
||||||
f'{variety_name}_min_oil_prod_l_ha': variety_info['Min Produzione Olio (litri/ettaro)'],
|
|
||||||
f'{variety_name}_max_oil_prod_l_ha': variety_info['Max Produzione Olio (litri/ettaro)'],
|
|
||||||
f'{variety_name}_avg_oil_prod_l_ha': variety_info['Media Produzione Olio (litri/ettaro)'],
|
|
||||||
f'{variety_name}_l_per_t': variety_info['Litri per Tonnellata'],
|
|
||||||
f'{variety_name}_min_l_per_t': variety_info['Min Litri per Tonnellata'],
|
|
||||||
f'{variety_name}_max_l_per_t': variety_info['Max Litri per Tonnellata'],
|
|
||||||
f'{variety_name}_avg_l_per_t': variety_info['Media Litri per Tonnellata']
|
|
||||||
}
|
|
||||||
|
|
||||||
# Aggiungi le feature binarie per le tecniche di coltivazione
|
|
||||||
for tech in ['tradizionale', 'intensiva', 'superintensiva']:
|
|
||||||
variety_features[f'{variety_name}_{tech}'] = 1 if technique == tech else 0
|
|
||||||
|
|
||||||
# Converti il dizionario in lista mantenendo l'ordine usato durante il training
|
|
||||||
static_features.extend([variety_features[key] for key in sorted(variety_features.keys())])
|
|
||||||
|
|
||||||
return np.array(static_features)
|
|
||||||
|
|
||||||
def clean_column_name(name):
|
def clean_column_name(name):
|
||||||
# Rimuove caratteri speciali e spazi, converte in snake_case e abbrevia
|
# Rimuove caratteri speciali e spazi, converte in snake_case e abbrevia
|
||||||
name = re.sub(r'[^a-zA-Z0-9\s]', '', name) # Rimuove caratteri speciali
|
name = re.sub(r'[^a-zA-Z0-9\s]', '', name) # Rimuove caratteri speciali
|
||||||
@@ -367,52 +322,21 @@ def clean_column_name(name):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
# Funzioni di supporto per la dashboard
|
# Funzioni di supporto per la dashboard
|
||||||
def prepare_prediction_data(weather_data, varieties_info, percentages, hectares):
|
def prepare_static_features_multiple(varieties_info, percentages, hectares, all_varieties):
|
||||||
"""
|
|
||||||
Prepara i dati per la predizione con multiple varietà.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
weather_data: DataFrame con i dati meteorologici
|
|
||||||
varieties_info: Lista di Series con le informazioni delle varietà selezionate
|
|
||||||
percentages: Lista con le percentuali per ogni varietà
|
|
||||||
hectares: Numero di ettari totali
|
|
||||||
"""
|
|
||||||
# Prepara dati temporali
|
|
||||||
monthly_stats = weather_data.groupby(['year', 'month']).agg({
|
|
||||||
'temp': 'mean',
|
|
||||||
'precip': 'sum',
|
|
||||||
'solarradiation': 'sum'
|
|
||||||
}).reset_index()
|
|
||||||
|
|
||||||
temporal_features = ['temp_mean', 'precip_sum', 'solar_energy_sum']
|
|
||||||
temporal_data = monthly_stats.rename(columns={
|
|
||||||
'temp': 'temp_mean',
|
|
||||||
'precip': 'precip_sum',
|
|
||||||
'solarradiation': 'solar_energy_sum'
|
|
||||||
})[temporal_features].values[-41:] # Ultimi 41 timestep come nel training
|
|
||||||
|
|
||||||
temporal_data = scaler_temporal.transform(temporal_data)
|
|
||||||
temporal_data = np.expand_dims(temporal_data, axis=0)
|
|
||||||
|
|
||||||
# Prepara dati statici per tutte le varietà
|
|
||||||
static_data = prepare_static_features_multiple(varieties_info, percentages, hectares)
|
|
||||||
static_data = np.expand_dims(static_data, axis=0)
|
|
||||||
static_data = scaler_static.transform(static_data)
|
|
||||||
|
|
||||||
return {'temporal': temporal_data, 'static': static_data}
|
|
||||||
|
|
||||||
def prepare_static_features_multiple(varieties_info, percentages, hectares):
|
|
||||||
"""
|
"""
|
||||||
Prepara le feature statiche per multiple varietà seguendo la struttura esatta della simulazione.
|
Prepara le feature statiche per multiple varietà seguendo la struttura esatta della simulazione.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
varieties_info: Lista di Series con le informazioni delle varietà selezionate
|
varieties_info (list): Lista di dizionari contenenti le informazioni sulle varietà selezionate
|
||||||
percentages: Lista con le percentuali per ogni varietà
|
percentages (list): Lista delle percentuali corrispondenti a ciascuna varietà selezionata
|
||||||
hectares: Numero di ettari totali
|
hectares (float): Numero di ettari totali
|
||||||
|
all_varieties (list): Lista di tutte le possibili varietà nel dataset originale
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
np.array: Array numpy contenente tutte le feature statiche
|
||||||
"""
|
"""
|
||||||
# Inizializza un dizionario per tutte le varietà possibili
|
# Inizializza un dizionario per tutte le varietà possibili
|
||||||
variety_data = {clean_column_name(variety): {
|
variety_data = {variety: {
|
||||||
'tech': '',
|
|
||||||
'pct': 0,
|
'pct': 0,
|
||||||
'prod_t_ha': 0,
|
'prod_t_ha': 0,
|
||||||
'oil_prod_t_ha': 0,
|
'oil_prod_t_ha': 0,
|
||||||
@@ -426,12 +350,8 @@ def prepare_static_features_multiple(varieties_info, percentages, hectares):
|
|||||||
'min_l_per_t': 0,
|
'min_l_per_t': 0,
|
||||||
'max_l_per_t': 0,
|
'max_l_per_t': 0,
|
||||||
'avg_l_per_t': 0,
|
'avg_l_per_t': 0,
|
||||||
'olive_prod': 0,
|
'tech': ''
|
||||||
'min_oil_prod': 0,
|
} for variety in all_varieties}
|
||||||
'max_oil_prod': 0,
|
|
||||||
'avg_oil_prod': 0,
|
|
||||||
'water_need': 0
|
|
||||||
} for variety in olive_varieties['Varietà di Olive'].unique()}
|
|
||||||
|
|
||||||
# Aggiorna i dati per le varietà selezionate
|
# Aggiorna i dati per le varietà selezionate
|
||||||
for variety_info, percentage in zip(varieties_info, percentages):
|
for variety_info, percentage in zip(varieties_info, percentages):
|
||||||
@@ -453,7 +373,6 @@ def prepare_static_features_multiple(varieties_info, percentages, hectares):
|
|||||||
) / 4 * percentage/100 * hectares
|
) / 4 * percentage/100 * hectares
|
||||||
|
|
||||||
variety_data[variety_name].update({
|
variety_data[variety_name].update({
|
||||||
'tech': technique,
|
|
||||||
'pct': percentage/100,
|
'pct': percentage/100,
|
||||||
'prod_t_ha': variety_info['Produzione (tonnellate/ettaro)'],
|
'prod_t_ha': variety_info['Produzione (tonnellate/ettaro)'],
|
||||||
'oil_prod_t_ha': variety_info['Produzione Olio (tonnellate/ettaro)'],
|
'oil_prod_t_ha': variety_info['Produzione Olio (tonnellate/ettaro)'],
|
||||||
@@ -467,31 +386,36 @@ def prepare_static_features_multiple(varieties_info, percentages, hectares):
|
|||||||
'min_l_per_t': variety_info['Min Litri per Tonnellata'],
|
'min_l_per_t': variety_info['Min Litri per Tonnellata'],
|
||||||
'max_l_per_t': variety_info['Max Litri per Tonnellata'],
|
'max_l_per_t': variety_info['Max Litri per Tonnellata'],
|
||||||
'avg_l_per_t': variety_info['Media Litri per Tonnellata'],
|
'avg_l_per_t': variety_info['Media Litri per Tonnellata'],
|
||||||
'olive_prod': annual_prod,
|
'tech': technique
|
||||||
'min_oil_prod': min_oil_prod,
|
|
||||||
'max_oil_prod': max_oil_prod,
|
|
||||||
'avg_oil_prod': avg_oil_prod,
|
|
||||||
'water_need': base_water_need
|
|
||||||
})
|
})
|
||||||
|
|
||||||
# Crea il vettore delle feature nell'ordine esatto
|
# Crea il vettore delle feature nell'ordine esatto
|
||||||
static_features = [hectares] # Inizia con gli ettari
|
static_features = [hectares] # Inizia con gli ettari
|
||||||
|
|
||||||
|
# Lista delle feature per ogni varietà
|
||||||
|
variety_features = ['pct', 'prod_t_ha', 'oil_prod_t_ha', 'oil_prod_l_ha', 'min_yield_pct', 'max_yield_pct',
|
||||||
|
'min_oil_prod_l_ha', 'max_oil_prod_l_ha', 'avg_oil_prod_l_ha', 'l_per_t', 'min_l_per_t',
|
||||||
|
'max_l_per_t', 'avg_l_per_t']
|
||||||
|
|
||||||
# Appiattisci i dati delle varietà mantenendo l'ordine esatto
|
# Appiattisci i dati delle varietà mantenendo l'ordine esatto
|
||||||
flattened_variety_data = {
|
for variety in all_varieties:
|
||||||
f'{variety}_{key}': value
|
# Feature esistenti
|
||||||
for variety, data in sorted(variety_data.items()) # Ordina per nome varietà
|
for feature in variety_features:
|
||||||
for key, value in sorted(data.items()) # Ordina per nome feature
|
static_features.append(variety_data[variety][feature])
|
||||||
}
|
|
||||||
|
|
||||||
# Aggiungi le feature nell'ordine corretto
|
# Feature binarie per le tecniche di coltivazione
|
||||||
static_features.extend([flattened_variety_data[key] for key in sorted(flattened_variety_data.keys())])
|
for technique in ['tradizionale', 'intensiva', 'superintensiva']:
|
||||||
|
static_features.append(1 if variety_data[variety]['tech'] == technique else 0)
|
||||||
|
|
||||||
return np.array(static_features)
|
print(f"lunghezza features {len(static_features)} ")
|
||||||
|
|
||||||
|
return np.array(static_features).reshape(1, -1)
|
||||||
|
|
||||||
def make_prediction(weather_data, varieties_info, percentages, hectares):
|
def make_prediction(weather_data, varieties_info, percentages, hectares):
|
||||||
"""Effettua una predizione usando il modello."""
|
"""Effettua una predizione usando il modello."""
|
||||||
try:
|
try:
|
||||||
|
print("Inizio della funzione make_prediction")
|
||||||
|
|
||||||
# Prepara i dati meteorologici mensili
|
# Prepara i dati meteorologici mensili
|
||||||
monthly_stats = weather_data.groupby(['year', 'month']).agg({
|
monthly_stats = weather_data.groupby(['year', 'month']).agg({
|
||||||
'temp': 'mean',
|
'temp': 'mean',
|
||||||
@@ -505,17 +429,42 @@ def make_prediction(weather_data, varieties_info, percentages, hectares):
|
|||||||
'solarradiation': 'solar_energy_sum'
|
'solarradiation': 'solar_energy_sum'
|
||||||
})
|
})
|
||||||
|
|
||||||
# Prendi gli ultimi 41 mesi di dati
|
print(f"Shape dei dati meteorologici mensili: {monthly_stats.shape}")
|
||||||
temporal_data = monthly_stats[['temp_mean', 'precip_sum', 'solar_energy_sum']].values[-41:]
|
|
||||||
|
# Definisci la dimensione della finestra temporale
|
||||||
|
window_size = 41
|
||||||
|
|
||||||
|
# Prendi gli ultimi window_size mesi di dati
|
||||||
|
if len(monthly_stats) >= window_size:
|
||||||
|
temporal_data = monthly_stats[['temp_mean', 'precip_sum', 'solar_energy_sum']].values[-window_size:]
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Non ci sono abbastanza dati meteorologici. Necessari almeno {window_size} mesi.")
|
||||||
|
|
||||||
|
print(f"Shape dei dati temporali prima della trasformazione: {temporal_data.shape}")
|
||||||
|
|
||||||
temporal_data = scaler_temporal.transform(temporal_data)
|
temporal_data = scaler_temporal.transform(temporal_data)
|
||||||
|
print(f"Shape dei dati temporali dopo la trasformazione: {temporal_data.shape}")
|
||||||
|
|
||||||
temporal_data = np.expand_dims(temporal_data, axis=0)
|
temporal_data = np.expand_dims(temporal_data, axis=0)
|
||||||
|
print(f"Shape finale dei dati temporali: {temporal_data.shape}")
|
||||||
|
|
||||||
|
all_varieties = olive_varieties['Varietà di Olive'].unique()
|
||||||
|
varieties = [clean_column_name(variety) for variety in all_varieties]
|
||||||
|
|
||||||
# Prepara i dati statici
|
# Prepara i dati statici
|
||||||
static_data = prepare_static_features_multiple(varieties_info, percentages, hectares)
|
print("Preparazione dei dati statici")
|
||||||
static_data = np.expand_dims(static_data, axis=0)
|
static_data = prepare_static_features_multiple(varieties_info, percentages, hectares,varieties)
|
||||||
|
|
||||||
|
# Verifica che il numero di feature statiche sia corretto
|
||||||
|
if static_data.shape[1] != scaler_static.n_features_in_:
|
||||||
|
print("ATTENZIONE: Il numero di feature statiche non corrisponde a quello atteso dallo scaler!")
|
||||||
|
print(f"Feature generate: {static_data.shape[1]}, Feature attese: {scaler_static.n_features_in_}")
|
||||||
|
|
||||||
static_data = scaler_static.transform(static_data)
|
static_data = scaler_static.transform(static_data)
|
||||||
|
print(f"Shape dei dati statici dopo la trasformazione: {static_data.shape}")
|
||||||
|
|
||||||
# Effettua la predizione
|
# Effettua la predizione
|
||||||
|
print("Effettuazione della predizione")
|
||||||
prediction = model.predict({'temporal': temporal_data, 'static': static_data})
|
prediction = model.predict({'temporal': temporal_data, 'static': static_data})
|
||||||
prediction = scaler_y.inverse_transform(prediction)[0]
|
prediction = scaler_y.inverse_transform(prediction)[0]
|
||||||
|
|
||||||
@@ -551,6 +500,10 @@ def make_prediction(weather_data, varieties_info, percentages, hectares):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Errore durante la preparazione dei dati o la predizione: {str(e)}")
|
print(f"Errore durante la preparazione dei dati o la predizione: {str(e)}")
|
||||||
|
print(f"Tipo di errore: {type(e).__name__}")
|
||||||
|
import traceback
|
||||||
|
print("Traceback completo:")
|
||||||
|
print(traceback.format_exc())
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
# Definizione del layout della dashboard
|
# Definizione del layout della dashboard
|
||||||
@@ -783,65 +736,6 @@ app.layout = dbc.Container([
|
|||||||
])
|
])
|
||||||
], fluid=True)
|
], fluid=True)
|
||||||
|
|
||||||
def prepare_static_features_multiple(varieties_info, percentages, hectares):
|
|
||||||
"""Prepara le feature statiche per multiple varietà."""
|
|
||||||
static_features = [hectares] # Inizia con gli ettari totali
|
|
||||||
|
|
||||||
# Dizionario per tenere traccia delle feature per ogni varietà possibile
|
|
||||||
all_varieties = olive_varieties['Varietà di Olive'].unique()
|
|
||||||
variety_features = {}
|
|
||||||
|
|
||||||
# Inizializza tutte le feature a 0 per tutte le varietà possibili
|
|
||||||
for variety in all_varieties:
|
|
||||||
variety_name = variety.lower().replace(" ", "_").replace("'", "")
|
|
||||||
# Feature base
|
|
||||||
variety_features[f'{variety_name}_pct'] = 0
|
|
||||||
variety_features[f'{variety_name}_prod_t_ha'] = 0
|
|
||||||
variety_features[f'{variety_name}_oil_prod_t_ha'] = 0
|
|
||||||
variety_features[f'{variety_name}_oil_prod_l_ha'] = 0
|
|
||||||
variety_features[f'{variety_name}_min_yield_pct'] = 0
|
|
||||||
variety_features[f'{variety_name}_max_yield_pct'] = 0
|
|
||||||
variety_features[f'{variety_name}_min_oil_prod_l_ha'] = 0
|
|
||||||
variety_features[f'{variety_name}_max_oil_prod_l_ha'] = 0
|
|
||||||
variety_features[f'{variety_name}_avg_oil_prod_l_ha'] = 0
|
|
||||||
variety_features[f'{variety_name}_l_per_t'] = 0
|
|
||||||
variety_features[f'{variety_name}_min_l_per_t'] = 0
|
|
||||||
variety_features[f'{variety_name}_max_l_per_t'] = 0
|
|
||||||
variety_features[f'{variety_name}_avg_l_per_t'] = 0
|
|
||||||
# Feature tecniche
|
|
||||||
variety_features[f'{variety_name}_tradizionale'] = 0
|
|
||||||
variety_features[f'{variety_name}_intensiva'] = 0
|
|
||||||
variety_features[f'{variety_name}_superintensiva'] = 0
|
|
||||||
|
|
||||||
# Aggiorna le feature per le varietà selezionate
|
|
||||||
for variety_info, percentage in zip(varieties_info, percentages):
|
|
||||||
if variety_info is not None and percentage > 0:
|
|
||||||
variety_name = variety_info['Varietà di Olive'].lower().replace(" ", "_").replace("'", "")
|
|
||||||
technique = variety_info['Tecnica di Coltivazione'].lower()
|
|
||||||
|
|
||||||
# Aggiorna le feature della varietà
|
|
||||||
variety_features[f'{variety_name}_pct'] = percentage / 100
|
|
||||||
variety_features[f'{variety_name}_prod_t_ha'] = variety_info['Produzione (tonnellate/ettaro)']
|
|
||||||
variety_features[f'{variety_name}_oil_prod_t_ha'] = variety_info['Produzione Olio (tonnellate/ettaro)']
|
|
||||||
variety_features[f'{variety_name}_oil_prod_l_ha'] = variety_info['Produzione Olio (litri/ettaro)']
|
|
||||||
variety_features[f'{variety_name}_min_yield_pct'] = variety_info['Min % Resa']
|
|
||||||
variety_features[f'{variety_name}_max_yield_pct'] = variety_info['Max % Resa']
|
|
||||||
variety_features[f'{variety_name}_min_oil_prod_l_ha'] = variety_info['Min Produzione Olio (litri/ettaro)']
|
|
||||||
variety_features[f'{variety_name}_max_oil_prod_l_ha'] = variety_info['Max Produzione Olio (litri/ettaro)']
|
|
||||||
variety_features[f'{variety_name}_avg_oil_prod_l_ha'] = variety_info['Media Produzione Olio (litri/ettaro)']
|
|
||||||
variety_features[f'{variety_name}_l_per_t'] = variety_info['Litri per Tonnellata']
|
|
||||||
variety_features[f'{variety_name}_min_l_per_t'] = variety_info['Min Litri per Tonnellata']
|
|
||||||
variety_features[f'{variety_name}_max_l_per_t'] = variety_info['Max Litri per Tonnellata']
|
|
||||||
variety_features[f'{variety_name}_avg_l_per_t'] = variety_info['Media Litri per Tonnellata']
|
|
||||||
|
|
||||||
# Aggiorna la tecnica
|
|
||||||
variety_features[f'{variety_name}_{technique}'] = 1
|
|
||||||
|
|
||||||
# Converti il dizionario in lista mantenendo l'ordine
|
|
||||||
static_features.extend([variety_features[key] for key in sorted(variety_features.keys())])
|
|
||||||
|
|
||||||
return np.array(static_features)
|
|
||||||
|
|
||||||
# Callback per la gestione delle percentuali e abilitazione dei campi
|
# Callback per la gestione delle percentuali e abilitazione dei campi
|
||||||
@app.callback(
|
@app.callback(
|
||||||
[Output('technique-2-dropdown', 'disabled'),
|
[Output('technique-2-dropdown', 'disabled'),
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -406,7 +406,152 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"source": "def prepare_data(df, olive_varieties_df):\n # Crea una copia del DataFrame per evitare modifiche all'originale\n df = df.copy()\n\n # Ordina per zona e anno\n df = df.sort_values(['zone', 'year'])\n\n # Definisci le feature\n temporal_features = ['temp_mean', 'precip_sum', 'solar_energy_sum']\n static_features = ['ha'] # Feature statiche base\n target_features = ['olive_prod', 'min_oil_prod', 'max_oil_prod', 'avg_oil_prod', 'total_water_need']\n\n # Ottieni le varietà pulite\n varieties = [clean_column_name(variety) for variety in olive_varieties_df['Varietà di Olive']]\n\n # Crea la struttura delle feature per ogni varietà\n variety_features = [\n 'tech', 'pct', 'prod_t_ha', 'oil_prod_t_ha', 'oil_prod_l_ha',\n 'min_yield_pct', 'max_yield_pct', 'min_oil_prod_l_ha', 'max_oil_prod_l_ha',\n 'avg_oil_prod_l_ha', 'l_per_t', 'min_l_per_t', 'max_l_per_t', 'avg_l_per_t'\n ]\n\n # Prepara dizionari per le nuove colonne\n new_columns = {}\n\n # Prepara le feature per ogni varietà\n for variety in varieties:\n # Feature esistenti\n for feature in variety_features:\n col_name = f\"{variety}_{feature}\"\n if col_name in df.columns:\n if feature != 'tech': # Non includere la colonna tech direttamente\n static_features.append(col_name)\n\n # Feature binarie per le tecniche di coltivazione\n for technique in ['tradizionale', 'intensiva', 'superintensiva']:\n col_name = f\"{variety}_{technique}\"\n new_columns[col_name] = df[f\"{variety}_tech\"].notna() & (\n df[f\"{variety}_tech\"].str.lower() == technique\n ).fillna(False)\n static_features.append(col_name)\n\n # Aggiungi tutte le nuove colonne in una volta sola\n new_df = pd.concat([df] + [pd.Series(v, name=k) for k, v in new_columns.items()], axis=1)\n\n # Ordiniamo per zona e anno per mantenere la continuità temporale\n df_sorted = new_df.sort_values(['zone', 'year'])\n\n # Definiamo la dimensione della finestra temporale\n window_size = 41\n\n # Liste per raccogliere i dati\n temporal_sequences = []\n static_features_list = []\n targets_list = []\n\n # Iteriamo per ogni zona\n for zone in df_sorted['zone'].unique():\n zone_data = df_sorted[df_sorted['zone'] == zone].reset_index(drop=True)\n\n if len(zone_data) >= window_size: # Verifichiamo che ci siano abbastanza dati\n # Creiamo sequenze temporali scorrevoli\n for i in range(len(zone_data) - window_size + 1):\n # Sequenza temporale\n temporal_window = zone_data.iloc[i:i + window_size][temporal_features].values\n # Verifichiamo che non ci siano valori NaN\n if not np.isnan(temporal_window).any():\n temporal_sequences.append(temporal_window)\n\n # Feature statiche (prendiamo quelle dell'ultimo timestep della finestra)\n static_features_list.append(zone_data.iloc[i + window_size - 1][static_features].values)\n\n # Target (prendiamo quelli dell'ultimo timestep della finestra)\n targets_list.append(zone_data.iloc[i + window_size - 1][target_features].values)\n\n # Convertiamo in array numpy\n X_temporal = np.array(temporal_sequences)\n X_static = np.array(static_features_list)\n y = np.array(targets_list)\n\n print(f\"Dataset completo - Temporal: {X_temporal.shape}, Static: {X_static.shape}, Target: {y.shape}\")\n\n # Split dei dati (usando indici casuali per una migliore distribuzione)\n indices = np.random.permutation(len(X_temporal))\n #train_idx = int(len(indices) * 0.7)\n #val_idx = int(len(indices) * 0.85)\n \n train_idx = int(len(indices) * 0.65) # 65% training\n val_idx = int(len(indices) * 0.85) # 20% validation\n # Il resto rimane 15% test\n\n # Oppure versione con 25% validation:\n #train_idx = int(len(indices) * 0.60) # 60% training\n #val_idx = int(len(indices) * 0.85) # 25% validation\n\n train_indices = indices[:train_idx]\n val_indices = indices[train_idx:val_idx]\n test_indices = indices[val_idx:]\n\n # Split dei dati\n X_temporal_train = X_temporal[train_indices]\n X_temporal_val = X_temporal[val_indices]\n X_temporal_test = X_temporal[test_indices]\n\n X_static_train = X_static[train_indices]\n X_static_val = X_static[val_indices]\n X_static_test = X_static[test_indices]\n\n y_train = y[train_indices]\n y_val = y[val_indices]\n y_test = y[test_indices]\n\n # Standardizzazione\n scaler_temporal = StandardScaler()\n scaler_static = StandardScaler()\n scaler_y = StandardScaler()\n\n # Standardizzazione dei dati temporali\n X_temporal_train = scaler_temporal.fit_transform(X_temporal_train.reshape(-1, len(temporal_features))).reLine truncated
|
"source": [
|
||||||
|
"def prepare_data(df, olive_varieties_df):\n",
|
||||||
|
" # Crea una copia del DataFrame per evitare modifiche all'originale\n",
|
||||||
|
" df = df.copy()\n",
|
||||||
|
"\n",
|
||||||
|
" # Ordina per zona e anno\n",
|
||||||
|
" df = df.sort_values(['zone', 'year'])\n",
|
||||||
|
"\n",
|
||||||
|
" # Definisci le feature\n",
|
||||||
|
" temporal_features = ['temp_mean', 'precip_sum', 'solar_energy_sum']\n",
|
||||||
|
" static_features = ['ha'] # Feature statiche base\n",
|
||||||
|
" target_features = ['olive_prod', 'min_oil_prod', 'max_oil_prod', 'avg_oil_prod', 'total_water_need']\n",
|
||||||
|
"\n",
|
||||||
|
" # Ottieni le varietà pulite\n",
|
||||||
|
" all_varieties = olive_varieties_df['Varietà di Olive'].unique()\n",
|
||||||
|
" varieties = [clean_column_name(variety) for variety in all_varieties]\n",
|
||||||
|
"\n",
|
||||||
|
" # Crea la struttura delle feature per ogni varietà\n",
|
||||||
|
" variety_features = [\n",
|
||||||
|
" 'tech', 'pct', 'prod_t_ha', 'oil_prod_t_ha', 'oil_prod_l_ha',\n",
|
||||||
|
" 'min_yield_pct', 'max_yield_pct', 'min_oil_prod_l_ha', 'max_oil_prod_l_ha',\n",
|
||||||
|
" 'avg_oil_prod_l_ha', 'l_per_t', 'min_l_per_t', 'max_l_per_t', 'avg_l_per_t'\n",
|
||||||
|
" ]\n",
|
||||||
|
"\n",
|
||||||
|
" # Prepara dizionari per le nuove colonne\n",
|
||||||
|
" new_columns = {}\n",
|
||||||
|
"\n",
|
||||||
|
" # Prepara le feature per ogni varietà\n",
|
||||||
|
" for variety in varieties:\n",
|
||||||
|
" # Feature esistenti\n",
|
||||||
|
" for feature in variety_features:\n",
|
||||||
|
" col_name = f\"{variety}_{feature}\"\n",
|
||||||
|
" if col_name in df.columns:\n",
|
||||||
|
" if feature != 'tech': # Non includere la colonna tech direttamente\n",
|
||||||
|
" static_features.append(col_name)\n",
|
||||||
|
"\n",
|
||||||
|
" # Feature binarie per le tecniche di coltivazione\n",
|
||||||
|
" for technique in ['tradizionale', 'intensiva', 'superintensiva']:\n",
|
||||||
|
" col_name = f\"{variety}_{technique}\"\n",
|
||||||
|
" new_columns[col_name] = df[f\"{variety}_tech\"].notna() & (\n",
|
||||||
|
" df[f\"{variety}_tech\"].str.lower() == technique\n",
|
||||||
|
" ).fillna(False)\n",
|
||||||
|
" static_features.append(col_name)\n",
|
||||||
|
"\n",
|
||||||
|
" # Aggiungi tutte le nuove colonne in una volta sola\n",
|
||||||
|
" new_df = pd.concat([df] + [pd.Series(v, name=k) for k, v in new_columns.items()], axis=1)\n",
|
||||||
|
"\n",
|
||||||
|
" # Ordiniamo per zona e anno per mantenere la continuità temporale\n",
|
||||||
|
" df_sorted = new_df.sort_values(['zone', 'year'])\n",
|
||||||
|
"\n",
|
||||||
|
" # Definiamo la dimensione della finestra temporale\n",
|
||||||
|
" window_size = 41\n",
|
||||||
|
"\n",
|
||||||
|
" # Liste per raccogliere i dati\n",
|
||||||
|
" temporal_sequences = []\n",
|
||||||
|
" static_features_list = []\n",
|
||||||
|
" targets_list = []\n",
|
||||||
|
"\n",
|
||||||
|
" # Iteriamo per ogni zona\n",
|
||||||
|
" for zone in df_sorted['zone'].unique():\n",
|
||||||
|
" zone_data = df_sorted[df_sorted['zone'] == zone].reset_index(drop=True)\n",
|
||||||
|
"\n",
|
||||||
|
" if len(zone_data) >= window_size: # Verifichiamo che ci siano abbastanza dati\n",
|
||||||
|
" # Creiamo sequenze temporali scorrevoli\n",
|
||||||
|
" for i in range(len(zone_data) - window_size + 1):\n",
|
||||||
|
" # Sequenza temporale\n",
|
||||||
|
" temporal_window = zone_data.iloc[i:i + window_size][temporal_features].values\n",
|
||||||
|
" # Verifichiamo che non ci siano valori NaN\n",
|
||||||
|
" if not np.isnan(temporal_window).any():\n",
|
||||||
|
" temporal_sequences.append(temporal_window)\n",
|
||||||
|
"\n",
|
||||||
|
" # Feature statiche (prendiamo quelle dell'ultimo timestep della finestra)\n",
|
||||||
|
" static_features_list.append(zone_data.iloc[i + window_size - 1][static_features].values)\n",
|
||||||
|
"\n",
|
||||||
|
" # Target (prendiamo quelli dell'ultimo timestep della finestra)\n",
|
||||||
|
" targets_list.append(zone_data.iloc[i + window_size - 1][target_features].values)\n",
|
||||||
|
"\n",
|
||||||
|
" # Convertiamo in array numpy\n",
|
||||||
|
" X_temporal = np.array(temporal_sequences)\n",
|
||||||
|
" X_static = np.array(static_features_list)\n",
|
||||||
|
" y = np.array(targets_list)\n",
|
||||||
|
"\n",
|
||||||
|
" print(f\"Dataset completo - Temporal: {X_temporal.shape}, Static: {X_static.shape}, Target: {y.shape}\")\n",
|
||||||
|
"\n",
|
||||||
|
" # Split dei dati (usando indici casuali per una migliore distribuzione)\n",
|
||||||
|
" indices = np.random.permutation(len(X_temporal))\n",
|
||||||
|
" #train_idx = int(len(indices) * 0.7)\n",
|
||||||
|
" #val_idx = int(len(indices) * 0.85)\n",
|
||||||
|
" \n",
|
||||||
|
" train_idx = int(len(indices) * 0.65) # 65% training\n",
|
||||||
|
" val_idx = int(len(indices) * 0.85) # 20% validation\n",
|
||||||
|
" # Il resto rimane 15% test\n",
|
||||||
|
"\n",
|
||||||
|
" # Oppure versione con 25% validation:\n",
|
||||||
|
" #train_idx = int(len(indices) * 0.60) # 60% training\n",
|
||||||
|
" #val_idx = int(len(indices) * 0.85) # 25% validation\n",
|
||||||
|
"\n",
|
||||||
|
" train_indices = indices[:train_idx]\n",
|
||||||
|
" val_indices = indices[train_idx:val_idx]\n",
|
||||||
|
" test_indices = indices[val_idx:]\n",
|
||||||
|
"\n",
|
||||||
|
" # Split dei dati\n",
|
||||||
|
" X_temporal_train = X_temporal[train_indices]\n",
|
||||||
|
" X_temporal_val = X_temporal[val_indices]\n",
|
||||||
|
" X_temporal_test = X_temporal[test_indices]\n",
|
||||||
|
"\n",
|
||||||
|
" X_static_train = X_static[train_indices]\n",
|
||||||
|
" X_static_val = X_static[val_indices]\n",
|
||||||
|
" X_static_test = X_static[test_indices]\n",
|
||||||
|
"\n",
|
||||||
|
" y_train = y[train_indices]\n",
|
||||||
|
" y_val = y[val_indices]\n",
|
||||||
|
" y_test = y[test_indices]\n",
|
||||||
|
"\n",
|
||||||
|
" # Standardizzazione\n",
|
||||||
|
" scaler_temporal = StandardScaler()\n",
|
||||||
|
" scaler_static = StandardScaler()\n",
|
||||||
|
" scaler_y = StandardScaler()\n",
|
||||||
|
"\n",
|
||||||
|
" # Standardizzazione dei dati temporali\n",
|
||||||
|
" X_temporal_train = scaler_temporal.fit_transform(X_temporal_train.reshape(-1, len(temporal_features))).reshape(X_temporal_train.shape)\n",
|
||||||
|
" X_temporal_val = scaler_temporal.transform(X_temporal_val.reshape(-1, len(temporal_features))).reshape(X_temporal_val.shape)\n",
|
||||||
|
" X_temporal_test = scaler_temporal.transform(X_temporal_test.reshape(-1, len(temporal_features))).reshape(X_temporal_test.shape)\n",
|
||||||
|
"\n",
|
||||||
|
" # Standardizzazione dei dati statici\n",
|
||||||
|
" X_static_train = scaler_static.fit_transform(X_static_train)\n",
|
||||||
|
" X_static_val = scaler_static.transform(X_static_val)\n",
|
||||||
|
" X_static_test = scaler_static.transform(X_static_test)\n",
|
||||||
|
"\n",
|
||||||
|
" # Standardizzazione dei target\n",
|
||||||
|
" y_train = scaler_y.fit_transform(y_train)\n",
|
||||||
|
" y_val = scaler_y.transform(y_val)\n",
|
||||||
|
" y_test = scaler_y.transform(y_test)\n",
|
||||||
|
"\n",
|
||||||
|
" print(\"\\nShape dopo lo split e standardizzazione:\")\n",
|
||||||
|
" print(f\"Train - Temporal: {X_temporal_train.shape}, Static: {X_static_train.shape}, Target: {y_train.shape}\")\n",
|
||||||
|
" print(f\"Val - Temporal: {X_temporal_val.shape}, Static: {X_static_val.shape}, Target: {y_val.shape}\")\n",
|
||||||
|
" print(f\"Test - Temporal: {X_temporal_test.shape}, Static: {X_static_test.shape}, Target: {y_test.shape}\")\n",
|
||||||
|
"\n",
|
||||||
|
" # Prepara i dizionari di input\n",
|
||||||
|
" train_data = {'temporal': X_temporal_train, 'static': X_static_train}\n",
|
||||||
|
" val_data = {'temporal': X_temporal_val, 'static': X_static_val}\n",
|
||||||
|
" test_data = {'temporal': X_temporal_test, 'static': X_static_test}\n",
|
||||||
|
"\n",
|
||||||
|
" return (train_data, y_train), (val_data, y_val), (test_data, y_test), (scaler_temporal, scaler_static, scaler_y)"
|
||||||
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"execution": {
|
"execution": {
|
||||||
"iopub.status.busy": "2024-10-28T18:19:04.089809Z",
|
"iopub.status.busy": "2024-10-28T18:19:04.089809Z",
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user