scikit-learn - how to force selection of at least a single label in LinearSVC
<p>I'm doing a <a href="http://scikit-learn.org/stable/modules/multiclass.html" rel="nofollow">multi-label classification</a>.  I've trained on a dataset and am getting back suggested labels.  However, not all have at least a single label.  I'm running into this exact issue that was <a href="http://scikit-learn-general.narkive.com/lm8imv9z/linearsvc-somtimes-returns-no-label" rel="nofollow">discussed on the mailing list</a>.  It looks like there was discussion around potentially adding a parameter to force selection of a minimum number of labels, however, in looking at the documentation I don't see that it was ever implemented.  I don't quite understand the suggested hack.  Is there no way to do this after all the learning has completed?</p>

<p>The learning portion of my code:</p>

<pre><code>lb = preprocessing.MultiLabelBinarizer()

Y = lb.fit_transform(y_train_text)

classifier = Pipeline([
    ('vectorizer', CountVectorizer(stop_words="english")),
    ('tfidf', TfidfTransformer()),
    ('clf', OneVsRestClassifier(LinearSVC()))])

classifier.fit(X_train, Y)
predicted = classifier.predict(X_test)
all_labels = lb.inverse_transform(predicted)
</code></pre>

<p>Thanks to "lejlot", this was extremely close to what I wanted.  I didn't want to override the cases where I had one or more predictions though.  This is what I came up with that seems to be working:</p>

<pre><code>lb = preprocessing.MultiLabelBinarizer()
Y = lb.fit_transform(y_train_text)

classifier = Pipeline([
    ('vectorizer', CountVectorizer(stop_words="english")),
    ('tfidf', TfidfTransformer()),
    ('clf', OneVsRestClassifier(LinearSVC()))])

classifier.fit(X_train, Y)
predicted = classifier.predict(X_test)
x = classifier.decision_function(X_test)
predicted_all = sp.sign(x - x.max(1).reshape(x.shape[0], 1) + 1e-20)
predicted_all = (predicted_all + 1)/2
for i in range(0, len(predicted)):
    #if we never came up with a prediction, use our "forced" single prediction
    if (all(v == 0 for v in predicted[i])):
        predicted[i] = predicted_all[i]
all_labels = lb.inverse_transform(predicted)
</code></pre>

python machine-learning scipy scikit-learn