Dalle schede perforate al ChatGPT

Dai buchi delle schede alla ChatGPT l'evoluzione della tecnologia

Lo sguardo di mio nonno sull’Intelligenza Artificiale generativa

Mio nonno materno, Skip, è sempre stato un contadino ai miei occhi. Tragicamente, mia madre è morta di leucemia solo un mese dopo la mia nascita nel 1988. Essendo il primo nipote della famiglia, io e Skip eravamo molto legati. Da bambino trascorrevo le giornate cavalcando il bracciolo dei trattori e delle mietitrebbie durante la raccolta annuale di grano – e quando sono diventato adolescente, ho lavorato come lavoro estivo nella fattoria.

Vista aerea di una mietitrebbia John Deere durante la raccolta estiva del grano. Mio nonno e io ne abbiamo usate due durante le nostre stagioni di raccolta del grano alla fine degli anni '90 / primi anni 2000. È stato il mio primo 'lavoro'. Foto di Scott Goodwill su Unsplash

Eppure, la vita precedente di Skip era molto diversa dal mondo agricolo che conoscevo. Prima della mia comparsa, si era immerse nelle accademie completando i suoi corsi di dottorato in Statistica presso l’Università del Texas A&M, College Station, nel 1972. Poco dopo, ha abbracciato una cattedra presso l’Università del Maryland, completando la sua tesi nel 1974. La sua ricerca innovativa mirava a prevedere e individuare rischi di sicurezza e materiali negli ambienti industriali. Questa mole di lavoro richiedeva anni di sforzo. Doveva raccogliere manualmente rapporti di incidenti di diverse società degli ultimi dieci anni, elaborare le statistiche manualmente, e quindi convertire queste informazioni in istruzioni per schede perforate per il sistema informatico dell’università. Ottenere tempo su quel computer non era immediato; richiedeva prenotazioni fatte settimane o addirittura mesi prima. Un solo errore di codice poteva significare ricominciare da capo, rallentando potenzialmente la sua ricerca di diversi mesi.

Lasciò quella vita negli anni ’80 per prendere in mano la fattoria di famiglia nel Texas orientale e intraprendere l’imprenditoria. Ma il desiderio di sfruttare l’inferenza statistica era intrinseco in tutto ciò che faceva come agricoltore – io non me ne rendevo conto da bambino. Per la mia mentalità infantile, Skip faceva “lavoro d’ufficio”, come lo chiamava lui; ma in realtà stava sfruttando l’informatica per prevedere e ottenere finanziamenti per sostenere le sue spese operative, ottimizzava la chimica dei fertilizzanti per aumentare i raccolti, sviluppava strategie per ridurre l’incertezza dei flussi di cassa attraverso il trading di prodotti futuri presso il Chicago Commodity Exchange, tutto tramite un TRS 80 che aveva comprato da Radio Shack con 16 KB di RAM collegato a una stampante a matrice di punti. L’agricoltura può essere un business a margine molto basso – e l’idea di Skip era che potesse utilizzare le statistiche per livellare un po’ il campo.

Nel corso degli anni, la fattoria non ha superato la prova del tempo. Scopri che l’attività agricola intergenerazionale non va molto bene quando si salta una generazione – e i costi degli input di oggi sono più implacabili che mai – l’economia di scala diventa l’unico modo per competere in modo redditizio – e così la maggior parte dei piccoli e medi agricoltori della generazione di Skip sono stati comprati e consolidati – ma accade gradualmente – poco a poco (almeno è successo per noi).

Io, naturalmente, ho imparato ad apprezzare la forte connessione tra le statistiche e l’agricoltura. Ricordo ancora la visita annuale del Dipartimento dell’Agricoltura degli Stati Uniti che campionava attentamente i raccolti (in ogni azienda agricola, compresa la nostra) come parte del loro servizio di Statistiche Agricole Nazionali. Che fornisce, secondo me, uno dei grandi progetti dati insuperati e in corso nella storia – aiutando generazioni di agricoltori a prendere decisioni “basate sui dati” – prima che fosse una parola alla moda. Ma ho trovato ancora più apprezzamento per tutto quello che Skip ha fatto decenni dopo mentre intraprendevo la mia carriera di Analisi e Scienza dei Dati – il mio secondo atto dopo aver trascorso i miei anni ’20 e ’30 servendo e viaggiando come ufficiale dell’esercito degli Stati Uniti. Riaccordo spesso con lui al telefono chiedendogli di raccontarmi come facevano le regressioni o le simulazioni o come tenevano conto del campionamento casuale “ai vecchi tempi”. E poi occasionalmente gli racconto come lo stiamo facendo ora, per percepire la sua eccitazione mentre gli descrivo concetti come l’apprendimento automatico, il deep learning, l’apprendimento per rinforzo – – è un po’ fantascienza per lui – ma gli piace sentirne parlare – anche se non è del tutto reale per lui a quest’età avanzata.

Ho dato a Skip aggiornamenti in tempo reale quando ho visto John Deere presentare il loro discorso principale al CES nel gennaio 2023 - mostrando nuove attrezzature, come il trattore raffigurato sopra, che utilizza 36 telecamere, visione artificiale e reti neurali per rilevare le erbacce dai raccolti in tempo reale e ridurre al minimo l'uso di erbicidi. Immagine dell'autore.

Entra nell’esperimento.

Ho deciso nel weekend di mostrare anziché raccontare. Volevo che Skip sperimentasse la nuova tecnologia di persona, non solo che la sentisse descrivere. E se potessimo creare un piano aziendale per avviare una nuova fattoria ipotetica in meno di 40 minuti? Potevo farlo utilizzando un ChatGPT 4 con Analisi avanzata dei dati abilitata, condivisione dello schermo sul suo iPhone: avremmo collaborato insieme per crearlo.

Abbiamo brevemente discusso delle nostre supposizioni:

  1. Abbiamo 1.000 acri di terreno agricolo in Texas orientale
  2. Abbiamo $1 milione di capitale iniziale per l’acquisto di attrezzature
  3. Abbiamo bisogno di ottenere un credito da una banca per le spese operative dell’anno 1 per iniziare
  4. Siamo interessati a coltivare grano e soia (quello che Skip coltivava realmente ai tempi)

Abbiamo iniziato in modo semplice:

Prompt 1: “Scrivimi una struttura di un piano aziendale per avviare una nuova fattoria in Texas orientale per coltivare grano e soia”.

È chiaro che Skip è rimasto immediatamente impressionato dai risultati in forma estesa. Ma aspetta, stavamo appena cominciando…

Prompt 2: “Dammi un elenco delle attrezzature di cui ho bisogno per iniziare”Prompt 3: “Mettilo in una tabella e assegnagli una priorità numerica in base a ciò che è più urgente e meno urgente”Prompt 4: “ora crea una nuova colonna per l’allocazione del budget, Supponiamo che userò una combinazione di leasing e acquisti, crea una colonna aggiuntiva per consigliare leasing vs acquisto, supponendo di avere $1 milione di capitale iniziale.”

(Tempo trascorso 4 minuti)

Risultato:

Dati generati da GPT-4, Immagine dell'autore

Prompt 5: “Quanto devo mettere da parte per chiedere un credito di linea per i costi variabili (semi, fertilizzanti, lavoro, ecc.), supponendo 1.000 acri. Crea una nuova tabella”.

Risultato:

Dati generati da ChatGPT 4, Immagine dell'autore

A questo punto, mi sembrava che Skip avesse appena rivisto Apollo 11 ancora una volta. A stento riusciva a contenere la sua eccitazione. Ma non eravamo ancora finiti…

Prompt 6: “Scrivimi una simulazione Monte Carlo che posso regolare con le mie supposizioni di input e testare il risultato sul mio budget”

Risultato:

import numpy as npimport matplotlib.pyplot as plt# Definisci il numero di simulazionin_simulations = 10000# Supposizioni con [media, deviazione standard]costo_seme_grano = [20, 2]  # Costo per acrocosto_seme_soia = [50, 5]fertilizzante_grano_costo = [50, 5]fertilizzante_soia_costo = [40, 4]costo_lavoro = [25, 3]costo_pesticidi = [30, 3]costo_carburante_manutenzione = [15, 2]costi_vari = [10, 1]def simulare_costi_fattoria():    seme_grano = np.random.normal(costo_seme_grano[0], costo_seme_grano[1])    seme_soia = np.random.normal(costo_seme_soia[0], costo_seme_soia[1])    fertilizzante_grano = np.random.normal(fertilizzante_grano_costo[0], fertilizzante_grano_costo[1])    fertilizzante_soia = np.random.normal(fertilizzante_soia_costo[0], fertilizzante_soia_costo[1])    lavoro = np.random.normal(costo_lavoro[0], costo_lavoro[1])    pesticidi = np.random.normal(costo_pesticidi[0], costo_pesticidi[1])    carburante_manutenzione = np.random.normal(costo_carburante_manutenzione[0], costo_carburante_manutenzione[1])    vari = np.random.normal(costi_vari[0], costi_vari[1])        costo_totale = (seme_grano + seme_soia + fertilizzante_grano + fertilizzante_soia +                   lavoro + pesticidi + carburante_manutenzione + vari) * 1000  # per 1000 acri    return costo_totalerisultati = [simulare_costi_fattoria() for _ in range(n_simulations)]# Visualizzazioneplt.hist(risultati, bins=50, edgecolor='black', alpha=0.7)plt.title('Distribuzione dei costi totali della fattoria')plt.xlabel('Costo totale')plt.ylabel('Frequenza')plt.grid(True, alpha=0.2)plt.show()

Ed ora il momento della verità – il codice funzionerà? Siamo andati su Jupyter notebook per eseguire il codice. E lì è proprio al primo tentativo:

Data Generati da ChatGPT 4, Immagine Generata da Python, Immagine dell'Autore

A questo punto, eravamo solo a 10-15 minuti. Abbiamo ancora un po’ di tempo libero… Potremmo renderlo interattivo?

Dobbiamo creare una lista di parametri che consentano all’utente di regolare dinamicamente le ipotesi su uno slider. Di nuovo, rivolgiamo il ChatGPT per alcune raccomandazioni su quali devono essere quei parametri in base al Monte Carlo che abbiamo costruito in precedenza:

Dati Generati da GPT 4, Immagine dell'Autore

Una volta costruita la nostra lista di parametri, creiamo una tabella ‘misure’ in Power BI collegata a 16 grafici di selezione che consentono all’utente di selezionare manualmente i propri input e aggiornare dinamicamente la simulazione del Monte Carlo. Per fare ciò, creiamo una ‘Visualizzazione Python’ in Power BI, trasciniamo tutte le nostre misure e quindi aggiorniamo il codice come segue:

# Il codice seguente per creare un dataframe e rimuovere righe duplicate viene sempre eseguito e funge da preambolo per il tuo script: # dataset = pandas.DataFrame(fertilizer_soybean_cost_avg Value, fertilizer_soybean_cost_std Value, fertilizer_wheat_cost_avg Value, fertilizer_wheat_cost_std Value, fuel_maintenance_cost_avg Value, fuel_maintenance_cost_std Value, labor_cost_avg Value, labor_cost_std Value, miscellaneous_cost_avg Value, miscellaneous_cost_std Value, pesticide_cost_avg Value, pesticide_cost_std Value, soybean_seed_cost_avg Value, wheat_seed_cost_avg Value, wheat_seed_cost_std Value)# dataset = dataset.drop_duplicates()# Incolla o digita qui il codice dello script:import numpy as npimport pandas as pdimport matplotlib.pyplot as plt# Supponendo che i dati da Power BI siano passati come 'dataset'df = dataset# Recupera i valori dal datasetwheat_seed_cost_avg = df['wheat_seed_cost_avg Value'].iloc[0]wheat_seed_cost_std = df['wheat_seed_cost_std Value'].iloc[0]soybean_seed_cost_avg = df['soybean_seed_cost_avg Value'].iloc[0]soybean_seed_cost_std = df['soybean_seed_cost_std Value'].iloc[0]fertilizer_wheat_cost_avg = df['fertilizer_wheat_cost_avg Value'].iloc[0]fertilizer_wheat_cost_std = df['fertilizer_wheat_cost_std Value'].iloc[0]fertilizer_soybean_cost_avg = df['fertilizer_soybean_cost_avg Value'].iloc[0]fertilizer_soybean_cost_std = df['fertilizer_soybean_cost_std Value'].iloc[0]labor_cost_avg = df['labor_cost_avg Value'].iloc[0]labor_cost_std = df['labor_cost_std Value'].iloc[0]pesticide_cost_avg = df['pesticide_cost_avg Value'].iloc[0]pesticide_cost_std = df['pesticide_cost_std Value'].iloc[0]fuel_maintenance_cost_avg = df['fuel_maintenance_cost_avg Value'].iloc[0]fuel_maintenance_cost_std = df['fuel_maintenance_cost_std Value'].iloc[0]miscellaneous_cost_avg = df['miscellaneous_cost_avg Value'].iloc[0]miscellaneous_cost_std = df['miscellaneous_cost_std Value'].iloc[0]# Definisci il numero di simulazionin_simulations = 10000# Assunzioni con [media, deviazione standard]wheat_seed_cost = [wheat_seed_cost_avg, wheat_seed_cost_std]soybean_seed_cost = [soybean_seed_cost_avg, soybean_seed_cost_std]fertilizer_wheat_cost = [fertilizer_wheat_cost_avg, fertilizer_wheat_cost_std]fertilizer_soybean_cost = [fertilizer_soybean_cost_avg, fertilizer_soybean_cost_std]labor_cost = [labor_cost_avg, labor_cost_std]pesticide_cost = [pesticide_cost_avg, pesticide_cost_std]fuel_maintenance_cost = [fuel_maintenance_cost_avg, fuel_maintenance_cost_std]miscellaneous_cost = [miscellaneous_cost_avg, miscellaneous_cost_std]def simulate_farm_costs():    wheat_seed = np.random.normal(wheat_seed_cost[0], wheat_seed_cost[1])    soybean_seed = np.random.normal(soybean_seed_cost[0], soybean_seed_cost[1])    fertilizer_wheat = np.random.normal(fertilizer_wheat_cost[0], fertilizer_wheat_cost[1])    fertilizer_soybean = np.random.normal(fertilizer_soybean_cost[0], fertilizer_soybean_cost[1])    labor = np.random.normal(labor_cost[0], labor_cost[1])    pesticide = np.random.normal(pesticide_cost[0], pesticide_cost[1])    fuel_maintenance = np.random.normal(fuel_maintenance_cost[0], fuel_maintenance_cost[1])    miscellaneous = np.random.normal(miscellaneous_cost[0], miscellaneous_cost[1])    total_cost = (wheat_seed + soybean_seed + fertilizer_wheat + fertilizer_soybean +                  labor + pesticide + fuel_maintenance + miscellaneous) * 1000  # per 1000 acri    return total_costresults = [simulate_farm_costs() for _ in range(n_simulations)]# Converte i risultati in un dataframe df_simulated_results = pd.DataFrame(results, columns=['Costo Totale'])# Calcola la gamma interquartile (IQR)Q1 = df_simulated_results['Costo Totale'].quantile(0.25)Q3 = df_simulated_results['Costo Totale'].quantile(0.75)# Disegna l'istogramma plt.figure(figsize=(10, 6))n, bins, patches = plt.hist(df_simulated_results['Costo Totale'], bins=50, color='blue', edgecolor='black', alpha=0.7)plt.title('Distribuzione dei Costi Variabili dell\'Anno 1 dalla Simulazione')plt.xlabel('Costo Variabile dell\'Anno 1')plt.ylabel('Frequenza')plt.grid(True, which='both', linestyle='--', linewidth=0.5)# Ombreggia l'IQRfor i in range(len(bins)):    if bins[i] > Q1 and bins[i] < Q3:        patches[i].set_facecolor('green')plt.axvline(Q1, color='red', linestyle='dashed', linewidth=1)plt.axvline(Q3, color='red', linestyle='dashed', linewidth=1)plt.tight_layout()plt.savefig('istogramma_costi_simulati.png')  # Salva l'immagineplt.show()

Solo per divertimento, abbiamo chiesto a ChatGPT di definire l’Interquartile Range (IQR) e di colorarlo in modo diverso, abbiamo anche aggiornato manualmente le etichette del grafico e l’asse x. Il resto riguarda solo una pulizia visiva in Power BI per renderlo un po’ più user-friendly. Il risultato finale:

Dati generati da una simulazione Monte Carlo basata su input di parametri selezionati dall'utente, codice Python generato da ChatGPT 4, dashboard creata in MS PowerBI, immagine dell'autore

Ora abbiamo una simulazione di Monte Carlo dinamica per giocare con diverse ipotesi di costo di input e proiettare le spese operative variabili necessarie per avviare la nostra operazione agricola. Sfruttando ChatGPT 4, non abbiamo scritto praticamente alcun codice, solo qualche modifica, abbiamo svolto la maggior parte del lavoro da un iPhone condividendo lo schermo, abbiamo creato l’ultima parte in PBI desktop e abbiamo condiviso lo schermo tramite l’app PBI per iPhone. Il tutto in circa 30-40 minuti di lavoro.

Il verdetto di mio nonno? “Abbiamo ottenuto in 40 minuti ciò che gli avrebbe richiesto 2 anni da solo ‘ai suoi tempi'”. Sì, riconosco che potremmo fare molto di più – e la “simulazione” è lontana dall’essere perfetta. (Ad esempio, non differenziamo tra la percentuale di colture destinate alla soia e al grano). Ma per 40 minuti? Anche io sono rimasto impressionato. E questa è la promessa di Gen AI: democratizzare la scienza dei dati, incoraggiare l’esperimento e accelerare la capacità di sviluppare, il tutto nel palmo della tua mano. Consentire a un nonno ed a suo nipote di riconnettersi attraverso le statistiche e sfruttare la tecnologia in modi nuovi ed inaspettati.