Etiqueta: Curso

  • Aprendizaje supervisado – Clasificación

    Aprendizaje supervisado – Clasificación

    Regresión logística

    LOGR o regresión logit, a pesar de su nombre no tiene nada que ver con algoritmos de regresión, si no que es un algoritmo de clasificación. Funciona creando una frontera lineal entre dos clases, es decir que nos da una probabilidad de que la predicción pertenezca a una determinada clase, suele ser P>0.5=1 pero podemos fijar este criterio de decisión dependiendo de nuestra necesidad.

    Una de las métricas mas utilizadas para medir la bondad de los clasificadores es la métrica AUC(área bajo la curva). La curva ROC mide la relación entre las tasas de aciertos y de falsos positivos en función del umbral de clasificación. Cuanto mayor sea el área bajo la curva ROC, mejor será el clasificador. Un clasificador perfecto tendrá un valor de AUC = 1.

    Como mencionamos anteriormente, este algoritmo separa en dos clases, es decir que cuando tenemos un problema multiclase lo que hace es validar una clase frente a todos los demás, si no corresponde toma la siguiente clase y vuelve a comparar, algo como un switch case iterativo, separa todos los items de una clase, luego la siguiente y así sucesivamente hasta que crea una línea de separación por cada clase, lo que significa que tenemos un subproblema por cada clase a predecir; con cada línea(corete de frontera) se calculan las bisectrices.

    Para llevar a cabo el entrenamiento utilizamos una función matemática que permite devolver predicciones a partir de la transformación exponencial de una combinación lineal de los atributos.

    \hat{y}=\frac{1}{1+e^{-W_0-W_1\cdot X_1-\cdots -W_p\cdot X_p}}

    Como mencionamos es un proceso iterativo, en donde cada época los coeficientes se van actualizando para acercarse al resultado deseado(separar la clase de las demás). El valor optimo de estos coeficientes son aquellos que maximizan la siguiente función objetivo(función de verosimilitud):

    f(W_0,\cdots,W_p)=\sum_{i=1}^{n}y_i\cdot ln(\hat{y_i})+(1-y_i)\cdot ln(1-\hat{y_i})

    Ventajas:

    • Simplicidad
    • Fácil de interpretar las predicciones
    • Tiempo de entrenamiento razonable
    • Tiempo de predicción casi instantáneo

    Desventajas:

    • Se asume que los atributos son independientes, no tienen una correlación significativa
    • Modelo muy simple, solo permite crear una línea de decisión entre dos clases

    Árboles de decisión

    Es un modelo de conocimiento que puede generarse a partir de datos y puede usarse tanto para clasificación como regresión. Se divide el conjunto de datos de manera jerárquica en trozos menores hasta lograr llegar a una única clase.

    A Tutorial to Understand Decision Tree ID3 Learning Algorithm

    Antes de ver la implementación vamos a conocer el índice de Gini, veamos un ejemplo.

    En este caso vamos a calcular el índice Gini por género.

    p_g=\frac{9}{16}=0.56

    q_g=1-p_g=0.44

    G_g=p_{g}^2+q_{g}^2=0.50

    p_b=\frac{6}{14}=0.42

    q_b=1-p_b=0.58

    G_b=p_{b}^2+q_{b}^2=0.51

    Tenemos el índice de Gini para las chicas y los chicos, ahora para sacar el ponderado por genero lo que hacemos es sumar ambos índices por la frecuencia de las posibilidades.

    Gini_G=\frac{16}{30}\cdot G_g+\frac{14}{30}\cdot G_b

    Gini_G=\frac{16}{30}\cdot 0.50+\frac{14}{30}\cdot 0.51

    Gini_G=0.50

    En este caso solo lo hicimos con un atributo, pero la idea es hacerlo por todos los atributos, por ejemplo altura, edad, etc. Este valor nos sirve para detectar los atributos mas discriminativos, es decir calculamos el índice Gini para cada condición y la que tenga mas valor es la que tiene mayor rango en la jerarquía.

    Ventajas:

    • Simplicidad
    • Fácil de interpretar las predicciones
    • Tiempo de entrenamiento razonable
    • Tiempo de predicción muy rápido
    • Flexibilidad en la características de los datos

    Desventajas:

    • Riesgo de sobreajuste
    • Sensibilidad al desbalanceo de las clases

    Support Vector Machine(SVN)

    Este algoritmo funciona a partir de funciones discriminales lineales, es decir que se limita a discriminar entre dos clases, sin embargo no significa que debamos huir a problemas multiclase, lo que hacemos es un one vs all para abordar estos problemas.

    Consiste en hallar un hiperplano optimo capaz de separar el espacio muestral en dos regiones de manera que cada región pertenezca a una clase, donde el optimo es el que maximiza el margen.

    A los dos puntos mas cercanos que tocan el limite del margen se les llama vectores de soporte. Definiendo un hiperplano positivo y uno negativo.

    Dada una muestra (x_i,y_i) y un hiperplano denotado por un vector w y un bias b, el objetivo es determinar la distancia de x_i al hiperplano.

    \beta =w\cdot x +b

    D=\{|(x_i,y_i)|x_i\in\mathbb{R}^{n}, y_1\in\{-1,1\}\}_{i=1}^{m}\to \textrm{}_{i=1\cdots m}^{B=\textrm{min}\beta_i}

    Al utilizar esta función nos encontramos con el problema del signo negativo, donde en la anterior imagen al minimizar \beta pareciera que cualquiera de las dos opciones funciona pero solo hay un hiperplano optimo.

    Para solucionar esto se introduce la variable y de manera que:

    • Si el resultado es positivo la clasificación es correcta
    • Si el resultado es negativo la clasificacion es incorrecta

    Ahora el objetivo a minimizar es:

    F=\textrm{}_{i=1\cdots m}^{B=\textrm{min }y_i(w\cdot x_i+b)}

    Tenemos adicionalmente otro problema, por ejemplo, un vector w_1=(2,1) y b_1=5 representa el mismo hiperplano que el vector w_2=(20,10) y b_2=50. Vemos que en el caso de w_2 tenemos una F diez veces mayor. A esto se le conoce como problema de escala. La solucion es dividir el vector w y el bias b, por su norma; por lo que la función objetivo a minimizar seria:

    M=\textrm{}_{i=1\cdots m}^{B=\textrm{min}}y_i(\frac{w}{||w||}\cdot x+\frac{b}{||w||})

    Minimizando:

    \textrm{min}\frac{1}{2}||w||^2 donde y_i(w\cdot x_i)+b\geq 1,i=1,\cdots,m

    Hasta ahora este proceso me genera un hard margin SVN que requiere que mis datos sean linealmente separables y que no haya distorcion en los datos; para solventar esto surge soft margin SVN.

    El soft margin SVN introduce una variable de holgura capaz de minimizar los errores de predicción, permitiendo cometer mas errores de clasificación durante el entrenamiento, su función a minimizar es:

    \textrm{min}\frac{1}{2}||w||^2+C\sum_{i=1}^{m}\zeta_i

    Donde

    y_i(w\cdot x_i+b)\geq 1-\zeta_i
    \zeta_i\geq0 para cualquier i=1,\cdots,m

    C(box constraint) es un parámetro de regularización que controla la compensación entre la penalización de las clasificaciones erróneas(teniendo en cuenta las variables de holgura) y el ancho del margen.

    Usando hard margin SVN podemos generar un problema de overfiting, ya que el hiperplano optimo se ajustara a nuestros datos.

    Usando la librería de SKlearn al colocar la C, entre mas alto menos importancia le damos a los errores y por lo tanto hay mas permisividad pero puedo caer en underfiting.

    Mencionamos que se puede utilizar en datos linealmente separables, pero cuando no lo son podemos aplicar el kernel trick usando una función kernel(cuadrático, gaussiano, etc); esto permite proyectar un espacio muestral D-dimensional a otro espacio M-dimensional, donde M>D

    \varnothing:\mathbb{R}^{D}\to\mathbb{R}^{M}

    Esto permite separar de manera lineal aquellos datos que originalmente no eran separables.

    Cuando trabajamos con kernel otro hiperparámetro que podemos usar es Gamma, se utiliza con la función RBF(radial basiss function) de kernel gaussiano. Este permite definir el grado de curvatura de la frontera de decisión. Normalmente se usan valores de gamma entre 0.01 y 100

    \gamma=\frac{1}{2\sigma^2}

    RBF=e^{-\gamma\cdot||x-x'||}

    menos permisivo –> más importancia a errores de entrenamiento

    más permisivo –> menos importancia a errores de entrenamiento

    Bagging – Bootstrap aggregating

    1. Divide en varios subconjuntos los datos de entrenamiento.
    2. Se crea un modelo(clasificador) por cada subdataset. Se puede utilizar cualquier clasificador pero el mas usado son los arboles de decisión dando el método mas conocido, random forest. Se utilizan también distinto numero de características en cada subdataset. El uso del modelo se basa en  weak learners (clasificadores con al menos un 51% de éxito) para construir el strong learner
    3. La clasificación final se obtiene del promedio de todos los clasificadores. De esta manera este algoritmo reduce la varianza y minimiza el overfitting.

    Ventajas:

    • Eficiente sin ajustar hiperparámetros en problemas de clasificación y regresión
    • Estabilidad y robustez en la predicción, ya que al utilizar muchos árboles prevalece el promedio de las votaciones.
    • Posibilidad de utilizar gran cantidad de características
    • Tiende a reducir el riesgo de overfitting.

    Desventajas:

    • Coste computacional más elevado que construir un solo árbol de decisión.
    • Inconsistencia cuando se utilizan datasets pequeños.

    BOOSTING

    El entrenamiento se realiza creando también varios modelos, pero en esta ocasión lo hace en serie y en cada iteración conserva el error cometido en la anterior iteración para mejorar el modelo actual.

    Aquí también se utiliza mucho los arboles de decisión como método de decisión. Y su método mas conocido es Adaboost.

    1. Adaboost solo se crea árboles compuestos por un solo nodo, es decir evaluá una característica y saca dos posibles predicciones, lo que se denomina stump; de esta manera, se crea lo que se conoce como Forest of StumpsLos stumps no son buenos clasificadores por sí solos, por eso son weak learners. La idea es utilizar el stump que tenga un menor índice Gini.
    2. Adaboost aplica la técnica de majority voting de manera ponderada, por lo que algunos árboles contribuyen más que otros en la decisión final. Esta ponderación se hace con la siguiente ecuación:
      \textrm{Importancia}=\frac{1}{2}log(\frac{1-\textrm{Total Error}}{\textrm{Total Error}})
      *El error es igual al número de fallos cometidos entre el total de los registros

    E_\gamma =\frac{1}{8}=0.125

    \textrm{Importancia}=\frac{1}{2}log(\frac{1-0.125}{0.125})=0.973

    1. En los registros donde se cometen errores otorgamos mayor peso \textrm{weight}_{t+1}=\textrm{weight}_t\cdot e^{\textrm{importancia}}
      Donde no se cometen errores \textrm{weight}_{t+1}=\textrm{weight}_t\cdot e^{-\textrm{importancia}}
      Tomando el ejemplo anterior:
      \textrm{weight}_{2}=\frac{1}{8}\cdot e^{0.97}=0.33 para el caso incorrecto
      \textrm{weight}_{2}=\frac{1}{8}\cdot e^{-0.97}=0.05 para los casos correctos
    2. Se normalizan los pesos dividiendo cada valor entre el sumatorio de los nuevos pesos. Los pesos normalizados constituirán el nuevo sample weight.
    3. Se define un conjunto de datos vacío de las mismas dimensiones que el original.  Después, se selecciona aleatoriamente un valor entre 0 y 1, y se añade el registro correspondiente en función de la suma ponderada de la columna de sample weight.

    Ventajas:

    • Fácil implementación.
    • Permite corregir errores de manera iterativa usando weak classifiers.
    • Mejora el rendimiento combinando weak learners.
    • No produce overfitting.

    Desventajas:

    • Es sensible a datos ruidosos.
    • Es poco robusto frente a outliers
  • TEORÍA DE LA EVIDENCIA

    TEORÍA DE LA EVIDENCIA

    Preliminares

    También llamada teoría de Dempster-Shafer, modela la incertidumbre del conocimiento eliminando algunos puntos débiles del enfoque probabilista bayesiano. Hace principal énfasis en la suma de la creencia en un hecho y en su contrario no tiene por que ser.

    En probabilidad el aumento de la probabilidad en una hipótesis hace disminuir automáticamente su contraria.

    Se considera como punto de partida una serie de entornos(q1,q2,\cdots). Un entorno(H) consta de un conjunto de hipótesis mutuamente exclusivas(una no puede influir una en otra) y exhaustivas(cubren todas las posibles situaciones de dicho entorno). Este conjunto de hipótesis se llama marco de discernimiento.

    H={h1,h2,\cdots,hn}

    Se define conjunto potencia del marco H al formado por todos los subconjuntos de hipótesis.

    P(H)=[\{\varnothing\},\{h1\},\{h2\}\cdots,\{h1,h2\}\cdots\{h1,h2,\cdots,hn\}]

    Para entender como trabajar con esta teoría necesitamos de algunos conceptos clave:

    La función de asignación de probabilidad básica o masa de probabilidad que asigna valores entre 0 y 1 a cada elemento del conjunto potencia. 2^N\in[0,1] definida como:

    m(\varnothing)=0 masa del conjunto vacío es cero

    \sum_{S_i\subseteq H}m(S_i)=1

    Donde:

    0<m(S_i)<1

    S_i cualquier subconjunto del marco de potencia.

    m(S_i) es asignado por el experto según su juicio.

    La creencia(BEL) en un conjunto de hipótesis S es la suma de todas las masas de probabilidad de los subconjuntos.

    BEL(S)=\sum_{X\subset S}m(X)

    El valor de m asignado a S_i indica la creencia en ese conjunto.

    Bel(S_i) indica la creencia en ese conjunto y todos sus subconjuntos.

    Bel(H)=1

    El intervalo de creencia o certidumbre de un conjunto S es:

    [BEL(S),1-BEL(\sim S)]

    \sim S es el conjunto complementario de S respecto al conjunto potencia.

    Plausibilidad es una medida del grado en que la evidencia no puede refutar S:

    PL(S)=1-BEL(\sim S)

     

    Incertidumbre es: PL(S)-BEL(S)

    En el enfoque de Bayes las probabilidades son un número, mientras que en esta teoría las probabilidades se expresan por intervalos de creencia. Sin embargo cuando estos intervalos se estrechan las teorías tienden a coincidir.

    Otra particularidad es que la probabilidad en Bayes de un subconjunto es menor o igual que el conjunto padre, sin embargo en la teoría DS no necesariamente es así.

    Además en Bayes la suma de un conjunto mas su complementario es 1 mientras en DS no esta definido.

    Es muy común que tengamos que añadir o actualizar las funciones de asignación básica de probabilidad sobre el marco de discernimiento, por ejemplo, en un diagnostico medico a medida que avanza un tratamiento o en un proceso en el que vamos recogiendo nueva evidencia. En este caso siendo m1 una función que estime previamente y m2 una función con evidencia añadida, el resultado de combinar ambas funciones es:

    m3(C)=\frac{\sum_{X\cap Y=C}m1(X)\cdot m2(Y)}{1-\sum_{X\cap Y=\varnothing }m1(X)\cdot m2(Y)}

    X,Y,C son subconjuntos del marco de discernimiento.

    En el numerador encontramos el soporte, que entre mas evidencia mas apoya las posibles hipótesis.

    En el denominador tenemos el conflicto entre las hipótesis. Si el conflicto da 1, la función quedaría como 1-1=0 lo que da una probabilidad contradictoria.

    Practica

    Imaginemos el siguiente caso: Cuatro personas, Bob, Jim, Silvia y Tania, se reúnen en una habitación, se va la luz y Tania esta muerta.

    En un principio se puede sacar las siguientes conclusiones:

    • Bob es culpable
    • Jim es culpable
    • Silvia es culpable
    • Alguna combinación de los participantes

    H={B,J,S}

    Conjunto potencia: H=[\{\varnothing\},\{B\},\{J\},\{S\},\{B,J\},\{B,S\},\{J,S\},\{B,J,S\}]

    Ahora, supongamos que después de las investigaciones se asignan las siguientes masas de probabilidad a las diferentes hipótesis:

    m(\{\varnothing\})=0

    m(\{B\})=0.1

    m(\{J\})=0.2

    m(\{S\})=0.1

    m(\{B,J\})=0.1

    m(\{B,S\})=0.1

    m(\{J,S\})=0.3

    m(\{B,J,S\})=0.1

    Creencia:

    BEL
    \{\varnothing\} 0 0
    \{B\} 0.1 0.1
    \{J\} 0.2 0.2
    \{S\} 0.1 0.1
    \{B,J\} 0.1 0.4
    \{B,S\} 0.1 0.3
    \{J,S\} 0.3 0.6
    \{B,J,S\} 0.1 1.0

    La investigación sigue avanzando y se encuentran nuevas pistas, reasignándose una nueva masa de probabilidad ante las nuevas evidencias:

    mr(\{\varnothing\})=0

    mr(\{B\})=0.2

    mr(\{J\})=0.1

    mr(\{S\})=0.05

    mr(\{B,J\})=0.05

    mr(\{B,S\})=0.3

    mr(\{J,S\})=0.1

    mr(\{B,J,S\})=0.2

    Vamos a sacar la nueva masa de probabilidad combinada.

    BJS 0.1
    JS 0.3 C
    BJ 0.1 C
    BS 0.1 C
    S 0.1 C C C
    J 0.2 C C C
    B 0.1 C C C
    B 0.2 J 0.1 S 0.05 BJ 0.05 BS 0.3 JS 0.1 BJS 0.2

    Conflicto:

    C=0.2\cdot 0.2+0.1\cdot 0.2+0.3\cdot 0.2+0.1\cdot 0.1+0.1\cdot 0.1+0.1\cdot 0.1+0.1\cdot 0.05+0.2\cdot 0.05+0.1\cdot 0.05+0.05\cdot 0.1+0.2\cdot 0.3+0.1\cdot 0.1

    C=0.245

    Normalización:

    1-0.245=0.755

    Vamos a sacar la estimación de la nueva masa combinada en base a Bob m3(B)

    BJS 0.1 X
    JS 0.3 C
    BJ 0.1 X C X
    BS 0.1 X C X
    S 0.1 C C C
    J 0.2 C C C
    B 0.1 X C C X X C X
    B 0.2 J 0.1 S 0.05 BJ 0.05 BS 0.3 JS 0.1 BJS 0.2

    Marcamos con X los valores que usaremos para sacar el numerador:

    0.1\cdot 0.2+0.1\cdot 0.2+0.1\cdot 0.2+0.1\cdot 0.2+0.1\cdot 0.05+0.1\cdot 0.05+0.1\cdot 0.3+0.1\cdot 0.3+0.1\cdot 0.2=0.17

    m3(B)=\frac{0.17}{0.755}

    m3(B)=0.225

  • Descriptores de forma

    Descriptores de forma

    Descriptores geométricos

    Analizan la forma estructural de objetos binarios y sus contornos. Se puede utilizar para identificar objetos y reconocer patrones.

    • Área: Mide el número de pixeles de la región de interés.
    • Bounding box(bbox): Rectángulo mas pequeño capaz de albergar la región de interés(rectángulo rojo).
    • Área de bbox: Número de pixeles de la bounding box.
    • Convex hull image: Polígono convexo mas pequeño capaz de albergar la región de interés(polígono cian).
    • Área de la convex image: Número de pixeles dentro de la convex image.
    • Excentricidad: Relación de la distancias entre los focos de la elipse y su longitud del eje principal. Una elipse con excentricidad = 0 es un circulo, una con excentricidad = 1 denota un segmento de línea.
    • Diámetro equivalente: Diámetro de un circulo cuya área sea la misma que la región de interés.
    • Extensión: Ratio de pixeles en la región con respecto al numero total de pixeles contenidos en la bounding box.
    • Longitud de eje mayor: Longitud del eje mayor de una elipse que tiene el mismo segundo momento central normalizado que la región.
    • Orientación: Angulo que forma la elipse anterior con respecto al eje horizontal. El valor se expresa en grados en un rango de -90, 90.
    • Perímetro: Numero de pixeles que forman parte del contorno del objeto de interés.
    • Solidez: Proporción de pixeles que contiene el área respecto a la convex hull image. En el caso de polígonos regulares su valor será 1.

    A partir de estos descriptores se pueden extraer otros de interés como:

    • Compacidad: Mide la circularidad del objeto. Se calcula como cociente entre el área y el perímetro al cuadrado.
    • Rectangularidad: Cociente entre el área del objeto y la bounding box.

    Descriptores de textura

    Matriz de concurrencias

    A partir de la imagen(matriz de pixeles), generamos una matriz midiendo la frecuencia en la que un pixel de intensidad i es adyacente a otro pixel de intensidad j. Se define a través de un número de pixeles vecinos d y una orientación(ángulo, \alpha). De estos valores podemos extraer características como:

    • contraste
    • correlación
    • homogeneidad
    • energía
    • segundo momento angular

    Scale-Invariant Feature Transform(SIFT)

    SIFT sirve para detección de esquinas, bordes o texturas; es estable frente a transformaciones de posición, escala, rotación, iluminación y contraste. Consta de las siguientes fases:

    1. Detección de extremos en la escala-espacio: Se crea aplicando convoluciones entre la imagen original(i) y un kernel gaussiano(G) con diferentes escalas(\sigma).
      L(x, y, \sigma)=G(x,y,\sigma)\cdot I(x,y),
      G(x,y,\sigma)=\frac{1}{\sqrt{2\pi\sigma^{2}}}e^{-(x^2+y^2)/2\sigma^2}
      Todas las imágenes(L) generadas forman una octave. Este proceso se repite para obtener varios octaves, donde el tamaño de cada una de ellas es la mitad de la anterior.
    2. Diferencia de Gaussianas(DOG): Restar para cada octave la imagen original.
    3. Detección de posibles puntos de interés: Cada pixel de una imagen es comparada con los 8 pixeles vecinos de la misma imagen y también con los 9 pixeles en la misma posición de la imagen anterior y posterior. Si el valor del pixel es un extremo local(mayor o menor intensidad), ese pixel se convierte en un posible punto de interés.
    4. Localización de puntos de interés: En el anterior punto se crean muchos puntos de interés por lo que en este paso nos quedamos con los puntos útiles. Se aplican series de Tylor(segundo orden) sobre cada punto de interés, se rechaza si la intensidad es menor a un determinado umbral. También eliminamos los bordes o puntos de interés que no son robustos al ruido, esto se hace con una matriz Hessiana de 2×2 que permite obtener la curvatura principal.
    5. Asignación de la orientación: localizados los puntos de interés(keypoints) necesitamos hacerlos robustos frente a las transformaciones que mencionamos anteriormente. Se selecciona un vecindario alrededor del punto de interés, se calcula la magnitud y la dirección del gradiente. A partir de las magnitudes y las direcciones del gradiente podemos construir un histograma de 36 bins, es decir de diez en diez para cubrir todas las direcciones posibles(360^{\circ}). Sumamos la magnitud a la dirección correspondiente, esto teniendo en cuenta el bin correspondiente del histograma.
    6. Descriptor del punto de interés: Se coge una ventana alrededor del punto de interés de 16×16 pixeles, luego se subdivide en 4×4 para en cada uno de estos calcular la magnitud y orientación de los pixeles obteniendo un histograma de 8 bins por lo que obtendríamos 16 histogramas de o bins, resultando en un fingerprint de 128 características.
    Imagen de https://towardsdatascience.com/sift-scale-invariant-feature-transform-c7233dc60f37

    Speeded-Up Robust Features(SURF)

    SURF es una versión mejorada de SIFT para la detección y descripción de puntos de interés, Su principal ventaja es que es hasta 3 veces mas rápido que el algoritmo SIFT, consta de los siguientes pasos:

    1. Cálculo de la matriz Hessiana: Permite sacar la segunda derivada, lo que hace es aproximar los filtros a una estructura mas simple.
    2. Cálculo de la orientación: Localizados los puntos de interés mediante la matriz Hessiana se calcula por bloque(wavelet) las derivadas verticales y horizontales.
    3. Cálculo del descriptor SURF: Se selecciona una ventana de 20×20, obteniendo 16 regiones de 5×5. Para cada subregión se calcula la derivada wavelet y se extraen las características en un vector v obteniendo 64 características para describir el punto de interés.

    Histogram of oriented gradients(HOG)

    HOG utiliza la distribución de los gradientes como características, muy similar al ultimo paso de SIFT. El algoritmo consta de los siguientes pasos:

    1. Cálculo de los gradientes de la imagen: Se calculan los gradientes verticales y horizontales con un kernel de tamaño 1, también se puede aplicando el algoritmo de Sobel. Una vez obtenidas las matrices G_x y G_y (representan las aproximaciones de las derivadas de intensidades) se calcula la magnitud y dirección del gradiente.
    2. Cálculo de gradientes en celdas mas grandes(8×8): tomamos celdas de 8×8 para obtener 128 características (64 magnitud, 64 dirección), se representan en un histograma de 9 bins en los ángulos correspondientes a los ángulos 0,20,40,60,80,100,120,140,160; esta representación es mas compacta y resistente al ruido.
    3. Cálculo del histograma de gradientes de 9 bins:
      • Si la dirección coincide con la etiqueta de un bin especifico, entonces se añade íntegramente el valor de su magnitud a dicho bin.
      • Si la dirección toma valores entre dos bins, la magnitud correspondiente se añadirá a los dos bins de manera proporcional.
      • En caso que la dirección sea mayor de 180^{\circ}, la magnitud se añadirá de manera proporcional entre los bins 160 y 0.
    4. Normalización del histograma de gradientes: La idea es que el descriptor sea invariante frente a cambios de contraste o luminosidad. Para esto recorremos con un celda de 16×16, lo que nos genera un vector de características de 36 elementos ya que estamos tomando 4 histogramas de 9 bins.
    5. Cálculo de HOG: El descriptor final tendrá un total de características igual a la cantidad de celdas de 16×16 en el eje horizontal por el total de celdas de 16×16 en el eje vertical.

    Local Binary Patterns(LBP)

    LBP describe patrones de la imagen a nivel local, dan buenos resultados en el reconocimiento de texturas, objetos y formas. Veamos los pasos del algoritmo:

    1. Se calcula la diferencia entre los pixeles vecinos y el central.
    2. Se construye una matriz auxiliar a partir de la umbralización de las diferencias con 0s en los valores negativos y 1s en los positivos.
    3. La matriz construida da lugar a una cadena binaria que se multiplica por una matriz de referencia.
    4. Se suman todos los valores que resultan de la multiplicación anterior y se establece el valor del pixel central.

    Para hacer el descriptor invariante a transformaciones de intensidad podemos variar P(número de pixeles vecinos) y R(radio de la frecuencia). LBP_{P,R}, P determina el espacio angular y R la resolución espacial.

    También lo podemos hacer invariante  las rotaciones asignándole un identificador único a todas aquellas cadenas binarias que presentan el mismo número de transiciones. LBP_{P,R}^{ri}

    Además se demostró que los patrones con un número de transiciones menor o igual a 2 tenían una capacidad discriminativa mucho mayor que el resto, por lo que se definieron dichos patrones como LBP uniformes. LBP_{P,R}^{riu2}

  • Segmentación en imágenes

    Segmentación en imágenes

    Para extraer las características de una imagen basado en descriptores de forma, previamente es necesario llevar a cavo una técnica de segmentación, para delimitar la región de interés que se desea analizar.

    La idea de los algoritmos de segmentación es dividir la imagen en diferentes segmentos(objetos) para posteriormente facilitar la comprensión del contenido. Lo que hacen es asignar una etiqueta a cada pixel, por lo que los pixeles con la misma etiqueta comparten características similares.

    Detección de objetos
    Segmentación semántica
    Segmentación de instancia

    Estos algoritmos de segmentación son muy usados en diferentes ámbitos, estamos rodeados por sistemas que dependen de recursos gráficos:

    • Reconocimiento de objetos en cámaras
    • Análisis de imágenes medicas
    • Reconocimiento aéreo(drones)
    • Reconocimiento de patrones
    • Conducción autónoma

    Algunas de las técnicas de segmentación son:

    • Métodos de umbralización(thresholding)
    • Métodos basados en espacio de color
    • Detección de bordes
    • Crecimiento de regiones(region growing)
    • Métodos de agrupación(clustering)
    • Watershed
    • Autoencoders(redes neuronales convolucionales)

    En este post solo vamos a trabajar con los métodos mas sencillos.

    Thresholding

    1. Necesitamos generar una mascara, y el primer paso es pasar nuestra imagen a escala de grises; esto nos ayudara a separar las formas del fondo.
    2. Vamos a visualizar el histograma que nos indica el numero de pixeles y su intensidad.
    3. A partir de los valores que visualizamos en el histogramas generamos la mascara final.

    Esta imagen tiene una particularidad y es que el fondo es blanco y las formas son muy fáciles de reconocer, en este caso utilizamos THRESH_BINARY_INV y en la segunda alternativa para sacar la mascara utilizamos la condición mask<t, de esta manera le indicamos que todos los pixeles menor al umbral son los que queremos destacar. En una imagen con color de fondo lo mas probable es que necesitemos usar las operaciones opuestas, es decir, THRESH_BINARY y mask>t, pero esto también depende de los colores y que tan fáciles sean de separar. Recordemos que esta es una de las técnicas mas básicas de segmentación.

    Ahora, vemos en el anterior ejemplo que el umbral lo sacamos manualmente, utilizando el histograma vemos la distribución de pixeles y su intensidad y decidimos que en este caso 180 era el umbral indicado. Esto obviamente no es posible cuando tenemos grandes cantidades de datos, la idea es que el umbral se pueda seleccionar de manera automática. La librería de OpenCV nos provee un método para hacer esto, usando la técnica de OTSU, este algoritmo consta de los siguientes pasos:

    1. Crear dos clases, una con los valores de intensidad de 0 hasta el t(umbral), y la otra clase desde t hasta la intensidad máxima encontrada en la escala. Entonces se itera sobre cada pixel se obtiene la intensidad de gris y se almacena en un vector que corresponde a cada clase.
      c_1=[0,1,2,\cdots ,t]
      c_1=[t+1,t+2,\cdots ,L]
    2. Se define la probabilidad del nivel de gris i
      p_i=\frac{f_i}{N}, siendo f_i la frecuencia de repetición del nivel de gris i
    3. Se calculan las medias para cada una de las clases
      \mu_1=\sum_{i=0}^{t}\frac{i\cdot p_i}{\omega_1(t)}; \omega_1(t)=\sum_{i=0}^{t}p_i
      \mu_2=\sum_{i=t+1}^{L}\frac{i\cdot p_i}{\omega_2(t)}; \omega_2(t)=\sum_{i=t+1}^{L}p_i
    4. Obtener la intensidad media total de la imagen
      \mu_r=\omega_1\cdot\mu_1+\omega_2\cdot\mu_2
    5. Calcular la varianza entre clases
      \sigma^2=\omega_1(\mu_1-\mu_r)^2+\omega_2(\mu_2-\mu_r)^2
    6. Se selecciona el umbral optimo, es aquel que maximiza la varianza, es decir vamos iterando sobre los anteriores pasos y donde la varianza sea máxima será nuestro umbral.
      t'=Max(\sigma^2(t))

    En el siguiente ejemplo implementamos esta técnica, todos los pasos ya están integrados en la librería de OpenCV, lo que vamos a hacer es sumarle a THRESH_BINARY_INV el THRESH_OTSU, esto lo hacemos justamente por que nuestra imagen tiene el fondo blanco, si fuese a color utilizaríamos directamente THRESH_OTSU.

    Espacios de color

    Vamos a obtener las figuras amarillas, para esto vamos a tener que utilizar las transformaciones de color para destacar justamente el canal amarillo y luego utilizamos los mismos pasos que en la segmentación anterior. En el caso de la mascara le resto un poco al máximo ya que el color en las formas no es un amarillo homogéneo.

    Detección de bordes

    En este caso vamos a obtener nuestra imagen y aplicaremos un filtro gaussiano(blur) para reducir el ruido, no es necesario pero se suele recomendar. Luego aplicaremos el método de Canny, rellenar y así obtenemos la mascara.

    Es importante conocer que hace internamente el método de Canny para así entender los resultados.

    1. Detectar bordes con Sobel: calcula la primera derivada para obtener el gradiente de intensidad en cada pixel, es decir que mide los cambios de intensidad en la imagen: esto lo hace con dos mascaras de convoluciones con kernels de 3×3, uno para los cambios horizontales y el otro para los cambios verticales. Se obtiene G_x y G_y que representan las aproximaciones de las derivadas de intensidades.
      Operador Sobel

      En cada pixel se combinan las aproximaciones de las derivadas para obtener la magnitud G
      G=\sqrt{G_{x}^{2}+G_{y}^{2}}

      Y con esto podemos calcular la dirección del gradiente: La dirección puede ser en estos ángulos(0, 45, 90 o 135)
      \Theta=arctan(\frac{G_y}{G_x})

    2. Filtrado de bordes mediante la supresión non-máximum: permite adelgazar los bordes basándose en el gradiente, elimina los pixeles que no corresponden a un borde. Esto lo hace comparando el valor de intensidad de cada pixel con los pixeles vecinos en la dirección del gradiente.
    3. Umbralización por histéresis: establece dos umbrales(máximo y mínimo):
      • Si el valor del pixel es mayor que el umbral máximo, el pixel se considera parte del borde.
      • Si el valor del pixel es menor que el umbral mínimo, el pixel no se considera parte del borde.
      • Si el valor del pixel esta entre el umbral mínimo y el máximo, el pixel se considera parte del borde si esta conectado a otro pixel que es borde.

    En el ejemplo vamos a ver que una de las figuras(estrella) no se resalta y eso es por que el borde esta abierto. Eso lo podemos solucionar probando con el filtro gaussiano, por ahora el que mejor me funciono fue 5 x 5. También aplique al método Canny la dilatación de bordes para solventar el problema.

    Crecimiento de regiones

    Este método esta implementado de manera muy sencillita. Consiste en coger un punto como semilla y a partir de este ir coloreando, en este caso el punto 0,0 sabemos que esta vacío, por lo que iremos rellenando con negro, nos quedara un fondo negro con formas a color, para completar la mascara simplemente hacemos una transformación de color y listo.

  • Transformaciones en imágenes

    Transformaciones en imágenes

    Introducción a los datos 2D

    Una imagen es simplemente una función bidimensional f(x,y) donde x y y representan las cordenadas espaciales y el valor de la f la intensidad de la imagen en dicho punto.

    Es decir que una imagen es una matriz de valores cuyo tamaño es la anchura y altura es el tamaño de la imagen; los valores corresponden al nivel de intensidad, que van del 0 al 255 en el caso de esta imagen en escala de grises. En el caso de imágenes de color(rgb), tenemos tres capas, es decir una matriz de intensidades por cada color(Rojo, Verde, Azul) que al combinarse generan los colores que visualizamos finalmente.

    Transformaciones

    Intensidad

    La transformación de intensidad nos ayuda para resaltar ciertas formas o características. La transformación de contraste nos puede ayudar para destacar contornos.

    Además tenemos otras transformaciones bastantes interesantes:

    • Lineal a tramos
    • Cambio de linealidad
    • Negativo
    • Ajuste del histograma
    • Ecualización del histograma

    Color

    Esta transformación es útil para destacar ciertos colores, por ejemplo una forma en particular que queremos resaltar.

    Geométricas

    Estas transformaciones son muy útiles para el aumento de datos. Aunque también nos sirven para destacar alguna característica.

  • Proceso de aprendizaje supervisado

    Proceso de aprendizaje supervisado

    En una síntesis muy simple el resultado de un proceso de aprendizaje automático el la suma de funciones, es decir que los datos están representados en estas funciones o los valores son muy aproximados. Por lo que tenemos un conjunto de datos y la idea es justamente encontrar las funciones mas apropiadas para describirlos.

    Supongamos que tenemos los siguientes datos:

    En nuestro proceso la idea es probar diferentes funciones y comparar cuales se ajustan mejor a nuestros datos.

    overfitting y underfitting

    Antes de ver el proceso al detalle debemos conocer estos dos conceptos, son muy importantes entenderlos y saber como manejarlos ya que de estos depende gran parte del éxito de nuestro proyecto.

    Como mencionamos el objetivo es encontrar las funciones que mas se ajusten a nuestros datos, pero esto tiene una pequeña trampa, mas bien es buscar las funciones que generalicen y representen los datos, esto en otras palabras es encontrar un modelo que nos sirve para predecir nuevos datos.

    Si entrenamos tanto el modelo que literalmente la función contiene cada uno de nuestros valores (a veces hasta incluyendo outliers) es una clara señal de que el modelo tiene overfitting(sobreajustado) y esto es un grave problema ya que las funciones que dan como resultado nuestros datos no necesariamente van a predecir correctamente, ya que las funciones que dan como resultado nuestros datos siempre pueden estar imprecisos, además que el modelo se ajusta tan bien a lo que conoce que futuros datos causaran predicciones erróneas. Por el contrario también tenemos underfitting(falta de ajuste), que precisamente es que las funciones están tan generales que las predicciones se pueden alejar bastante de los casos reales.

    Hay diversas métricas para medir y controlar esto durante la creación de nuestro modelos; pero por ahora no ahondaremos en ellas. Vamos a ver que el proceso de undefitting y overfitting se puede ir controlando desde el principio, como ya vimos en el anterior post desde la limpieza de datos y a continuación con la segmentación de la data preparándonos a la creación del modelo.

    Partición de los datos

    Continuando con nuestro proceso de crear un modelo supervisado vamos a particionar los datos, es una parte importante en la creación del modelo. Se suele separar en datos de entrenamiento y datos para pruebas, dejando unos porcentajes entre 70%(train) – 30%(test)  y 95%(train) – 5%(test) dependiendo de nuestra cantidad de datos y necesidades.

    Sin embargo también es muy frecuente además subdividir el set de datos de entrenamiento en dos, quedándonos un set de datos mas para validación.

    • Pruebas(test): Este dataset se separa al inicio y se deja aislado de todo el proceso, eso es para no contaminarlo con transformaciones y no exponer al modelo a estos datos, esto justamente ayuda a que el modelo se enfrente a valores a los que no ha estado expuesto y mostrarnos que tan preparado esta para enfrentarse a datos reales. Usamos los datos una vez generado el modelo, para validar el error real de nuestro modelo.
    • Entrenamiento(train): Este dataset provee los datos para entrenar nuestro modelo, de aquí se extraen los datos para que el modelo cree las funciones que generalizaran y representaran nuestros datos.
    • Validación: Este dataset se extrae del dataset de entrenamiento, y nos sirve justamente para ir validando la bondad del modelo, es decir ir validando durante la construcción del modelo la evolución de este. Tenemos varias maneras de ir haciendo estas evaluaciones; vamos a ver unas técnicas sencillas de como usar este data set para validar el modelo.

    Validación

    En cada iteración realizamos el proceso de de ir ajustando los pesos de cada una de las neuronas(veremos ese proceso de aprendizaje mas al detalle en otro post), que básicamente consiste en ir probando diferentes valores para crear funciones que se adapten a nuestros datos. Para medir que tan preciso es nuestro modelos utilizamos el dataset de validación. Tenemos diferentes métricas para medir el error, veamos algunas de introducción:

    MAE(Error absoluto medio)

    Se utiliza en problemas de regresión donde calculamos la desviación de la predicción al valor real. Es decir calculamos para cada registro del set de validación la desviación y luego sacamos un media general para todo el grupo de datos. Este resultado se guarda y se compara con la siguiente iteración; de esta manera voy comprobando si mi modelo mejora o empeora y puedo ir ajustando los pesos.

    MAE=\frac{1}{n}\cdot \sum_{i=1}^{n}|Y_i-\hat{Y_i}|

    RMSE(Error cuadrático medio)

    Básicamente usamos los mismos fundamentos del MAE, ambas son métricas de evaluación absolutas, pero elevamos el error al cuadrado lo que permite que el error se penalice mas.

    RMSE=\sqrt{\frac{1}{n}\cdot \sum_{i=1}^{n}(Y_i-\hat{Y_i})^2}

    MAPE(Porcentaje de error absoluto medio)

    Es una métrica de evaluación relativa, utilizamos el porcentaje en vea de los valores absolutos.

    MAPE=\frac{100}{n}\cdot \sum_{i=1}^{n}\begin{vmatrix}\frac{Y_i-\hat{Y_i}}{Y_i}\end{vmatrix}

    La diferencia entre métricas de evaluación absolutas y relativas es que en las absolutas las desviaciones tienen la misma unidad de magnitud, por ejemplo si estamos comparando una cantidad de productos te devuelve la cantidad de productos que hay de error.

    Exactitud

    Esta métrica se utiliza en problemas de clasificación. Simplemente consiste en comparar la tasa de acierto. Se suman todas las clases predichas que si coinciden con la clase real, de la siguiente manera:

    Exactitud=\frac{100}{n}\cdot \sum_{i=1}^{n}Y_i=\hat{Y_i}

    Es muy importante para conocer a fondo las métricas de clasificación el uso de la matriz de confusión: esta consiste en una tabla donde se comparan los valores de la clase real frente a los valores de la clase predicha.

    Conociendo esta tabla también podemos definir la métrica de Exactitud de la siguiente manera:

    Exactitud=\frac{TP+TN}{TP+TN+FP+FN}

    Precisión

    Precision=100\cdot \frac{TP}{TP+FP}

    Sensibilidad

    Sensibilidad=\frac{TP}{TP+FN}

    F1(F1-score, F1-measure)

    Combina la sensibilidad y precisión. Es una de las métricas mas robustas para clasificación.

    F1=100\cdot \frac{2\cdot Sensibilidad \cdot Precision}{Sensibilidad + Precision}

    Teniendo nuestras métricas planteadas vamos a ver unos ejemplos de como se hace la separación de datos.

    Validación Hold-out

    Esta es una de las particiones mas sencillas, simplemente es obtener un porcentaje de nuestro dataset para usarlo por separado. En el ejemplo a continuación lo que hacemos es separar los datos con la función train_test_split:

    Validación cruzada

    Esta es una selección de datos un poco mas robusta, ya que evita el sobreajuste, debido a que no tenemos siempre el mismo conjunto de datos de validación. La técnica consiste en cada iteración ir cambiando nuestro dataset de validación. Siempre mantendremos la misma cantidad de datos pero iremos intercambiando entre ellos.

    Ahora veamos un ejemplo mas real usando la función KFold.

    Validación leave-one-out

    Como su nombre lo indica es dejar un registro afuera, ese único registro se va a usar para validar. En cada iteración usamos uno, luego el siguiente y así sucesivamente, por lo que al final usaremos todos los datos como validación. Esto es especialmente bueno cuando tenemos pocos datos.

    Validación en regresión

    Validación en clasificación

  • Selección de atributos

    Selección de atributos

    Valores ausentes

    Anteriormente vimos el preprocesamiento de datos, sin embargo nos falto el manejo de los valores ausentes. La mayoría de las veces simplemente vamos eliminar estos registros, pero no siempre es buena opción, ya que si tenemos pocos registros eliminarlos puede ser una mala alternativa;  sin embargo podemos asignarle valores:

    • Imputar valores con media o mediana para datos continuos.
    • Imputar con la moda valores para datos categóricos.
    • Entrenar un modelo de regresión o predicción para asignar los valores faltantes.
    • Crear un algoritmo o técnica propia.

    Selección de atributos

    La selección de atributos permite trabajar con las columnas mas relevantes y eliminar ruido, esto genera modelos mas robustos.

    Vamos a ver uno de los modelos mas sencillos para ejemplificar la selección de atributos. El siguiente algoritmo cuenta con las siguientes características:

    • Selección de atributos univariante: Esto se refiere a que la selección tiene en cuenta los atributos de manera individual.
    • Selección no supervisada: No tiene en cuenta la clase.
    • El algoritmo selecciona por medio de un umbral definido: En este caso se establece un valor arbitrario, pero para hacerlo de manera correcta debemos tener el cuenta el tamaño del dataset y análisis estadísticos.

    También vamos a ver dos métricas de aprendizaje supervisado, es decir que tiene en cuenta la clase, y de selección multivariante.

    F-test: Pruebas de regresión lineal univariante que devuelven el estadístico F y los valores p (Dependencia lineal).

    Información mutua: entre dos variables aleatorias es un valor no negativo que mide la dependencia entre las variables. Es igual a cero si y sólo si dos variables aleatorias son independientes, y los valores más altos significan una mayor dependencia, además a diferencia de la métrica F-test esta tiene en cuenta la dependencia lineal y la no lineal.

    Como mencionamos inicialmente estos métodos son muy básicos, nos pueden servir para evaluaciones muy rápidas. Obviamente tenemos algoritmos mas robustos como los algoritmos de búsqueda o la misma PCA. Los veremos en otro post mas adelante.

  • Preprocesamiento de datos

    Preprocesamiento de datos

    En el anterior post vimos una introducción a la metodología CRISP-DM, que es una de las mas usadas en general para desarrollo de sistemas de inteligencia artificial. En este post vamos a continuar con ese flujo orientándolo al aprendizaje supervisado.

    Existe otra metodología muy similar pero orientada a Machine Learning, CRISP-ML(Q). Esta metodología comparte prácticamente todas las fases de la metodología de donde hereda sus características, pero se enfoca en el desarrollo de modelos de ML y agrega una fase al final; el monitoreo y mantenimiento de los modelos, ya que en el transcurso del tiempo podemos obtener mas data he irlo puliendo. Esto se conoce como evaluación continua del modelo.

    El aprendizaje supervisado tiene como principal característica el uso de registros de los cuales tenemos su clase(predicción) ya sea para un problema de regresión o clasificación. Con estos registros debidamente categorizados o predichos procederemos a recorrer todas las fases de la metodología CRISP-DM. En este post en particular empezaremos a adentrarnos en la parte mas técnica.

    Preparación de los datos

    Esta es una fase primordial, ya que de aquí depende en gran parte el éxito del proyecto. Una correcta limpieza o preprocesado de los datos permite exponer los patrones y características que luego extraerá el modelo.

    Normalización y estandarización

    Normalización

    La normalización permite centrar y escalar los datos, es decir, transformamos sus atributos en un rango continuo entre 0 y 1 mediante una operación matemática llamada homotecia.

    x_{i}^{N}=\begin{Bmatrix}\frac{x_{i,j}-min(x_i)}{max(x_i)-min(x_i)},\forall j\in1,\cdots ,n\end{Bmatrix}

    Este proceso es reversible con la formula contraria:

    x=x^{N}\cdot (max(x_i)-min(x_i))+min(x_i)

    Esta transformación es recomendada cuando se pretenden usar distancias o productos escalares. Veamos un ejemplo practico. Sklearn nos provee la mayoría de estos algoritmos ya funcionales, por lo que nos reduce el trabajo a solo utilizar sus métodos.

    Estandarización

    Consiste en hacer que los valores posean una media y desviación típica determinada, es decir que la media de loas valores sea igual a 0 y su desviación estándar igual a 1.

    x_{S}^{i}=\begin{Bmatrix}\frac{x_{i,j}-media(x_i)}{desv(x_i)},\forall j\in 1,\cdots ,n \end{Bmatrix}

    Este proceso es reversible con la formula contraria:

    x=x^{S}\cdot desv(x_i)+media(x_i)

    En el caso de querer hacer la reversión con SKLearn podemos usar la función inverse_transform

    La estandarización al no tener un rango acotado se vuelve menos sensible a los outliers.

    Outliers

    Este es uno de los problemas mas habituales, y se refiere a la presencia de valores anómalos, ya sea por errores de digitación, valores fuera de lo común o eventos inesperados que se registraron.

    Los outliners por lo general queremos identificarlos para eliminarlos o modificarlos, sin embargo no es una tarea sencilla cuando tenemos muchos datos. Tenemos muchas maneras de abordar el problema, desde una clasificación manual hasta algoritmos diseñados. Como en los anteriores ejemplos ya utilizamos SKLearn vamos a continuar por este rumbo. Esta librería nos provee varios métodos para la evaluación de outliners.

  • Razonamiento aproximado – Introducción

    Razonamiento aproximado – Introducción

    Desde la invención del perceptrón hemos avanzado muchísimo en el campo de la inteligencia artificial, el poder de computo y las técnicas para procesamiento de datos a crecido de manera extraordinaria y hoy en día tenemos modelos predictivos y generativos francamente impresionantes, cada día salen nuevas noticias e investigaciones de modelos de millones de parámetros, que si tienen conciencia (obviamente no), o que mejoran en predicciones y en general en lo que consideramos un comportamiento inteligente.

    Justamente la clave para analizar estos avances radica en nuestra concepción de inteligencia ¿Qué entendemos por inteligente? Por ejemplo, podemos decir que un sistema es inteligente por que nos permite diferenciar entre perritos y gatitos, pero si extrapolamos esto a un humano claramente no asumiríamos que una persona es inteligente solo por diferencias entre perros y gatos; ahora si llevamos esto a diferentes etapas del desarrollo humano, en especifico a la infancia temprana podemos decir que hay indicios de inteligencia. Entonces, definimos la inteligencia artificial como sistemas que replican comportamientos humanos que consideramos inteligentes.

    Teniendo en cuenta la premisa anterior debemos considerar que la inteligencia humana esta llena de incertidumbre e imprecisión, justamente la curiosidad es el mayor motor para el avance científico y es producto de un camino que recorremos hace miles de años, un proceso evolutivo y mental que queremos concluir por ejemplo en una teoría del todo, o en deserciones filosóficas para tratar de tener control y superar a la misma muerte (Si tiene curiosidad de por que digo esto vea este libro: Política para Amador). El punto del asunto es preguntarnos que tan relevante debería ser la incertidumbre en nuestros algoritmos; por eso se celebra un congreso para crear sistemas híbridos, dejando en claro que la inteligencia artificial no lo resuelve todo y que se necesita un acercamiento humano para entender y contextualizar los problemas; estamos acostumbrados a obtener grandes cantidades de datos y luego por medio de procesos estadísticos o métodos de inteligencia artificial inferir resultados y estimar predicciones, pero en estos procesos no se tiene en cuenta los sesgos humanos, coloquemos un ejemplo mas claro: imaginemos que se realiza una encuesta a diferentes poblaciones para determinar el nivel de felicidad, esto es muy subjetivo tanto para los encuestados como para los encuestadores, ya que los encuestadores por mas imparciales que pretendan ser interpretaran los datos a su propio contexto y por ejemplo no se tiene en cuenta la propia conducta y pensamiento humano; ahora podríamos decir que es por que nos falta variables, pero en si es imposible obtenerlas todas y ya veremos el por que.

    El universo en si es un sistema caótico, por mas modelos o representaciones que hagamos de el simplemente no alcanzamos a modelar la realidad, para poder predecir algo con suma certeza deberíamos tomar todo nuestro universo y descomponerlo en variables, crear una simulación completa del todo, lo cual es imposible ya que ni siquiera conocemos la totalidad del universo y avanzamos poco a poco pero parece que nunca alcanzaremos datos totalmente certeros; y es que esta es la magia de los sistemas caóticos, podemos medir tanto como queramos, aproximarnos a cantidades de errores infinitesimales y aun así no obtendremos la cantidad exacta, vivimos en la paradoja de Zenón.

    A pesar del caos muchas de nuestras mediciones y predicciones podemos hacerlas a partir de un contexto local, dándonos resultados muy buenos, este tipo de aproximaciones las trabajamos con la lógica difusa, que justamente considera las relaciones entre las variables de un contexto. Recuerdo un anécdota muy curioso de cuando la Nasa estrelló una sonda por una mala comunicación entre los ingenieros, esto demuestra que no solo es tomar datos y asumir que es suficiente, se debe hacer un análisis humano, a conciencia, previniendo y teniendo en cuenta nuestros sesgos y contextos.

    Las principales causas de incertidumbre son:

    • Insuficiente experiencia
    • Inadecuada representación del conocimiento
    • Información poco fiable
    • No completitud
    • Inexactitud inherente al lenguaje

    Sabemos que no podemos mitigar en su totalidad la incertidumbre pero podemos asociar niveles de confianza a la información, por ejemplo usando probabilidades o factores de certeza. Veamos algunos ejemplos de esto:

    Probabilidad

    Podemos modelar la incertidumbre a través del teorema de Bayes.

    *estos datos son ilustrativos
    P(S/M)=0,5 Probabilidad de tener Covid y fiebre
    P(M)=1/6 Probabilidad de tener Covid
    P(S)=1/20 Probabilidad de tener fiebre
    P(M/S)=(0,5)*(1/6)/(1/20)=1.6

    Como dijimos es muy difícil tener una certeza por que no tenemos todas las variables, además que debemos tener en cuenta las variables excluyentes también, ahí se nos va complicando la cosa.

    Valores de certeza

    Otra aproximación puede ser el uso de factores de certeza, estos son básicamente juicios dados por un experto e implementados correctamente puede facilitar muchísimo las estimaciones.

    Por ejemplo, con la pandemia si tenias tos y fiebre el valor de certeza de Covid era muy alto, los médicos señalaban casi con total seguridad de que se trataba de este virus.

    Los valores de certeza se dan en un intervalo de [-1,1], donde 1 indica completa confianza y -1 la no creencia. Veamos la definición matemática para calcular un valor de certeza. R1 y R2 son reglas que alcanzan una misma conclusión h, a partir de dos evidencias e_1 y e_2:

    R1: Si e_1 entonces h, CF(h,e_1)

    R2: Si e_2 entonces h, CF(h,e_2)

    El factor de certeza de h se calcula como:

    • CF(h,e_1)+CF(h,e_2)(1-CF(h,e_1)), si CF(h,e_1)>0CF(h,e_2)>0
    • CF(h,e_1)+CF(h,e_2)(1+CF(h,e_1)), si CF(h,e_1)<0 y CF(h,e_2)<0
    • [CF(h,e_1)+CF(h,e_2)]/(1-min(|CF(h,e_1)|,|CF(h,e_2)|), en cualquier otro caso

    Veamos unos ejemplos:

    R1: Si viernes entonces trafico, 0.8

    R2: Si llueve entonces trafico, 0.7

    h: Hoy es viernes y llueve ¿Cuál es la certeza de trafico?

    0.8+0.7*(1-0.8)=0.94

    *Se refuerza la certeza con ambas positivas

    R1: Si viernes entonces trafico, 0.8

    R2: Si fin de mes entonces trafico, -0.4

    h: Hoy es viernes y fin de mes ¿Cuál es la certeza de trafico?

    0.8+(-0.4)/(1-min(0.8,0.4))=0.66

    *Se disminuye la fuerza de la mayor

    Es importante tener presente las diferencias entre el enfoque probabilístico y los valores de certeza.

    Las probabilidades vienen a partir de la medición y calculo de los datos; por el contrario los factores de certeza son evaluaciones o apreciaciones personales.

    En resumen debemos quedarnos con que los modelos que realizamos son aproximaciones de la realidad y no son capaces de prevenir outliers. Estamos en un universo caótico y debemos tener en cuenta la incertidumbre. En próximos post veremos al detalle métodos que tratan de superar e incluso se apoyan en la incertidumbre.

  • Spring Boot – Configuración

    Spring Boot – Configuración

    Vimos anteriormente que se puede hacer la inyección de dependencias por medio de archivos xml y usando anotaciones; sin embargo también podemos usar clases de configuración para instanciar objetos de manera fácil y limpia.

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
     
    @Configuration
    public class AppConfig {
         
        @Bean("student")
        public Student getStudent(Service service) {
            return new StudentImpl(service);
        }
         
        @Bean("service")
        public Service getService() {
            return new ServiceImpl();
        }
    }

    La ventaja de este método es que permite liberar a las clases de negocio de anotaciones, dejándolas limpias.

    La clave es marcar la clase con el decorador @Configuration, es cual es procesado por el Spring IoC, que en este caso crea las instancias marcadas con @Bean.

    Veamos un ejemplo muy básico:

    1. Creamos una interfaz con un método de prueba:
      public interface Service {
          String hello();
      }
    2. Creamos la implementación del servicio:
      public class ServiceImpl implements Service {
          @Override
          public String hello() {
              return "Hola";
          }
      }
    3. Creamos el archivo de configuración:
      @Configuration
      public class Config {
          @Bean("service")
          public Service getService() {
              Service myService = new ServiceImpl();
              System.out.println(myService.hello());
              return myService;
          }
      }

      Lo que hacemos es instanciar la implementación e imprimir en consola el String que viene del método hello, lo que resulta que al ejecutar la aplicación veamos un “hola” en consola.

        .   ____          _            __ _ _
       /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
      ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
       \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
        '  |____| .__|_| |_|_| |_\__, | / / / /
       =========|_|==============|___/=/_/_/_/
       :: Spring Boot ::                (v2.7.0)
      
      Hola

    Al ser una clase Java obtenemos las ventajas propias del lenguaje, como asegurarnos del tipado correcto, comprobación en tiempo de compilación y algo mas amigable para la lectura.

    También si se desea, podemos usar las anotaciones en conjunto con con las clases de configuración.

¡Hola a todos los entusiastas de la tecnología! Quería informarles que en mi blog utilizamos cookies para mejorar la experiencia de usuario. Estas pequeñas herramientas nos ayudan a personalizar el contenido y ofrecer funciones específicas. Al continuar explorando el sitio, aceptas nuestro uso de cookies. Puedes obtener más información sobre cómo las utilizamos en nuestra política de privacidad. ¡Gracias por ser parte de esta comunidad tecnológica! 🍪    Más información
Privacidad