{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": true }, "source": [ "

Tabla de contenidos

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Introducción \n", "\n", "En un [post anterior](https://bigdatafran.github.io/big_data//RegresionLogit){:target=\"_blank}, ya se ha comentado la parte teórica sobre la que se construye este modelo, además se han mostrado algunos ejemplos realizados con R.\n", "\n", "En este post me voy a centrar en el enfoque de este modelo que se da [desde scikit-learn](http://scikit-learn.org/stable/modules/linear_model.html#logistic-regression){:target=\"_blank\"}.\n", " \n", "Como puede observarse en la parte expositiva, el concepto puede parecer diferente al expuesto en este sitio web, pero el enfoque y resltado final es muy similar en ambos enfoques. En resumen se trata de minimizar también unas serie de funciones con un enfoque similar, lo único que en scikit-learn, además de utilizar la métrica L2, también emplea la métrica L1.\n", "\n", "En scikit-learn el problema se enfoca desde un punto de vista de optimización, de tal manera que si se utiliza la métrica L2, se minimizará la siguiente función de coste:\n", "\n", "\\\\[ \\underset{w,c}{min}\\frac{1}{2}W^{T}W+C\\sum_{i=1}^{n}log(exp(-y_{i}(X_{i}^{T}W+c))+1) \\\\]\n", "\n", "En el supuesto de que se quiera minimizar la función de coste utilizando la norma L1, el problema de optimización es el siguiente:\n", "\n", "\\\\[ \\underset{w,c}{min}\\left\\Vert W\\right\\Vert _{1}+C\\sum_{i=1}^{n}log(exp(-y_{i}(X_{i}^{T}W+c))+1) \\\\]\n", "\n", "\n", "Recordar del post anterior que en este tipo de modelos, las probabilidades de los valores que toma la variable independiente , se modelan de acuerdo a la función de tipo logístico, y en concreto que:\n", "\n", "\\\\[ \\frac{1}{1+e^{-z}} \\\\]\n", "\n", "Los diferentes \"solvers\" implementados en scikit-learn para resolver los anteriores problemas de optimización son: \"liblinear\" ( es el que utiliza por defecto), \"newton-cg\", \"lbfgs\", \"sag\" y \"saga\". El modelo elegido se implementa dentro del parámetro *solver* de la funcion *LogisticRegression*.\n", "\n", "A continuación comenzamos importando las librerías que se necesitan para este modelo." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from sklearn import linear_model \n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Datos utilizados\n", "\n", "En primer lugar lo que hacemos es definir una función que va a servir, para delimitar las zonas de decisión que nos facilita el modelo. Antes de presentar la función, vamos a ver ciertas funciones de numpy que se utilizan en el ejemplo y conviene aclarar con carácter previo." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 4]\n", " [2 5]\n", " [3 6]]\n", "[1 2 3 4 5 6]\n", "se obtiene el mismo resultado que antes\n", "[1 2 3 4 5 6]\n", "Lo mismo pero en orden diferente\n", "[1 4 2 5 3 6]\n" ] } ], "source": [ "#Primero un ejemplo de lo que hace np.c_\n", "print(np.c_[np.array([1,2,3]), np.array([4,5,6])])\n", "# A continuación veamos cómo trabaja la función ravel\n", "x = np.array([[1, 2, 3], [4, 5, 6]])\n", "print(np.ravel(x))\n", "print(\"se obtiene el mismo resultado que antes\")\n", "print(x.reshape(-1))\n", "print(\"Lo mismo pero en orden diferente\")\n", "print(np.ravel(x, order='F'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A continuación definimos la función que se va a utilizar." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "def plot_classifier(classifier, X, y):\n", " # Se definen los rangos para dibujar la figura \n", " x_min, x_max = min(X[:, 0]) - 1.0, max(X[:, 0]) + 1.0\n", " y_min, y_max = min(X[:, 1]) - 1.0, max(X[:, 1]) + 1.0\n", "\n", " # Se define el paso que se va a utilizar para definir la malla de datos\n", " step_size = 0.01\n", "\n", " # Ahora definimos la malla\n", " x_values, y_values = np.meshgrid(np.arange(x_min, x_max, step_size), np.arange(y_min, y_max, step_size))\n", "\n", " # se calcula la predición dada por el modelo sobre los puntos de la malla\n", " #Ver el apartado anterior para entender el funcionamiento de las funciones\n", " mesh_output = classifier.predict(np.c_[x_values.ravel(), y_values.ravel()])\n", "\n", " # redimensionamos los valores de mesh_output\n", " mesh_output = mesh_output.reshape(x_values.shape)\n", "\n", " # Dibujamos la figura\n", " plt.figure()\n", " \n", " # Elegimos un color para definir las zonas de predicción\n", " # Ver enlace: http://matplotlib.org/examples/color/colormaps_reference.html\n", " plt.pcolormesh(x_values, y_values, mesh_output, cmap=plt.cm.gray)\n", "\n", " # Overlay the training points on the plot \n", " plt.scatter(X[:, 0], X[:, 1], c=y, s=80, edgecolors='black', linewidth=1, cmap=plt.cm.Paired)\n", "\n", " # especificamos los bordes del gráfico\n", " plt.xlim(x_values.min(), x_values.max())\n", " plt.ylim(y_values.min(), y_values.max())\n", "\n", " # indicamos lo ticks tanto del eje X como del eje Y \n", " plt.xticks((np.arange(int(min(X[:, 0])-1), int(max(X[:, 0])+1), 1.0)))\n", " plt.yticks((np.arange(int(min(X[:, 1])-1), int(max(X[:, 1])+1), 1.0)))\n", "\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como pequeña introducción a la creación de un modelo de estas acarcaterísticas, inicialmente se introducen unos pocos datos para entender el funcionamiento de cómo utilizar los comandos que facilita la [clase LogisticRegression](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html){:target=\"_blank\"}. \n", "\n", "Como vemos con las datos introducidos, se entiende que existen tres clases diferentes." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Generamos los datos\n", "X = np.array([[4, 7], [3.5, 8], [3.1, 6.2], [0.5, 1], [1, 2], [1.2, 1.9], [6, 2], [5.7, 1.5], [5.4, 2.2]])\n", "y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])\n", "\n", "# Se inicializa el clasificador\n", "classifier = linear_model.LogisticRegression(solver='liblinear', C=100)\n", "#Para más opciones de los parámetros del modelo, ver la definición de la \n", "#clase en el enlace anterior\n", "\n", "# Entrenamos el clasificador\n", "classifier.fit(X, y)\n", "\n", "# Ejecutamos la función definida anteriormente para dibujar las zonas de decisión\n", "plot_classifier(classifier, X, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Extración de datos del modelo\n", "\n", "La función *classifier* admite muchos más parámetros que los utilizados en este ejemplo, su utilidad se puede ver en la página web que define el modelo. En este ejemplo se han utilizado:\n", "\n", "1.- **solver**.- Para indicar el algoritmo utilizado para la resolución del problema de optimización.\n", "\n", "2.- **C** .- que indica la inversa de la *\"regularization strength\"*. [Ver explicación de regularization aquí](https://en.wikipedia.org/wiki/Regularization_%28mathematics%29#Regularization_in_statistics_and_machine_learning){:_target=\"_blank\"}. Al igual que ocurre con el método de *support vector machines*, valores más pequeños especifican una regularización más fuerte. En un post futuro, tengo la intención de desarrollar con mayor precisión este concepto. De momento ten presente que este parámetro va a servir para controlar tanto el sub ajuste como el sobre ajuste.\n", "\n", "La función **decision_function**, nos va a facilitar las puntuaciones en cada punto de la muestra para cada una de las categorías de la variable independiente." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 4.7571468 , -6.10180605, -11.58794507],\n", " [ 7.21949016, -5.74395713, -15.52888975],\n", " [ 3.86180697, -3.76504774, -11.6304974 ],\n", " [ -4.64423906, 4.86628767, -3.91881734],\n", " [ -3.00846098, 3.20641548, -5.40183274],\n", " [ -3.3786801 , 2.86797242, -4.63904887],\n", " [ -7.14128738, -6.88219012, 6.8878137 ],\n", " [ -7.91784816, -5.95136796, 7.50642493],\n", " [ -6.23553607, -5.80175977, 4.87066012]])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "classifier.decision_function(X)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "LogisticRegression(C=100, class_weight=None, dual=False, fit_intercept=True,\n", " intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,\n", " penalty='l2', random_state=None, solver='liblinear', tol=0.0001,\n", " verbose=0, warm_start=False)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Obtenemos los parámetros con los que ha trabajado el modelo\n", "classifier.densify()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Obtenemos las predicciones de clasificación de cada uno de los puntos con los que se ha entrenado el modelo" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 0 0 1 1 1 2 2 2]\n" ] } ], "source": [ "Y_Predic=classifier.predict(X)\n", "print(Y_Predic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si en lugar de obtener las predicciones, queremos conocer las probabilidades que el modelo ha asignado, lo haremos con el siguiente código." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[9.97742742e-01, 2.24792260e-03, 9.33573773e-06],\n", " [9.96815802e-01, 3.18401770e-03, 1.79813200e-07],\n", " [9.77395569e-01, 2.25955586e-02, 8.87246208e-06],\n", " [9.32603904e-03, 9.71603642e-01, 1.90703191e-02],\n", " [4.64593281e-02, 9.49108477e-01, 4.43219534e-03],\n", " [3.33424487e-02, 9.56974605e-01, 9.68294649e-03],\n", " [7.90475947e-04, 1.02402738e-03, 9.98185497e-01],\n", " [3.63177191e-04, 2.58928294e-03, 9.97047540e-01],\n", " [1.95992874e-03, 3.02110724e-03, 9.95018964e-01]])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "classifier.predict_proba(X)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A continuación calculamos los parámetros estimados del modelo." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "coef=classifier.coef_" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-6.28001714 6.52615987 -2.43580195]\n" ] } ], "source": [ "inter=classifier.intercept_\n", "print(inter)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Veamos cómo calcular las probabilidades obtenidas tres celdas más arriba. Lo único que hay que aplicar es que\n", "\n", "\\\\[ p(i/X_1,X_2) =\\frac{1}{1+e^{-(b_0+b_1*X_1+b_2*X_2)}} \\\\]\n", "\n", "siendo b0 los parámetros para cada una de las tres categorías obtenidos con la propiedad *_intercept* y b1 y b2 los parámetros almacenados en la variable *inter*.\n", "\n", "Al ejecutar el siguiente script, vemos que los valores obtenidos para las probabilidades que nos da la instrucción *\"classifier.predict_proba(X)\"* coinciden con el resultado que a continuación se muestra." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 9.915E-01, 2.234E-03, 9.277E-06, \n", "\n", " 9.993E-01, 3.192E-03, 1.803E-07, \n", "\n", " 9.794E-01, 2.264E-02, 8.891E-06, \n", "\n", " 9.525E-03, 9.924E-01, 1.948E-02, \n", "\n", " 4.705E-02, 9.611E-01, 4.488E-03, \n", "\n", " 3.297E-02, 9.462E-01, 9.574E-03, \n", "\n", " 7.911E-04, 1.025E-03, 9.990E-01, \n", "\n", " 3.641E-04, 2.596E-03, 9.995E-01, \n", "\n", " 1.955E-03, 3.013E-03, 9.924E-01, \n", "\n" ] } ], "source": [ "import math\n", "for i in range(0,X.shape[0]):\n", " for j in range(0,X.shape[1]+1):\n", " p=1/(1+math.exp(-(inter[j]+coef[j,0]*X[i,0]+coef[j,1]*X[i,1])))\n", " #print(\"%0.5f\" % (p),end=\", \")\n", " print(\"%10.3E\" % (p),end=\", \")\n", " print(\"\\n\")\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En scikit-learn, muchas clases tienen el método denominado *score* que obtiene la precisión del modelo (recordar que precisión=(casos bien clasificados)/(n. total de casos)). En nuestro caso, podemos comprobar que hemos acertado en todos los casos, ya que el valor obtenido es 1" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "classifier.score(X,y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Con la matriz de confusión, nos permite clasificar en una tabla de doble entrada, el número de casos que hay en cada cruce entre los valores observados y los valores predichos." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[3, 0, 0],\n", " [0, 3, 0],\n", " [0, 0, 3]], dtype=int64)" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import confusion_matrix\n", "confusion_matrix(y,Y_Predic)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# initialize the logistic regression classifier\n", "classifier = linear_model.LogisticRegression(solver='liblinear', C=1000)\n", "# train the classifier\n", "classifier.fit(X, y)\n", "\n", "# draw datapoints and boundaries\n", "plot_classifier(classifier, X, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Evolución del modelo con parámetro C\n", "\n", "A continuación se va a ver el efecto que sobre el modelo puede tener el valor del parámetro C. Para ello, lo que se va a obtener son una serie de regiones de predicción haciendo variar el parámetro C. Lo primero que se hace es definir la función *plot_classifier2* muy similar a la vista en un bloque anterior, pero ligeramente modificada, para obtener todas las representaciones gráficas dentro del mismo gráfico." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "def plot_classifier2(figura,classifier, X, y,a=1,b=1,c=1,titulo=\"\"):\n", " # Se definen los rangos para dibujar la figura \n", " x_min, x_max = min(X[:, 0]) - 1.0, max(X[:, 0]) + 1.0\n", " y_min, y_max = min(X[:, 1]) - 1.0, max(X[:, 1]) + 1.0\n", "\n", " # Se define el paso que se va a utilizar para definir la malla de datos\n", " step_size = 0.01\n", "\n", " # Ahora definimos la malla\n", " x_values, y_values = np.meshgrid(np.arange(x_min, x_max, step_size), np.arange(y_min, y_max, step_size))\n", "\n", " # se calcula la predición dada por el modelo sobre los puntos de la malla\n", " mesh_output = classifier.predict(np.c_[x_values.ravel(), y_values.ravel()])\n", "\n", " # redimensionamos el array\n", " mesh_output = mesh_output.reshape(x_values.shape)\n", " \n", " ax=figura.add_subplot(a,b,c)\n", " ax.set_title(titulo)\n", " \n", " # Definimos los colores que queremos usar\n", " # here: http://matplotlib.org/examples/color/colormaps_reference.html\n", " ax.pcolormesh(x_values, y_values, mesh_output, cmap=plt.cm.gray)\n", " \n", " ax.scatter(X[:, 0], X[:, 1], c=y, s=80, edgecolors='black', \n", " linewidth=1, cmap=plt.cm.Paired)\n" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "image/png": "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zBYRaSChhtfdv5rqQkREJDmU2SIim9Kd1kREREQkq6nhFREREZGspoZXRERERLKaGl4RERERyWpqeEVEREQkq6nhFREREZGspoZXRERERLKaGl4RERERyWpqeEVEREQkq6nhFREREZGsltCthUUySX5BATm5ebg7ZkZleVnUJYmISAssJ4fComLqamvJycujYmNp1CVJFlLDK1mlsLiEI089l/2PPJ78gkLenTqFR2/5IxvWraWmuirq8kREpIGCwiL2PuwYDjvxdHr3G8D8Oe8z+dY/s/iTuVRWlEddnmQRc/e2FzK7GDgHcOBd4Ex3r2hl+bZfVCTJCouK+c3dT7HFtjts8nzZhvX84tSjWL5wfjSFSaaZ4e5joi6iM5TZkgkKCos499fXsd8Rx27yfF1dHTf97PvMmPIvqitb/G8rUi+hzG5zDq+ZDQV+CIxx952BXOCkztcnkjy5+fmM/dZpTZpdgJIePfnOj6+kqKRbBJWJpJcyWzLFoC2HN2l2AXJycjjjsqvA6yKoSrJVoiet5QHFZpYHlABLUleSSPsVFBSyz+Ffb3F81D4HUl2lKQ3SZSizJdbyCwo48JhvtTjec7O+DNtupzRWJNmuzYbX3RcD1wOfAUuBz939hcbLmdkEM5tuZtOTX6ZI23LzWp6Sbjk55ORYGqsRiYYyWzKDkZPb+mlErWW6SHslMqVhM+DrwNbAEKCbmZ3aeDl3n+TuYzJ97ptkpprqama89HyL43NmvtFmuIpkA2W2ZILqqkpef+GpFsfLSjfw6Zz30liRZLtEpjSMBT5195XuXg1MBvZNbVki7VNdVckz99zK6uVLmx2794bf6PJk0lUosyUjfDr7Hd5/87Vmxx796/WY6aicJE8iDe9nwN5mVmLB/75DgNmpLUuk/SrLy/j5yeN46cmHqCwvp662llmv/ZdffWc8i+d9FHV5IumizJaMUF1ZyXUXncljf/sT61atwN1Z8OEHTPzxBF58/AGqdFkySaJEL0t2JXAiUAO8BZzj7pWtLK9L3EhkCotLqKqowHGKikuoKNsYdUmSWbLhsmTKbMkY+QWF1NXVUltbS0FhETVVVdTV1UZdlmSOhDI7oYa3vRSeIpLBMr7hbS9ltohksORch1dEREREJJOp4RURERGRrKaGV0RERESymhpeEREREclqanhFREREJKup4RURERGR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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig=plt.figure(figsize=(12,20))\n", "C_param_range = [0.0001,0.001,0.01,0.1,1,10,100,1000,2000,5000]\n", "J=1\n", "for i in C_param_range:\n", " # initialize the logistic regression classifier\n", " classifier = linear_model.LogisticRegression(solver='liblinear', C=i)\n", " # train the classifier\n", " classifier.fit(X, y)\n", "\n", " # draw datapoints and boundaries\n", " title=\"Resultado para C= \"+ str(i)\n", " plot_classifier2(fig,classifier, X, y,a=5,b=2,c=J,titulo=title)\n", " J =J+1\n", "plt.show() " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para entender los gráficos anteriores hay que aclarar que **al aumentar C se tienen una penalización más alta por un error de clasificación**, y como puede verse se tiene una clasificación más óptima. Para valores bajos de C, los resultados son bastante malos, e incluso las zonas de decisión, prácticamente quedan delimitadas por una recta." ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Otro ejemplo\n", "\n", "En los apartados anteriores se ha mostrado un ejemplo muy simple para que el lector se vaya familiarizando con esta metodoligía. En lo que sigue, vamos a utilizar este método con otro tipo de aplicación. En concreto, se utilizará para poder clasificar los correos en spam o no spam, dependiendo del contenido del mensaje que traiga el correo. El ejemplo que utilizaremos, serán los datos de la [página UCI que puedes ver en este enlace](https://archive.ics.uci.edu/ml/datasets/sms+spam+collection){:target=\"_blank\"}. \n", "\n", "Como es un fichero de tipo zip, tenemos que descargarlo, descomprimirlo y posteriormente leerlo.Comenzamos por leer los datos con Pandas y obtener agunos estadísticos resumenes de los mismos." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
0hamGo until jurong point, crazy.. Available only ...
1hamOk lar... Joking wif u oni...
2spamFree entry in 2 a wkly comp to win FA Cup fina...
3hamU dun say so early hor... U c already then say...
4hamNah I don't think he goes to usf, he lives aro...
\n", "
" ], "text/plain": [ " 0 1\n", "0 ham Go until jurong point, crazy.. Available only ...\n", "1 ham Ok lar... Joking wif u oni...\n", "2 spam Free entry in 2 a wkly comp to win FA Cup fina...\n", "3 ham U dun say so early hor... U c already then say...\n", "4 ham Nah I don't think he goes to usf, he lives aro..." ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "datos= pd.read_csv('G:/MisCodigos/web/data/SMSSpamCollection.txt', delimiter='\\t',header=None)\n", "datos.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como podemos observar el conjunto de datos está constituido por dos columnas. La primera indica si el correo es o no espam y la segunda columna, contiene el cuerpo del correo electrónico.\n", "\n", "Veamos cómo están distribuidos los correos, enter ser o no der spam." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Número de mensajes que son spam: 747\n", "Número de mensajes que son ham 4825\n" ] } ], "source": [ "print ('Número de mensajes que son spam:', datos[datos[0] == 'spam'][0].count())\n", "print (\"Número de mensajes que son ham\",datos[datos[0] == 'ham'][0].count())" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "#datos[datos[0]=='ham',0]\n", "print(type(datos))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Inicio construcción del modelo\n", "\n", "Comencemos importando las bibliotecas necesarias para construir el modelo que buscamos." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "D:\\programas\\Anaconda\\lib\\site-packages\\sklearn\\cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.\n", " \"This module will be removed in 0.20.\", DeprecationWarning)\n" ] } ], "source": [ "import numpy as np\n", "import pandas as pd\n", "from sklearn.feature_extraction.text import TfidfVectorizer\n", "from sklearn.linear_model.logistic import LogisticRegression\n", "from sklearn.cross_validation import train_test_split, cross_val_score" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por regla general al construir un modelo con machine, lo que debe hacerse es dividir el conjunto de datos en dos subconjuntos: Unos será el que sirva para entrenar el modelo, mientras que el otro conjunto servirá para chequear el modelo obtenido en el paso anterior. Scikip-learn tiene una herramienta muy fácil de utilizar para conseguir esto, veamos cómo con el siguiente código (observar que se pone *\"random_state=20\"* para obtener siempre el mismos resultado en la elección aleatoria que se produce)." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(5572, 2)\n", "(4179,)\n", "(1393,)\n" ] }, { "data": { "text/plain": [ "'hi baby im sat on the bloody bus at the mo and i wont be home until about 7:30 wanna do somethin later? call me later ortxt back jess xx'" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X_train_raw, X_test_raw, y_train, y_test = train_test_split(datos[1],datos[0],\n", " random_state=20)\n", "\n", "print(datos.shape)\n", "print(X_train_raw.shape)\n", "print(X_test_raw.shape)\n", "X_test_raw.iloc[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Codificamos la primera feature con cero si no es spam y uno si es spam" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "y_train[y_train=='ham']=0\n", "y_train[y_train=='spam']=1\n", "y_test[y_test=='ham']=0\n", "y_test[y_test=='spam']=1\n", "y_train=y_train.astype('int')\n", "y_test=y_test.astype('int')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hacemos una trasnformación de los datos de la siguiente manera:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " (0, 6996)\t0.16556792560597175\n", " (0, 1324)\t0.26429710567869324\n", " (0, 1133)\t0.1996198979225791\n", " (0, 515)\t0.3722864947919741\n", " (0, 6672)\t0.14736275914770847\n", " (0, 5055)\t0.1951816469442735\n", " (0, 3574)\t0.28733559192349983\n", " (0, 1628)\t0.17373886759530308\n", " (0, 1566)\t0.11041199528377776\n", " (0, 115)\t0.28733559192349983\n", " (0, 1770)\t0.16310476115118047\n", " (0, 2586)\t0.17968998495260385\n", " (0, 710)\t0.28733559192349983\n", " (0, 5057)\t0.2251215486221769\n", " (0, 7273)\t0.25688036969281397\n", " (0, 4323)\t0.18170499641768148\n", " (0, 516)\t0.1922031619366998\n", " (0, 4795)\t0.2508204551521012\n", " (0, 139)\t0.25688036969281397\n", " (0, 3520)\t0.34759690783680136\n", " (0, 2513)\t0.937644063417614\n" ] } ], "source": [ "vectorizer = TfidfVectorizer()\n", "X_train = vectorizer.fit_transform(X_train_raw)\n", "X_test = vectorizer.transform(X_test_raw)\n", "print(X_train[0:1])\n", "print(X_test[0:1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Implementación del modelo\n", "\n", "Ahora ya estamos en disposición de implementar un modelo de regresión logit." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Predicción: 0 . mensage: K:)eng rocking in ashes:)\n", "Predicción: 0 . mensage: hi baby im sat on the bloody bus at the mo and i wont be home until about 7:30 wanna do somethin later? call me later ortxt back jess xx\n", "Predicción: 0 . mensage: We left already we at orchard now.\n", "Predicción: 0 . mensage: I absolutely LOVE South Park! I only recently started watching the office.\n", "Predicción: 0 . mensage: network operator. The service is free. For T & C's visit 80488.biz\n" ] } ], "source": [ "classifier = LogisticRegression()\n", "# Entrenamos ahora el modelo\n", "classifier.fit(X_train, y_train)\n", "#Ahora obtenemos la predicción de los datos que se han dejado para contraste del modelo\n", "predictions = classifier.predict(X_test)\n", "\n", "for i, prediction in enumerate(predictions[:5]):\n", " print('Predicción: {} . mensage: {}'.format(prediction, X_test_raw.iloc[i]))\n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Medidas de fiabilidad\n", "\n", "Una vez construido el modelo, siempre es necesario hacer alfunas pruebas con él a fin de ver su fiabilidad. Scikip-learn tiene muchas funciones para hacer este tipo de estudios. En el ejemplo que sigue se muestra cómo se puede construir una matriz de confusión, para ver los posibles errores que se puedan cometer." ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1191 4]\n", " [ 45 153]]\n" ] } ], "source": [ "from sklearn.metrics import confusion_matrix\n", "matrizConfusion=confusion_matrix(y_test,predictions)\n", "print(matrizConfusion)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A continuación hacemos una representación gráfica de los datos contenidos en la matriz de confusión." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as pl\n", "\n", "fig, ax = plt.subplots()\n", "ax.matshow(matrizConfusion)\n", "plt.title('Matriz de confusión')\n", "for (i, j), z in np.ndenumerate(matrizConfusion):\n", " ax.text(j, i, '{:0.0f}'.format(z), ha='center', va='center')\n", "\n", "plt.ylabel('Valor observado')\n", "plt.xlabel('valor predicho')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Acuracidad\n", "\n", "Esta medida nos da el porcentaje de aciertos del modelo, y por lo tanto su valor se calculará como la suma de los elementos de la diagonal, dividido entre la suma total." ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Acuracidad: 0.964824120603015\n", "0.964824120603015\n" ] } ], "source": [ "from sklearn.metrics import accuracy_score\n", "print('Acuracidad: {}'.format(accuracy_score(y_test,predictions)))\n", "# Calculado de forma manual, sería de la siguiente forma\n", "acu=((matrizConfusion[0,0]+matrizConfusion[1,1])/matrizConfusion.sum())\n", "print(acu)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Existe otro procedimiento para medir la fiabilidad del modelo, a grandes rasgos consiste en los siguiente. Se divide la muestra en una serie de grupos (K-fold's), en el ejemplo que sigue, esto se ha indicado con el parámetro *\"cv=5\"*, con lo que se indique que se haga una división en 5 grupos. Unos de estos grupos servirá para chequear el modelo y los otros cuatro para su entrenamiento. Con esta distribución de la muestra, se obtiene un valor de la acuracidad.\n", "\n", "En cada paso se van intercambiando los grupos que tienen datos de tipo test y por consiguiente de tipo train. En este caso concreto en total tenderemos 5 pasos pues cv=5. Los resultados obtenidos se muestran en el siguiente script." ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.956447583302295\n", "[0.9569378 0.96052632 0.96052632 0.95334928 0.9508982 ]\n" ] } ], "source": [ "from sklearn.cross_validation import cross_val_score\n", "scores = cross_val_score(classifier, X_train, y_train, cv=5)\n", "print (np.mean(scores))\n", "\n", "print(scores)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Precisión y recall\n", "\n", "Si bien la acuracidad es un valor muy importante, pues está midiendo la tasa de aciertos del modelo, no es menos importante saber qué estrutura tiene los casos en los que el modelo se equivoca. Para explicar lo que sigue, vamos a definir antes los siguientes conceptos:\n", "\n", "1.- Verdaderos Positivos (VP). Número de casos en los que el modelo predice positivo, y el dato real es positivo.\n", "\n", "2.- Verdaderos Negativos (VN). Número de casos en los que el modelo predice negativo, y el dato real es negativo.\n", "\n", "3.- Falsos Positivos (FP). Número de casos en los que el modelo predice un valor positivos, pero el valor real es negativo. \n", "\n", "4.- Falsos Negativos (FN). Número de casos en los que el modelo predice un valor negativo, pero el valor real es positivo.\n", "\n", "Interesa mucho también evaluar los casos 3 y 4, pues si el modelo está prediciendo la aparición o no de cáncer, con el error 3 estaríamos pronosticando que hay cáncer cuando no lo hay, mientra que el error 4 sería más grave aún, pues estamos pronosticando que una persona no tienen cáncer, cuando realmente lo tiene, y esto puede ser sumamente grave, pues el retraso de la aplicación de la medicación pertinente puede acarrear nefastas consecuencias para el paciente.\n", "\n", "Para estudiar este tipo de casos, se definen los siguiente indicadores: Precisión y Recall,\n", "\n", "Precisión se define de la siguiente manera:\n", "\n", "\\\\[ P=\\frac{VP}{VP+FP} \\\\]\n", "\n", "Mientras que Recall, se define así\n", "\n", "\\\\[ R=\\frac{VP}{VP+FN} \\\\]\n", "\n", "De lo que se trata con estas dos fórmulas es relativizar los verdaderos positivos y compararlo con las ocasiones en las que el predictor se equivoca.\n", "\n", "Veamos cómo se pueden obtener estos valores mediante la utilización de scikit-learn." ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Precision 0.989690423420296 [0.98684211 1. 0.97530864 0.98630137 1. ]\n", "Recalls 0.6756797331109258 [0.68181818 0.7 0.71818182 0.65454545 0.62385321]\n" ] } ], "source": [ "precisions = cross_val_score(classifier, X_train, y_train, cv=5, scoring='precision')\n", "print ('Precision', np.mean(precisions), precisions)\n", "recalls = cross_val_score(classifier, X_train, y_train, cv=5, scoring='recall')\n", "print ('Recalls', np.mean(recalls), recalls)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos ver que el valor de Recall es ligeramente bajo y ello es debido a que se detectan bastantes falsos negativos, por lo tanto habrá que tener cuidado en este aspecto, cuando se utilice este modelo para la predicción. En nuestro ejemplo concreto se puede detectar un número algo alto de correos que el modelo predice son Spam, cuando realmente no lo es, en concreto se estarían clasificando aproximadamente el 22 por ciento de correo spam como no spam.\n", "\n", "# F1 score\n", "\n", "Es otro indicador muy utilizado dentro del mundo de la clasificación, y en términos matemáticos, no es otra cosa más que la media armónica entre la precisión y el recall, y se calcula utilizando la siguiente fórmula:\n", "\n", "\\\\[ F1= (\\frac{P^{-1}+R^{-1}}{2})^{-1} =2 \\frac{P*R}{P+R} \\\\]\n", "\n", "\n", "La medida de F1 penaliza a los clasificadores con una precisión y Recall desequilibrado. Veamos, cómo medir esto con scikit learn\n" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "F1: 0.8024905966761053 [0.80645161 0.82352941 0.82722513 0.78688525 0.76836158]\n" ] } ], "source": [ "f1s = cross_val_score(classifier, X_train, y_train, cv=5, \n", "scoring='f1')\n", "print ('F1: ', np.mean(f1s), f1s)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Resumen fiabilidad\n", "\n", "En scikit learn existe la función *\"classification_report\"* que nos facilita estos tipos de valores con ejecutarla sólo una vez. Veamos cómo se haría en nuestro ejemplo:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "' precision recall f1-score support\\n\\n No spam 0.96 1.00 0.98 1195\\n spam 0.97 0.77 0.86 198\\n\\navg / total 0.97 0.96 0.96 1393\\n'" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import classification_report\n", "targets = ['No spam', 'spam']\n", "classification_report(y_test,predictions,target_names=targets)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Curva de Roc\n", "\n", "En un [post anterior](https://bigdatafran.github.io/big_data//LogitClasificacion), se ha presentado la curva de ROC y la forma de obtenerla mediante R, aquí vamos a ver cómo se consigue este resultado con scikit-learn.\n", "\n", "A diferencia de la acuracidad, la curva de ROC no depende de si los datos de cada una de las clases están o no balanceados.\n", "\n", "Recordemos, que el área de la curva de ROC es un indicador de la fiabilidad o bondad del modelo, de tal manera que cuanto mayor sea el valor del área de la curva de ROC, mejores predicciones tendremos.\n", "\n", "La curva de ROC en scikit-learn se calcula de la siguiente manera:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "image/png": "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hAn1jicbiUsUkY5in3gijBwgNPGbNQv694/wG4pILjz00EPst99+jBs3Luuv+Z//+R+++OILZs6cycyZM3nqqadYsWJFveKYPXs248aNY9asWTz77LOcffbZrF+/fqP1zjrrLB544AGmT5/OiBEjGDNmDABjxoxhyJAhvPvuu4wbN46zzz67XvFkS1NPAF99Bb/5DTzySChajx4d+jOpiZ9IgznvvHDZUUPac0+4/vrM63z33Xe89tprvPTSSxx11FFcdtllNW73+++/584772T+/Pk0b94cgO23354hQ4bUK94nn3ySYcOG0bx5czp16kTnzp1566236NevX6X1zIxvv/0WgOXLl/Pj1Cn41b0etcQdCRt0ROEO//hH+A3+7jv485/hoovClJOIFIQnnniCgQMH0rVrV370ox/xzjvv0Lt374xfM3fuXNq3b0+rLKaczz//fF566aWNXh82bBiXXHJJpdcWLlzIPvvs88Ny27ZtWbhw4UZfO3bsWA4//HA222wzWrVqxZQpUwC47LLLOPTQQ7nppptYuXIlzz//fI3xNYTEJYoGVVwMp58ORUXh6updd407IpGCVdMn/6g89NBDnHfeeUA4eD/00EP07t272rODanvW0HXXXZf1uumuW0v3/a677jomTJhA3759ueqqq7jgggsYO3YsDz30ECNHjmT06NG88cYbnHjiicycOZMmEd97ofElirImfoMGhSZ+r70Wur2qP5NIwVmyZAkvvvgiM2fOxMxYv349ZsaVV15J69atWbp0aaX1v/nmG9q0aUPnzp0pLi5mxYoVtGzZMuP3qM2Iom3btixYsOCH5ZKSko2mjxYtWsSMGTPo27cvAEOHDmXgwIEA3HXXXTz77LMA9OvXj9LSUhYvXsx2222X5R6pI3dP1GPTTff2Opszx33//d3BfdKkum9HRLIye/bsWL//bbfd5qNGjar0Wv/+/X3y5MleWlrqHTt2/CHGTz/91Nu3b+/Lli1zd/eLLrrIR44c6atXr3Z3988//9zvv//+esUzc+ZM79mzp5eWlvq8efO8U6dOvm7dukrrrF271lu3bu1z5sxxd/exY8f6Mccc4+7uAwcO9Hvuucfdw77dcccdfcOGDRt9n3T7HZjmdTzuxn7gr+2jToli7Vr3v/7VvXlz9623dr/nHvc0O1dEGlbciWLAgAH+zDPP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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from sklearn.metrics import roc_curve, auc\n", "\n", "false_positive_rate, recall, thresholds = roc_curve(y_test,predictions)\n", "roc_auc = auc(false_positive_rate, recall)\n", "plt.title('Curva de ROC')\n", "plt.plot(false_positive_rate, recall, 'b', label='AUC = %0.2f' % roc_auc)\n", "plt.legend(loc='lower right')\n", "plt.plot([0, 1], [0, 1], 'r--')\n", "plt.xlim([0.0, 1.0])\n", "plt.ylim([0.0, 1.0])\n", "plt.ylabel('Recall')\n", "plt.xlabel('Fall-out')\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Tabla de contenidos", "title_sidebar": "Contenidos", "toc_cell": true, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }