Molti degli argomenti che sembrano tenere banco nell’ambito della divulgazione delle informazioni canalizzate attraverso i social midia, sono indubbiamente legati alle potenzialità d’uso della tecnologia hardware e software, inerente applicazioni di quella che quasi tutti chiamano “Intelligenza artificiale”.
Da parte mia, preferirei chiamare questi strumenti con l’appellativo di “macchine inferenziali” , in quanto, mi sembrerebbe più appropriato, ma poco importa, quello che conta, il fatto che le potenzialità date dall’uso di queste opere dell’ingegno umano, siano impiegate in modo etico e sicuramente, uno degli ambiti d’uso di queste macchine, dove si spera, siano in grado di fornire delle agevolazioni utili alla risoluzione di varie problematiche, è il campo medico.
Sono sicuramente molte le applicazioni possibili, in questo settore, sia per quanto riguarda
l’hardware (robot che potranno essere ad esempio impiegati in chirurgia, per interventi sempre più specifici), sia per quanto riguarda il software, come ad esempio, in ambito diagnostico, per l’individuazione precoce di determinate patologie.
Negli studi che sto conducendo, in questo ambito, vorrei portare, nelle pagine di questo articolo, un esempio pratico relativo ad un potenziale impiego di un algoritmo per la classificazione di nei e melanomi.
Usare l'IA per analizzare Nei e Melanomi
Come molti sapranno, nei e melanomi, a livello visivo, sono delle irregolarità presenti nel derma: macchioline più o meno scure, in rilievo o meno, solitamente presenti in modo più accentuato in alcune parti del corpo, come la schiena.
La differenza fondamentale tra un neo ed un melanoma, consiste nel fatto che, se il primo non ha una potenziale incidenza sulla salute della persona, il secondo invece, potrebbe risultare estremamente pericoloso, porche potrebbe risultare essere una espressione cancerosa di cellule epidermiche.
Tipicamente la differenza visiva tra un neo (nevo) e un potenziale melanoma, potrebbe essere riassunta in queste immagini:
Se chiediamo ad una “intelligenza artificiale di fornirci una descrizione di nei e melanomi,
probabilmente ci darà una risposta simile a questa:
mi puoi fornire una descrizione su nei e melanomi?
Chat GPT: Certo, posso darti una breve descrizione su nei e melanomi.
Nei (o nei melanocitici): I nei, o nevi, sono accumuli di cellule pigmentate chiamate melanociti, che sono responsabili della produzione del pigmento melanina. Questi nevi possono essere presenti sulla pelle fin dalla nascita o svilupparsi nel corso della vita a causa dell'esposizione al sole. La maggior parte dei nevi è benigna e non causa problemi. Essi possono apparire di colore marrone, nero o rosa e possono variare in forma e dimensione.
È importante monitorare i cambiamenti nei nei, come la forma, il colore e la dimensione, poiché modifiche insolite possono essere segnali di possibili problemi.
Melanoma: Il melanoma è un tipo di cancro della pelle che origina dai melanociti. È meno comune rispetto ad altri tipi di cancro della pelle, ma è più aggressivo e può diffondersi ad altri organi se non trattato precocemente. Il melanoma può svilupparsi in modo indipendente o derivare da un nevo esistente. I fattori di rischio includono l'esposizione eccessiva ai raggi UV, la predisposizione genetica e la presenza di molti nevi atipici (nevi che presentano caratteristiche insolite). I segni di melanoma includono cambiamenti nei bordi del nevo, nella forma, nel colore e nella dimensione, nonché la comparsa di prurito o sanguinamento.
La prevenzione del melanoma include pratiche di protezione solare, come l'uso di creme solari e l'evitare l'esposizione prolungata al sole. In caso di sospetto melanoma, è fondamentale consultare un medico per una valutazione approfondita e, se necessario, per la rimozione e il trattamento precoce. La diagnosi precoce è cruciale per migliorare le prospettive di guarigione nel caso del melanoma.
Quindi, dopo aver consultato il parere dell’intelligenza artificiale possiamo dire che, ovviamente, spetta ad un medico con specializzazione in dermatologia, effettuare una analisi diagnostica accurata e valutare, caso per caso, le azioni da intraprendere, in questo contesto, ma, per il nostro caso d’uso della intelligenza artificiale in questo ambito, sarebbe già un buon risultato far si che, con l’utilizzo di un algoritmo operante come classificatore di immagini, riuscissimo a far distinguere, con un buon grado di probabilità, un nevo da un potenziale melanoma.
Per noi è semplice, siamo abituati e predisposti per distinguere, categorizzare, concettualizzare e classificare la maggior parte delle immagini che i nostri occhi vedono, ma per una macchina inferenziale potrebbe essere complesso, l’apprendimento, in questo caso, si basa su degli algoritmi che vanno addestrati su dei “set di immagini”.
La difficoltà che potremmo incontrare, nell’operare con un algoritmo di classificazione, potremmo immaginarla come dover decidere se, quello che viene percepito, assomiglia di più ad una categoria, piuttosto che ad un’altra, tanto per rendere l’idea, con una immagine, avvienequalcosa di simile a quello che percepiamo noi guardando questa immagine:
Forse qualcuno in questa immagine percepisce il volto di una vecchia, ma altri invece potrebbero percepire il volto di una ragazza, vista di profilo, ma tutti riescono a percepire il collo di pelliccia.
Algoritmi di classificazione, come aiutano la medicina a fare previsioni
Un algoritmo di classificazione è uno strumento software che utilizza tecniche di deep learning per attribuire un attributo di proprietà, basato su un calcolo statistico ad un elemento analizzato, quale ad esempio una immagine.
Uno dei sistemi per poter fare in modo che una rete neurale impari a classificare delle immagini, in relazione al contenuto, è quello di fornire una certa quantità di esempi, pre-classificati per categorie, ad esempio, a titolo didattico, viene solitamente proposto un esercizio per classificare le lettere dell’alfabeto, scritte in corsivo manualmente, oppure i numeri, da 0 a 9, scritti manualmente.
Un mio consiglio che posso dare, per approfondire questo specifico esercizio, è quello di seguire le pagine Youtube dedicate da Piero Savastano, proprio su questo argomento:
Nel nostro caso, per poter distinguere nei o nevi, da melanomi, o potenziali melanomi, bisognerà disporre di un minimo quantitativo di immagini per le due classi di figure.
Quindi, prima di tutto, si dovranno ricercare e clusterizzare le immagini separandole in due cartelle distinte, il mio suggerimento, in questo caso è fare una cartella denominandola “train_set”, che al suo interno dovrà contenere le due directory, una con le immagini dei melanomi e l’altra con quelle dei nevi.
La prima parte delle attività, sarà quella di addestrare il classificatore proprio su queste figure. L’addestramento consiste nel “plasmare un modello neurale”, facendolo ripassare i dati di ogni immagine, per un numero sufficiente di volte, (definite epoche), attraverso una rete costituita da diversi layer (strati) di neuroni, che potrà rilevare le caratteristiche distintive di ogni immagine, tali da stabilire un criterio inferenziale tale da stabilire con un certo grado di precisione, la differenza tra le immagini appartenenti all’una o all’altra directory.
Ad ogni passaggio, verrà eseguita una operazione, definita backpropagation, o retropropagazione dell'errore, atta ad abbassare, di volta in volta, l’errore predittivo, riferito alla classificazione delle immagini, in base statistica.
Generato il modello, lo si fa “validare”, con un altro set di immagini conosciute, raccolte in un altra cartellina, di test che a sia volta disporrà di due directory più corpose, una per i nei e una per i melanomi.
Quando il modello itererà su queste immagini, per lui sconosciute, ma simili, per costituzione, alle immagini che ha imparato a classificare, otterrà un errore predittivo, inizialmente randomizzato, ma attraverso la procedura di controllo della funzione di backpropagation, questo errore sarà via via sempre minore, controllato da una “loss function” e, per contro, l’accuratezza (accuracy) predittiva, diverrà via via sempre maggiore.
Quando si trova un buon compromesso di riconoscimento che sia superiore ad un valore di
underfitting, ma inferiore di poco ad un valore di overfitting, ovvero superiore ad una sottostima di classificazione, ma inferiore ad una pura memorizzazione dei dati, come rappresentat dalla seguente immagine:
il che significa ottenere un buon grado di accuratezza predittiva, si è in grado di sottoporre il nostro modello al riconoscimento di immagini nuove, e perfettamente incognite, sulle quali si dovrà inferire una classificazione, in questo caso, binaria; o nevo o melanoma.
Una definizione “artificilale di algoritmo classificatore: Questa volta lo chiedo a Bard:
Una definizione per l'algoritmo classificatore di tensorflow
Un classificatore TensorFlow è un algoritmo di machine learning che viene utilizzato per
identificare o categorizzare entità in base a un insieme di dati. I classificatori TensorFlow sono ampiamente utilizzati in una varietà di applicazioni, tra cui la visione artificiale, l'analisi del linguaggio naturale e il riconoscimento delle sequenze.
TensorFlow fornisce una vasta gamma di classificatori predefiniti, tra cui:
• DNN (Deep Neural Networks): Le reti neurali profonde sono classificatori potenti ed
efficaci che possono modellizzare relazioni complesse tra input e output. Sono
particolarmente adatti per problemi di classificazione multiclasse.
• SVM (Support Vector Machines): Le macchine a vettori di supporto sono classificatori
efficienti e robusti che possono gestire dati non lineari. Sono particolarmente adatti per
problemi di classificazione binaria.
• Random Forests: Le foreste casuali sono classificatori ensemble che combinano la
previsione di diversi alberi decisionali. Sono robusti al rumore nei dati e possono gestire dati
multidimensionali.
• K-NN (K-Nearest Neighbors): Il K-NN è un classificatore basato sulla distanza che
classifica un nuovo punto dati in base alla sua vicinanza ai punti dati etichettati nel training
set. È semplice da implementare ma può essere sensibile al rumore nei dati.
TensorFlow consente agli utenti di creare classificatori personalizzati combinando diversi tipi di modelli e di definire funzioni di perdita e ottimizzatori personalizzati.
L'apprendimento automatico supervisionato è una tecnica di machine learning che utilizza un insieme di dati etichettati per addestrare un classificatore. L'insieme di dati etichettato contiene esempi di input e le corrispondenti etichette di output. Il classificatore apprende le relazioni tra input e output durante l'addestramento e utilizza queste informazioni per classificare nuovi punti dati.
I classificatori TensorFlow sono potenti strumenti per l'analisi dei dati e possono essere utilizzati per risolvere una varietà di problemi. Sono ampiamente utilizzati in applicazioni reali, tra cui:
•Visone artificiale: I classificatori TensorFlow sono utilizzati per identificare e classificare
oggetti in immagini e video. Ad esempio, possono essere utilizzati per analizzare video di
sorveglianza, riconoscere volti e identificare oggetti in immagini.
•Analisi del linguaggio naturale: I classificatori TensorFlow sono utilizzati per analizzare
testi e classificare i contenuti. Ad esempio, possono essere utilizzati per classificare email
come spam o non spam, analizzare recensioni di prodotti e identificare argomenti di
conversazione.
•Riconoscimento delle sequenze: I classificatori TensorFlow sono utilizzati per analizzare
sequenze di dati, come sequenze di DNA o sequenze di tempo. Ad esempio, possono essere utilizzati per identificare modelli genetici, prevedere tendenze del mercato azionario e
diagnosticare malattie.
Il software necessario per creare un IA a casa
Le procedure software, per poter mettere in pratica un algoritmo di classificazione, possono essere ottenute con vari linguaggi, ma quello che, a mio parere, è il più indicato per questo tipo di elaborazioni e Python, anche perché supportato da delle librerie di notevole interesse ed utilità, sviluppate da giganti dell’informatica moderna e, cosa da non trascurare, “Open Source”, che considero una filosofia sociale moderna, altamente etica e all’avanguardia, per le potenzialità che implica, in quanto a potenziali sinergie di collaborazione globale.
A tal proposito, suggerisco la lettura di questo libro, che ho scritto poco tempo fa, e credo molto attuale, viste le inclinazioni politiche che riguardano il futuro delle produzioni software a livello mondiale, soprattutto riferite all’utilizzo dell’intelligenza artificiale.
Questo testo è acquistabile su www.amazon.it.
Quindi, il software necessario, in python viene reso disponibile nel programma “classificatore”, per mezzo delle funzioni di importazione.
Per questo esercizio didattico, è stato utilizzato un file con estensione . ipynb è un file Jupyter Notebook che contiene l'intero contenuto di Notebook creato con la sessione dell'applicazione web Jupyter Notebook. Jupyter Notebook è un'applicazione web interattiva utilizzata per creare e condividere documenti computazionali per l'analisi utilizzando Python.
In particolare, in questo caso si è utilizzato una libreria: “Scipy”, che è un software open source per matematica, scienza e ingegneria, ovvero, una raccolta di algoritmi matematici e funzioni di convenienza costruite su Numpy, che aggiunge una potenza significativa a Python fornendo all'utente comandi e classi di alto livello per manipolare e visualizzare i dati.
La base operativa di python, utilizzata in questo caso, per lo sviluppo degli algoritmi di deeplearning è Tensorflow: un framework open source, sviluppato da Google, specificatamente per il riconoscimento dei numeri, degli oggetti e dei simboli in una foto che utilizza delle funzioni di algebra lineare denominate tensori.
Questa immagine, potrebbe dare l’idea di che cosa si tratta:
I tensori sono usati, ad esempio in geometria differenziale per definire su una varietà differenziabile le nozioni geometriche di distanza, angolo e volume, sembrano fatti apposta per gestire, interpretare, le relazioni tra i pixel colorati delle immagini utilizzate in questi casi.
In particolare, per Tensorflow, è stata sviluppata Keras che è una interfaccia per l'apprendimento automatico e le reti neurali, scritta in Python, Questa interfaccia pensata per un livello di astrazione superiore ad altre librerie simili di più basso livello, supporta come back-end le librerie TensorFlow e permettere una rapida prototipazione di reti neurali profonde, caratterizzandosi sulla facilità d'uso, la modularità e l'estensibilità.
Per le funzionalità grafiche di rappresentazione delle immagini e degli elaborati, si è utilizzata la libreria Matplotlib molto efficacie per la creazione di grafici per il linguaggio di programmazione Python.
Questo software viene utilizzato per creare una vasta gamma di visualizzazioni statiche, animate e interattive, come grafici di linea, grafici a dispersione, grafici a barre e istogrammi.
Fornisce una vasta gamma di opzioni di personalizzazione, come stili di linea, stili di marcatore e mappe dei colori, che possono essere utilizzate per creare grafici professionali e pronti per la pubblicazione di alta qualità; oppure all’occorrenza, una serie di funzioni di animazione.
L’ambiente di sviluppo, in questo caso, è una partizione virtuale gestita da Visual Studio Code: che è un editor di codice sorgente sviluppato da Microsoft per Windows, Linux e macOS. VS code, include il supporto per debugging, un controllo per Git integrato, syntax highlighting, IntelliSense, snippet e refactoring del codice.
Lo sviluppo del programma:
inizializzazione per l’installazione di librerie #!nvidia-smi # non utilizzata in questo caso !python -m pip install scipy |
## -- DEFINIZIONE VARIABILI import os # dichiariamo la posizione dei nostri file di addestramento e validazione base_dir = '../tf/notebooks/data' os.getcwd() print(os.getcwd()) train_dir = os.path.join(base_dir, 'train_set') os.listdir(path='./train_set') |
validation_dir = os.path.join(base_dir, 'test_set') |
# punto alle cartelle di melanomi e Nevi per il training train_Melanomi_dir = os.path.join(train_dir, 'Melanomi') print("train_dir = ", train_dir) print(train_Melanomi_dir) trainNevi_dir = os.path.join(train_dir, 'Nevi') dir_Melanomi = os.listdir(path='./train_set/Melanomi') print("directory melanomi", dir_Melanomi[0]) dir_Nevi= os.listdir(path='./train_set/Nevi') print(dir_Nevi[0]) |
# punto alle cartelle di melanomi e Nevi per la validazione validation_melanomi_dir = os.path.join(validation_dir, 'Melanomi') print (validation_melanomi_dir) validation_nevi_dir = os.path.join(validation_dir, 'Nevi') print (validation_melanomi_dir) dir__val_melanomi = os.listdir(path = './test_set/Melanomi') print(dir__val_melanomi[0]) dir__val_nevi = os.listdir(path = './test_set/Nevi') print(dir__val_nevi[0]) |
import tensorflow as tf from tensorflow import keras from keras.models import Sequential import scipy from keras.preprocessing.image import ImageDataGenerator |
model = tf.keras.models.Sequential([ # poiché Conv2D è il primo strato della rete neurale, dovremmo specificare anche la dimensione dell'input tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)), # applichiamo uno strato di aggregazione 2D tf.keras.layers.MaxPooling2D(2,2), # ripetiamo il processo tf.keras.layers.Conv2D(32, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), # appiattiamo il risultato per fornirlo allo strato denso per la classificazione tf.keras.layers.Flatten(), # e definiamo 512 neuroni per l'elaborazione dell'output processato dagli |
strati precedenti tf.keras.layers.Dense(512, activation='relu'), # un singolo neurone di output. Il risultato sarà 0 se l'immagine è un melanoma, 1 se è un nevo tf.keras.layers.Dense(1, activation='sigmoid') ]) |
model.summary()
model.compile(optimizer="adam", loss='binary_crossentropy', metrics = ['accuracy']) |
model = tf.keras.models.Sequential([ # poiché Conv2D è il primo strato della rete neurale, dovremmo specificare anche la dimensione dell'input tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)), # applichiamo uno strato di aggregazione 2D tf.keras.layers.MaxPooling2D(2,2), # e ripetiamo il processo tf.keras.layers.Conv2D(32, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), # appiattiamo il risultato per fornirlo allo strato denso per la classificazione tf.keras.layers.Flatten(), # e definiamo 512 neuroni per l'elaborazione dell'output processato dagli strati precedenti tf.keras.layers.Dense(512, activation='relu'), # un singolo neurone di output. Il risultato sarà 0 se l'immagine è un melanoma, 1 se è un nevo tf.keras.layers.Dense(1, activation='sigmoid') ]) |
from keras.preprocessing.image import ImageDataGenerator train_dir ='./train_set' validation_dir = './test_set' print(train_dir) print(validation_dir)
# riscaliamo tutte le nostre immagini con il parametro rescale train_datagen = ImageDataGenerator(rescale = 1.0/255) test_datagen = ImageDataGenerator(rescale = 1.0/255) |
# utilizziamo flow_from_directory per creare un generatore per il training train_generator = train_datagen.flow_from_directory(train_dir, batch_size=20, class_mode='binary', target_size=(150, 150))
# utilizziamo flow_from_directory per creare un generatore per la validazione validation_generator = test_datagen.flow_from_directory(validation_dir, batch_size=20, class_mode='binary', target_size=(150, 150)) |
history = model.fit( train_generator, # passiamo il generatore per il training steps_per_epoch=10, epochs=10, validation_data=validation_generator, # passiamo il generatore per la validazione validation_steps=10, verbose=2 ) |
import numpy as np import random from tensorflow.keras.utils import img_to_array,load_img |
# definiamo un nuovo modello custom di Keras che riceve una immagine in input # e restituisce le rappresentazioni degli strati del modello precedente successive_outputs = [layer.output for layer in model.layers] visualization_model = tf.keras.models.Model(inputs=model.input, outputs=successive_outputs) |
# prepariamo una immagine a caso dal nostro dataset train_melanomi_dir='./train_set/Melanomi' train_nevi_dir = './train_set/Nevi' melanomi_img_files = [] nevi_img_files= [] for filename in os.listdir(train_melanomi_dir): c = os.path.join(train_melanomi_dir, filename) melanomi_img_files.append(c) #print(c) for filename in os.listdir(train_nevi_dir): |
d = os.path.join(train_nevi_dir, filename) nevi_img_files.append(d) print(train_melanomi_dir) file_melanomi = os.listdir(train_melanomi_dir) print("melanoma_0", file_melanomi[0]) file_nevi = os.listdir(train_nevi_dir) print("nevo_0",file_nevi[0]) img_path = random.choice(melanomi_img_files + nevi_img_files) print ("img_path",img_path) img = load_img(img_path, target_size=(150, 150)) # questa è una immagine grezza in formato PIL x = img_to_array(img) # array numpy con dimensione (150, 150, 3) x = x.reshape((1,) + x.shape) # array numpy con dimensione 1, 150, 150, 3) print("x", x) |
# normalizziamo i valori dei pixel per 1/255 x /= 255.0 |
# facendo una previsione non facciamo altro che ottenere # le rappresentazioni "intermedie" di questa immagine dal modello precedente successive_feature_maps = visualization_model.predict(x) |
# normalizziamo i valori dei pixel per 1/255 x /= 255.0 |
# mappiamo gli strati di questo modello con il loro nome layer_names = [layer.name for layer in model.layers] print("layer_names",layer_names) |
# plottiamo il tutto import matplotlib.pyplot as plt
for layer_name, feature_map in zip(layer_names, successive_feature_maps):
if len(feature_map.shape) == 4: # se è uno strato convoluzionale o di pooling n_features = feature_map.shape[-1] # numero di feature size = feature_map.shape[ 1] # dimensione print("size", size) # creiamo una griglia per visualizzare i dati display_grid = np.zeros((size, size * n_features)) |
# un po' di post processing per capirci qualcosa for i in range(n_features): np.seterr(invalid='ignore') x = feature_map[0, :, :, i] x -= x.mean() x /= x.std () x *= 64 x += 128 x = np.clip(x, 0, 255).astype('uint8') #print ("questo è x", x) display_grid[:, i size : (i + 1) size] = x # mostriamo il grafico scale = 10. / n_features plt.figure( figsize=(scale * n_features, scale) ) plt.title ( layer_name ) print (layer_name) plt.grid ( False ) plt.imshow( display_grid, aspect='auto', cmap='viridis' |
# recuperiamo le metriche che ci interessano da history
acc = history.history['accuracy'] print ("accuracy",acc) val_acc = history.history['val_accuracy'] print ("val_accuracy",val_acc) loss = history.history['loss'] print ("loss",loss) val_loss = history.history['val_loss'] print ("val_loss",val_loss)
epochs = range(len(acc)) #print ("epochs",epochs) |
# plottiamo la loss con matplotlib #fig, ax = plt.subplots(figsize=(5, 5)) plt.title('Loss in training') #plt.plot(figsize=(5, 2.7), layout='constrained') plt.plot(epochs, loss, label='loss') #plt.plot(epochs, val_loss, label='val loss') plt.xlabel('epochs') plt.ylabel('data') plt.legend() #fig = plt.figure() #fig, ax = plt.subplots(figsize=(5, 5))
#df.plot(x='date', y='GVA', legend=True, color='g', ax=axplt.figure() plt.show() |
# image test import matplotlib.image as img #file_melanomi = os.listdir(train_melanomi_dir) #print("file_melanomi",file_melanomi)
#image = img.imread("./Nevo_1.png") #plt.imshow(image) plt.show() img = load_img("./incognite/Incognita_05.png", target_size=(150, 150)) plt.imshow(img) plt.show() #img = image.load_img(path, target_size=(150, 150)) # e usiamo load_img per scalarla alla dimensione target x = img_to_array(img) # array numpy con dimensione (150, 150, 3) x = x.reshape((1,) + x.shape) # scaliamo i valori #x = image.img_to_array(img) x /= 255 #x = np.expand_dims(x, axis=0) # appiattiamo l'output images = np.vstack([x]) |
Spero che questo esercizio di didattica, adibito all’uso potenziale in medicina degli algoritmi di intelligenza artificiale, possa dare modo a qualcuno di trovare una fonte di ispirazione o perlomeno di appagare qualche curiosità.
Da parte mia, mi rendo disponibile, per eventuali approfondimenti in merito a potenziali usi di questo ed altri algoritmi similari e ne approfitto per augurare a tutti buon Coding
Grazie per la lettura. Romeo Ceccato
Molto interessante e utile...peccato che non c'è la possibilità di scaricare gli archivi per poterlo provare...