2016-03-10 7 views
5

Ho una varietà di termini nella lista nera che voglio identificare all'interno di un corpus di paragrafi di testo. Ogni termine è lungo circa 1 - 5 parole e contiene determinate parole chiave che non voglio nel mio corpus di documenti. Se un termine o qualcosa di simile ad esso è identificato nel corpus, lo voglio rimosso dal mio corpus.Come classificare accuratamente il testo con molti valori potenziali usando scikit?

Rimozione a parte, sto lottando con l'identificazione accurata di questi termini nel mio corpus. Sto usando scikit-learn e ho provato due approcci separati:

  1. Un approccio MultinomialNB la classificazione secondo le caratteristiche di vettore TF-IDF con un mix di termini nella lista nera e termini pulite, utilizzate come dati di allenamento.

  2. Un approccio OneClassSVM in cui solo le parole chiave inserite nella lista nera vengono utilizzate come dati di allenamento e qualsiasi testo trasmesso che non sembra simile ai termini della lista nera sono considerati valori anomali.

Ecco il codice per il mio approccio OnceClassSVm:

df = pd.read_csv("keyword_training_blacklist.csv") 

keywords_list = df['Keyword'] 

pipeline = Pipeline([ 
    ('vect', CountVectorizer(analyzer='char_wb', max_df=0.75, min_df=1, ngram_range=(1, 5))), 
    # strings to token integer counts 
    ('tfidf', TfidfTransformer(use_idf=False, norm='l2')), # integer counts to weighted TF-IDF scores 
    ('clf', OneClassSVM(nu=0.1, kernel="rbf", gamma=0.1)), # train on TF-IDF vectors w/ Naive Bayes classifier 
]) 

kf = KFold(len(keywords_list), 8) 
for train_index, test_index in kf: 
    # make training and testing datasets 
    X_train, X_test = keywords_list[train_index], keywords_list[test_index] 

    pipeline.fit(X_train) # Train classifier using training data and labels 
    predicted = pipeline.predict(X_test) 
    print(predicted[predicted == 1].size/predicted.size) 

csv_df = pd.read_csv("corpus.csv") 

testCorpus = csv_df['Terms'] 

testCorpus = testCorpus.drop_duplicates() 


for s in testCorpus: 
    if pipeline.predict([s])[0] == 1: 
     print(s) 

In pratica, io sono sempre molti falsi positivi quando provo a passare nel mio corpus all'algoritmo. I miei dati relativi alla formazione a scadenze vincolanti ammontano a circa 3000 termini. La dimensione dei miei dati di allenamento deve essere ulteriormente aumentata o mi manca qualcosa di ovvio?

+0

Quali sono le tue caratteristiche effettive - solo singole parole? Hai provato a utilizzare invece coppie di parole adiacenti? Inoltre, cosa intendi con "un termine o qualcosa di simile ad esso" - semanticamente simile, o all'interno di qualche distanza di modifica, o qualcos'altro? – tripleee

+0

stai cercando di rimuovere documenti contenenti questi termini? o i termini stessi? perché non usi regexp? –

+0

Voglio prendere termini con lo spelling simile a quelli che sono nella mia lista nera. Un termine sarebbe una semplice stringa come "questo è un termine" e "loren ipsum". Un termine inserito nella lista nera sarebbe "ragazze sexy" e voglio prendere termini simili come "sexxy girls". Ho cercato metodi come la distanza di Levenshtein ma non sono sicuro che possano essere inclusi in un algoritmo ML. Un approccio regexp sembra ovvio in un primo momento, ma ho migliaia di termini nella lista nera e milioni di termini da ordinare, il che spiega la mia necessità di un approccio ML. – GreenGodot

risposta

2

Prova a utilizzare difflib per identificare la corrispondenza più simile nel corpus a ciascuno dei tuoi termini elencati in nero.

import difflib 
from nltk.util import ngrams 

words = corpus.split(' ') # split corpus to words based on spaces (can be improved) 

words_ngrams = [] # ngrams from 1 to 5 words 
for n in range(1,6): 
    words_ngrams.extend(' '.join(ngrams(words, n))) 


to_delete = [] # will contain tuples (index, length) of matched terms to delete from corpus. 
sim_rate = 0.8 # similarity rate 
max_matches = 4 # maximum number of matches for each term 
for term in terms: 
    matches = difflib.get_close_matches(term,words_ngrams,n=max_matches,cutoff=sim_rate) 
    for match in matches: 
     to_delete.append((corpus.index(match), len(match))) 

È inoltre possibile utilizzare difflib.SequenceMatcher se si vuole ottenere un punteggio di somiglianza tra i termini e ngrams.

Problemi correlati