Juan David Velásquez Henao
jdvelasq@unal.edu.co
Universidad Nacional de Colombia, Sede Medellín
Facultad de Minas
Medellín, Colombia
[Licencia]
[Readme]
Software utilizado.
Este es un documento interactivo escrito como un notebook de Jupyter, en el cual se presenta un tutorial sobre regresión logistica usando R en el contexto de aprendizaje de maquinas. Los notebooks de Jupyter permiten incoporar simultáneamente código, texto, gráficos y ecuaciones. El código presentado en este notebook puede ejecutarse en los sistemas operativos Linux y OS X.
Haga click aquí para obtener instrucciones detalladas sobre como instalar Jupyter en Windows y Mac OS X.
Haga clic [aquí] para ver la última versión de este documento en nbviewer.
Descargue la última versión de este documento a su disco duro; luego, carguelo y ejecutelo en línea en Try Jupyter!
Haga clic aquí para ver el tutorial de visualización y gráficas.
Las máquinas de soporte vectorial (SVM) son algoritmos no-lineales de aprendizaje supervisado utilizados para el problema de clasificación, no obstante se pueden utilizar para aproximar funciones o regresiones a partir de ciertos métodos. En esta sección se en clasificación.
Básicamente, el algoritmo crea una frontera llamada hiperplano, la cual divide el espacio en particiones de las clases a predecir. En este sentido se puede considerar que las SVM combinan aspectos de los métodos de regresión y de vecinos más cercanos (k-NN).
Uno de los conceptos más importantes en SVM, es el de Maximal Margin Classification, donde se asumirá que se tiene una variable respuesta binaria para ilustar. Dentro de los árboles de regresión y clasificación, usualmente la partición (hiperplanos de separación) del espacio de las variables es lineal. A diferencia de SVM donde dependiendo de la estructura, los supuestos y el criterio de optimización se puede terminar con uno de los infinitos hiperplanos (incluyendo no lineales) que pueden particionar los datos.
Cuando se tiene dos o más variables predictoras, se expresar el hiperplano como una combinación lineal de dichas variables, por lo tanto:
$$ \beta_{0} + \sum_{k=1}^{p} \beta_{k} x_{i,k} > 0 \hspace{0.25cm} si \hspace{0.25cm} y_{i}=1 $$$$ \beta_{0} + \sum_{k=1}^{p} \beta_{k} x_{i,k} < 0 \hspace{0.25cm} si \hspace{0.25cm} y_{i}=-1 $$Estas ecuaciones indican que cualquier punto que pertenezca a la clase 1, se encuentran por encima de la ecuación (mayor que 0). Análogmente, cualquier punto que pertenzca a la clase -1, se ubicará por debajo de ella (menor que 0).
Ahora bien, para determinar cuál de todas las rectas utilizar para la separacion de datos, se define una cantidad denominada margen, la cual representa la mínima distancia perpendicular de cualquier punto de los datos al hiperplano. Para este ejemplo, siempre se tienen al menos dos (ya que son dos variables predictoras) que tengan la menor distancia al hiperplano. A veces, pueden existir puntos con iguales distancias mínimas.
Lo anterior gráficamente es:
Por lo tanto, el hiperplano de maximo margen como aquel cuyo margen sea el mayor posible de todos los hiperplanos posibles. Lo anterior definición busca el hiperplano que separará las clases de predicción mientras al mismo tiempo busca que este sea lo más alejado posible de las observaciones evitando así cualquier sesgo. En la imagen anterior, se observa que la linea es aquella con menor margen igual a 2, donde los tres vectores perpendiculares al hiperplano se llaman vectores de soporte.
Para entender esto matemáticamente se define lo siguiente:
$$ Seleccionar \hspace{0.25cm} \beta_{0},\beta_{1},\beta_{2},... \hspace{0.25cm} que \hspace{0.1cm} maximicen \hspace{0.25cm} M $$$$ Tal \hspace{0.1cm} que: \hspace{0.25cm} \sum_{k=1}^{p} \beta_{k}^{2}=1 $$$$ además \hspace{0.25cm} \forall_{i}:y_{i} (\beta_{0} + \sum_{k=1}^{p} \beta_{k} x_{i,k}) > M $$Las restricciones del problema establecen que deben ser correctamente clasificados los datos del problema así como que deben estar al menos de M unidades alejados del hiperplano, para esto se modifican los parámetros $ \beta $ hasta encontrar el mayor M que cumpla las restricciones.
Cuando los datos de entranamiento no son lineamente clasificables se puede utilizar la definición de vectores de soporte para definir el margen, no obstante se permite que algunas observaciones estén mal clasificadas por el algoritmo, por lo tanto se estima un margen debil. Estas observaciones se permitiran estar dentro de un rango establecido y no afectaran la elección del hiperplano.
Hay que tener en cuenta que entre más largo el margen es más confiable el hiperplano de clasificar las observaciones, es por esto que cuando los datos no son linealmente clasificables "relajar" el margen puede ser beneficioso para el algortimo ya que evita que datos alejados modifiquen el hiperplano como se evidencia en la siguiente imagen donde se introdujo una observación de clase 1 cerca a los datos de clase -1 y el margen disminuyó de 2 a 0.29:
Para esto, matematicamente, se ingresa un parametro de "suavizamiento" $ \xi $ tal que:
$$ Seleccionar \hspace{0.25cm} \beta_{0},\beta_{1},\beta_{2},... \hspace{0.25cm} que \hspace{0.1cm} maximicen \hspace{0.25cm} M $$$$ Tal \hspace{0.1cm} que: \hspace{0.25cm} \sum_{k=1}^{p} \beta_{k}^{2}=1 $$$$ además \hspace{0.25cm} \forall_{i}:y_{i} (\beta_{0} + \sum_{k=1}^{p} \beta_{k} x_{i,k}) > M(1-\xi_{i}) $$$$ además \hspace{0.25cm} \forall_{i}:\xi_{i} > 0, \sum_{i=1}^{n} \xi_{i} <= C $$A las variables $ \xi $ se les conocen como variables flojas, donde hay una para cada observacion y se cumple que:
$$ \xi_{i} = 0, \hspace{1cm} x_{i} \hspace{0.1cm} está \hspace{0.1cm} correctamente \hspace{0.1cm} clasificada \hspace{0.1cm} y \hspace{0.1cm} fuera \hspace{0.1cm} del \hspace{0.1cm}margen $$$$ 0 < \xi_{i} <= 1, \hspace{0.6cm} x_{i} \hspace{0.1cm} está \hspace{0.1cm} correctamente \hspace{0.1cm} clasificada \hspace{0.1cm} pero \hspace{0.1cm} dentro \hspace{0.1cm} del \hspace{0.1cm}margen $$$$ \xi_{i} > 1, \hspace{4cm} x_{i} \hspace{0.1cm} está \hspace{0.1cm} incorrectamente \hspace{0.1cm} clasificada \hspace{0.1cm} $$Donde la magnitud de la variable suelta es proporcional a la distancia entre la observación y el hiperplano.
El hecho de que dichas variables no sobrepasen una cantidad C significa un límite superior de error en clasificación que estamos dispuestos a asumir. Si dicha constante C es baja (menor que 1) siginfica que el modelo tolerará pocas observaciones dentro del margen pero no permitirá errores de clasificación. Si por el contrario el valor de C es alto (mayor a 1) el modelo permitirá muchas observaciones dentro del margen o mal clasificadas, resultando en varios vectores de soporte. El primer escenario nos otorgará un modelo con mayor varianza pero menos sesgo, donde el último escenatio resultará en un modelo con menor varianza pero mayor sesgo. A esto se le conoce como el intercambio sesgo-varianza (Bias-Variance trade off)
Una forma de introducir la no-linealidad a las SVM es utilizar representaciones que involucren el concepto de producto interno de álgebra lineal para aplicar transformaciones no-lineales a su resultado. Para esto definimos una funcion general $ K $ que llamara la función núcleo (kernel) que opera en dos vectores y produce un resultado escalar. Esto se representa como:
$$ y(x)=\beta_{0}+\sum_{s \in S} \alpha_{s} K \langle x, x_{s} \rangle $$El modelo de SVM tiene tantas características como vectores de soporte tenga y se definen estas características como un kernel aplicado a la observaciones con uno de los vectores de soporte. Para el ejemplo que anterior donde se evaluó un modelo lineal, se tiene que:
$$ K_{lineal}(x_{i},x_{j}) = \sum_{k=1}^{p} x_{i,k} x_{j,k} $$También estas funciones kernel puede medir la similaridad aplicando funciones que lo representen. Para introducir la no-linealidad simplemente se introducen los kernels no lineales y se crea las máquinas de soporte vectorial. Entre los kernels más usados están el polinómico y el de base radial.
Esta función utiliza una expasión a la potencia del producto interno de dos vectores. Esencialmente este kernel transforma el espacio de las variables predictoras en uno de mayor grado, lo cual lo hace más eficiente comparado con transformar todas las características primero e intentar ajustar un modelo lineal en ese espacio.
$$ K_{polinomico}(x_{i},x_{j}) = (1+\sum_{k=1}^{p} x_{i,k} x_{j,k})^{d} $$En este kernel el numero de dimensiones a la que se transforma el espacio de las variables predictoras es infinito dado al número infinito en la expansión. Si $ d \approx \infty $ entonces $ (1+\frac{1}{d})^{d}=e $. Es por esto que este kernel no usa el producto interno, en su lugar usa la suma de la distnacia entre los dos vectores. Este kernel permite que solo los vectores de soporte cerca a la observación de interes interfieran significativamente en los cálculos.
$$ K_{radial}(x_{i},x_{j}) = e^{-\frac{1}{2\sigma^{2}}\sum_{k=1}^{p}(x_{i,k}- x_{j,k})^{2}} $$Aplicación : En este ejemplo se utiliza la base de datos de creditos en Alemania la cual contiene las solicitudes de créditos que han realizado personas en un banco. La tarea del algoritmo es determinar si una solicitud contiene un alto riesgo de crédito para la entidad.
In [ ]:
## Instale y cargue las siguientes librerias
library(caret)
library(e1071)
In [1]:
## Lectura de datos
link <-"https://archive.ics.uci.edu/ml/machine-learning-databases/statlog/german/german.data"
german_raw <- read.table(link, # Variable link
quote = "\"") # Separador del encabezado
names(german_raw) <- c( "checking", "duration", "creditHistory", # Titulos de las variables
"purpose", "credit", "savings", "employment", "installmentRate",
"personal", "debtors", "presentResidence", "property", "age",
"otherPlans", "housing", "existingBankCredits", "job",
"dependents", "telephone", "foreign", "risk")
head(german_raw) # Primeros datos
Se puede observar que existen varias variables categoricas dentro de la base de datos, por lo cual se calculará y estimará variables dummys además de forzar la variable respuesta como 0 para buen crédito y 1 para mal crédito.
In [2]:
## Preparacion de los datos
dummies <- dummyVars(risk ~ ., # Generar modelo para arrojar las variables dummy con risk de variable respuesta
data = german_raw) # Base de datos
german <- data.frame(predict(dummies, newdata = german_raw), # Generar la matriz con los dummy
risk = factor((german_raw$risk - 1))) # Generar la respuesta con el dummy 0 o 1
dim(german) # Dimensiones de la matriz
head(german) # Primeras filas
Conjunto de datos de entrenamiento y el de validación.
In [2]:
## Partición de la data
set.seed(977) # Semilla aleatoria
german_sampling_vector <- createDataPartition(german$risk, # Generar vector de posiciones de la partición
p = 0.80, # Porcentaje de partición
list = FALSE) # Devuelve lista es falso
german_train <- german[german_sampling_vector,] # Datos de entrenamiento
german_test <- german[-german_sampling_vector,] # Datos de validacion
Dado que en este ejemplo el hecho que una empresa clasifique favorablemente a un cliente cuando esté se no cuenta con buen perfil credictio es cinco veces más costoso para la entidad ya que está dejando de colocar óptimamente. Para esto se define un vector de costo donde castigue más el error tipo II, es decir, clasificar como 1 al cliente, cuando en realidad es 1.
In [4]:
## Crear el vector de costos
class_weights <- c(1, 5) # Vector de costos
names(class_weights) <- c("0", "1") # Se les asigna nombre de la clase
class_weights # Se observa el data.frame
Una vez creado el vector de costos, usando la función tune() para entrenar varios modelos svm() y encontrar el que tenga mejor desempeño con ciertos parámetros de búsqueda. Esta optimización arroja que los parámetros óptimos son costo igual a 10 y gamma igual a 0.05.
In [5]:
# Entrenar la SVM
set.seed(2423) # Semilla aleatoria
german_radial_tune <- tune(svm, # Maquinas de soporte vectorial
risk ~ ., # Riesgo como variable dependiente
data = german_train, # Data de entrenamiento
kernel = "radial", # Tipo de Kernel = Radial
ranges = list(cost = c(0.01, 0.1, 1, 10, 100), # Valores de busqueda para el parámetro cost
gamma = c(0.01, 0.05, 0.1, 0.5, 1)), # Valores de busqueda para el parámetro gamma
class.weights = class_weights) # Vector de costos para los errores
german_radial_tune$best.parameters # Mejores parámetros del SVM
german_radial_tune$best.performance # Mejor métrica de desempeño
Se extrae modelo final de la lista que devuelve la función tune(), se realizan las predicciones para comparar desempeño y hace la tabla cruzada de aciertos y errores.
In [6]:
## Modelo final
german_model <- german_radial_tune$best.model # Extraer el mejor modelo
test_predictions <- predict(german_model, # Modelo SVM
german_test[,1:61]) # Data de validación
mean(test_predictions == german_test[,62]) # Ma media del acierto en las predicciones
In [7]:
## Tabla cruzada
table(predicted = test_predictions, # Predicciones
actual = german_test[,62]) # Verdaderos
Ejercicio.-- Utilice la base de datos de biodegradación QSAR para predecir si un elemento en particular será biodegradable dadas sus características por ejemplo, cantidad de oxigeno, carbono, nitrogeno así como el numero de atomos pesados en la molecula.
Utilice la librería e1070 en R.
In [ ]:
In [ ]:
## Instale y cargue las siguientes librerias
library(kernlab)
En la siguiente aplicación se tienen las 26 letras en mayuscula del alfabeto en inglés donde se incluyen letras script, cursivas, góticas y letras tipo tipografía (Serif). Se tiene una muestra de 20000 letras y la tarea de la SVM es determinar para cada una de ellas cuál es la letra correspondiente utilizando 16 características con atributos numéricos.
Para clasificar se utilizó un espacio de 45x45 pixeles en los que se identificó los pixeles blancos (fondo de la imagen) y los negros (pixeles utilizados para crear el caracter) y los valores encontrados para cada característica se normalizaron en un rango de 0 a 15.
Características utilizadas:
Para objeto de estudio se dividió la muestra en entrenamiento y validación equivalente al 80% de los datos que se tomó para entrenar el algoritmo y el 20% restante utilizado para hacer las validaciones.
In [8]:
## Lectura datos
letters <- read.csv("data.csv") # Lectura de la data
str(letters) # Estructura de la data
In [9]:
## Partición de los datos
set.seed(1) # Semilla aleatoria
trainIndex <- createDataPartition(letters$letter, # Generar vector de posiciones de la partición
p = 0.80, # Porcentaje de partición
list = FALSE) # Devuelve lista es falso
letters_train <- letters[trainIndex,] # Datos de entrenamiento
letters_test <- letters[-trainIndex,] # Datos de validacion
In [10]:
# Entrenamiento del modelo SVM
letter_classifier <- ksvm(letter ~ ., # Variable respuesta es la letra
data = letters_train, # Datos de entrenamiento
kernel = "vanilladot") # Tipo de kernel lineal
letter_classifier # Visualizamos el svm
In [11]:
##Predicción y evaluacion con el modelo
letter_predictions <- predict(letter_classifier, # Clasificador SVM
letters_test) # Datos de validación
mean(letter_predictions == letters_test$letter) # Media de los aciertos del modelo.
In [12]:
# Tabla cruzada
table(letter_predictions, # Predicciones
letters_test$letter) # Reales
In [13]:
# Calculo de aciertos y errores
aciertos <- letter_predictions == letters_test$letter # Vector de comparacion lógica
table(aciertos) # Mostrar tabla de aciertos
prop.table(table(aciertos)) # Mostrar tabla de aciertos en porcentaje
In [15]:
# Realización del mismo modelo pero con base radial y comparación de resultados
letter_classifierEV <- ksvm(letter ~ ., data = letters_train,kernel = "rbfdot")
letter_predictionsEV <- predict(letter_classifierEV, letters_test)
aciertosEV <- letter_predictionsEV == letters_test$letter
table(aciertosEV)
prop.table(table(aciertosEV))
In [20]:
# Realización del mismo modelo pero con base sigmoidea y comparacion resultados
letter_classifierEV2 <- ksvm(letter ~ ., data = letters_train,kernel = "tanhdot")
letter_predictionsEV2 <- predict(letter_classifierEV2, letters_test)
aciertosEV2 <- letter_predictionsEV2 == letters_test$letter
table(aciertosEV2)
prop.table(table(aciertosEV2))
Ejercicio.-- Se busca identificar si la voz transmitida por una persona es de hombre o mujer, el conjunto de datos tiene analisis y caracteristicas de onda que tiene la voz transmitida. Utilice las caracteristicas deel siguiente conjunto de datos para realizar la predicción si es hombre o mujer
In [ ]: