sklearn LabelBinarizer returns vector when there are 2 classes
this should do it
labels = ['yes', 'no', 'no', 'yes']
np.array([[1,0] if l=='yes' else [0,1] for l in labels])
After so many years, now there is a nice elegant solution. The MultiLabelBinirazer.
The difference with LabelBinarizer is that treats all features as multi-class.
In scikit-learn 0.18 it cannot handle unseen values.
In scikit-learn 0.20 it can handle unseen values and assign them [0,0,...,0,0] which fixed recently.
I think there is no direct way to do it especially if you want to have inverse_transform
.
But you can use numpy to construct the label easily
In [18]: import numpy as np
In [19]: from sklearn.preprocessing import LabelBinarizer
In [20]: lb = LabelBinarizer()
In [21]: label = lb.fit_transform(['yes', 'no', 'no', 'yes'])
In [22]: label = np.hstack((label, 1 - label))
In [23]: label
Out[23]:
array([[1, 0],
[0, 1],
[0, 1],
[1, 0]])
Then you can use inverse_transform
by slicing the first column
In [24]: lb.inverse_transform(label[:, 0])
Out[24]:
array(['yes', 'no', 'no', 'yes'],
dtype='<U3')
Based on the above solution, you can write a class that inherits LabelBinarizer
, which makes the operations and results consistent for both binary and multiclass case.
from sklearn.preprocessing import LabelBinarizer
import numpy as np
class MyLabelBinarizer(LabelBinarizer):
def transform(self, y):
Y = super().transform(y)
if self.y_type_ == 'binary':
return np.hstack((Y, 1-Y))
else:
return Y
def inverse_transform(self, Y, threshold=None):
if self.y_type_ == 'binary':
return super().inverse_transform(Y[:, 0], threshold)
else:
return super().inverse_transform(Y, threshold)
Then
lb = MyLabelBinarizer()
label1 = lb.fit_transform(['yes', 'no', 'no', 'yes'])
print(label1)
print(lb.inverse_transform(label1))
label2 = lb.fit_transform(['yes', 'no', 'no', 'yes', 'maybe'])
print(label2)
print(lb.inverse_transform(label2))
gives
[[1 0]
[0 1]
[0 1]
[1 0]]
['yes' 'no' 'no' 'yes']
[[0 0 1]
[0 1 0]
[0 1 0]
[0 0 1]
[1 0 0]]
['yes' 'no' 'no' 'yes' 'maybe']