Estrategías One-Vs-One y One-Vs-Rest#
Algunas técnicas, como la regresión logística, permiten resolver problemas de clasificación dicotómica, pero en la práctica, muchos de los problemas reales son multiclase.
La teoría está basada en el supuesto de que únicamente existen dos clases dicotómicas C_1 y C_2. En la realidad pueden existir más de dos clases, por lo que existen diversas estrategias comúnmente utilizadas para convertir un problema de varias clases en un problema dicotómico.
One-Vs-Rest: Esta estrategia consiste en construir un clasificador por clase. Para un problema con tres clases, se construye un clasificador que decide si el patrón presentado pertenece a la clase C_1 o al resto (C_2 o C_3), otro si pertenece a C_2 o al resto, y finalmente otro para diferenciar entre C_3 y el resto. En esta estructura existen puntos del espacio de entrada que no pertencen a ninguna clase. Supongamos que hay tres clases A, B y C, y un patrón x que pertenece a C, entonces:
x \in A?, No (pertence a B o a C).
x \in B?, No, entonces x \in C.
One-Vs-One: Se construye un clasificador por cada par de clases y la clasificación se realiza seleccionando la clase que recibe más votos. Si se tienen tres clases, se constuirian clasificadores para diferenciar entre las siguientes parejas de clases (C_1, C_2), (C_1, C_3) y (C_2, C_3). Supongamos que hay tres clases A, B y C, y un patrón x que pertenece a C, entonces:
x \in A o x \in B?, supongamos que se concluye que x \in B.
x \in A o x \in C?, se concluye que x \in C.
x \in B o x \in C?, se concluye que x \in C.
B recibe un punto y C recibe dos puntos, por tanto, x \in C.
[1]:
%%writefile data.csv
x1,x2,y
1,1,A
1,2,A
1,3,A
1,4,A
2,1,A
2,2,B
2,3,B
2,4,B
3,1,B
3,2,B
3,3,C
3,4,C
4,1,B
4,2,B
4,3,C
4,4,C
Overwriting data.csv
[2]:
import pandas as pd
df = pd.read_csv(
"data.csv",
sep=",",
thousands=None,
decimal=".",
)
[3]:
from sklearn.linear_model import LogisticRegression
from sklearn.multiclass import OneVsOneClassifier, OneVsRestClassifier
X = df[["x1", "x2"]].values
y = df.y
y_one_vs_the_rest = (
OneVsRestClassifier(LogisticRegression(solver="lbfgs", multi_class="ovr"))
.fit(X, y)
.predict(X)
)
y_one_vs_one = (
OneVsOneClassifier(LogisticRegression(solver="lbfgs", multi_class="ovr"))
.fit(X, y)
.predict(X)
)
pd.DataFrame(
{"real": df.y, "one-vs-rest": y_one_vs_the_rest, "one-vs-one": y_one_vs_one}
)
[3]:
real | one-vs-rest | one-vs-one | |
---|---|---|---|
0 | A | A | A |
1 | A | A | A |
2 | A | A | A |
3 | A | A | A |
4 | A | B | A |
5 | B | B | B |
6 | B | B | B |
7 | B | C | B |
8 | B | B | B |
9 | B | B | B |
10 | C | B | B |
11 | C | C | C |
12 | B | B | B |
13 | B | B | B |
14 | C | C | C |
15 | C | C | C |