miércoles, 11 de julio de 2018

Apache Spark MLlib parte 4

Continuamos!!!

Vamos a ver un ejemplo utilizando el algoritmo Kmeans que es uno de los algoritmos más fáciles de clasificación.

K-means es un método de agrupamiento, que tiene como objetivo la partición de un conjunto de n observaciones en k grupos en el que cada observación pertenece al grupo cuyo valor medio es más cercano.

Si bien se puede indicar que es una técnica utilizada por minería de datos más que para Maching learning, vamos a empezar de a poco.

Empecemos viendo los datos, los cuales supongamos ya hemos limpiado :

0 1:0.0 2:0.0 3:0.0
1 1:0.1 2:0.1 3:0.1
2 1:0.2 2:0.2 3:0.2
3 1:9.0 2:9.0 3:9.0
4 1:9.1 2:9.1 3:9.1
5 1:9.2 2:9.2 3:9.2

Como se puede ver son 4 columnas, de la cuales la primera es un id (identificador) y las demás están compuestas por un indice y un dato, por ejemplo 1:0.0 (el indice es 1 y el dato 0.0 el cual es continuo)

Esto se encuentra en el archivo sample_kmeans_data.txt

Empecemos tomando los datos y llevándolos a un RDD :

//creamos la aplicación de spark si utilizamos spark-shell esto no es necesario.
val spark = SparkSession.builder.appName("KMeansExample") .getOrCreate()

//Leemos el archivo con el formato libsvm
val dataset = spark.read.format("libsvm").load("path/sample_kmeans_data.txt")

//Probamos que se leyeron los datos, si estamos en spark-shell
dataset.show()
+-----+--------------------+
|label|            features|
+-----+--------------------+
|  0.0|           (3,[],[])|
|  1.0|(3,[0,1,2],[0.1,0...|
|  2.0|(3,[0,1,2],[0.2,0...|
|  3.0|(3,[0,1,2],[9.0,9...|
|  4.0|(3,[0,1,2],[9.1,9...|
|  5.0|(3,[0,1,2],[9.2,9...|
+-----+--------------------+


// Entrenamos nuestro modelo
import org.apache.spark.ml.clustering.KMeans
val kmeans = new KMeans().setK(2).setSeed(1L)
val model = kmeans.fit(dataset)

// Evaluamos la agrupación mediante el cómputo dentro de la suma establecida de errores cuadrados.
val WSSSE = model.computeCost(dataset)
println(s"Within Set Sum of Squared Errors = $WSSSE")

// Mostramos el resultado
println("Cluster Centers: ")
model.clusterCenters.foreach(println)
[0.1,0.1,0.1]
[9.1,9.1,9.1]

Para los que como yo no entendieron que paso el ultimo momento... Reiteramos!

Dado un conjunto de observaciones (x1, x2, …, xn), donde cada observación es un vector real de d dimensiones, k-means construye una partición de las observaciones en k conjuntos (k ≤ n) a fin de minimizar la suma de los cuadrados dentro de cada grupo (WCSS): S = {S1, S2, …, Sk}

Si vemos la Wikipedia : 

Paso de asignación: Asigna cada observación al grupo con la media más cercana (es decir, la partición de las observaciones de acuerdo con el diagrama de Voronoi generado por los centroides).
Donde cada  va exactamente dentro de un , incluso aunque pudiera ir en dos de ellos.
Paso de actualización: Calcular los nuevos centroides como el centroide de las observaciones en el grupo.
El algoritmo se considera que ha convergido cuando las asignaciones ya no cambian.

Grafícado : 

Si hablamos en criollo el algoritmo trata de hacer grupos y calcular su centro, y va moviendo el centro según los datos hasta que estos centros no cambian y ahí finaliza.