Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pickle a sklearn pipeline for multi label classifier/one vs rest classifier?

I am trying to create a multi-label classifier using the one vs rest classifier wrapper.

I used a pipeline for TFIDF and the classifier.

When fitting the pipeline, I have to loop through my data by category and then fit the pipeline each time to make predictions for each category.

Now, I want to export this like how one would usually export a fitted model using pickle or joblib.

Example:

pickle.dump(clf,'clf.pickle')

How can I do this with the pipeline? Even if I pickle the pipeline, do I still need to fit the pipeline every time when I want to predict on a new keyword?

Example:

pickle.dump(pipeline,'pipeline.pickle')
pipeline = pickle.load('pipeline.pickle')

for category in categories:
    pipeline.fit(X_train, y_train[category])
    pipeline.predict(['kiwi'])
    print (predict)

If I skip the pipeline.fit(X_train, y_train[category]) after loading the pipeline, I only get a single value array in predict. If I fit the pipeline, I get a three value array.

Also, how can I incorporate the grid search into my pipeline for export?

raw_data

keyword        class1 class2 class3
"orange apple"    1      0      1
"lime lemon"      1      0      0
"banana"          0      1      0

categories = ['class1','class2','class3']

pipeline

SVC_pipeline = Pipeline([
                ('tfidf', TfidfVectorizer(stop_words=stop_words)),
                ('clf', OneVsRestClassifier(LinearSVC(), n_jobs=1)),
            ])

Gridsearch (dont know how to incorporate this into the pipeline)

parameters = {'tfidf__ngram_range': [(1, 1), (1, 2)],
              'tfidf__use_idf': (True, False),
              'tfidf__max_df': [0.25, 0.5, 0.75, 1.0],
              'tfidf__max_features': [10, 50, 100, 250, 500, 1000, None],
              'tfidf__stop_words': ('english', None),
              'tfidf__smooth_idf': (True, False),
              'tfidf__norm': ('l1', 'l2', None),
              }

grid = GridSearchCV(SVC_pipeline, parameters, cv=2, verbose=1)
grid.fit(X_train, y_train)

Fitting pipeline

for category in categories:
    print('... Processing {}'.format(category))

    SVC_pipeline.fit(X_train, y_train[category])

    # compute the testing accuracy
    prediction = SVC_pipeline.predict(X_test)
    print('Test accuracy is {}'.format(accuracy_score(y_test[category], prediction)))
like image 888
jxn Avatar asked Nov 20 '25 07:11

jxn


1 Answers

OneVsRestClassifier internally fits one classifier per class. So you should not be fitting the pipeline for each class like you are doing in

for category in categories:
    pipeline.fit(X_train, y_train[category])
    pipeline.predict(['kiwi'])
    print (predict)

You should be doing something like this

SVC_pipeline = Pipeline([
                ('tfidf', TfidfVectorizer()), #add your stop_words
                ('clf', OneVsRestClassifier(LinearSVC(), n_jobs=1)),
            ])
SVC_pipeline.fit(["apple","boy","cat"],np.array([[0,1,1],[1,1,0],[1,1,1]]))

You can now save the model using

pickle.dump(SVC_pipeline,open('pipeline.pickle', 'wb'))   

Later you can load back the model and make predictions using

obj = pickle.load(open('pipeline.pickle', 'rb'))
obj.predict(["apple","boy","cat"])

You can binarise your multiclass labels using MultiLabelBinarizer before passing them to fit method

Sample:

from sklearn.preprocessing import MultiLabelBinarizer
y = [['c1','c2'],['c3'],['c1'],['c1','c3'],['c1','c2','c3']]
mb = MultiLabelBinarizer()
y_encoded = mb.fit_transform(y)
SVC_pipeline.fit(["apple","boy","cat", "dog", "rat"], y_encoded)

Using Grid Search (sample)

grid = GridSearchCV(SVC_pipeline, {'tfidf__use_idf': (True, False)}, cv=2, verbose=1)
grid.fit(["apple","boy","cat", "dog", "rat"], y_encoded)
# Save the pipeline
pickle.dump(grid,open('grid.pickle', 'wb'))
# Later load it back and make predictions
grid_obj = pickle.load(open('grid.pickle', 'rb'))
grid_obj.predict(["apple","boy","cat", "dog", "rat"])
like image 137
mujjiga Avatar answered Nov 21 '25 21:11

mujjiga



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!