2017-04-15 1 views
0
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer 

Hallo Ich habe die folgende Liste der Kommentare:Warum funktioniert die folgende Teilanpassung nicht?

comments = ['I am very agry','this is not interesting','I am very happy'] 

Dies sind die entsprechenden Etiketten:

sents = ['angry','indiferent','happy'] 

ich TFIDF verwende diese Kommentare zu vektorisieren wie folgt:

tfidf_vectorizer = TfidfVectorizer(analyzer='word') 
tfidf = tfidf_vectorizer.fit_transform(comments) 
from sklearn import preprocessing 

Ich verwende Label-Encoder zur Vektorisierung der Etiketten:

le = preprocessing.LabelEncoder() 
le.fit(sents) 
labels = le.transform(sents) 
print(labels.shape) 
from sklearn.linear_model import PassiveAggressiveClassifier 
from sklearn.model_selection import train_test_split 
with open('tfidf.pickle','wb') as idxf: 
    pickle.dump(tfidf, idxf, pickle.HIGHEST_PROTOCOL) 
with open('tfidf_vectorizer.pickle','wb') as idxf: 
    pickle.dump(tfidf_vectorizer, idxf, pickle.HIGHEST_PROTOCOL) 

Hier sind passiv aggressiv bin mit dem Modell passen:

clf2 = PassiveAggressiveClassifier() 


with open('passive.pickle','wb') as idxf: 
    pickle.dump(clf2, idxf, pickle.HIGHEST_PROTOCOL) 

with open('passive.pickle', 'rb') as infile: 
    clf2 = pickle.load(infile) 

with open('tfidf_vectorizer.pickle', 'rb') as infile: 
    tfidf_vectorizer = pickle.load(infile) 
with open('tfidf.pickle', 'rb') as infile: 
    tfidf = pickle.load(infile) 

Hier Ich versuche, die Nutzung von Teil fit zu testen, wie mit drei neuen Kommentaren und ihren entsprechenden Etikett folgt:

new_comments = ['I love the life','I hate you','this is not important'] 
new_labels = [1,0,2] 
vec_new_comments = tfidf_vectorizer.transform(new_comments) 

print(clf2.predict(vec_new_comments)) 
clf2.partial_fit(vec_new_comments, new_labels) 

Das Problem ist, dass ich nicht die richtigen Ergebnisse nach der Teilanpassung wie folgt erhalten:

print('AFTER THIS UPDATE THE RESULT SHOULD BE 1,0,2??') 
print(clf2.predict(vec_new_comments)) 

aber ich erhalte diese Ausgabe:

[2 2 2] 

So habe ich wirklich schätzen zu finden unterstützen, warum das Modell nicht aktualisiert wird, wenn ich es mit den gleichen Beispielen mich entschieden, dass es trainiert werden verwendet die gewünschter Ausgang sollte sein:

Ich würde gerne Unterstützung zu ajust vielleicht die Hyperparameter schätzen, um die gewünschte Ausgabe zu sehen.

dies ist der vollständige Code, die teilweise fit zeigen:

from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer 
import sys 
from sklearn.metrics.pairwise import cosine_similarity 
import random 


comments = ['I am very agry','this is not interesting','I am very happy'] 
sents = ['angry','indiferent','happy'] 
tfidf_vectorizer = TfidfVectorizer(analyzer='word') 
tfidf = tfidf_vectorizer.fit_transform(comments) 
#print(tfidf.shape) 
from sklearn import preprocessing 
le = preprocessing.LabelEncoder() 
le.fit(sents) 
labels = le.transform(sents) 

from sklearn.linear_model import PassiveAggressiveClassifier 
from sklearn.model_selection import train_test_split 
with open('tfidf.pickle','wb') as idxf: 
    pickle.dump(tfidf, idxf, pickle.HIGHEST_PROTOCOL) 
with open('tfidf_vectorizer.pickle','wb') as idxf: 
    pickle.dump(tfidf_vectorizer, idxf, pickle.HIGHEST_PROTOCOL) 

clf2 = PassiveAggressiveClassifier() 

clf2.fit(tfidf, labels) 


with open('passive.pickle','wb') as idxf: 
    pickle.dump(clf2, idxf, pickle.HIGHEST_PROTOCOL) 

with open('passive.pickle', 'rb') as infile: 
    clf2 = pickle.load(infile) 



with open('tfidf_vectorizer.pickle', 'rb') as infile: 
    tfidf_vectorizer = pickle.load(infile) 
with open('tfidf.pickle', 'rb') as infile: 
    tfidf = pickle.load(infile) 

new_comments = ['I love the life','I hate you','this is not important'] 
new_labels = [1,0,2] 

vec_new_comments = tfidf_vectorizer.transform(new_comments) 

clf2.partial_fit(vec_new_comments, new_labels) 



print('AFTER THIS UPDATE THE RESULT SHOULD BE 1,0,2??') 
print(clf2.predict(vec_new_comments)) 

Allerdings habe ich:

AFTER THIS UPDATE THE RESULT SHOULD BE 1,0,2?? 
[2 2 2] 
+0

Wie Sie die 'clf2' passend sind. Bitte posten Sie den gesamten Code als ein Code-Snippet. Jetzt ist es sehr nervig, Paste immer wieder zu kopieren. –

+0

@VivekKumar Ich habe die Frage aktualisiert, ich habe den kompletten Code hinzugefügt, um mein Problem zu reproduzieren, danke für die Unterstützung – neo33

Antwort

1

Nun gibt es mehrere Probleme mit Ihrem Code. Ich werde mit der Angabe der offensichtlichen zu komplexeren beginnen:

  1. Sie beizen die clf2, bevor es etwas gelernt hat. (dh Sie pikieren es, sobald es definiert ist, es dient keinem Zweck). Wenn Sie nur testen, dann gut. Ansonsten sollten sie nach den fit() oder gleichwertigen Anrufen gebeizt werden.
  2. Sie rufen clf2.fit() vor der clf2.partial_fit(). Dies vereitelt den gesamten Zweck von partial_fit(). Wenn Sie fit() aufrufen, beheben Sie im Wesentlichen die Klassen (Beschriftungen), die das Modell erfahren wird. In Ihrem Fall ist es akzeptabel, denn bei Ihrem nächsten Anruf an partial_fit() geben Sie die gleichen Etiketten. Aber es ist immer noch keine gute Übung.

    See this for more details

    In einem partial_fit() Szenario nicht die fit() jemals nennen. Rufen Sie immer die partial_fit() mit Ihren Startdaten und neuen kommenden Daten an. Stellen Sie jedoch sicher, dass Sie beim ersten Aufruf von parital_fit() in einem Parameter classes alle Beschriftungen angeben, die das Modell lernen soll.

  3. Jetzt der letzte Teil, über Ihre tfidf_vectorizer. Sie rufen fit_transform() (das ist im Wesentlichen fit() und dann transformed() kombiniert) auf tfidf_vectorizer mit comments Array. Das bedeutet, dass es bei folgenden Aufrufen an transform() (wie Sie in transform(new_comments) getan haben), es neue Wörter von new_comments nicht lernen wird, aber nur die Wörter verwenden, die es während des Aufrufs an fit() (Wörter vorhanden in comments) sah.

    Gleiches gilt für LabelEncoder und sents.

    Dies ist wiederum nicht in einem Online-Lernszenario vorzuziehen. Sie sollten alle verfügbaren Daten auf einmal anpassen. Aber da Sie versuchen, die partial_fit() zu verwenden, nehmen wir an, dass Sie sehr große Datenmenge haben, die möglicherweise nicht in Speicher gleichzeitig passt. Sie möchten also auch eine Art Partial_Fit auf TfidfVectorizer anwenden. Aber TfidfVectorizer unterstützt partial_fit() nicht. Tatsächlich ist es nicht für große Datenmengen geeignet. Also müssen Sie Ihren Ansatz ändern. Auch die folgenden Fragen, um weitere Informationen: -

Alle Dinge beiseite, wenn Sie nur den TFIDF Teil ändern, um die gesamten Daten des Anpassens (comments und new_comments an einmal), erhalten Sie Ihre gewünschten Ergebnisse.

Siehe folgende Änderungen am Code (I organisiert es ein wenig haben und umbenannt vec_new_comments-new_tfidf, gehen Sie bitte durch sie mit Aufmerksamkeit):

comments = ['I am very agry','this is not interesting','I am very happy'] 
sents = ['angry','indiferent','happy'] 

new_comments = ['I love the life','I hate you','this is not important'] 
new_sents = ['happy','angry','indiferent'] 

tfidf_vectorizer = TfidfVectorizer(analyzer='word') 
le = preprocessing.LabelEncoder() 

# The below lines are important 

# I have given the whole data to fit in tfidf_vectorizer 
tfidf_vectorizer.fit(comments + new_comments) 

# same for `sents`, but since the labels dont change, it doesnt matter which you use, because it will be same 
# le.fit(sents) 
le.fit(sents + new_sents) 

unten ist das nicht so bevorzugt Code (die Sie verwenden und über die ich in Punkt 2 gesprochen habe, aber die Ergebnisse sind gut, solange Sie die obigen Änderungen vornehmen.

tfidf = tfidf_vectorizer.transform(comments) 
labels = le.transform(sents) 

clf2.fit(tfidf, labels) 
print(clf2.predict(tfidf)) 
# [0 2 1] 

new_tfidf = tfidf_vectorizer.transform(new_comments) 
new_labels = le.transform(new_sents) 

clf2.partial_fit(new_tfidf, new_labels) 
print(clf2.predict(new_tfidf)) 
# [1 0 2]  As you wanted 

richtige Ansatz, oder die Art und Weise partial_fit() soll verwendet werden:

# Declare all labels that you want the model to learn 
# Using classes learnt by labelEncoder for this 
# In any calls to `partial_fit()`, all labels should be from this array only 

all_classes = le.transform(le.classes_) 

# Notice the parameter classes here 
# It needs to present first time 
clf2.partial_fit(tfidf, labels, classes=all_classes) 
print(clf2.predict(tfidf)) 
# [0 2 1] 

# classes is not present here 
clf2.partial_fit(new_tfidf, new_labels) 
print(clf2.predict(new_tfidf)) 
# [1 0 2] 
+0

vielen Dank für die Unterstützung, die ich endlich diese Situation überwinden – neo33

Verwandte Themen