Domanda

Ho circa 300k documenti memorizzati in un database Postgres che sono contrassegnati con categorie di argomenti (ce ne sono circa 150 categorie in totale). Ho un altro 150k documenti che non hanno ancora categorie. Sto cercando di trovare il modo migliore per programmaticly loro categorizzare.

Ho esplorato NLTK e la sua Naive Bayes Classificatore. Mi sembra un buon punto di partenza (se si può suggerire un algoritmo di classificazione migliore per questo compito, sono tutto orecchie).

Il mio problema è che non ho abbastanza RAM per addestrare il NaiveBayesClassifier su tutti i 150 categoies / 300k documenti contemporaneamente (formazione su 5 categorie utilizzato 8GB). Inoltre, la precisione del classificatore sembra cadere come mi alleno su altre categorie (90% di precisione con 2 categorie, 81% con 5, 61% con 10).

Devo solo addestrare un classificatore in 5 categorie alla volta, ed eseguire tutti i 150k documenti attraverso il classificatore per vedere se ci sono le partite? Sembra che questo dovrebbe funzionare, se non che ci sarebbe un sacco di falsi positivi in ??cui i documenti che in realtà non corrispondono a nessuna delle categorie ottengono scarpa-cornuto in data dal classificatore solo perché è la migliore corrispondenza disponibile ... C'è un modo per avere un "nessuna delle precedenti" opzione per il classificatore nel caso in cui il documento non rientra in nessuna delle categorie?

Qui è la mia classe di test http://gist.github.com/451880

È stato utile?

Soluzione

Si dovrebbe iniziare con la conversione dei documenti in TF-log (1 + IDF) vettori : frequenze termine sono sparse così si dovrebbe usare pitone dict con termine come chiavi e contare come valori e poi dividere per conteggio totale per ottenere le frequenze globali.

Un'altra soluzione è quella di utilizzare i abs (hash (termine)), per esempio come tasti interi positivi. Poi si un uso scipy.sparse vettori che sono più a portata di mano e più efficiente per eseguire l'algebra lineare operazione di pitone dict.

Anche costruire le 150 frequenze vettori mediando le frequenze di tutti i documenti classificati appartenenti alla stessa categoria. Poi per nuovo documento di etichetta, è possibile calcolare la coseno di similitudine tra il vettore del documento e ogni categoria di vettore e scegliere la categoria più simile come etichetta per il documento.

Se questo non è abbastanza buono, allora si dovrebbe cercare di formare un modello di regressione logistica con un rigore L1, come spiegato in questo esempio di scikit-learn (questo è un involucro per liblinear come spiegato da @ephes). I vettori utilizzati per addestrare il vostro modello di regressione logistica dovrebbe essere il TD-log precedentemente introdotto (1 + IDF) vettori per ottenere buone prestazioni (precisione e richiamo). Lo scikit imparare offerte lib modulo A sklearn.metrics con routine per calcolare quelli punteggio per un dato modello e dato insieme di dati.

Per i set di dati più grandi: si dovrebbe provare il vowpal wabbit che è probabilmente il coniglio più veloce sulla terra per la grande problemi di classificazione del documento di scala (ma non facile da usare wrapper python AFAIK).

Altri suggerimenti

Quanto è grande (numero di parole) sono i documenti? Il consumo di memoria a 150K trainingdocs non dovrebbe essere un problema.

Naive Bayes è una buona scelta soprattutto quando si hanno molte categorie con solo alcuni esempi di formazione o trainingdata molto rumoroso. Ma in generale, lineare Support Vector Machines fanno eseguire molto meglio.

è il vostro problema multiclasse (un documento appartiene solo a una categoria exclusivly) o multietichetta (un documento appartiene a una o più categorie)?

La precisione è una scelta sbagliata per le prestazioni giudice classificatore. Si dovrebbe invece usare precisione vs richiamo, punto di richiamo di precisione pareggio (prbp), f1, l'AUC e devono guardare la precisione curva della richiamo in cui il richiamo (x) è tracciata contro precisione (y) in base al valore della vostra fiducia soglia (castrato un documento appartiene ad una categoria o meno). Di solito si potrebbe costruire un classificatore binario per categoria (esempi di addestramento positivi di una categoria vs tutti gli altri trainingexamples che non appartengono alla categoria corrente). Dovrete scegliere una soglia di sicurezza ottimale per ogni categoria. Se si desidera combinare le singole misure per categoria in una misura della performance globale, dovrete micro (riassumere tutti i veri positivi, falsi positivi, falsi negativi e veri negativi e calc combinato spartiti) o macro (punteggio calc per categoria e poi la media i punteggi su tutte le categorie) media.

Abbiamo un corpus di decine di milioni di documenti, milioni di esempi di formazione e migliaia di categorie (multietichetta). Dal momento che ci troviamo ad affrontare gravi problemi di tempo di formazione (il numero di documenti sono nuovi, aggiornati o cancellati al giorno è abbastanza alto), si usa una versione modificata di liblinear . Ma per problemi più piccoli che utilizzano uno dei wrapper Python intorno liblinear ( liblinear2scipy o scikit-learn ) dovrebbe funzionare bene.

  

C'è un modo per avere un "nessuna delle   sopra" l'opzione per il classificatore solo   nel caso in cui il documento non si adatta   una delle categorie?

Si potrebbe ottenere questo effetto semplicemente avendo un "nessuna delle precedenti" pseudo-categoria addestrati ogni volta. Se il massimo che si può allenare a 5 categorie (anche se non so perché è divorando poi così tanto RAM sono), formare 4 categorie effettivi dai loro effettivi 2K documenti ciascuno, e un "nessuna delle precedenti" uno con le sue 2K documenti presi a caso da tutte le altre categorie 146 (circa 13-14 da ognuno, se vuole l'approccio "stratificato di campionamento", che può essere più solida).

si sente ancora come un po 'un ripiego e si potrebbe essere meglio con un approccio completamente diverso - trovare una misura doc multidimensionale che definisce i 300K documenti pre-tag in 150 cluster ragionevolmente separabili, poi basta assegnare a ciascuno di gli altri documenti non ancora senza tag al cluster appropriato come così determinate. Non credo NLTK ha nulla direttamente a disposizione per supportare questo genere di cose, ma, ehi, NLTK del cresciuta così in fretta che io possa anche aver perso qualcosa ...; -)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top