0

Ich schreibe gerade einen naiven Bayes-Klassifikator, weil ich eine große Gruppe von Textdokumenten habe, die ich klassifizieren muss. Aber wenn ich versuche, meine Vorhersagen zu testen, bekomme ich folgende FehlerWie kann ich Tfidf die Werte für meinen Textklassifizierer korrekt transformieren und "anpassen"?

sklearn.utils.validation.NotFittedError: TfidfVectorizer - Vocabulary wasn't fitted.

Was ich tat, bevor hier fragen

Ich bin mir bewusst, der Theorie, wie Naive Bayes-Klassifizierung funktioniert.

      P(B|A)*P(A) 
    P(A|B) =   ____________________ 

      P(B|A)*P(A) + P(B|C)*P(C) +...+P(B|n)*P(n) 

wo A n die verschiedenen Klassen, die Sie wollen, klassifizieren und P (B | A) ist die Wahrscheinlichkeit von B gegeben Auftretende dass A aufgetreten ist, und P (A) ist die Wahrscheinlichkeit von A auftritt. Es sollte angemerkt werden, dass ich speziell mit den multinomialen Naiven Bayes arbeite.

Ich fand auch diese Frage:

SciPy and scikit-learn - ValueError: Dimension mismatch

sowie diese Frage

cannot cast array data when a saved classifier is called

Allerdings habe ich immer noch Probleme, wenn ich versuche, Vorhersagen zu machen oder testen meine Vorhersagen.

Ich habe folgende Funktionen geschrieben, die ich verwende, um eine Ausbildung zu schaffen und ein Test gesetzt

def split_data_set(original_data_set, percentage): 
    test_set = [] 
    train_set = [] 

    forbidden = set() 

    split_sets = {} 

    if is_float(percentage): 
     stop_len = int(percentage * len(original_data_set)) 

    while len(train_set) < stop_len: 
     random_selection = randrange(0, len(original_data_set)) 
     if random_selection not in forbidden: 
      forbidden.add(random_selection) 
      train_set.append(original_data_set[random_selection]) 

    for j in range(0, len(original_data_set)-1): 
     if j not in forbidden: 
      test_set.append(original_data_set[j]) 

    split_sets.update({'testing set': test_set}) 
    split_sets.update({'training set': train_set}) 
    split_sets.update({'forbidden': forbidden}) 

    return split_sets 

erstellen und trainiert ein Modell

def create_and_fit_baes_model(data_set): 

    train = [] 
    expect = [] 

    for data in data_set['training set']: 
     train.append(data[1]) 
     expect.append(data[0]) 

    vectorizer = TfidfVectorizer(min_df=1) 

    # I think this is one of the places where I'm doing something 
    # incorrectly 
    vectorized_training_data = vectorizer.fit_transform(train) 


    model = MultinomialNB() 


    model.fit(vectorized_training_data, expect) 

    return model 

und mein Modell zu testen

def test_nb_model(data_set, model): 

    test = [] 
    expect = [] 

    for data in data_set['testing set']: 
     test.append(data[1]) 
     expect.append(data[0]) 

    #This is the other section where I think that 
    # I'm doing something incorrectly 
    vectorizer = TfidfVectorizer(min_df=1) 
    vectorized_testing_data = vectorizer.transform(test) 
    fitted_vectorized_testing_data = vectorizer.fit(vectorized_testing_data) 

    predicted = model.predict(fitted_vectorized_testing_data) 

    print(metrics.confusion_matrix(expect,predicted)) 
    print(metrics.classification_report(expect, predicted)) 

Ich glaube, dass ich ein Problem während der Transformation/Anpassungsphase habe.

Ich weiß, dass TFIDF Vektorisierung funktioniert wie folgt

Dies wäre eine regelmäßige Matrix aus Dokumenten, die die Zählungen für verschiedene Laufzeiten.

 _term1____term2____term3____termn____________ 
doc1| 5 | 0 |  13 | 1 
doc2| 0 | 8 |  2 | 0 
doc3| 1 | 5 |  5 | 10 
. | . | . |  . | . 
. | . | . |  . | . 
. | . | . |  . | . 
docn| 10 | 0 |  0 | 0 

Von hier wenden Sie ein Gewichtungsschema, um zu bestimmen, wie wichtig bestimmte Worte zu Ihrem Korpus sind.

Ich weiß, wie das alles in der Theorie funktioniert und ich kann die Mathematik auf dem Papier arbeiten, aber wenn ich versuche, the documentation für sklearn zu lesen, bin ich immer noch ein wenig verwirrt, wie ich alles programmieren soll.

Ich habe in den letzten zwei Tagen damit zu kämpfen. Wenn jemand einen Einblick geben könnte, was ich falsch mache und wie ich mein Modell vollständig trainieren und betreiben kann, würde ich es begrüßen.

+1

Sie müssen auch tfidf Vectorizer speichern, und verwenden ** die gleiche ** in der Trainingsphase. – lejlot

+0

@lejlot Meinst du den gleichen Vektorizer? Wie muss ich es von einer Methode zur anderen weitergeben? –

+0

ja, ich meine du musst es auch speichern – lejlot

Antwort

2

Ich denke, die sauberste Option ist eine Pipeline verwenden, um Ihren Vektorisierer mit Ihrem Klassifikator zu packen; Wenn Sie dann aufrufen, passt das Vokabular und die Termhäufigkeiten Ihres Vektorisierers und machen sie für spätere Funktionen verfügbar.Auf diese Weise können Sie immer nur ein einzelnes "Modell" aus Ihrer Trainingsfunktion zurückgeben, und Sie können dies auch beilegen, wenn Sie Ihr Modell speichern müssen.

from sklearn.pipeline import Pipeline 

def create_and_fit_model(data): 
    # ... get your train and expect data 
    vectorizer = TfidfVectorizer(min_df=1) 
    nb = MultinomialNB() 
    model = Pipeline([('vectorizer', vectorizer), ('nb', nb)]) 
    model.fit(train, expect) 
    return model 

Durch die Art und Weise brauchen Sie nicht Ihren eigenen Code für Zug/Test Split zu schreiben, Sie sklearn.cross_validation.train_test_split verwenden können. Außerdem sollten Sie Pandas zum Speichern Ihrer Daten anstelle von einfachen Listen verwenden. Es erleichtert das Extrahieren von Spalten.