[Pubblichiamo una versione italiana dell’articolo Analyzing Cultural Domains with Python scritto dall’autore di Data Science con Python. La prima parte è apparsa lo scorso 18 aprile; la seconda, il 16 maggio e la terza l’8 giugno.]
Nei tre articoli precedenti a questo si è lavorato per realizzare un modello analizzabile del nostro dominio culturale scelto come campione: la community che su LiveJournal commenta la serie televisiva americana The Good Wife. Con Python e librerie assortite abbiamo eliminato doppioni, risolto ambiguità lessicali e semantiche e preparato una struttura dati di tipo DataFrame (come la chiama Pandas) dalla quale, nel terzo articolo, abbiamo ricavato una comunità di termini attraverso moduli disponibili in Anaconda.
Comunità di termini
Il modulo community usa il metodo di Louvain per estrarre comunità di termini dal network: gruppi di nodi connessi più strettamente del previsto tra essi che con il resto del network. Le comunità scoperte vengono rappresentate come una partizione: un dizionario chiave-valore con etichette di nodo come chiavi e identificatori interi di comunità come valori. Il modulo calcola inoltre la modularità della partizione. Un network con una struttura perfetta di comunità ha modularità 1, mentre un network di dati ammassati su se stessi, rappresentabile come una palla pelosa, ha modularità tendente a zero. La mia modularità non è così male:
partition = community.best_partition(words_network) print("Modularity:", community.modularity(partition, words_network)) # Output: Modularity: 0.8724188314419324
La partizione definisce compiutamente le comunità, o cluster (agglomerati), di termini. I cluster però sono senza nome. Potevo guardarli e pensare a nomi appropriati, ma non sarei stato un programmatore Python duro e puro. Ho invece aggiunto come ciliegina sulla torta altre sette righe di codice che individuano i cinque termini più utilizzati in ogni cluster. Spero che ne descrivano in modo sufficiente il contenuto. Ho creato una piccola funzione ausiliaria describe_cluster() (che poi è l’unica funzione creata da me nel progetto). Esamina un elenco di termini presenti in una comunità, considera i nomi delle righe nel DataFrame originale, ne calcola la frequenza di utilizzo e restituisce l’elenco dei termini più gettonati (HOW_MANY) performers.
HOW_MANY = 5 def describe_cluster (x): # x è un frame; seleziona da "domain" le righe che corrispondono rows = domain.ix[x.index] # Calcola i totali delle righe, li ordina, prende l’ultimo HOW_MANY top_N = rows.sum(axis=1).sort_values(ascending=False)[ : HOW_MANY] # Che etichette hanno? return top_N.index.values
Ho convertito la partizione in un DataFrame, raggruppato le righe per identificativo di partizione e chiesto alla funzione ausiliaria di tirare fuori un nome. L’ultima riga è orrenda e molto non-Python (nessuno chiama print() nell’analisi di una lista!).
word_clusters = pd.DataFrame({"part_id" : pd.Series(partition)}) results = word_clusters.groupby("part_id").apply(describe_cluster) _ = [print("--", "; ".join(r.tolist())) for r in results]
Ma funziona:
-- criminal mind; ncis; cold case; without trace -- london; lady gaga; sherlock holmes; paris; muse -- tennis; tegan sara; pretender; u2; killer -- music; reading; movie; writing; book -- harry potter; jane austen; pride prejudice; colin firth; leverage -- gilmore girl; lauren graham; kristen bell; oc; one tree hill -- veronica mar; firefly; glee; friend; buffy vampire slayer -- west wing; true blood; friday night light; mad men; sport night -- grey ' anatomy; csi; brother sister; private practice; desperate housewife -- supernatural; vampire diary; prison break; jensen ackles; dean winchester -- food; yoga -- slash; fan fiction; anime; johnny depp; manga -- good wife; white collar; josh charles; kalinda sharma; julianna margulies -- musical; ugly betty; theatre; singing; broadway -- battlestar galactica; x - file; mulder / scully; gillian anderson; femslash -- lord ring; beatles; disney; queen; monty python -- internet; twilight; romance; family; concert -- office; daily show; jon stewart; stephen colbert; life -- hugh laurie; house md; lisa edelstein; house m . d .; jennifer morrison -- x - men; fantasy; science fiction «…altre 50 descrizioni…»
Ciascuna riga mostra un massimo di cinque termini tra i più menzionati in un cluster, separati da punto e virgola. Alcuni termini hanno un aspetto strano e quasi irriconoscibile (x – file), ma può succedere dopo tutte le trasformazioni che abbiamo applicato! Alcuni termini sono chiaramente duplicati (house md – house m . d.), ma significa semplicemente che tutte le trasformazioni applicate non sono state abbastanza drastiche.
Interpretare i risultati
L’interpretazione dei risultati di una analisi dei dominî culturali avviene su due livelli. Al livello inferiore, concludo che tutti i 331 termini selezionati come importanti per gli spettatori di The Good Wife lo sono davvero, altrimenti non sarebbero stati selezionati. Alcuni dei termini, inoltre, si associano meglio tra loro di altri. Capisco che jensen ackless ha qualcosa a che fare con supernatural (infatti ha recitato nella serie omonima) e anche vampire diary è supernatural, per ragioni evidenti. Music, reading, e writing sono attività; anime è vicino a manga. Posso arrivare a queste conclusioni meccanicistiche senza avere la minima idea del reale contenuto del dominio culturale. Al livello superiore, potrei essere un etnografo, antropologo, psicologo, sociologo interessato all’ambito mentale dei fan di The Good Wife. Potrei magari volerlo confrontare con quello dei fan di Harry Potter o di House M.D. [Dr. House in Italia]. Ma sono solo un umile computer scientist e lascio volentieri l’intepretazione di livello superiore a un esperto di dominî.