Estrategías One-Vs-One y One-Vs-Others#

  • 45 min | Ultima modificación: Junio 22, 2019

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-The-Rest (única implementada en Spark): 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.

  • 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).

[1]:
%%writefile data.csv
x,y,label
1,1,0
1,2,0
1,3,0
1,4,0
2,1,0
2,2,1
2,3,1
2,4,1
3,1,1
3,2,1
3,3,2
3,4,2
4,1,1
4,2,1
4,3,2
4,4,2
Overwriting data.csv
[2]:
!hdfs dfs -copyFromLocal data.csv /tmp/data.csv
[3]:
##
## Carga de las librerías de Spark
##
import findspark
from pyspark import SparkConf, SparkContext
from pyspark.sql import SparkSession

findspark.init()

APP_NAME = "spark-app"

conf = SparkConf().setAppName(APP_NAME)
sc = SparkContext(conf=conf)
spark = SparkSession(sc)
[4]:
##
## Lectura del archivo.
##
spark_df = spark.read.load(
    "/tmp/data.csv", format="csv", sep=",", inferSchema="true", header="true"
)

##
## Número de registros cargados
##
spark_df.count()
[4]:
16
[5]:
from pyspark.ml.feature import VectorAssembler

vectorAssembler = VectorAssembler(
    inputCols=['x', 'y'],
    outputCol="features",
)

spark_df = vectorAssembler.transform(spark_df)

spark_df.select("features").show()
+---------+
| features|
+---------+
|[1.0,1.0]|
|[1.0,2.0]|
|[1.0,3.0]|
|[1.0,4.0]|
|[2.0,1.0]|
|[2.0,2.0]|
|[2.0,3.0]|
|[2.0,4.0]|
|[3.0,1.0]|
|[3.0,2.0]|
|[3.0,3.0]|
|[3.0,4.0]|
|[4.0,1.0]|
|[4.0,2.0]|
|[4.0,3.0]|
|[4.0,4.0]|
+---------+

[6]:
from pyspark.ml.classification import LogisticRegression, OneVsRest
from pyspark.ml.evaluation import MulticlassClassificationEvaluator

(train, test) = spark_df.randomSplit([0.8, 0.2])

lr = LogisticRegression(maxIter=10, tol=1E-6, fitIntercept=True)

ovr = OneVsRest(classifier=lr)
ovrModel = ovr.fit(train)
predictions = ovrModel.transform(test)

evaluator = MulticlassClassificationEvaluator(metricName="accuracy")

accuracy = evaluator.evaluate(predictions)
print("Test Error = %g" % (1.0 - accuracy))
Test Error = 0.4