Solución:
Clasificación multiclase
Para ilustrar mejor las diferencias, supongamos que su objetivo es clasificar las preguntas SO en n_classes
clases diferentes, mutuamente excluyentes. En aras de la simplicidad en este ejemplo, solo consideraremos cuatro clases, a saber 'Python'
, 'Java'
, 'C++'
y 'Other language'
. Supongamos que tiene un conjunto de datos formado por solo seis preguntas SO y que las etiquetas de clase de esas preguntas se almacenan en una matriz. y
como sigue:
import numpy as np
y = np.asarray(['Java', 'C++', 'Other language', 'Python', 'C++', 'Python'])
La situación descrita anteriormente se suele denominar clasificación multiclase (también conocida como clasificación multinomial). Para ajustar el clasificador y validar el modelo a través de la biblioteca scikit-learn, necesita transformar las etiquetas de la clase de texto en etiquetas numéricas. Para lograr eso, puede usar LabelEncoder:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y_numeric = le.fit_transform(y)
Así es como se codifican las etiquetas de su conjunto de datos:
In [220]: y_numeric
Out[220]: array([1, 0, 2, 3, 0, 3], dtype=int64)
donde esos números denotan índices de la siguiente matriz:
In [221]: le.classes_
Out[221]:
array(['C++', 'Java', 'Other language', 'Python'],
dtype="|S14")
Un caso particular importante es cuando solo hay dos clases, es decir n_classes = 2
. A esto se le suele llamar clasificación binaria.
Clasificación de múltiples etiquetas
Supongamos ahora que desea realizar dicha clasificación multiclase utilizando un grupo de n_classes
clasificadores binarios, siendo n_classes
el número de clases diferentes. Cada uno de estos clasificadores binarios toma una decisión sobre si un artículo pertenece a una clase específica o no. En este caso, no puede codificar etiquetas de clase como números enteros de 0
para n_classes - 1
, debe crear una matriz de indicadores bidimensionales. Considere esa muestra n
es de clase k
. Entonces el [n, k]
La entrada de la matriz de indicadores es 1
y el resto de elementos en fila n
están 0
. Es importante tener en cuenta que si las clases no son mutuamente excluyentes, puede haber múltiples 1
está en una fila. Este enfoque se llama clasificación de múltiples etiquetas y se puede implementar fácilmente a través de MultiLabelBinarizer:
from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
y_indicator = mlb.fit_transform(y[:, None])
El indicador se ve así:
In [225]: y_indicator
Out[225]:
array([[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[0, 0, 0, 1]])
y los números de columna donde 1
son en realidad índices de esta matriz:
In [226]: mlb.classes_
Out[226]: array(['C++', 'Java', 'Other language', 'Python'], dtype=object)
Clasificación de salida múltiple
¿Qué sucede si desea clasificar una pregunta de SO en particular de acuerdo con dos criterios diferentes simultáneamente, por ejemplo, el idioma y la aplicación? En este caso tiene la intención de hacer clasificación de salida múltiple. En aras de la simplicidad, consideraré solo tres clases de aplicaciones, a saber 'Computer Vision'
, 'Speech Processing
‘ y 'Other application
‘. La matriz de etiquetas de su conjunto de datos debe ser bidimensional:
y2 = np.asarray([['Java', 'Computer Vision'],
['C++', 'Speech Recognition'],
['Other language', 'Computer Vision'],
['Python', 'Other Application'],
['C++', 'Speech Recognition'],
['Python', 'Computer Vision']])
Nuevamente, necesitamos transformar las etiquetas de clase de texto en etiquetas numéricas. Hasta donde yo sé, esta funcionalidad aún no está implementada en scikit-learn, por lo que deberá escribir su propio código. Este hilo describe algunas formas inteligentes de hacer eso, pero para los propósitos de esta publicación, la siguiente frase debería ser suficiente:
y_multi = np.vstack((le.fit_transform(y2[:, i]) for i in range(y2.shape[1]))).T
Las etiquetas codificadas tienen este aspecto:
In [229]: y_multi
Out[229]:
array([[1, 0],
[0, 2],
[2, 0],
[3, 1],
[0, 2],
[3, 0]], dtype=int64)
Y el significado de los valores en cada columna se puede inferir de las siguientes matrices:
In [230]: le.fit(y2[:, 0]).classes_
Out[230]:
array(['C++', 'Java', 'Other language', 'Python'],
dtype="|S18")
In [231]: le.fit(y2[:, 1]).classes_
Out[231]:
array(['Computer Vision', 'Other Application', 'Speech Recognition'],
dtype="|S18")