English Русский 中文 Deutsch 日本語 Português
preview
Interpretación de modelos: Una comprensión más profunda de los modelos de aprendizaje automático

Interpretación de modelos: Una comprensión más profunda de los modelos de aprendizaje automático

MetaTrader 5Aprendizaje automático | 30 mayo 2024, 12:49
193 0
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Introducción

En el aprendizaje automático, con frecuencia debemos hacer concesiones. Optimizando una métrica, a menudo empeoramos otra. A medida que se crean modelos más grandes y complejos, comprenderlos, explicarlos y depurarlos se convierte en una tarea cada vez más compleja. Las características ocultas del modelo resultan vitales para descifrar por qué nuestros modelos toman determinadas decisiones. Sin esta claridad, ¿cómo podremos creer con confianza que podemos gestionar este modelo para alcanzar los objetivos deseados? No podemos permitir que el modelo funcione mal o nuestros esfuerzos serán en vano. En este artículo:

  1. Identificaremos las características más importantes: qué características considera importantes el modelo de usuario.

  2. Descifraremos el impacto de una característica individual: entenderemos cómo afecta cada característica al rendimiento del modelo de usuario.

  3. Contabilizaremos el impacto de las funciones colectivas, explorando una influencia más amplia de las funciones en las predicciones de los modelos.

El artículo revelará los entresijos del aprendizaje automático, lo cual nos permitirá comprender mejor y modificar el comportamiento del modelo. Los conocimientos que adquiera le permitirán optimizar sus esfuerzos al trabajar con el aprendizaje automático.


Por qué esto es importante.

Depuración:

Fig. 1. El arte de depurar

"Errar es humano, perdonar es divino" ~ Alexander Pope

La depuración puede parecer algo a primera vista mundano, pero no se puede exagerar su importancia. Imagínese la de errores escurridizos que pasamos por alto en la fase de ejecución. Los conocimientos que ofrece este artículo le ayudarán a descifrar los intrincados patrones que tejen sus modelos. Así, podrá ver si estos patrones armonizan con su comprensión del mundo real. En el laberinto de proyectos de la vida real, podrá rastrear y eliminar hábilmente sus propios errores, adquiriendo la experiencia necesaria.

Desarrollo de funciones mejorado:

Desarrollo de funciones

Fig. 2. Desarrollo de funciones

"La mejora continua es mejor que la perfección tardía" ~ Mark Twain

Ahora vamos a abordar el desarrollo de funciones. Imagine un círculo. Trace una línea roja sobre su diámetro. ¿Cuántas veces puede su diámetro dar la vuelta a la circunferencia de un círculo? La respuesta, claro, es alrededor de 3.145 veces. Es una constante que todos conocemos por el número Pi.

Este experimento mental nos servirá de guía y pondrá de relieve el impacto de la presentación en nuestra capacidad de aprendizaje. De la misma manera que la curvatura de nuestro círculo afecta a su forma, las transformaciones de los objetos mejorarán la armonía de nuestro conjunto de datos. Al crear nuevas columnas, iremos más allá de lo ordinario, llevando la precisión de nuestras previsiones a cotas extraordinarias. Y aquí es donde la intuición se convertirá en nuestra brújula, guiándonos por aguas desconocidas. Pero, ¿qué ocurrirá cuando falle la intuición? No hay por qué preocuparse. Tenemos estrategias para navegar incluso por las rutas más confusas. Pero no nos quedaremos ahí, seguiremos midiendo empíricamente la eficacia de las nuevas funciones.


Gestión de la futura recogida de datos:

Fig. 3. Mejora de la recogida de datos


"Si quieres conocer el futuro, mira al pasado" ~ Albert Einstein

Cuando trabajamos con datos, debemos recordar el viejo dicho: la clave del futuro está en el pasado. ¿Se han agotado nuestras capacidades de desarrollo de funciones? En un mundo de datos, el pasado será nuestro faro. Los nuevos tipos de datos nos atraen y prometen llenar de vida nuestros modelos. La comprensión, nuestra fiel compañera, nos servirá de mediadora, guiándonos hasta las piedras preciosas del tesoro de los datos. Con cada conocimiento adquirido, nuestro camino hacia nuevas funciones se hará más claro.

Mejora de la toma de decisiones:

Fig. 4. Mejora de la toma de decisiones

"Aprender poco es peligroso" ~ Alexander Pope

En la sinfonía del aprendizaje automático, nosotros somos el director. El modelo bailará a nuestro son, dando testimonio de las decisiones que insuflan vida a nuestras previsiones. El aprendizaje automático va más allá de las simples predicciones. Nuestra comprensión, nuestra habilidad, formarán la base sobre la que se asentará nuestra ambición. Cada percepción afectará a nuestros esfuerzos.


Teoría

En este artículo, nuestro objetivo será utilizar el modelo de árbol con gradiente reforzado (gradient boosted tree model) disponible en la biblioteca CatBoost Python para realizar análisis de regresión de precios. No obstante, desde el principio surge un problema digno de mención que exige un examen más detenido del modelo. Antes de profundizar en la aplicación de las técnicas de explicación de la "caja negra" a nuestro modelo, deberemos reconocer las limitaciones de nuestro modelo de "caja negra" y la razón de ser del bloque de explicación de la misma (explaniers) en este contexto.

Los árboles con gradiente reforzado muestran un buen rendimiento en tareas de clasificación. Sin embargo, muestran claras limitaciones al aplicarse a problemas específicos de regresión de series temporales. Estos árboles, pertenecientes a la familia de los modelos de aprendizaje automático, clasifican los datos de entrada en grupos según el valor objetivo. Posteriormente, el algoritmo calcula el valor objetivo medio dentro de cada grupo y usa estas medias de grupo para la predicción. Cabe destacar que estos promedios de grupo establecidos durante el entrenamiento, permanecen invariables hasta que se realiza un nuevo entrenamiento. De esta naturaleza fija surge una desventaja crítica, ya que los árboles con gradiente reforzado suelen tener dificultades para extrapolar tendencias de forma eficiente. Cuando el modelo encuentra valores de entrada fuera del dominio de aprendizaje, tiende a hacer predicciones repetidas, basándose en valores medios derivados de grupos conocidos, que pueden no reflejar con precisión la tendencia básica fuera del rango de aprendizaje observado.

Además, el modelo asume que valores similares de las características conducirán a valores similares de los objetivos, lo cual resulta contrario a nuestra experiencia colectiva de negociación con instrumentos financieros. En los mercados financieros, los patrones de precios pueden mostrar semejanzas, aunque terminen en puntos diferentes. Esta discrepancia cuestiona el supuesto del modelo de que el proceso generativo produce datos que entran en grupos homogéneos. Por ello, la violación de estos supuestos provocará un desplazamiento en nuestro modelo.

Para corroborar dichas observaciones, haremos una demostración para los lectores que no hayan observado el fenómeno por sí mismos. Nuestro objetivo será ofrecer una comprensión global a todos los lectores.

Empezaremos cargando las dependencias necesarias

#pip install pandas if you haven't installed it allready
#We'll use pandas to store and retrieve data
import pandas as pd       

#pip install pandas-ta if you haven't installed it allready
#We'll use pandas_ta to calculate technical indicators
import pandas_ta as ta    

#pip install numpy if you haven't installed it allready
#We'll use numpy to perform optmized vector calculations 
import numpy as np

import matplotlib.pyplot as plt

#pip install numpy if you haven't installed it allready
#We'll use MetaTrader 5 connect to and control our MetaTrader 5 Terminal 
import MetaTrader5 as MT5

#Standard python library
import time
A continuación, introduciremos nuestras datos de entrada
login = enter_your_login
password =  enter_your_password
server = enter_your_broker_server
Luego inicializaremos nuestro terminal MetaTrader 5 e iniciaremos sesión.
if(MT5.initialize(login=login, password= password, server=server)):
    print("Logged in succesfully")
else:
    print("Failed to initialize the terminal and login")
La autorización ha tenido éxito
Ahora consultaremos un millón de filas de datos M1 según el índice de volatilidad 75 o cualquier otro símbolo que usted prefiera.

data = pd.DataFrame(MT5.copy_rates_from_pos("Volatility 75 Index",MT5.TIMEFRAME_M1,0,100000))
data

Datos de mercado

Fig. 5. Nuestros datos de mercado del terminal MetaTrader 5

Calcularemos los indicadores técnicos que pueden ayudarnos a pronosticar el precio.

#20 period exponential moving average
data["ema_20"] = data.ta.ema(length=20)
#40 period exponential moving average
data["ema_40"] = data.ta.ema(length=40)
#100 period exponential moving average
data["ema_100"] = data.ta.ema(length=100)
#20 period relative strength indicator
data.ta.rsi(length=20,append=True)
#20 period bollinger bands with 3 standard deviations
data.ta.bbands(length=20,sd=3,append=True)
#14 period average true range
data.ta.atr(length=14,append=True)
#Awesome oscilator with default settings
data.ta.ao(append=True)
#Moving average convergence divergence (MACD)
data.ta.macd(append=True)
#Chaikins commidity index
data.ta.cci(append=True)
#Know sure thing oscilator
data.ta.kst(append=True)
#True strength index
data.ta.tsi(append=True)
#Rate of change
data.ta.roc(append=True)
#Slope between 2 points
data.ta.slope(append=True)
#Directional movement
data.ta.dm(append=True)

Configuramos los objetivos

data["target"] = data["close"].shift(-30)

Configuremos nuestro modelo de "caja negra"

from catboost import CatBoostRegressor

Preparamos los splits de entrenamiento y prueba

train_start = 100
train_end   = 10000

test_start = train_end + 100
test_end = test_start + 30000

predictors = [
    "open",
    "high",
    "low",
    "close",
    "KSTs_9",
    "KST_10_15_20_30_10_10_10_15",
    "CCI_14_0.015",
    "AO_5_34",
    "ATRr_14",
    "BBM_20_2.0",
    "BBP_20_2.0",
    "BBB_20_2.0",
    "BBU_20_2.0",
    "BBL_20_2.0",
    "RSI_20",
    "ema_20",
    "ema_40",
    "ema_100",
    "SLOPE_1",
    "ROC_10",
    "TSIs_13_25_13",
    "TSI_13_25_13",
    "MACD_12_26_9",
    "MACDh_12_26_9",
    "MACDs_12_26_9",
    "DMP_14",
    "DMN_14"
]
target = "target"
Los árboles de decisión son sensibles a la escala, por lo que normalizaremos los valores de entrada y almacenaremos las primeras lecturas de cada objeto en este array llamado first_values.
first_values = {}
#Iterating over the columns in the dataset
for col in data.columns:
    #Which of those columns are part of the model inputs?
    if col in predictors:
        #What was the first value in that column?
        first_values[col] = data[col][train_start]
        data[col] = data[col]/first_values[col]

Luego realizaremos un split de prueba de Train

train_x = data.loc[train_start:train_end,predictors]
train_y = data.loc[train_start:train_end,target]

test_x = data.loc[test_start:test_end,predictors]
test_y = data.loc[test_start:test_end,target]
Después instalaremos nuestro modelo de "caja negra"

cat_full = CatBoostRegressor()
cat_full.fit(train_x,train_y)
Y obtendremos las predicciones a partir de nuestro modelo de "caja negra"
cat_full_predictions = pd.DataFrame(index=test_x.index)
cat_full_predictions["predictions"] = cat_full.predict(test_x)
cat_full_predictions.plot(label=True)
test_y.plot()

Predicción de "caja negra"

Fig. 6. Nuestra predicción de la "caja negra"


En una primera observación, resulta evidente que el modelo de predicción presenta periodos planos atípicos. Dada nuestra exhaustiva revisión de la implementación típica de los algoritmos mejorados con gradiente, estos patrones resultan bastante esperables. Queremos averiguar qué características tienen un impacto positivo en el rendimiento de nuestro modelo y cuáles son fuentes potenciales de ruido. Para ello, deberemos considerar la capacidad de diseño de las funciones.

Para desentrañar estos matices, le proponemos utilizar un bloque explicativo de "caja negra". No obstante, antes de aplicar ciegamente estas explicaciones, será necesario comprender los mecanismos básicos del algoritmo de bloques de explicación de la "caja negra". Esto implicará una evaluación crítica de los supuestos en los que se basa, lo cual nos permitirá determinar si se cumplen o pueden incumplirse.

Abordar la aplicación de las técnicas de explicación de la "caja negra" considerando esta comprensión subyacente nos permitirá interpretar cada explicación de forma inteligente. Si examinamos detenidamente los métodos de explicación y sopesamos su pertinencia, podremos atribuir a las conclusiones los niveles de confianza correspondientes. Este enfoque metódico mejorará nuestra capacidad para extraer información significativa y tomar decisiones fundamentadas basadas en los resultados del proceso de explicación de la "caja negra".


Algoritmos para explicar la "caja negra"

Importancia de la eliminación de columnas (Drop Column Importance):

El método de la importancia de la eliminación de columnas se usa para evaluar la precisión del modelo considerando inicialmente todos los predictores y, a continuación, eliminando de forma iterativa una sola columna, teniendo en cuenta el efecto resultante sobre la precisión. Este enfoque ofrece información valiosa sobre la contribución específica de cada columna al rendimiento global del modelo.

El método se caracteriza por ser práctico y razonable. La hipótesis en la que se basa este método se corresponde con situaciones reales en las que a menudo se producen incoherencias en los datos. Ya sea por cortes de la conectividad a Internet, cortes de electricidad, condiciones meteorológicas adversas u otros imprevistos, la metodología simula un modelo sólido que refleja diferentes sucesos en un entorno operativo real. Este realismo aumentará la aplicabilidad y eficacia del método al considerar escenarios que pueden encontrarse en situaciones prácticas cotidianas.

Ventajas:

  • Mejora del rendimiento del modelo: la eliminación de columnas innecesarias o redundantes puede mejorar el rendimiento de los modelos de aprendizaje automático al reducir el ruido y mejorar la relación señal/ruido.
  • Modelo simplificado: la eliminación de columnas innecesarias puede dar lugar a modelos más simples e interpretables, lo cual facilitará su comprensión y explicación por parte de los interesados.

Desventajas:

  • Pérdida de información: la supresión de una columna puede provocar la pérdida de información valiosa, creando potencialmente un modelo excesivamente simplificado que no capte patrones importantes en los datos.
  • Repercusión en los procesos posteriores: si una columna se usa en análisis posteriores o es necesaria para determinados procesos empresariales, su eliminación puede interrumpir esos flujos de trabajo.

Posibilidades:

  • Desarrollo de características: la eliminación de una columna puede ofrecer la oportunidad de desarrollar características, lo cual permitirá crear nuevas características a partir de los datos existentes o modificar las características restantes para mejorar el rendimiento del modelo.
  • Optimización de recursos: la eliminación de columnas innecesarias puede suponer un ahorro de recursos en términos de memoria, almacenamiento y tiempo de procesamiento, especialmente con grandes conjuntos de datos.

Posibles problemas:

  • Desplazamiento del modelo: si una columna suprimida contiene información importante para las predicciones objetivas, su supresión puede sesgar el modelo, dando lugar a resultados inexactos.
  • Problema de integridad de los datos: la eliminación de columnas sin un conocimiento completo de los datos puede provocar problemas de integridad, afectando a la calidad general del conjunto de datos y a los análisis posteriores.


Importancia de la permutación (Permutation Importance):

La importancia de la permutación ofrece un método alternativo para estimar la importancia de una función permutando aleatoriamente los valores de una columna concreta y evaluando la influencia resultante en las métricas de error del modelo. La idea básica se basa en la suposición de que si una columna desempeña un papel significativo a la hora de influir en el modelo, la infracción de sus valores iniciales debería provocar un aumento de las tasas de error y una reducción de la precisión global. Por el contrario, si la influencia de la columna es mínima, los cambios observados serán limitados y en algunos casos incluso podría haber una mejora del rendimiento.

Este método ofrece una visión detallada de la importancia de las características, permitiendo una evaluación dinámica de la contribución de cada característica al poder predictivo del modelo. El proceso de permutación introduce un nivel de aleatoriedad que ayuda a revelar la sensibilidad del modelo a las características individuales, permitiéndonos una comprensión más completa de su importancia en el sistema de previsión.

Ventajas:

  • Independencia del modelo: la importancia de la permutación es independiente del modelo, es decir, puede aplicarse a cualquier modelo de aprendizaje supervisado sin suposiciones sobre el algoritmo básico. Esto lo convierte en un método versátil y de uso amplio.
  • Interpretación intuitiva: el concepto de importancia de las permutaciones resulta relativamente fácil de entender. Mide el cambio en el rendimiento del modelo cuando los valores de una característica concreta se reordenan aleatoriamente, lo cual ofrece una interpretación clara de la importancia de la característica.

Desventajas:

  • Intensidad computacional: el cálculo de la importancia de las permutaciones implica estimar nuevamente el rendimiento del modelo para cada permutación de características, lo cual hace que la computación resulte intensiva y potencialmente lenta, especialmente con grandes conjuntos de datos.
  • Sensibilidad al tamaño de la muestra: la importancia de la permutación puede depender del tamaño del conjunto de datos. Con conjuntos de datos pequeños, la influencia de la permutación de objetos puede ser exagerada, lo cual lleva a estimaciones de importancia menos fiables.

Posibilidades:

  • Guía de selección de características: los resultados sobre la importancia de la permutación pueden ayudar en la selección de características determinando qué características tienen mayor impacto en el rendimiento del modelo. Esta información puede resultar útil para simplificar los modelos y reducir la dimensionalidad.
  • Identificación de relaciones no lineales: a diferencia de los modelos lineales, la importancia de las permutaciones puede captar relaciones no lineales entre las características y la variable objetivo, lo cual permite comprender patrones complejos en los datos.

Posibles problemas:

  • Impacto de las funciones correlacionadas: la importancia de la permutación puede que no se adapte bien a situaciones en las que las funciones están fuertemente correlacionadas. Si dos características están correlacionadas, la reordenación de una de ellas podría tener un efecto insignificante en el rendimiento del modelo si la otra característica sigue ofreciendo información similar.
  • Posibilidad de sobreentrenamiento: en algunos casos existe el riesgo de sobreentrenamiento (ajuste), sobre todo si el modelo es demasiado complejo o si el conjunto de datos es pequeño. Es posible que las estimaciones de importancia no se generalicen bien a los nuevos datos.

Gráficos de dependencia parcial (Partial Dependence Plots, PDP) y expectación condicional individual (Individual Conditional Expectation, ICE):

Los gráficos ofrecen una comprensión más detallada del comportamiento del modelo. Los gráficos de dependencia parcial ilustran cómo evoluciona un resultado previsto a medida que cambia un factor predictivo mientras se mantienen constantes todos los demás. Por su parte, los gráficos ICE ofrecen una visión detallada de la importancia de las características al presentar curvas separadas para cada caso, lo cual facilitará un análisis exhaustivo del impacto de cada característica.

Juntos, PDP e ICE Plots ofrecen una sólida representación visual más allá de las tendencias añadidas. Los PDP proponen una visión global de la relación entre un predictor concreto y las predicciones del modelo, mientras que los gráficos de ICE profundizan en los matices presentando un conjunto de curvas, cada una de las cuales representa el impacto individual de ese predictor en diferentes casos. Este enfoque combinado mejora nuestra capacidad para discernir patrones complejos y las variaciones en la respuesta del modelo a diferentes valores de predicción, lo que contribuye a una comprensión más profunda de la importancia de las características en el marco general de predicción.

Ventajas:

  • Interpretabilidad: Los PDP ofrecen una representación intuitiva y visual de la relación entre una función y un resultado previsto, lo cual facilita a los no expertos la interpretación y comprensión del impacto de una función concreta en las predicciones del modelo.
  • Identificación de patrones: Los PDP pueden ayudar a identificar patrones y tendencias en la relación entre una característica y un resultado predicho, permitiendo una comprensión más profunda de cómo los cambios en un característica afectan a las predicciones del modelo.

Desventajas:

  • Asunción de independencia: Los PDP asumen que la función de interés es independiente de otras funciones. En modelos complejos con características correlacionadas, la interpretación del PDP puede resultar difícil y los gráficos pueden no reflejar con exactitud las verdaderas relaciones.
  • Limitación por efecto marginal: Los PDP muestran el efecto marginal de una función manteniendo fijas las demás funciones. Puede que no capten las complejas interacciones entre múltiples funciones, lo cual limita su capacidad para revelar toda la complejidad del modelo.

Posibilidades:

  • Validación del modelo: El PDP puede utilizarse como herramienta de validación de modelos. Comparando la información del PDP con los conocimientos o las expectativas del dominio de la materia, los profesionales pueden evaluar si el modelo se ajusta al comportamiento esperado de las funciones.
  • Clasificación de la importancia de las funciones: Los PDP pueden ayudar a clasificar la importancia de las características resaltando visualmente las que muestran un impacto más significativo en las predicciones del modelo. Esta información podría ayudar a seleccionar características y simplificar el modelo.

Posibles problemas:

  • Posibilidad de interpretaciones erróneas: sin una comprensión adecuada de los conceptos estadísticos, existe el riesgo de interpretaciones erróneas. Los usuarios pueden atribuir de forma errónea relaciones causales a las relaciones observadas, especialmente si desconocen posibles variables distorsionadoras o complejidades subyacentes del modelo.
  • Complejidad de los datos multidimensionales: El PDP resulta difícil de interpretar en espacios multidimensionales debido a la explosión combinatoria de posibles combinaciones de funciones. La visualización de las interacciones entre funciones resulta cada vez más compleja.


Los valores SHAP (Shapley Additive Explanations, explicaciones aditivas de Shapley):


Lloyd Shepley

Fig. 7. En memoria de Lloyd Shepley, fallecido el 12 de marzo de 2016 en Tucson, Arizona. Sus ideas vivirán para siempre

Los valores SHAP, llamados así por su descubridor, Lloyd Shapley, se utilizan para explicar los resultados del modelo determinando la contribución de cada característica a la predicción.

Los valores SHAP pueden calcularse estimando los resultados del modelo para todas las combinaciones de características posibles. En pocas palabras, consisten en barajar los valores de una característica concreto manteniendo constantes los demás y observar el efecto en las predicciones del modelo.

De manera similar a lo que ocurre con los jugadores, si una característica no cambia sistemáticamente el resultado del modelo cuando se baraja su valor (por ejemplo, un jugador no influye en el rendimiento del equipo cuando no participa), el valor SHAP para esa característica tenderá a ser menor. Por el contrario, si el cambio en la característica afecta significativamente al resultado del modelo, el valor SHAP será mayor, lo cual indicará una contribución más significativa.

Los valores SHAP cuantifican la contribución de cada función. Comparando los valores SHAP de los distintos objetos, podemos deducir qué características tienen un impacto más significativo en las predicciones del modelo.

Así, si una característica se ignora repetidamente (sus valores se mezclan o cambian) y el rendimiento del modelo no cambia de forma sustancial, significará que la contribución de esa característica a las predicciones del modelo puede ser relativamente pequeña.

Ventajas:

  • Independencia del modelo: los valores SHAP son independientes del modelo, lo cual significa que pueden aplicarse a cualquier modelo de aprendizaje automático, incluidos modelos complejos como métodos de conjuntos, redes neuronales y máquinas de vectores de soporte.
  • Interpretabilidad global y local: los valores SHAP ofrecen interpretabilidad tanto global como local. Estos pueden explicar el impacto de las características individuales en una predicción concreta (interpretabilidad local) y la contribución global de cada característica a todo el conjunto de datos (interpretabilidad global).

Desventajas:

  • Intensidad computacional: el cálculo de los valores SHAP puede resultar intensivo desde el punto de vista computacional, especialmente en el caso de grandes conjuntos de datos o modelos complejos. Esto puede crear problemas en aplicaciones en tiempo real o en situaciones en las que los recursos computacionales son limitados.
  • Desafíos en la interpretación de los datos multidimensionales: interpretar los valores SHAP para modelos con un gran número de características puede suponer todo un reto. Visualizar y comprender la contribución de múltiples características resulta más difícil en espacios multidimensionales.

Posibilidades:

  • Clasificación de la importancia de los objetos: los valores SHAP pueden usarse para clasificar los objetos según su influencia en las predicciones del modelo. Esta información resulta útil para seleccionar características e identificar las variables más influyentes en el modelo.
  • Visualizaciones explicativas: los valores SHAP permiten crear visualizaciones detalladas, como gráficos de resumen SHAP o gráficos de fuerzas individuales, que ayudan a transmitir las predicciones del modelo y la información de caracterización a las partes interesadas.

Posibles problemas:

  • Suposición de consistencia: los valores SHAP suponen consistencia, lo cual significa que el efecto de la función en la predicción será el mismo en todos los ejemplares. En algunos casos, este supuesto podría no cumplirse, lo cual puede dar lugar a interpretaciones erróneas.
  • Dificultad de interpretación: aunque los valores SHAP ofrecen información valiosa, su correcta interpretación requiere una clara comprensión de los conceptos subyacentes. Los usuarios pueden malinterpretar el significado de ciertos valores o no captar los matices de la contribución de determinadas funciones.

Información mutua (Mutual Information, MI):

La información mutua es una medida de la cantidad de información que la presencia o ausencia de una variable ofrece sobre otra variable. Cuantifica el grado de dependencia o relación entre dos variables.

Ventajas:

  • Independencia del modelo: la información mutua es independiente de un modelo concreto de aprendizaje automático. Puede aplicarse a cualquier tipo de relación entre variables, incluidas las relaciones lineales y las no lineales.
  • Capta las relaciones no lineales: a diferencia de la correlación, que resulta más adecuada para las relaciones lineales, la información mutua puede captar las relaciones no lineales entre variables, lo que la hace versátil para distintos tipos de datos.

Desventajas:

  • Sensibilidad al tamaño de la muestra: la información mutua puede resultar sensible al tamaño del conjunto de datos. En conjuntos de datos pequeños, la estimación de la MI puede ser menos estable y pequeños cambios en los datos pueden tener un impacto más significativo en los resultados.
  • Dificultad para interpretar la magnitud: aunque la MI proporciona una medida de la fuerza de la asociación, sus valores absolutos pueden ser difíciles de interpretar directamente. La interpretación de una "alta" o "baja" información mutua dependerá del contexto y la escala de las variables.

Posibilidades:

  • Selección de características: la información mutua puede usarse para seleccionar características clasificándolas según su relevancia para la variable objetivo. Las características con valores de MI más altos se consideran más informativas para predecir el objetivo.
  • Importancia de las variables en los modelos de conjuntos: en el aprendizaje de conjuntos, la información mutua puede usarse para evaluar la importancia de las variables, lo cual ayuda a construir modelos de conjuntos más precisos e interpretables.

Posibles problemas:

  • Suposición de independencia: la información mutua supone que las variables son independientes cuando su MI es cero. En la práctica, podría no reflejar las dependencias o relaciones complejas influidas por factores ocultos o variables que interfieren.
  • Computacionalmente intensivo para alta dimensionalidad: estimar la información mutua para datos multidimensionales puede requerir grandes recursos computacionales. y esto puede crear problemas en términos de tiempo y recursos.


Afortunadamente, las bibliotecas especializadas de Python simplifican dicho proceso, evitándonos tener que crear gran parte del código desde cero.

En este artículo no profundizaremos en los entresijos del entrenamiento y la selección de modelos. En su lugar, nos centraremos en la fase posterior al entrenamiento y estudiaremos cómo evaluar e interpretar el rendimiento del modelo. En el ejemplo de código anterior, el modelo básico se construye únicamente con fines ilustrativos, demostrando los pasos que se dan después de diseñar y entrenar el modelo. 

Comencemos 

Importancia de la eliminación de columnas

Utilizaremos el algoritmo de eliminación recursiva de características (Recursive Feature Elimination algorithm) de la biblioteca sklearn, que servirá para mostrar la importancia de la eliminación de columnas.

from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
El algoritmo de eliminación recursiva de características espera que le proporcionemos un modelo de aprendizaje supervisado que pueda acomodar y evaluar.
El modelo debe ofrecer información sobre la importancia de una característica mediante coeficientes o una función especial.
El modelo no tiene por qué ser el mismo que el usado en nuestra tarea.
El modelo no tiene que ser de la biblioteca sklearn, pero debe tener al menos una envoltorio sklearn.

Usaremos un modelo lineal y evaluaremos su precisión eliminando características aleatoriamente.

lm = LinearRegression()
rfe = RFE(lm,step=1)

El argumento de paso especifica cuántos objetos deben eliminarse en cada iteración.

A continuación, estableceremos el algoritmo de eliminación recursiva de funciones

rfe = rfe.fit(train_x,train_y)
Y comprobaremos qué características informativas ha encontrado nuestro algoritmo RFE
rfe.support_
array([ True, True, True, True, False, False, False, False, False, True, False, True, True, True, False, True, True, True, False, False, False, False, False, False, True, False, True])
También podremos obtener la calificación de cada función

rfe.ranking_
array([ 1, 1, 1, 1, 2, 5, 14, 11, 13, 1, 7, 1, 1, 1, 8, 1, 1, 1, 12, 15, 3, 4, 9, 10, 1, 6, 1])

La implementación de sklearn nos ofrece una máscara que podremos aplicar a las columnas de nuestro marco de datos train_x para ver los nombres de columna que RFE considera importantes.

train_x.columns[rfe.support_]
Index(['open', 'high', 'low', 'close', 'BBM_20_2.0', 'BBB_20_2.0', 'BBU_20_2.0', 'BBL_20_2.0', 'ema_20', 'ema_40', 'ema_100', 'MACDs_12_26_9', 'DMN_14'], dtype='object')
Así pues, de todos los indicadores aplicados, podemos ver que los siguientes contienen información valiosa:
    1)Open         2)High         3)Low         4)Close         6)KSTs_9         7)KST_10_15_20_30_10_10_10_15         7)Las 3 medias móviles exponenciales         8)4 Componentes de la banda de Bollinger: 'BBM_20_2.0' 'BBB_20_2.0' 'BBU_20_2.0' 'BBL_20_2.0'         9)MACD: 'MACDs_12_26_9'         10)Movimiento direccional negativo Otros indicadores pueden haber introducido ruido, ¡pero recuerde esto!
No podemos concluir que sea así, pero nos sigue pareciendo una afirmación razonable.


A continuación, pasaremos a estimar la importancia de la permutación

Para implementar el algoritmo, usaremos una biblioteca de Python llamada Explain Like I'm 5 (ELI5)

#pip install eli5 if you don't allready have it installed
import eli5
from eli5.sklearn import PermutationImportance
from sklearn.ensemble import GradientBoostingRegressor
gbr = GradientBoostingRegressor().fit(train_x,train_y)

permutation = PermutationImportance(gbr).fit(test_x,test_y)

Ahora evaluaremos los pesos que el algoritmo ha asignado a cada una de nuestras características.

eli5.show_weights(permutation,feature_names = test_x.columns.to_list())


Pesos de importancia de las permutaciones

Fig. 8. Pesos de importancia de las permutaciones


La interpretación de los resultados de la importancia de las permutaciones es bastante sencilla. Las funciones se clasifican en orden de importancia descendente, con las más importantes arriba y las menos importantes abajo. Un valor de peso (por ejemplo, "0,0986 +- 0,0256") indicará un cambio en las medidas de error del modelo. En resumen, la importancia de la permutación implicará barajar aleatoriamente los valores de las características. Si la función afecta sustancialmente al modelo, esta aleatorización debería provocar un aumento de los porcentajes de error del mismo. Debido a la naturaleza estocástica del algoritmo, este aumento se representará como un intervalo y no como un valor específico.

Por el contrario, para las características que no son importantes, no habrá ningún cambio o, en algunos casos, cuando los valores se barajen aleatoriamente, se reducirá la tasa de error del modelo. Esta doble naturaleza de los resultados -aumento o disminución de los porcentajes de error- ofrece una indicación clara de la importancia relativa de cada función, lo cual facilita una interpretación concisa y clara de los resultados de la importancia de la permutación. Por consiguiente, podemos concluir que la importancia de la eliminación de columnas y la importancia de la permutación tienen "opiniones" similares sobre la importancia de las características en nuestro modelo.

Gráficos de dependencia parcial (PDP) y expectativa condicional individual (ICE):

#Import partial dependence display from sklearn
from sklearn.inspection import PartialDependenceDisplay

for feature_name in predictors:
    PartialDependenceDisplay.from_estimator(cat_full,test_x,[feature_name])
    plt.grid()
    plt.show()

PDP Open Price

MACDS PDP

Fig. 9. Gráfico de dependencia parcial del precio de apertura y línea de señal MACD



El gráfico de dependencia parcial sirve como una valiosa herramienta para comprender cómo un cambio en una variable concreta afecta a las predicciones de nuestro modelo. Analizando el gráfico de dependencia parcial de la línea de señal MACD, podemos concluir de forma razonable que, en general, el aumento de la línea de señal MACD está asociado a un aumento del precio de cierre previsto por nuestro modelo.

No obstante, la interpretación de los gráficos de dependencia parcial puede resultar más compleja, como se muestra en el gráfico MACD Height que figura a continuación.

Gráfico de dependencia parcial de altura de MACD

Fig. 10. Gráfico de dependencia parcial de altura de MACD

A la hora de interpretar estos gráficos, pueden surgir dificultades debido a las relaciones no lineales o interacciones con otras variables que requieren un análisis más detallado. En el caso del gráfico de altura de MACD, podrían ser necesarias consideraciones e investigaciones adicionales para revelar la naturaleza exacta de la relación entre la altura de MACD y el precio de cierre previsto del modelo.

Este reconocimiento subraya la necesidad de analizar los gráficos de dependencia parcial de forma exhaustiva, considerando las características únicas de cada variable y, cuando surjan problemas de interpretación, buscar información adicional mediante análisis complementarios o consultas a expertos.

Los gráficos de expectativas condicionales individuales (ICE) se crean para ofrecer una visión detallada sobre cómo responden los ejemplares individuales a los cambios en una variable predictora concreta. A continuación explicamos paso a paso cómo se crean y utilizan los gráficos ICE:

1. Opciones individuales de previsión:

  • Empezamos con un conjunto de datos que contiene la variable predictiva de interés y otras funciones necesarias.
  • Seleccionamos un ejemplar específico del conjunto de datos.

2. Cambiamos la variable predictora:

  • Para el ejemplar seleccionado, cambiamos sistemáticamente los valores de la variable predictora manteniendo constantes las demás características.
  • Creamos el conjunto de predicciones correspondientes a cada valor de la variable de predicción.

3. Creamos curvas separadas:

  • Repetimos los pasos 1-2 para múltiples ejemplares con el conjunto de datos, creando un conjunto de curvas separadas (una para cada ejemplar) que ilustren la relación entre la variable predictora y las predicciones del modelo.

4. Dibujado:

  • Trazamos cada curva individual en el mismo gráfico. El eje X representa los valores de las variables predictoras, mientras que el eje Y representa las predicciones del modelo.

5. Interpretación:

  • Analizamos el gráfico ICE para observar cómo cambian las predicciones del modelo para cada ejemplar cuando cambia la variable predictora.
  • Identificamos patrones, tendencias o variaciones en las curvas para conocer la influencia de la variable de predicción en las previsiones individuales.

6. Análisis comparativo:

  • Comparamos varios gráficos ICE, especialmente al trabajar con diferentes ejemplares, para comprender la heterogeneidad del efecto de la variable en el conjunto de datos.

Uso:

  • Comprensión detallada: Los gráficos ICE ofrecen una comprensión detallada y concreta de cómo la variable predictora afecta a las predicciones, lo cual permite una visión más detallada.
  • Comprensión del modelo: Los gráficos ayudan a los usuarios a explorar relaciones no lineales, interacciones y anomalías potenciales que pueden no resultar obvias en visiones conjuntas.
  • Importancia de las funciones: Los gráficos ICE pueden ayudar a estimar la importancia de una característica concreta ilustrando su impacto en las previsiones individuales.
  • Soporte de soluciones: La información de los gráficos ICE puede ayudar en la toma de decisiones, especialmente cuando resulta importante comprender cómo cambian las previsiones para casos específicos en respuesta a los cambios en una variable concreta.

De hecho, el gráfico PDP es simplemente la media de los gráficos ICE dibujados. La línea PDP se muestra en naranja, más abajo.

for feature in predictors:
    PartialDependenceDisplay.from_estimator(cat_full,test_x,[feature],kind='both')

ICE High

ICE EMA

Fig. 11. Gráfico ICE con precio alto y una EMA con periodo 40

A juzgar por los gráficos observados, está claro que un aumento del precio alto o de la media móvil exponencial no tiene un impacto inmediato en las predicciones de nuestro modelo. En cambio, parece que estas variables tendrán que aumentar significativamente antes de que podamos esperar algún cambio notable en las predicciones del modelo. Esta observación sugiere que el modelo no es demasiado sensible a los cambios graduales de estas características particulares.

Principales conclusiones derivadas de los gráficos:

  1. Umbral de sensibilidad: El modelo parece mostrar sensibilidad umbral, lo cual significa que requiere un nivel significativo o un umbral de cambio en el precio alto o en la media móvil exponencial antes de ajustar significativamente sus previsiones.

  2. Respuesta paulatina: Los cambios graduales o moderados en las características mencionadas no parecen provocar ajustes inmediatos en las predicciones de los modelos. Dicha característica sugiere una respuesta gradual o contenida a tales cambios.

  3. Baja sensibilidad: La conclusión de que el modelo no es muy sensible a los cambios en estas características implica que resulta poco probable que pequeñas fluctuaciones en el precio alto o en la media móvil exponencial tengan un efecto notable en los resultados del modelo.

Comprender la sensibilidad del modelo a las distintas funciones resulta fundamental para la interpretación eficaz del modelo y la toma de decisiones. Estos datos pueden ayudar en análisis posteriores, mejorar el modelo o informar a las partes interesadas sobre la naturaleza de las relaciones entre predictores concretos y las predicciones del modelo.

También podemos comprobar los gráficos de dependencia parcial bidimensional para ver el efecto conjunto de dos funciones.

#Setting up the plot
fig , ax = plt.subplots(figsize=(10,5))
column_names = [('ROC_10','ATRr_14')]

#Plotting 2D PDP
disp_4 = PartialDependenceDisplay.from_estimator(cat_full, test_x[0:1000],column_names, ax=ax)
plt.show()

Gráfico de dependencia parcial 2D

Fig. 12. Gráfico de dependencia parcial 2D del indicador de la tasa de cambio (ROC) y del rango medio verdadero (ATR).

El análisis del gráfico de dependencia parcial 2D muestra que, en general, el aumento del ROC (tasa de cambio) y el ATR (rango medio verdadero) es coherente con el aumento de la predicción esperada de nuestro modelo. Esta correlación positiva resulta coherente con el comportamiento esperado del modelo en respuesta a los cambios de estos indicadores.

No obstante, el gráfico también ofrece una indicación de la interacción entre los dos indicadores. En particular, la ausencia de límites bien definidos en el gráfico sugiere que la relación no siempre es estable. En cambio, existen zonas de fortaleza y debilidad mixtas, lo cual indica que el impacto de los indicadores ROC y ATR en las predicciones del modelo puede diferir en distintas zonas del gráfico.

La presencia de enclaves aleatorios de expectativas débiles dentro de los límites de las expectativas fuertes destaca aún más la naturaleza dinámica de la interacción. Es importante señalar que el comportamiento observado puede verse influido por el método de muestreo, especialmente si se ha usado un subconjunto del marco de datos por razones de eficiencia computacional.

Algunas de las consideraciones e impactos potenciales incluyen:

  1. Limitaciones de la muestra: Las discrepancias observadas pueden explicarse en parte por el uso de una muestra más pequeña para mejorar la eficiencia computacional. Un enfoque de muestreo más amplio podría haber ofrecido una imagen más completa de la interacción.

  2. No linealidad o interacciones: La ausencia de límites bien definidos y la presencia de zonas mixtas sugieren una posible no linealidad o interacción entre los indicadores ROC y ATR. Otros estudios, quizá con muestras más amplias, podrían descubrir patrones más sutiles.

  3. Fiabilidad del modelo: Comprender la variabilidad de la interacción ayudará a evaluar la solidez del modelo y su sensibilidad a distintas combinaciones de características de entrada.

En conclusión, la interpretación del gráfico de dependencia parcial bidimensional ofrece información valiosa sobre la respuesta del modelo a los cambios en ROC y ATR. Reconociendo el impacto potencial del tamaño de la muestra en los patrones observados, una investigación más profunda y, si es posible, una estrategia de muestreo más amplia, podrían mejorar la precisión de estos resultados.


Valores de las explicaciones aditivas de Shapley (SHAP)

#pip install shap if you don't have it installed
#Import SHAP
import shap

#Initialise the shap package
shap.initjs()

Algunos factores a considerar:

  • Los valores SHAP suponen que los objetos son independientes o no están correlacionados

  • Los valores SHAP son difíciles de calcular con precisión. El problema se agrava con el aumento de la dimensionalidad del conjunto de datos.

  • Los valores SHAP son independientes del modelo, lo cual significa que pueden no ayudarnos a captar ciertos comportamientos específicos del modelo. Ahí radican tanto los puntos fuertes como los débiles de los valores.

  • Los valores SHAP son sensibles al orden de entrada.

En nuestro conjunto de datos existen términos de correlación estricta, lo cual supone un grave problema en el cálculo de los valores SHAP, ya que infringe el supuesto de independencia de los objetos. Por fortuna, hay muchas maneras de resolver este problema:

  • La solución más sencilla sería descartar las funciones correlacionadas, pero debe considerarse como último recurso en la mayoría de los casos

  • Usar técnicas de reducción de características como el análisis de componentes principales u otras técnicas de selección de características con las que pueda estar familiarizado.

  • Discretizar los objetos en compartimentos podría ayudar a mitigar los efectos adversos de la correlación en el cálculo de los valores SHAP.

  • Usar algoritmos SHAP diseñados para tratar datos correlacionados

  • Utilizar funciones no correlacionadas, por ejemplo, en nuestro caso, Volume y High Low Spread tienen una correlación muy débil

En este caso, usaremos la cuarta solución, utilizando algoritmos SHAP especiales diseñados para tratar datos correlacionados. Los algoritmos SHAP basados en la estructura de árbol obtienen buenos resultados en correlación.

#Initialise shap value calculator
tree_explainer = shap.TreeExplainer(cat_full)

#Store SHAP values
shap_values = tree_explainer.shap_values(test_x)

#Plot SHAP values
shap.summary_plot(shap_values,test_x)

Valores SHAP

Fig. 13. Gráficos de los valores SHAP

Así es como interpretamos el gráfico de resumen de SHAP:

  1. Importancia de las características: las características situadas en la parte superior del eje Y tienen un mayor efecto en el aumento del precio de cierre, mientras que las características situadas en la parte inferior del eje Y tienen un mayor efecto en la disminución del precio de cierre. 

  2. Dirección de influencia: cada objeto tiene puntos de color a lo largo del eje X. Los puntos azules simbolizan los valores de función más bajos; los rojos serán los más altos. La posición horizontal de estos puntos nos informa sobre la influencia del valor de la función en el precio de cierre. Así, nuestros cálculos del valor SHAP muestran que nuestro High_Low_Sread no indica demasiado bien el precio de cierre.

  3. Magnitud de ubicación: la ubicación horizontal de cada punto a lo largo del eje X representa la magnitud del impacto, por lo que los valores extremos altos y bajos tienen un impacto relativamente mayor en el precio de cierre en comparación con las funciones Volume, Open y High_Low_Spread de este ejemplo demostrativo.


Información mutua

from sklearn.feature_selection import mutual_info_regression
mi_scores = mutual_info_regression(train_x, train_y)
mi_scores = pd.Series(mi_scores, name="MI Scores", index=train_x.columns)
mi_scores = mi_scores.sort_values(ascending=False)
mi_scores

ema_100                                       1.965130

ema_40                                         1.960548

ema_20                                         1.933651

BBM_20_2.0                                   1.902066

BBL_20_2.0                                   1.895867

BBU_20_2.0                                  1.881435

high                                             1.795941

low                                              1.786879

close                                            1.783567

open                                            1.777118

TSIs_13_25_13                              0.232247

ATRr_14                                        0.215980

MACDs_12_26_9                            0.214559

KST_10_15_20_30_10_10_10_15    0.208868

KSTs_9                                         0.205177

MACD_12_26_9                            0.174518

TSI_13_25_13                              0.168086

AO_5_34                                     0.128653

BBB_20_2.0                                 0.104481

RSI_20                                         0.095368

MACDh_12_26_9                          0.076360

DMP_14                                      0.060191

DMN_14                                     0.048856

ROC_10                                     0.042115

BBP_20_2.0                               0.028558

CCI_14_0.015                            0.022320

SLOPE_1                                   0.004144

def plot_mi_scores(scores):
    scores = scores.sort_values(ascending=True)
    width = np.arange(len(scores))
    ticks = list(scores.index)
    plt.barh(width, scores)
    plt.yticks(width, ticks)
    plt.title("Mutual Information Scores")
plt.figure(dpi=100, figsize=(8, 5))
plt.grid()
plot_mi_scores(mi_scores)


Información mutua

Fig. 14. Valores de información mutua

Observamos un consenso coherente en todos nuestros métodos de explicación de la "caja negra", lo cual sugiere que las características que se destacan sistemáticamente en estas explicaciones contienen información esencial que podemos utilizar eficazmente. La media móvil exponencial, las Bandas de Bollinger y los precios máximo, mínimo y de cierre de apertura se encuentran sistemáticamente más cerca de la parte superior, por lo que al medir la tendencia central podemos concluir lógicamente que estas características pueden ser muy informativas y así podemos descartar todo lo demás. 

Comprobemos ahora nuestras conclusiones.

Utilizaremos dos modelos: una regresión lineal simple y nuestra potente "caja negra". Seleccionaremos las características usando la información que hemos obtenido de nuestros métodos de explicación de la "caja negra". 

En primer lugar, importaremos las dependencias que necesitamos.

from sklearn.linear_model import LinearRegression
from catboost import CatBoostRegressor
from sklearn.metrics import mean_squared_error

    En primer lugar, estableceremos un modelo más sencillo

    #First we fit the simpler model
    lm = LinearRegression()
    
    lm.fit(train_x.loc[:,["open","high","low","close"]],train_y)

    A continuación, evaluaremos hasta qué punto el modelo más sencillo se ajusta a los datos de entrenamiento.

    lm_predictions = pd.DataFrame(lm.predict(train_x.loc[:,["open","high","low","close"]]), index = train_y.index)
    lm_fit = lm.predict(train_x.loc[:,["open","high","low","close"]])
    residuals = pd.DataFrame(train_y - lm_fit)

    Ahora utilizaremos nuestro modelo de "caja negra", más potente, para explorar los restos de nuestro modelo más simple. Ofreceremos a nuestro modelo de "caja negra" las características que consideramos más informativas.

    #Now we bring in our more powerfull black-box model
    cat = CatBoostRegressor()
    cat.fit(
        train_x.loc[:,["BBM_20_2.0","BBL_20_2.0","BBU_20_2.0","ema_40","ema_20","ema_100"]],
        residuals)

    Luego compararemos las tasas de error en los datos de prueba, evaluando el rendimiento de nuestro modelo original de "caja negra", que utilizaba todas las características disponibles, frente a la precisión del modelo refinado. El modelo mejorado incorpora una regresión lineal más sencilla y utilizará estratégicamente un subconjunto de características cuidadosamente seleccionadas.

    lm_test_predictions = pd.DataFrame(lm.predict(test_x.loc[:,["open","high","low","close"]]),index=test_y.index)
    cat_full_test_predictions = cat_full.predict(test_x[predictors])
    
    cat_residuals_predictions = pd.DataFrame(cat.predict(test_x.loc[:,["BBM_20_2.0","BBL_20_2.0","BBU_20_2.0","ema_40","ema_20","ema_100"]]),index=test_y.index)

    Ahora estimaremos la tasa de error de nuestra caja negra inicial.

    full_error = mean_squared_error(test_y,cat_full_test_predictions)

    Y la compararemos con la tasa de error de nuestro nuevo híbrido de "caja negra".

    hybrid_predictions = lm_test_predictions.iloc[:,0] + cat_residuals_predictions.iloc[:,0]
    hybrid_error = mean_squared_error(test_y, hybrid_predictions)
    delta_error = full_error - hybrid_error
    (delta_error / full_error) * 100

    94.428

    Nuestro nuevo híbrido de "caja negra" tiene unos índices de error que han mejorado en un 94%.

    hybrid_predictions.plot()

    Predicción de la "caja negra" híbrida

    Fig. 15. Nuevo pronóstico de "caja negra"

    Resulta esencial la mejora notable en el realismo de nuestras nuevas previsiones de "caja negra", desprovistas de los antinaturales periodos planos observados inicialmente. Hemos logrado una mayor precisión con un conjunto de características optimizado. Esto pone de relieve el principio de que, cuando trabajamos con eficacia, podemos conseguir más con menos esfuerzo.


    Vamos a reunirlo todo junto

    Estamos preparados para integrar todos los componentes en una estrategia comercial global.

    MARKET_SYMBOL = "Volatility 75 Index"
    DEVIATION = 100
    VOLUME = 0
    symbol_info = MT5.symbol_info(MARKET_SYMBOL)
    VOLUME = symbol_info.volume_min * 1
    def preprocess(df):
        #20 period exponential moving average
        df["ema_20"] = df.ta.ema(length=20)
        #40 period exponential moving average
        df["ema_40"] = df.ta.ema(length=40)
        #100 period exponential moving average
        df["ema_100"] = df.ta.ema(length=100)
        #20 period bollinger bands with 3 standard deviations
        df.ta.bbands(length=20,sd=2,append=True)
        df = df.loc[100:,:]
    def fetch_prices():
        current_prices = pd.DataFrame()
        current_prices = pd.DataFrame(MT5.copy_rates_from_pos(MARKET_SYMBOL,MT5.TIMEFRAME_M1,0,200))
        preprocess(current_prices)
        return(current_prices)
    def normalise_prices(raw_data):
        for col in raw_data.columns:
            if col in first_values:
                raw_data[col] = raw_data[col] / first_values[col]
    model_forecast = 0
    def hybrid_forecast(model_1,model_2):
        market_data = fetch_prices()
        normalise_prices(market_data)
        forecast_1 = model_1.predict(market_data.loc[199:200,["open","high","low","close"]])
        forecast_2 = model_2.predict(market_data.loc[199:200,["BBM_20_2.0","BBL_20_2.0","BBU_20_2.0","ema_40","ema_20","ema_100"]])
        out = forecast_1 + forecast_2
        return(out)
    INITIAL_BALANCE = MT5.account_info().balance
    CURRENT_BALANCE = 0
    if __name__ == "__main__":
        while True:
            
            #Account standing
            info = MT5.account_info()
            CURRENT_BALANCE = info.balance
            profit = CURRENT_BALANCE - INITIAL_BALANCE
            
            model_forecast = hybrid_forecast(lm,cat)
            print("Current forecast: ",model_forecast)
            
            #We have no open positions
            if(MT5.positions_total() == 0):
                print("No open positions")
                
                #Buy
                if(model_forecast > MT5.symbol_info(MARKET_SYMBOL).ask):
                    print("Following model forecast buy")
                    MT5.Buy(MARKET_SYMBOL,VOLUME)
                    last_trade = 1
                            
                #Sell    
                elif(model_forecast < MT5.symbol_info(MARKET_SYMBOL).ask):
                    print("Following model forecast sell")
                    MT5.Sell(MARKET_SYMBOL,VOLUME)
                    last_trade = 0
                    
            elif(MT5.positions_total() > 0):
                print("Checking model forecast")
                
                if((model_forecast > MT5.symbol_info(MARKET_SYMBOL).ask) & (last_trade == 0)):
                    print("Model is forecasting a move that hurts our exposure. Closing positions")
                    MT5.Close()
                
                elif((model_forecast < MT5.symbol_info(MARKET_SYMBOL).ask) & (last_trade == 1)):
                    print("Model is forecasting a move that hurts our exposure. Closing positions")
                    MT5.Close()
                    
            print("Total Profit/Loss: ",profit)
            time.sleep(60)

    Current forecast: [239100.04622681] No open positions Following model forecast buy Total Profit/Loss: 0.0


    Conclusión

    A medida que avanzamos en el entrenamiento de modelos más grandes y complejos, estos se vuelven más difíciles de entender, explicar y depurar. Si no logramos entender exactamente cómo funcionan nuestros modelos de aprendizaje automático y por qué toman determinadas decisiones, no podremos estar seguros de que el modelo funcione como suponemos. La falta de comprensión de los modelos y la resolución de problemas no garantiza las complejidades adicionales de estos métodos. El valor que podemos extraer sistemáticamente de una herramienta estará limitado por lo mucho que entendamos de esa herramienta. Ese es el propósito de este artículo: animar al lector a confiar más en sus modelos y a comprender mejor los engranajes de los modelos de aprendizaje automático que se encuentran en la "caja negra".

    Traducción del inglés realizada por MetaQuotes Ltd.
    Artículo original: https://www.mql5.com/en/articles/13706

    Escribimos el primer modelo de caja de cristal (Glass Box) en Python y MQL5 Escribimos el primer modelo de caja de cristal (Glass Box) en Python y MQL5
    Los modelos de aprendizaje automático son difíciles de interpretar, y entender por qué los modelos no se ajustan a nuestras expectativas puede ayudarnos mucho a conseguir, en última instancia, el resultado deseado al utilizar técnicas tan avanzadas. Sin un conocimiento exhaustivo del funcionamiento interno del modelo, podría resultar difícil encontrar fallos que degraden el rendimiento. De este modo, podremos dedicar tiempo a crear funciones que no afecten a la calidad de la previsión. La conclusión es que, por muy bueno que sea un modelo, nos perderemos todas sus grandes ventajas por culpa de nuestros propios errores. Afortunadamente, existe una solución sofisticada y bien diseñada que permite ver con claridad lo que sucede bajo el capó del modelo.
    Características del Wizard MQL5 que debe conocer (Parte 08): Perceptrones Características del Wizard MQL5 que debe conocer (Parte 08): Perceptrones
    Los perceptrones, o redes con una sola capa oculta, pueden ser una buena opción para quienes estén familiarizados con los fundamentos del comercio automatizado y quieran sumergirse en las redes neuronales. Paso a paso veremos como se pueden implementar en el ensamblado de clases de señales que forma parte de las clases del Wizard MQL5 para asesores expertos.
    Patrones de diseño en MQL5 (Parte 3): Patrones conductuales 1 Patrones de diseño en MQL5 (Parte 3): Patrones conductuales 1
    En el nuevo artículo de la serie sobre patrones de diseño, nos ocuparemos de los patrones conductuales para comprender cómo crear de forma eficaz métodos de interacción entre los objetos creados. Diseñando estos patrones conductuales, podremos entender cómo construir software reutilizable, extensible y comprobable.
    Algoritmos de optimización de la población: Método de Nelder-Mead Algoritmos de optimización de la población: Método de Nelder-Mead
    En el artículo de hoy, le presentamos un estudio completo del método de Nelder-Mead, en el que se explica cómo el símplex (el espacio de parámetros de la función) se modifica y reordena en cada iteración para alcanzar la solución óptima; asimismo, describiremos una forma de mejorar este método.