Quando si lavora con complesse strutture dati, specie quando queste strutture sono generate a partire da dati offuscati, è estremamente importante utilizzare uno strumento in grado di rappresentare visivamente tali grafi. Io stesso ho perso alcune settimane dietro i problemi matematici che si nascondono dietro la visualizzazione dei grafi. Un esempio fra i tanti riguarda il problema di disporre i nodi in modo tale da minimizzare gli accavallamenti degli archi.

Non avevo però la pretesa di riscrivere da capo una libreria che disegnasse grafi e alberi in quanto ero sicuro che esistesse già qualcosa di pronto nel marasma del codice libero.

La risposta è iGraph. Fra tutte le librerie che ho visto e provato questa è sicuramente la più interessante. Il punto di forza di questa libreria consiste nel numero di piattaforme e linguaggi che supporta: C/C++, Python e anche Ruby più altre piattaforme di statistica. Inoltre, dando un occhiata alle API e alla documentazione, sembra molto semplice, intuitiva e ben tenuto.

Allora lo installo sfruttando i repository di Launchpad (ho utilizzato karmic anche se uso Sidux e pare che tutto funzioni bene). Scrivo un codicillo di prova e ho la brutta sorpresa:

NotImplementedError: showing plots is not implemented on this platform: Linux

Accidenti! La funzione principe del programma non è ancora stata implementata!? Non vi nascondo che ci sono rimasto malissimo. Anche perché era una libreria di cui avevo bisogno per visualizzare alcuni grafi di stato di piccoli progetti di prova di IA.

Pazienza. Guarderò il codice e cercherò di contattare gli sviluppatori per sapere come procede l’implementazione di questa funzionalità. Magari posso dare anche una mano. Alla fine è questo il bello del software libero.

UPDATE:

HO RISOLTO IL PROBLEMA! Ora funziona bene anche la visualizzazione. Vi aggiornerò a breve!

SEGUIMI SU TWITTER

 


Python dispone di numerosissimi strumenti che facilitano e completano l’esperienza di programmazione. Il problema è, appunto, che sono troppi. Ogni volta bisogna ricercare i migliori fra la sterminata costellazione di strumenti di sviluppo.

E quindi ho deciso di fare una lisa. Soprattutto per me, dato che ogni volta che mi capita di reinstallare il sistema perdo un bel po’ di tempo a ricordarmi quali fossero tutti i tools che avevo installato.

IDE

La scelta dell’IDE è sempre la più importante. Sebbene Python non necessiti di chissà quale IDE avanzato, un po’ di comodità in più non fa certo male. La mia scelta ricade a pari merito su due IDE molto importanti:

Per il momento sto utilizzando la seconda configurazione ma in passato ho usato la prima. A voi la scelta.

CHECKER

Python è un linguaggio interpretato, ragion per cui gran parte degli errori di sintassi vengono fuori solamente in fase di esecuzione. Ci sono però programmi in grado di individuarli da subito.

Questa è la mia scelta. Fa tutte le cose di PyChecker e, in aggiunta, fa anche alcuni controlli riguardo le convenzioni stilistiche di Python. Un ottimo “tutor”. Inoltre è integrato con PyDev, quindi se usate Eclipse è veramente una mano santa.

DEBUGGER

Il debug in python è integrato. Basta importare il modulo pdb e lanciare il programma con:

<span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">pdb.run('mymodule.test()')

Vi rimando alla guida ufficiale per maggiori informazioni.

TESTING FRAMEWORK

Gli ambienti di test sono strumenti che permettono di scrivere dei test per verificare il buon funzionamento di una classe o di un modulo che abbiamo appena scritto. In Java io utilizzavo JUnit. È quindi naturale che in Python abbia scelto:

PyUnit ricalca molto da vicino la sintassi di JUnit. Inoltre è integrato con Eclipse. Per test semplici è veramente intuitivo, per roba più complessa basta dare una letta alla documentazione.

CODE COVERAGE

Gli strumenti di code coverage sono tools che tengono traccia di quale parte di codice eseguiamo durante un test e di quale non eseguiamo. È molto facile infatti che durante un test capiti di trovarsi ad eseguire, ad esempio, solamente un ramo di un IF e che, come al solito, l’errore si nasconda nel ramo che non eseguiamo mai. I programmi di code coverage ci segnalano proprio questa eventualità.

Questo è il programma di coverage in Python per eccellenza. Integrata con PyDev. Esiste anche un espansione (figleaf) che però non ho mai avuto modo di provare.

DOCUMENTAZIONE

Scrivere la documentazione è essenziale. Generare la documentazione dai commenti del codice sorgente è ancora più essenziale in quanto ci risparmia una marea di tempo. In Java esiste il famoso javadoc. Ovviamente il Python non è da meno.

Epydoc, di cui ho scritto anche una rapida guida tempo fa, è un tool fenomenale. Non è perfettamente integrato con Python 3 (almeno nell’ultima versione che ho usato) ma fa dannatamente bene il suo lavoro.

Credo che per il momento la lista sia piuttosto esaustiva. Spero vi sia utile.

Alla prossima. :)

 

Segnalo ancora un nuovo aggiornamento. Arrivato in ritardo ma è arrivato. :D Purtroppo sono stato distratto da interessanti argomenti di Intelligenza Artificiale e mi è passato tutto il resto di mente! :D

Fra le modifiche che ho fatto segnalo che ho completato la parte sui modelli astratti di algoritmi (forse approfondisco un po’ le macchine a registri) e ho corretto alcune sviste.

Ecco il solito link:

DIGITAL MIND

Alla prossima.

 

Probabilmente fra tutti gli esempi di applicazioni dell’Intelligenza Artificiale la più semplice e famosa consiste sicuramente nel gioco 20q. Il gioco in questione funziona così: il giocatore pensa ad un oggetto o ad un animale e il marchingegno tenta di indovinare di cosa si tratta in meno di 20 domande a cui il giocatore può rispondere si o no. Potete trovare una versione online del gioco all’indirizzo http://www.20q.net/. Potrete constatare che in alcuni casi il programma sembra proprio leggervi nella mente con risultati quasi spaventosi.

La versione usata dal sito è piuttosto avanzata ed utilizza le reti neurali e permette quindi una gamma di riposte più vasto (c’è anche forse, probabilmente, a volte, ecc…). Il programma è inoltre in grado di apprendere mentre si gioca: ogni qual volta si gioca, o il programma si arrende richiedendo di inserire l’oggetto a cui si pensava, l’insieme di risposte appena date plasma la struttura dati interna del programma in modo tale che la prossima volta l’oggetto venga riconosciuto più velocemente. È un modello di apprendimento molto basilare ma che è analogo a quello umano percezione-previsione-modifica: il programma riceve dati percettivi (le risposte alle domande), formula un ipotesi (i tentativi di indovinare) e modifica la struttura dati in base all’esito della previsione.

Sarei curioso di sapere se il programma del sito ha qualche contromisura contro il problema del sovra-adattamento: questo tipo di problema affligge gran parte dei modelli decisionali, comprese le reti neurali, ed è causato da un eccessivo adattamento della rete a certi tipi di dati piuttosto che ad altri. Facciamo un esempio. Nel gioco 20q è molto più probabile che il giocatore pensi a cose “banali” come “gatto”, “cane”, “fiore” e simili piuttosto che a “antilope”, “spinterogeno” e “neutrino”. Questo significa che nel corso dell’esistenza del gioco il programma verrà addestrato alla perfezione a riconoscere cani e gatti mentre riceverà poche informazioni riguardo antilopi e neutrini. Possiamo quindi dire che “gatto” e “fiore” e le parole comuni facciano parte dell’insieme di addestramento di una rete. Bene, è possibile dimostrare che una rete sovra-adattata al suo insieme di addestramento indovina, in media, molto meno volte oggetti che non appartengono a tale insieme rispetto ad una rete che è solo parzialmente adattata.

Rimandiamo però questi approfondimenti sulle reti neurali. Il motivo per cui ho scritto questo articolo era di mostrare come sia possibile in una manciata di righe scrivere un programma che emuli in modo semplice il gioco di 20q. Per questa approssimazione consideriamo che sia possibile dare alle domande soltanto le risposte si o no.

Il metodo che vi mostrerò non utilizza nessuna tecnica propria dell’IA bensì dei semplicissimi alberi binari. Questi alberi binari li indicheremo come alberi decisionali binari. Nel nostro albero decisionale definaiamo:

  • I nodi interni dell’albero sono domande.
  • I nodi foglia dell’albero sono gli oggetti da indovinare.
  • Il sotto-albero destro di un nodo corrisponde al caso in cui la risposta alla domanda sia si.
  • Il sotto-albero sinistro di un nodo corrisponde al caso in cui la risposta alla domanda sia no.

L’algoritmo del gioco consiste in una cosa del tipo:

  • Il programma formula la prima domanda che trova (cominciando con il nodo radice).
  • Se non c’è più nessuna domanda il programma si arrende e chiede al giocatore di inserire 1) l’oggetto a cui stava pensando. 2) una domanda che rappresenta l’oggetto 3) la risposta a questa domanda.
  • Il programma aggiunge questa domanda e la relativa risposta al sotto albero in cui si era fermato (oppure come nodo radice se l’albero era vuoto).
  • Se invece la domanda c’è il programma formula la domanda e scende nel sotto-albero relativo alla risposta.
  • Il programma ricomincia dal punto 1.

Tutto qui. Tale algoritmo è effettivamente molto grezzo e sono possibili un gran numero di migliorie (ad esempio usare dei modelli di albero più “elastici” per evitare alberi troppo sbilanciati) ma svolge decentemente il proprio lavoro. Dopo che l’avete fatto girare per qualche tempo vedrete che inizierà ad imparare e ad indovinare un discreto numero di parole. Ovviamente potete partire da un albero vuoto oppure pre-costruire un albero di base con alcune domande comuni.

Un altra cosa che può farci capire questo semplice programma è una considerazione che mi ha fatto notare un gentile commentatore: la capacità degli algoritmi di AI non dipende dalla dimensione del programma ovvero dal suo numero di righe di codice allo stesso modo di come le capacità celebrali umane non dipendono dalla dimensione del cervello (una balena ha il cervello molto più voluminoso di un essere umano eppure fa molte meno cose). Le capacità cognitive di un programma dipendono solamente dalle relazioni che si auto-generano fra le strutture dati del programma (nel nostro caso tali relazioni sono i collegamenti ad albero fra i nodi).

Se qualcuno avesse voglia di creare questo programmino usando il minor numero di righe possibili sarei felice di pubblicarlo. Inoltre potreste anche usarlo per sbalordire amici, parenti e vicini di casa! XD

Alla prossima!

 

Ebbene si… Dato che sono frequentatore di social network (se per alcuni è una grave colpa chiedo scusa anticipatamente) ho deciso in una mezz’ora di noia di integrare Slashcode ai vari socialnetwork. Per chi è interessato può trovare SC anche su:

TWITTER: https://twitter.com/slashcode

FACEBOOK: http://www.facebook.com/pages/SlashCode/101937993183122

In pratica svolgono le stesse funzioni dei Feed ma potrei twitterare anche delle cose “flash” per cui non ritengo necessario un intero articolo di blog. :)

Per chi mi seguirà anche li, un bel grazie.

 

Per chi volesse approfondire un po’ le meccaniche di funzionamento della mente umana vi consiglio caldamente il libro Inventare la Mente di Frith Chris, professore specializzato in neuroimaging all’Università di Londra. Questo libro fa veramente capire, in modo anche molto leggero, come percezione, apprendimento e azione siano sempre filtrati dalla nostra mente mettendo in evidenza la soggettività di molti eventi che noi riteniamo comuni.

ISBN: 8860301904

ISBN-139788860301901

 

L’Intelligenza Artificiale offre sempre spunti interessanti per riflettere su noi stessi. Per prima cosa è bene che sappiate che io sono un fermo sostenitore dell’ IA forte e pienamente convinto che, prima o poi, sarà possibile replicare artificialmente una mente  cosciente di se. Questo non implica che tali agenti intelligenti debbano per forza avere meccanismi di pensiero simili ai nostri, dopotutto la storia scientifica ci insegna che tutte le idee umanocentriche sono sempre state demolite dall’evidenza dei fatti, è quindi poco furbo ipotizzare che il cervello umano sia l’unica forma di “coscienza” possibile nell’universo. Tuttavia il cervello umano è senza dubbio l’unico che conosciamo attualmente e, quindi, è naturale che gran parte dell’IA si affidi a quello come musa ispiratrice e come traguardo.

A sostegno di questa tesi c’è poi la constatazione che, in più di un caso isolato, l’AI è riuscita ad anticipare scoperte che le neuroscienze cognitive avrebbero fatto solo alcuni anni dopo. Un caso fra i tanti è quello delle reti neurali. Una rete neurale non è altro che un sistema di neuroni artificiali (che non sono altro che sommatori pesati collegati ad un meccanismo “a soglia”, ovvero la cui uscita si attiva solamente se l’ingresso supera un certo valore) strettamente collegati fra loro. Tale meccanismo, sebbene composto da elementi relativamente semplici, è in grado di svolgere compiti estremamente complessi come, ad esempio, guidare un auto per centinaia di miglia  (si veda il progetto ALVINN). Queste reti vengono addestrate tramite il meccanismo di retro-propagazione. Questa tecnica consiste, per farla breve, nel modificare i pesi in ingresso ai neuroni artificiali in base al valore di predizione dell’intera rete: ho un dato ingresso x, la rete risponde y, se il valore esatto è y allora la rete non subisce variazioni, se invece il valore giusto era z la rete viene modificata in proporzione alla differenza fra il valore predetto e il valore desiderato. Bene, questo processo è del tutto simile al meccanismo alla base dell’apprendimento nella gran parte degli agenti viventi (non solo l’uomo):  è stato infatti constatato come il cervello rilasci dopamina a seconda se un evento previsto si verifichi o no. L’apprendimento tramite il modello errore-predizione è stato quindi sviluppato dall’AI alcuni anni prima che tale modello venisse formalizzato dai neuroscienziati.

L’AI inoltre ci permette anche di rivalutare molte nostre capacità. Tutti noi sappiamo riconoscere volti o comprendere il linguaggio naturale, ragion per cui consideriamo queste due attività delle cose “facili”. Diversamente solo poche persone sanno giocare bene a scacchi e quindi concludiamo che questo sia un compito “difficile”. In realtà dopo oltre 50 anni di ricerca nelle intelligenze artificiali  abbiamo decine di programmi in grado di giocare stupendamente a scacchi ma ben pochi programmi in grado di riconoscere un volto con prestazioni paragonabili a quelle umane. Questo quindi ci mostra come, in realtà, il giudizio che diamo ai vari problemi sia spesso invertito nel caso delle AI.

Perché? Una prima risposta consiste nel valutare l’importanza di tali problemi. Riconoscere un volto e capire il linguaggio sono cose essenziali a livello evolutivo. Animali che non siano in grado di riconoscere un potenziale predatore o preda da un sasso o da una pozza di lava difficilmente raggiungono l’età adulta, è quindi prevedibile che nel corso dell’evoluzione si siano formati cervelli abilissimi a riconoscere figure forme e colori e meno a giocare a scacchi. Ipoteticamente, infatti, se uccidessimo in fasce tutti i bambini che non siano in grado di giocare a scacchi ad un livello accettabile ci ritroveremmo, fra qualche milione di anni, davanti a esseri dotati di un cervello incredibilmente bravo a giocare a scacchi e, probabilmente, meno bravi a riconoscere un volto.

Il problema dell’evoluzione è quindi cruciale quando cerchiamo di imitare il cervello umano. Dobbiamo sempre tenere presente che il nostro cervello è quello che è perché c’è stata, nel corso delle ere, una pressione evolutiva che lo ha spinto ad avere certe capacità e a non averne altre.

Il secondo punto risiede proprio nella rappresentazione e nel modo in cui essa viene generata. Spesso infatti pretendiamo troppo dalle macchine che progettiamo. Prendiamo ad esempio la percezione visiva. Quando ci troviamo difronte alla percezione visiva ci rendiamo subito conto del problema fondamentale che la divide da problemi “semplici” come il gioco degli scacchi: il rumore. Il gioco degli scacchi è infatti facilmente rappresentabile in termini puramente matematici, è possibile cioè togliere semplicemente tutti gli aspetti rumorosi, ovvero che non danno alcuna informazione aggiuntiva tipo la forma degli scacchi o il colore della scacchiera. Quando invece tentiamo di semplificare la visione vengono alla luce notevoli problemi e domande. Ad esempio il concetto di forma e di bordo: che cos’è una forma? Quand’è che un quadrato a cui arrotondiamo via via gli angoli, smette di essere un quadrato e diventa un cerchio? Come definiamo il bordo di un oggetto data la sua immagine? Sappiamo che le risposte a queste domande sono essenziali per la visione ma non abbiamo idea di come il cervello umano le calcoli.

Abbiamo un gran numero di algoritmi in grado di darci i contorni e  la forma di un oggetto ma tali algoritmi sono spesso complessi, macchinosi ed utilizzano equazioni matematiche non banali sull’intera matrice dell’immagine. Ma, oltre al fatto che tali algoritmi sono piuttosto imprecisi, non è così che funziona l’occhio umano. L’occhio, ad esempio, è in gran parte ceco ad eccezione di una piccola zona centrale. L’impressione di avere un unica grande immagine è del tutto illusoria e prodotta dalla mente. L’immagine quindi è un prodotto della mente non un input percettivo. Perché allora vogliamo che le macchine funzionino direttamente sull’immagine? Non sarebbe meglio concentrarsi su come creare questa immagine partendo da una migliore copia dell’occhio umano? Ad esempio utilizzando i meccanismi basilari dell’uomo quali visione spot (ovvero concentrata al centro)  e rilevatore di movimento nella periferia dell’occhio (che serve a direzionare istintivamente il punto “vedente” dell’occhio in direzione di qualcosa che è cambiato per aggiornare l’immagine mentale). Queste cose potrebbero insegnarci nuovi modi per valutare  figure e bordi (un bordo potrebbe essere segnalato da una variazione repentina della visione (spot) che si avverte mentre l’occhio si muove oppure la forma di un oggetto può essere elaborata anche dal modo in cui l’occhio percorre il suo bordo (infatti quando osserviamo un quadrato, capiamo che è un quadrato percorrendo con gli occhi il bordo del quadrato, non lo facciamo consciamente ma lo facciamo).

Insomma, la neuroscienza ha molto da imparare dall’intelligenza artificiale, ma anche  l’intelligenza artificiale apprende molto dalla prima. Le due discipline si trascinano a vicenda verso nuovi traguardi e molto possiamo aspettarci da entrambe nei prossimi anni. E’ con questa consapevolezza che potremo arrivare un giorno a trovare la chiave, il punto di svolta, quella scoperta che ci farà capire che la soluzione ce l’avevamo da sempre sotto gli occhi. O forse dietro.

 

A partire da qualche mese è possibile che voi utenti Eclipse vi siate trovati nella condizione di non riuscire più ad utilizzare Eclipse per aggiornamenti, scaricare plugin e, più in generale, accedere alla rete.

Il problema è dovuto ad un bug conteso fra Debian (che potrebbe essersi propagato anche alle sue derivate come Ubuntu) e la virtual machine Java. In pratica c’è un gran casino fra IPv4 e IPv6 che ha come conseguenza il completo isolamento della rete di alcuni programmi Java.

Per risolvere basta lanciare il programma con i parametri

-vmargs -Djava.net.preferIPv4Stack=true

E Eclipse tornerà a funzionare come prima.

PS: I parametri che vi ho segnalato con buona probabilità funzionano anche per altri programmi soggetti allo stesso bug.

 

Avevo promesso aggiornamenti settimanali ed eccomi qui. Il capitolo sulla logica booleana è grossomodo terminato. Mancano degli esercizi che inizierò a mettere presto. Inoltre c’è anche la prima parte del capitolo sugli algoritmi.

Come al solito sono gradite segnalazioni di errori, commenti e richieste di maggiori chiarimenti su parti della guida che ho involontariamente lasciato troppo fumose.

Trovate tutto al solito link: DIGITAL MIND

Ciao

© 2008-2012 SlashCode Suffusion theme by Sayontan Sinha