Una panoramica sul mondo della Sicurezza Informatica, del Networking, della Virtualizzazione e non solo. Blog particolarmente indicato per i reparti IT che comunque alterna articoli scritti per specialisti con articoli formulati con linguaggio semplice e comprensibile a tutti.

Ogni articolo di questo blog è stato integralmente scritto dall'autore. Il contenuto è completamente originale e la riproduzione, anche parziale, è vietata salvo autorizzazione.

venerdì 4 ottobre 2024

Ho addestrato un'AI a fare trading di bitcoin! [Parte1]

Ho addestrato un'Intelligenza Artificiale a fare trading di Bitcoin... sarò riuscito a prevedere le variazioni del prezzo? Scopriamolo insieme.


Premessa

Utilizzare un'IA preaddestrata, come ad esempio ChatGPT, è molto diverso dall'addestrare da zero una rete neurale. I parametri da tenere in considerazione sono davvero molti. Mi scuso fin d'ora se  il mio linguaggio risulterà impreciso ai puristi, non sono un ricercatore ma un sistemista. Durante un week end piovoso, non potendo girare in pista in moto e non potendo uscire per mare a vela (due delle mie tante passioni) mi è venuta voglia di approfondire l'argomento AI Train. 
 
I dataset finanziari sono molto ben strutturati e si prestano molto bene ad iniziare a muovere i primi passi in materia, quindi sono partito proprio da questi per non perdere troppo tempo nel processo di normalizzazione dei dati. Ovviamente, l'amico intelligente che ho citato all'inizio (ed il suo incredibile modello o-preview), mi ha dato una mano nel capire le logiche, nello scrivere parti di codice in python e nel dipanare molti dubbi.
Per iniziare ho stabilito un obiettivo binario: il prezzo dello slot temporale successivo aumenterà o diminuirà? Se il modello restituisce dati congrui e usabili, allora si passa allo step successivo: il prezzo di che percentuale aumenterà o diminuirà (mi accontento anche di "poco o molto")?



I dataset

Per iniziare ho creato uno script in grado di scaricare i dati di apertura, chiusura, volumi scambiati, prezzo massimo e minimo (le candele finanziarie) con intervallo temporale di 1 minuto dal 2018 al 2023 compresi per circa 15 delle principali e più stabili criptovalute. Per mia esperienza, le dinamiche spesso si assomigliano, quindi ho inserito tutti questi dati sempre come elaborazione base per il processo di apprendimento del modello di Intelligenza Artificiale. Per la parte di test pura, ho invece usato i valori del 2024 (da gennaio a settembre compresi). Nonostante i modelli abbiano una percentuale di Learn e Test, comunque ho voluto fare un "test indipendente" su valori che il modello non aveva mai visto per evitare il fenomeno di Overfitting (che vedremo più avanti).
unix,date,symbol,open,high,low,close,volume,base-volume,quote-volume,tradecount 1577836800,2020-01-01 00:00:00,BTCUSDT,7195.24,7196.25,7183.14000000,7186.68000000,51.64281200,19.59823000,140888.41428273,493 1577836860,2020-01-01 00:01:00,BTCUSDT,7187.67,7188.06,7182.20000000,7184.03000000,7.24814800,2.03177200,14599.21192429,135



La versione 1 - LSTM

Per iniziare sono partito da tensorflow, ma dopo innumerevoli tentativi in cui la GPU (4090 con 24gb di VRAM) non veniva vista, sono passato con successo a torch. Lavorare solo con la CPU (nonostante sia un i9 di ultima generazione) sarebbe stato impossibile sia come tempi sia come risultati.

Superati i problemi tecnici, ho iniziato ad utilizzare una rete neurale di tipo LSTM ed ho iniziato a giocare con le epochs (i cicli di addestramento) implementando tecniche di resume dai checkpoint e uno script separato per fare tutta la parte di testing. Qui mi sono apparsi chiari i parametri di inferenza (ovvero quanto il modello è in grado di prevedere correttamente): l'accuracy ed il loss. Nel modello l'accuratezza era spesso molto alta (vicina all'1... ci prendeva sempre, quindi sarei diventato finalmente milionario) ma l'accuracy su dati nuovi mai visti dal modello lo era molto meno. Ho scoperto, quindi, il fenomeno dell'overfitting, ovvero all'aumentare dei cicli di apprendimento il modello rischia di imparare a memoria i dati. Questo ovviamente non va bene perchè comunque su dati mai visti prima il modello si comporterà in maniera deludente. Per evitare questo si gioca con diversi parametri tra cui il patience, ovvero uno stop forzato dell'apprendimento nel momento in cui i valori danno segnali in tal senso o banalmente il modello non apprende più. Sfatiamo quindi subito un mito in cui credevo anche io: più cicli di apprendimento faccio e più imparo. NO, perchè rischio di imparare a memoria e quindi imparo uno schema inutilizzabile.



La versione 2 - Preprocessing


I dati non erano molto incoraggianti, sostanazialmente era come lanciare una monetina e scommettere sul risultato. Quindi ho aggiunto una fase di preprocessing così da dare all'IA anche dei parametri basati su indicatori finanziari normalmente utilizzati, ovvero 
  • MACD(Moving Average Convergence/Divergence)
  • Incrocio delle Medie Mobili,  
  • OBV (On-Balance Volume)
  • VPT (Volume–price trend),
  • RSI (Relative Strength Index) 
ognuno con diversi parametri. Ho preso i dati in mio possesso ed ho creato uno script per applicare tutti questi indicatori finanziari su molteplici finestre per capire quale, senza IA, comunque era in grado di aggiungere accuratezza di per se. Ho scritto quindi un ulteriore script per ordinare questi dati.
In fase di preprocessing ho quindi passato l'indicatore che mi dava il miglior risultato al modello da addestrare, vedendo finalmente dei risultati migliori della semplice casualità.



 

La versione 3 - CNN e Transformer

Nella versione 3 ho aggiunto al modello un CNN (Rete Neurale Convoluzionale). Una CNN viene utilizzata nel contesto delle serie temporali per estrarre automaticamente delle feature rilevanti dai dati.I vantaggi sono sostanzialmente 3:
  1. Riduzione della dimensionalità: Filtrare i dati temporali attraverso una convoluzione per ridurre le informazioni ridondanti.
  2. Pattern locali: Identificare pattern locali nei dati, come trend di breve periodo o picchi nei dati temporali. Nel caso dei prezzi, potrebbe identificare movimenti locali di prezzo o anomalie.
  3. Pre-elaborazione per LSTM: La CNN riduce la complessità dei dati che vengono poi passati all'LSTM per elaborare le relazioni sequenziali a lungo termine.
 
 undefined
 
Oltre al CNN ho aggiunto anche un processo di Transformer. I Transformer sono molto efficaci nel gestire sequenze lunghe e relazioni complesse tra le diverse parti di una sequenza grazie al meccanismo di attenzione, che permette al modello di concentrarsi sulle parti rilevanti della sequenza.

In questo script, il Transformer può:
  1. Identificare quali parti della sequenza temporale hanno una maggiore influenza su ogni predizione, permettendo al modello di "prestare attenzione" a movimenti di prezzo rilevanti, ignorando i movimenti meno significativi.
  2. Aiutare a catturare le relazioni temporali a lungo termine più efficacemente di un semplice LSTM, che tende a concentrarsi solo sulle relazioni a breve termine. 


 

La versione 4 - Approfondimento sui parametri e seed

Ad un certo punto è risultato chiaro che alcuni parametri dovevano essere affinati. Mi sono concentrato su:
  • Hidden Size: Banalizzando questi sono i neuroni dell'IA. Valori bassi rendono il modello troppo semplice e incapace di imparare pattern complessi, valori alti portano al rischio di Overfitting (il modello impara a memoria) oltre a rendere l'elaborazione molto più lenta
  • Number of Layers: Indica il numero di livelli, come per gli Hidden Size troppo pochi o troppi sono controproducenti, tuttavia 1 Layer è sufficiente spesso per molti compiti, ma potrebbe non essere in grado di catturare relazioni complesse nei dati. Se Hidden Size è il numero dei neuroni X Y su una rappresentazione cartesiana, i Layer sono la profondità Z.
  • Learning Percentage: Indica la percentuale di dati che viene dedicata all'addestramento e la percentuale che viene dedicata ai test. Percentuali alte dedicano più dati all'addestramento, ma lasciano meno dati per valutare le prestazioni. Percentuali basse dedicano più dati al test, ma riducono la quantità di dati usati per l'addestramento.
  • Learning Rate: Si occupa di ponderare il tasso di apprendimento. Valori alti fanno apprendere rapidamente, ma superficialmente. Valori bassi solitamente sono più precisi, ma richiedono più tempo (oppure non fanno apprendere proprio il modello).
  • Batch Size: Indica il numero di campioni che vengono elaborati prima che il modello aggiorni i pesi durante l'addestramento. Un valore più grande significa che più dati vengono elaborati contemporaneamente, riducendo il numero di aggiornamenti dei pesi, mentre un valore più piccolo aumenta il numero di aggiornamenti dei pesi, ma con meno dati processati in ogni aggiornamento.
L'equilibrio tra questi valori non è banale, quindi ho scritto due script. Uno che lancia una sequenza di learning dell'IA con diversi parametri magliati tra di loro (sotto un esempio di una configurazione che ha comportato 1536 train differenti), ed uno che prende i log dei risultati, gli fa un test indipendente su un dataset esterno mai visto dal modello (per evitare l'Overfitting) e scrive tutto in un database.



 
Addestrando lo stesso modello con gli stessi parametri uscivano tuttavia delle accuratezze (ovvero percentuali di previsioni azzeccate) diverse, e la cosa mi ha meravigliato. Perchè identici parametri davano risultati differenti? Poi ho scoperto i "seed". Alcune variabili vengono generati casualmente durante il processo di addestramento, come i pesi iniziali delle connessioni tra i neuroni, lo Shuffle dei dati di addestramento, i batch presi dal Stochastic Gradient Descent (SGD), i livelli neurali Batch Normalization e Dropout, il calcolo dei gradienti usati dalla GPU, i processi di cross-validation o ricerca casuale degli iperparametri (random search), la Random Augmentations nei Dati ed altri valori. Fissando il Seed (seme) la casualità viene contenuta al massimo, rendendo i test ripetibili. Fattore, questo, assolutamente  fondamentale per avere dei test comparativi accurati.

Com'è andata a finire?

Sarò diventato milionario? Questo lo scopriremo nella parte 2, anche perchè per ora sto ancora addestrando il modello e sto cercando la combinazione che mi restituisce l'accuratezza migliore!
Qualora non mi doveste vedere più in giro, allora vorrà dire che effettivamente sarò diventato milionario. In caso contrario, bhè... almeno avrò sperimentato un po'. E si sa, la conoscenza non ha prezzo.


martedì 23 luglio 2024

La faccenda Crowdstrike e le riflessioni che deve sollevare

Qualche giorno fa 8 milioni di dispositivi windows nel mondo si sono bloccati presentando un blue screen. Si è parlato molto, ovviamente, di questo accadimento che ha comportato danni per miliardi di dollari. Non mi soffermerò oltre, ma voglio giusto farvi vedere un video, ovvero i tracciati del traffico aereo prima, durante e dopo i disservizi.


Intendiamoci, il mondo intero è stato coinvolto, non solo il settore dei trasporti. Con questo video preso da YT voglio solo focalizzare l'attenzione sulla gravità della cosa. E a renderla ancor più grave è che questi sistemi sono solitamente utilizzati proprio da grandi aziende e proprio per evitare i danni di un attacco informatico, assolutamente sovrapponibili e similari a quelli causati da questo disservizio.


Cos'è successo?

Per farla breve, l'endpoint di CS per funzionare installa, tra le altre cose, anche dei driver. I driver sono, per un sistema operativo, qualcosa di estremamente intimo e dall'accesso assolutamente privilegiato. Nulla come un driver può accedere al sistema e ai suoi meandri più vulnerabili.

Dalle ricostruzioni, pare che vi sia stato un rilascio di un driver chiaramente buggato, ovvero con un puntatore di memoria su un'area riservata (#0x9c) del sistema operativo. Qualsiasi programma che tenti di accedere a quest'area viene immediatamente terminato dal sistema operativo per ragioni di sicurezza in quanto, alla base di moltissime violazioni, vi è proprio il meccanismo della lettura (e scrittura) di porzioni di memoria arbitrarie.


Qualche considerazione

Ho riassunto la vicenda molto brevemente, i più curiosi potranno approfondire ovunque maggiori dettagli.

La mia prima riflessione è: il bug era evidentissimo, bastava un riavvio per accorgersene. Possibile che un'azienda leader mondiale non abbia una procedura di revisione e rilascio degli aggiornamenti tale da evitare un problema simile? Stiamo scherzando? Mi blocchi mezzo mondo perchè un tuo sviluppatore la notte prima ha fatto le ore piccole? Ovviamente sto volontariamente un po' banalizzando, ma se noi per rilasciare anche solo una virgola su quattro gatti di clienti verifichiamo e incrociamo controlli come se da quello dipendesse la vita di tutta la nostra famiglia fino alla terza generazione... possibile che una multinazionale di sicurezza rilasci roba così alla leggera? E bug meno visibili chi li controlla, se persino questo è passato inosservato? In pieno spirito aeronautico (visto che ci siamo), quindi, che qualcuno relazioni analiticamente e con dovizia di particolari ciò che non ha funzionato, così che l'intero mondo possa trarne beneficio. Perchè non ho alcun dubbio che CS disponga di procedure rigidissime di rilascio, ma va capito cosa non ha funzionato e perchè. Persino nella basilare ISO27001 vi sono meccanismi di controllo di rilascio, obiettivamente è incredibile tutto questo.

La mia seconda riflessione è: e se invece di un bug, qualcuno nella posizione di rilasciare aggiornamenti venisse avvicinato ed inserisse volontariamente backdoor? Non sarebbe mica la prima volta, anzi, visti i numeri economici che oramai girano sulla sicurezza informatica offensiva, è una tendenza assolutamente consolidata quella di corrompere gente all'interno di organizzazioni. Chi se ne sarebbe accorto e quando? Ci sono enti terzi che fanno solo questo, ovvero l'analisi del codice rilasciato, quando si parla di software così delicati, è opportuno che questo venga reso obbligatorio a livello normativo?

La mia terza riflessione è: anni fa successe a Sophos, poi ad Avast, oggi a Crowdstrike. Concordo, i driver sono delicati, ma è davvero complesso per Microsoft introdurre una procedura di recovery di un precedente driver in caso di BSOD continuo? Possibile che la procedura di ripristino (sono solidale con i colleghi che non ci stanno dormendo da qualche notte) sia così complessa (e non prevista)? Forse è arrivato il momento di prevedere anche l'imprevedibile, perchè è solo questione di tempo, ma l'imprevedibile prima o poi accade.

Chiudo questo articolo/sfogo con un'ultima riflessione: gli amanti del mondo Linux (tra cui il sottoscritto) non si vantino troppo del fatto che solo i sistemi Microsoft sono stati affetti dal problema, perchè i più accorti sanno perfettamente che questa ruota gira continuamente.


Ogni articolo di questo blog è stato integralmente scritto dall'autore. Il contenuto è completamente originale e la riproduzione, anche parziale, è vietata salvo autorizzazione.