Caso de uso: seguimiento de envíos

Aprendizaje automático: cómo las incrustaciones simplifican los datos complejos

Trabajar con datos no numéricos puede ser difícil, incluso para científicos de datos con experiencia. Un modelo típico de aprendizaje automático espera que sus características sean números, no palabras, correos electrónicos, páginas de sitios web, listas, gráficos o distribuciones de probabilidad. Para ser útil, los datos deben transformarse primero en un espacio vectorial. ¿Pero cómo?

Un enfoque popular sería tratar una característica no numérica como categórica. Esto podría funcionar bien si el número de categorías es pequeño (por ejemplo, si los datos indican una profesión o un país). Sin embargo, si intentamos aplicar este método a los correos electrónicos, es probable que obtengamos tantas categorías como muestras. No hay dos correos electrónicos exactamente iguales, por lo tanto, este enfoque sería inútil.

Otro enfoque sería definir una distancia entre muestras de datos, una función que nos dice qué tan cerca están dos muestras. O podríamos definir un medida de similitud, lo que nos daría la misma información, excepto que la distancia entre dos muestras cercanas es pequeña, mientras que la similitud es grande. Calcular la distancia (similitud) entre todas las muestras de datos nos daría una matriz de distancia (o similitud). Estos son datos numéricos que podríamos usar.

Sin embargo, estos datos tendrían tantas dimensiones como muestras, lo que generalmente no es bueno si queremos usarlo como una característica (ver maldición de dimensionalidad) o para visualizarlo (mientras una parcela puede manejar incluso 6D, Todavía tengo que ver una trama 100D). ¿Podríamos reducir el número de dimensiones a una cantidad razonable?

¡La respuesta es sí! Eso es lo que tenemos incrustaciones para.

(Leer: Todo lo que necesitas saber sobre el aprendizaje de transferencia en IA)

¿Qué es una incrustación y por qué debería usarla?

Una incrustación es una representación de baja dimensión de datos de alta dimensión. Normalmente, una incrustación no capturará toda la información contenida en los datos originales. Sin embargo, una buena integración capturará lo suficiente para resolver el problema en cuestión.

Existen muchas incrustaciones adaptadas para una estructura de datos particular. Por ejemplo, es posible que hayas oído hablar de word2vec para datos de texto, o Descriptores de Fourier para datos de imagen de forma. En cambio, discutiremos cómo aplicar incrustaciones a cualquier dato donde podamos definir una distancia o una medida de similitud. Mientras podamos calcular una matriz de distancia, la naturaleza de los datos es completamente irrelevante. Funcionará igual, ya sean correos electrónicos, listas, árboles o páginas web.

En este artículo, le presentaremos diferentes tipos de incrustaciones y discutiremos cómo funcionan algunas incrustaciones populares y cómo podríamos usar incrustaciones para resolver problemas del mundo real que involucran datos complejos. También veremos los pros y los contras de este método, así como algunas alternativas. Sí, algunos problemas pueden resolverse mejor por otros medios, pero desafortunadamente, no hay una bala de plata en el aprendizaje automático.

Empecemos.

Cómo funcionan las incrustaciones

Todas las incrustaciones intentan reducir la dimensionalidad de los datos mientras preservan la información "esencial" en los datos, pero cada incrustación lo hace a su manera. Aquí, veremos algunas incrustaciones populares que se pueden aplicar a una matriz de distancia o similitud.

Ni siquiera intentaremos cubrir todas las incrustaciones que existen. Hay al menos una docena de incrustaciones bien conocidas que pueden hacer eso y muchas más incrustaciones menos conocidas y sus variaciones. Cada uno de ellos tiene su propio enfoque, ventajas y desventajas.

Si desea ver qué otras incrustaciones hay, puede comenzar aquí:

Matriz de distancia

Toquemos brevemente las matrices de distancia. Encontrar una distancia adecuada para los datos requiere una buena comprensión del problema, algunos conocimientos de matemáticas y a veces pura suerte. En el enfoque descrito en este artículo, ese podría ser el factor más importante que contribuye al éxito o fracaso general de su proyecto.

También debe tener en cuenta algunos detalles técnicos. Muchos algoritmos de integración supondrán que una distancia (o disimilitud) matriz <span id = "MathJax-Element-1-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "re"role =" presentation "tabindex =" 0 ">

tiene ceros en su diagonal y es simétrica. Si no es simétrico, podemos usar <span id = "MathJax-Element-2-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "(re+reT)/ /2"role =" presentation "tabindex =" 0 ">

en lugar. Algoritmos que usan el truco del grano también asumirá que una distancia es una métrica, lo que significa que la desigualdad del triángulo es válida:

<span id = "MathJax-Element-3-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "∀una,si,Cre(una,C)≤re(una,si)+re(si,C)"role =" presentation "tabindex =" 0 ">

Además, si un algoritmo requiere una matriz de similitud, podríamos aplicar cualquier función monótona decreciente para transformar una matriz de distancia en una matriz de similitud: por ejemplo, <span id = "MathJax-Element-4-Frame" class = "mjx- chtml MathJax_CHTML "data-mathml ="Exp-X"role =" presentation "tabindex =" 0 ">

Análisis de componentes principales (PCA)

Análisis de componentes principales, o PCA, es probablemente la incrustación más utilizada hasta la fecha. La idea es simple: Encuentre una transformación lineal de características que maximice la varianza capturada o (equivalentemente) minimice el error de reconstrucción cuadrática.

Específicamente, deje que las características sean una matriz de muestra <span id = "MathJax-Element-5-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "X∈Rnorte×pags"role =" presentation "tabindex =" 0 ">

tener <span id = "MathJax-Element-6-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "norte"role =" presentation "tabindex =" 0 "> características y <span id = "MathJax-Element-7-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "pags"role =" presentation "tabindex =" 0 "> dimensiones. Para simplificar, supongamos que la media de la muestra de datos es cero. Podemos reducir el número de dimensiones de <span id = "MathJax-Element-8-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "pags"role =" presentation "tabindex =" 0 "> <span id = "MathJax-Element-9-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "q"role =" presentation "tabindex =" 0 "> multiplicando <span id = "MathJax-Element-10-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "X"role =" presentation "tabindex =" 0 "> por una matriz ortonormal <span id = "MathJax-Element-11-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "Vq∈Rpags×q"role =" presentation "tabindex =" 0 ">:

<span id = "MathJax-Element-12-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "X^=XVq"role =" presentation "tabindex =" 0 ">

Entonces, <span id = "MathJax-Element-13-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "X^∈Rnorte×q"role =" presentation "tabindex =" 0 "> será el nuevo conjunto de características. Para asignar las nuevas características al espacio original (esta operación se llama reconstrucción), simplemente necesitamos multiplicarlo nuevamente por <span id = "MathJax-Element-14-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "VqT"role =" presentation "tabindex =" 0 ">.

Ahora, debemos encontrar la matriz <span id = "MathJax-Element-15-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "Vq"role =" presentation "tabindex =" 0 "> que minimiza el error de reconstrucción:

<span id = "MathJax-Element-16-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "minVqEl |El |XVqVqT-XEl |El |2"role =" presentation "tabindex =" 0 ">

Columnas de matriz <span id = "MathJax-Element-17-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "Vq"role =" presentation "tabindex =" 0 "> se llaman direcciones de componentes principales y las columnas de <span id = "MathJax-Element-18-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "X^"role =" presentation "tabindex =" 0 "> se llaman componentes principales. Numéricamente, podemos encontrar <span id = "MathJax-Element-19-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "Vq"role =" presentation "tabindex =" 0 "> aplicando SVD-descomposición a <span id = "MathJax-Element-20-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "X"role =" presentation "tabindex =" 0 ">, aunque hay otras formas igualmente válidas de hacerlo.

PCA se puede aplicar directamente a las características numéricas. O, si nuestras características no son numéricas, podemos aplicarlo a una matriz de distancia o similitud.

Si usa Python, PCA es implementado en scikit-learn.

La ventaja de este método es que es rápido de calcular y bastante robusto al ruido en los datos.

La desventaja sería que solo puede capturar estructuras lineales, por lo que es probable que se pierda la información no lineal contenida en los datos originales.

Kernel PCA

Kernel PCA es una versión no lineal de PCA. La idea es usar truco del grano, de lo que probablemente haya oído hablar si está familiarizado con Soporte de máquinas de vectores SVM.

Específicamente, existen algunas formas diferentes de calcular PCA. Una de ellas es calcular la descomposición propia de la versión de doble matriz de la matriz de gramo <span id = "MathJax-Element-21-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "XXT∈Rnorte×norte"role =" presentation "tabindex =" 0 ">. Ahora, si calculamos un matriz de grano <span id = "MathJax-Element-22-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "K∈Rnorte×norte"role =" presentation "tabindex =" 0 "> para nuestros datos, Kernel PCA lo tratará como una matriz de gramo para encontrar componentes principales.

Deje <span id = "MathJax-Element-23-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "Xyo"role =" presentation "tabindex =" 0 ">, <span id = "MathJax-Element-24-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "yo∈1,..,norte"role =" presentation "tabindex =" 0 "> ser las muestras de características. La matriz del núcleo se define mediante una función del núcleo <span id = "MathJax-Element-25-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "K(Xyo,Xj)=⟨ϕ(Xyo),ϕ(Xj)⟩"role =" presentation "tabindex =" 0 ">.

Una opción popular es un núcleo radial:

<span id = "MathJax-Element-26-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "K(Xyo,Xj)=Exp-γ⋅re(Xyo,Xj)"role =" presentation "tabindex =" 0 ">

donde <span id = "MathJax-Element-27-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "re"role =" presentation "tabindex =" 0 "> Es una función de distancia.

Kernel PCA nos requirió especificar una distancia. Por ejemplo, para las características numéricas, podríamos usar la distancia euclidiana: <span id = "MathJax-Element-28-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "re(Xyo,Xj)=El |El |Xyo-XjEl |El |2"role =" presentation "tabindex =" 0 ">.

Para las características no numéricas, es posible que necesitemos ser creativos. Una cosa para recordar es que este algoritmo supone que nuestra distancia es una métrica.

Si usa Python, Kernel PCA es implementado en scikit-learn.

La ventaja del método Kernel PCA es que puede capturar estructuras de datos no lineales.

La desventaja es que es sensible al ruido en los datos y que la elección de las funciones de distancia y kernel afectará en gran medida los resultados.

Escalamiento multidimensional (MDS)

Escalamiento multidimensional (MDS) intenta preservar las distancias entre muestras a nivel mundial. La idea es bastante intuitiva y funciona bien con matrices de distancia.

Específicamente, las muestras de características dadas <span id = "MathJax-Element-29-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "Xyo"role =" presentation "tabindex =" 0 ">, <span id = "MathJax-Element-30-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "yo∈1,..,norte"role =" presentation "tabindex =" 0 "> y una función de distancia <span id = "MathJax-Element-31-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "re"role =" presentation "tabindex =" 0 ">, calculamos nuevas muestras de características <span id = "MathJax-Element-32-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "zyo∈Rq"role =" presentation "tabindex =" 0 ">, <span id = "MathJax-Element-33-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "yo∈1,..,norte"role =" presentation "tabindex =" 0 "> minimizando un función de estrés:

<span id = "MathJax-Element-34-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "minz1,..,znorte∑1≤yo<j≤norte(re(Xyo,Xj)-El |El |zyo-zjEl |El |)2"role =" presentation "tabindex =" 0 ">

Si usa Python, MDS es implementado en scikit-learn. Sin embargo, scikit-learn no admite la transformación de puntos fuera de muestra, lo que podría ser un inconveniente si queremos utilizar una incrustación junto con un modelo de regresión o clasificación. En principio, sin embargo, es posible.

La ventaja de MDS es que su idea concuerda perfectamente con nuestro marco y que no se ve muy afectado por el ruido en los datos.

La desventaja es que su implementación en scikit-learn es bastante lenta y no admite la transformación fuera de la muestra.

Caso de uso: seguimiento de envíos

Algunos asentamientos en una pequeña isla tropical han desarrollado servicios de envío de paquetes para atender a la industria turística local. Un comerciante en uno de estos asentamientos decidió tomar medidas para obtener una ventaja sobre la competencia, por lo que estableció un sistema de vigilancia por satélite que rastrea todos los envíos de paquetes en la isla. Una vez que se recopilaron los datos, el comerciante llamó a un científico de datos (¡eso somos nosotros!) Para ayudarlo a responder la siguiente pregunta: ¿Podemos predecir el destino de un paquete que está actualmente en ruta?

El conjunto de datos contiene información sobre 200 envíos rastreados. Para cada envío rastreado, hay una lista de coordenadas (x, y) de todas las ubicaciones donde se detectó el paquete, que generalmente se encuentra entre 20 y 50 observaciones. La siguiente gráfica muestra cómo se ven estos datos.

Caso de uso: seguimiento de envíos

Estos datos parecen problemas, dos tipos diferentes de problemas, en realidad.

El primer problema es que los datos que estamos tratando son de alta dimensión. Por ejemplo, si cada paquete se detectara en 50 ubicaciones, nuestros datos tendrían 100 dimensiones, suena como mucho, en comparación con las 200 muestras a su disposición.

El segundo problema: las diferentes rutas de envío en realidad tienen un número diferente de observaciones, por lo que no podemos simplemente apilar las listas con coordenadas para representar los datos en forma de tabla (e incluso si lo hubieran hecho, eso todavía no tendría sentido).

El comerciante tamborilea impacientemente la mesa con los dedos, y el científico de datos está tratando de no mostrar signos de pánico.

Aquí es donde las matrices de distancia y las incrustaciones serán útiles. Solo necesitamos encontrar una manera de comparar dos rutas de envío. Distancia Fréchet Parece ser una opción razonable. Con una distancia, podemos calcular una matriz de distancia.

Nota: Este paso puede llevar un tiempo. Necesitamos calcular <span id = "MathJax-Element-35-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "O(norte2)"role =" presentation "tabindex =" 0 ">

distancias con cada distancia que tiene <span id = "MathJax-Element-36-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "O(k2)"role =" presentation "tabindex =" 0 "> iteraciones, donde <span id = "MathJax-Element-37-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "norte"role =" presentation "tabindex =" 0 "> es el número de muestras y <span id = "MathJax-Element-38-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "k"role =" presentation "tabindex =" 0 ">

es el número de observaciones en una muestra. Escribir una función de distancia de manera eficiente es clave. Por ejemplo, en Python, podría usar numba para acelerar este cálculo muchas veces.

Visualizar incrustaciones

Ahora, podemos usar una incrustación para reducir la cantidad de dimensiones de 200 a unas pocas. Podemos ver claramente que solo hay unas pocas rutas comerciales, por lo que podemos esperar encontrar una buena representación de los datos, incluso en dos o tres dimensiones. Utilizaremos las incrustaciones que discutimos anteriormente: PCA, Kernel PCA y MDS.

En los gráficos a continuación, puede ver los datos de ruta etiquetados (dados en aras de la demostración) y su representación mediante una incrustación en 2D y 3D (de izquierda a derecha). Los datos etiquetados marcan cuatro puestos comerciales conectados por seis rutas comerciales. Dos de las seis rutas comerciales son bidireccionales, lo que hace ocho grupos de envío en total (6 + 2). Como puede ver, obtuvimos una separación bastante clara de los ocho grupos de envío con incrustaciones en 3D.

Visualización de incrustaciones "ancho =" 731 "altura =" 719

Este es un buen comienzo.

Incrustaciones en una tubería modelo

Ahora, estamos listos para entrenar una incrustación. Aunque MDS mostró los mejores resultados, es bastante lento; Además, la implementación de scikit-learn no admite la transformación fuera de la muestra. No es un problema para la investigación, pero puede ser para la producción, por lo que utilizaremos Kernel PCA. Para Kernel PCA, no debemos olvidar aplicar un kernel radial a la matriz de distancia de antemano.

¿Cómo selecciona el número de dimensiones de salida? El análisis mostró que incluso el 3D funciona bien. Solo para estar seguros y no omitir ninguna información importante, configuremos la salida de incrustación en 10D. Para obtener el mejor rendimiento, la cantidad de dimensiones de salida se puede establecer como un hiperparámetro del modelo y luego ajustarse mediante validación cruzada.

Entonces, tendremos 10 características numéricas que podemos usar como entrada para casi cualquier modelo de clasificación. ¿Qué tal un modelo lineal y uno no lineal: digamos, Regresión logística y aumento de gradiente? A modo de comparación, también usemos estos dos modelos con una matriz de distancia completa como entrada. Además, también vamos a probar SVM (SVM está diseñado para trabajar directamente con una matriz de distancia, por lo que no será necesario incrustarlo).

La precisión del modelo en el conjunto de prueba se muestra a continuación (se generaron 10 conjuntos de datos de tren y prueba para que podamos estimar la varianza del modelo):

  • Aumento de gradiente emparejado con una incrustación (KernelPCA + GB) obtiene el primer lugar. Superó a Gradient Boosting sin incrustación (GB). Aquí, Kernel PCA demostró ser útil.
  • Regresión logística hizo bien Lo interesante es que la regresión logística sin incrustación (LR) funcionó mejor que con una incrustación (KernelPCA + LR). Esto no es del todo inesperado. Los modelos lineales no son muy flexibles pero relativamente difíciles de sobreajustar. Aquí, la pérdida de información causada por una incrustación parece superar el beneficio de una menor dimensionalidad de entrada.
  • Por último, si bien no menos importante, SVM funcionó bien también, aunque la varianza de este modelo es bastante significativa.

Precisión del modelo

Precisión del modelo

El código de Python para este caso de uso está disponible en GitHub.

Explicamos qué son las incrustaciones y demostramos cómo se pueden usar junto con matrices de distancia para resolver problemas del mundo real. Hora del veredicto:

¿Son las incrustaciones algo que un científico de datos debería usar? Echemos un vistazo a ambos lados de la historia.

Pros y contras del uso de incrustaciones

Pros:

  • Este enfoque nos permite trabajar con estructuras de datos inusuales o complejas siempre que pueda definir una distancia que, con cierto grado de conocimiento, imaginación y suerte, generalmente puede.
  • El resultado son datos numéricos de baja dimensión, que puede analizar, agrupar o usar fácilmente como características de modelo para prácticamente cualquier modelo de aprendizaje automático.

Contras:

  • Usando este enfoque, necesariamente perderemos cierta información:
    • Durante el primer paso, cuando reemplazamos los datos originales con una matriz de similitud
    • Durante el segundo paso, cuando reducimos la dimensionalidad usando una incrustación
  • Dependiendo de los datos y la función de distancia, el cálculo de una matriz de distancia puede llevar mucho tiempo. Esto puede ser mitigado por una función de distancia escrita de manera eficiente.
  • Algunas incrustaciones son muy sensibles al ruido en los datos. Esto puede ser mitigado por la limpieza de datos adicionales.
  • Algunas incrustaciones son sensibles a la elección de sus hiperparámetros. Esto puede mitigarse mediante un análisis cuidadoso o un ajuste de hiperparámetros.

Alternativas: ¿por qué no usar …?

  • ¿Por qué no usar una incrustación directamente en los datos, en lugar de una matriz de distancia?
    Si conoce una incrustación que pueda codificar eficientemente sus datos directamente, utilícela por todos los medios. El problema es que no siempre existe.
  • ¿Por qué no simplemente usar la agrupación en una matriz de distancia?
    Si su único objetivo es segmentar su conjunto de datos, sería totalmente correcto hacerlo. Algunos métodos de agrupación también aprovechan las incrustaciones (por ejemplo, Agrupación espectral) Si desea obtener más información, aquí está un tutorial sobre clusterización.
  • ¿Por qué no solo usar una matriz de distancia como características?
    El tamaño de una matriz de distancia es <span id = "MathJax-Element-39-Frame" class = "mjx-chtml MathJax_CHTML" data-mathml = "(nortesunametropagslmis,nortesunametropagslmis)"role =" presentation "tabindex =" 0 ">
  • No todos los modelos pueden manejarlo de manera eficiente: algunos pueden sobreajustarse, algunos pueden ser lentos para adaptarse, algunos pueden no encajar todos juntos. Los modelos con baja varianza serían una buena opción aquí, como los modelos lineales y / o regularizados.
  • ¿Por qué no solo usar SVM con una matriz de distancia?
    SVM es un gran modelo, que funcionó bien en nuestro caso de uso. Sin embargo, hay algunas advertencias. Primero, si queremos agregar otras funciones (podrían ser simples números numéricos), no podremos hacerlo directamente. Tendríamos que incorporarlos a nuestra matriz de similitud y potencialmente perder información valiosa. Segundo, tan bueno como SVM es, otro modelo puede funcionar mejor para su problema particular.
  • ¿Por qué no solo usar el aprendizaje profundo?
    Es verdad, para cualquier problema, puede encontrar una red neuronal adecuada si buscas lo suficiente Sin embargo, tenga en cuenta que el proceso de encontrar, entrenar, validar e implementar esta red neuronal no será necesariamente simple. Entonces, como siempre, usa tu mejor juicio.

Las incrustaciones junto con las matrices de distancia son una herramienta increíblemente útil si trabaja con datos no numéricos complejos, especialmente cuando no puede transformar sus datos en un espacio vectorial directamente y prefiere tener una entrada de baja dimensión para su modelo.

los Blog de ingeniería de Toptal es un centro para tutoriales de desarrollo en profundidad y anuncios de nuevas tecnologías creados por ingenieros de software profesionales en la red de Toptal. Puedes leer la pieza original escrita por Yaroslav Kopotilov aquí. Siga el Blog de ingeniería de Toptal en Gorjeo y LinkedIn.

Publicado el 24 de julio de 2020 – 06:30 UTC

Deja un comentario