Problemas de la esperanza y aversión al riesgo y a la pérdida

Usando matemáticas para decidir muchas veces acabas confiando en la esperanza, matemática se entiende. La esperanza no es un beneficio real, es una forma de estimar un posible beneficio, es lo que ganarías de media si se repite infinitas veces el proceso aleatorio.

Supongamos que participas en un sorteo de 1000€, han vendido solo 10 billetes. Así que tu billete tiene una esperanza de 100€….ahora bien. Intenta comprar algo con esos 100€ que según las matemáticas es el potencial beneficio de ese billete. Al final tienes 0€ o 1000€. El uso de la esperanza como un beneficio real es lo que hace que puedan surgir paradojas.

Paradoja de los dos sobres

Imagina que te dan un sobre, llamemosle 1 con una cantidad desconocida de dinero, indiquemosla como X. El sobre 2 tiene o el doble o la mitad que el 1. Es decir o 2X o X/2. Ahora nos piden elegir si cambiamos de sobre o no. ¿Qué es lo más provechoso? Sabemos que el sobre 1 contiene X, pero ¿Cuál es la esperanza del sobre 2?

1/2 * 2X + 1/2 * X/2 = 5X/4

Mientras que tu sobre tiene X dinero el otro sobre tiene una esperanza de 1,25X. Deberíamos coger el sobre 2. Así que eso haces. Ahora te ofrecen volver al sobre 1. Si lo piensas tú has elegido en sobre con la mitad o el doble de dinero que 1, pero eso significa que 1 tiene la mitad (si el 2 tiene el doble) o el doble (si el 2 tiene la mitad) que el tuyo…Un momento ¿Un sobre que tiene el doble o la mitad que el tuyo no es como ha empezado todo esto?. Efectivamente. Y si antes has cambiado, lo lógico sería volver a hacerlo ahora ¿No?. La esperanza es la misma, 1,25 veces lo que tenga tú sobre. Pero si lo cambias estarás en la misma situación que al principio y ya hemos visto que lo mejor era cambiarlo…..así que puedes estar cambiando sobres infinito número de veces.

Paradoja de San Petersburgo

Te ofrecen un juego de tirar una moneda. Si sale cara vuelves a tirar, si sale cruz se acaba la partida. Ganas 2^n euros. Siendo n el número de caras obtenidas. Veamos cual es la esperanza de beneficio. En este caso será la suma de la esperanza de cada tirada. Sabiendo que la probabilidad de ganar en la primera tirada es 1/2 (la probabilidad de salir cara), la de la segunda tirada es 1/2 * 1/2(dos caras seguidas), la tercera 1/21/21/2 y así consegutivamente:

Tirada 1 = 1/2 * 2^1 = 2/2 = 1
Tirada 2 = 1/21/2 * 2^2 = 4/4 = 1 Tirada n = (1/2^n) 2^n = 2^n/2^n = 1

La esperanza es la suma de todas las posibles tiradas….como todas son igual a 1 la esperanza es infinita. Luego te pidan lo que te pidan por participar sale rentable. Aunque te pidan un millón de euros es poco por la esperanza de ganar infinitos.

Aversión a la pérdida

Para este tipo de problemas se plantean varias soluciones, no todas posibles de implementar en código, pero yo voy a optar por usar una inspirada en dos mecanismos de los humanos. La aversión a la perdida o al riesgo. Suenan parecidos pero son distintos.

La aversión a la pérdida se podría definir como que se valora más lo que tienes que lo que puedes ganar. O lo que es lo mismo cuando has de comparar lo que puedes ganar con lo que puedes perder has de multiplicar la perdida por una variable que la incrementa. Además para simular el comportamienti humano esta variable ha de incrementarse conforme aumenta el valor de la cantidad que arriesgamos. Pongamos el caso de el tipico juego de tirar la moneda con una moneda justa (50% de que salga cara y 50% de que salga cruz). Si sale cara ganamos, si sale cruz perdemos. Si las condiciones son que si ponemos 1€ de apuesta podemos ganar 2€ la esperanza nos dice que da igual si jugamos o no:

(0.5 * 2) + (0.5 * 0) = 1

1 que es igual a la apuesta por lo que no hay esperanza de beneficio

Sin embargo con una adversion al riesgo de 1.1 la apuesta se multiplica por ese valor siendo 1.1 por lo que necesitamos una esperanza mayor.

Ya no jugariamos Por supuesto en este caso en que la perdida es tan solo 1€ muchos se plantearan jugar. Sin embargo si fueran 1000€ lo que nos jugamos, aunque el beneficio sea igualmente 1000€ habrá menos gente gente dispuesta a jugar. Esos se debe a que la aversión a la perdida crece con la cantidad que se va perder, no es siemrpe la misma. Para 1€ puede ser 1 pero para 1000€ puedes ser 100. De hecho en caso de cantidades muy pequeñas puede ser menor que 1. Ya que la perdida la consideramos despreciable y eso podría animarnos a correr ese riesgo.

Aversión al riesgo

Por otro lado la aversión al riesgo favorece la elección de las opciones más probables. Si la anterior aversión aplicaba según la cantidad “apostada”, está aplica según la probabilidad de ganar. Es menor que 1 y a menor probabilidad menor será.

Siendo Ar la función que devuelve la aversión al riesgo. P la probabilidad y V el valor, la nueva esperanza seria:

Esp = Pi * Vi * Ar(P)

Es importante tener en cuenta que se multiplica el valor y no la probabilidad. Si, ya sé que parece lo mismo, pero las probabilidades han de sumar 1.

El asno de Buridan

Por último un caso especial, no es un gran problema ya que estamos habituados a resolverlo, tan habituados que puede que ni nos demos cuenta de que existe.

La historia original habla de un asno hambriento que situado equidistante a dos pesebres idénticos muere de hambre por no saber por cual decidirse. O lo que en el caso de la I.A. sería un agente enfrentado a dos opciones con la misma esperanza no sabría cual decidir.

Elección irracional

El ejemplo más sencillo es que nos toque diseñar un agente que elige entre cara o cruz. ¿Qué es lo que hacemos habitualmente? Elegirla al azar. Esto es realizar una elección no racional. No hay ningún motivo para elegir una u otra así que dejamos al azar esa elección. Este mismo sistema nos puede servir cuando el valor de la esperanza no nos sirva de guía. Nada nos garantiza elegir la mejor opción pero nos permite no quedarnos congelados sin saber que elegir.

Algoritmos que “olvidan” con el tiempo

Una de las virtudes de las máquinas es que no olvidan. ¿Para qué sirve que lo aprendido pierda valor con el tiempo?. Para aprender datos que pueden cambiar con el tiempo. Por ejemplo hábitos, gustos e intereses. Realmente el concepto de olvidar es que con el tiempo la información aprendida pierda valor.

Supongamos que queremos hacer un agente que recomiende noticias para ello tiene en cuenta dos parámetros. El tema de la noticia y su popularidad. Vamos a suponer que la primera parte ya está hecha y estamos peleando con la segunda. La idea es valorar la importancia de una noticia por el número de lectores que tiene. Pero no basta solo con eso. Las noticias pierden importancia con el tiempo, por lo que tenemos que ser capaces de incluir eso en nuestro sistema.

Podemos ver cada lector como un voto a favor de la noticia, ahora hemos de tener en cuenta la antigüedad del voto para valorarlo según esta. El truco es que el voto solo cuenta como un voto durante un periodo de tiempo desde que “votó”. Cada voto lo multiplicamos por un valor que disminuye con el tiempo. De esa forma cuanto más tiempo hace que se votó menos valor tiene el voto.

Algunas fórmulas:

V(t) representa el valor del voto V en t unidades de tiempo después de que se votará. Las llamo “unidades de tiempo” porque para las fórmulas da igual que sean segundos, horas, días, días de Júpiter, una unidad de tiempo inventada,….

t son las unidades de tiempo desde que se votó.

V representa el valor del voto.

k es una constante que determina como de rápido pierde valor el voto.

V(t) = V – k*t

V(t) = V – k * t     En rojo k = 0,2 En azul k = 0,5

Para esta función k tiene que ser menos que 1.

La caída del valor el lineal

V(t) = V/(k*t)

V(t) = 1/(k*t)   K = 2

En este caso k tiene que ser mayor que 1 si es menor aumenta el valor de V en lugar de reducirlo. Cuidado también con valores de t pequeños

V(t) = V * k^t

Vt) = V * k^t         En negro k = 0.9 en rojo k = 0.5

En este caso k ha de ser menor que 1. A mayor valor tenga k más rápida será la perdida de valor con el paso del tiempo.

V(t) = V * e ^ -kt

V(t) = V * e ^ -kt     En azul  k = 2 en verde k = 1

Basta con que k sea positivo. A mayor valor de k más rápido cae el valor.

Permite ajustar la “vida media” (vm) que seria la cantidad de tiempo en que el valor V valdría la mitad. Para calcular el k necesario para tener esa vida media basta con hacer la siguiente operación: 

k =  ln 2 / vm

Por ejemplo si queremos una vida media de 3 unidades de tiempo:

k = ln 2 / 3 = 0,23104906

Una vez tenemos el valor actualizado de cada voto lo único que hay que hacer es sumarlos.

Un último consejo es que aquellos votos cuyo valor caiga por debajo de uno que consideremos mínimo se borren o al menos no se tengan en cuenta, ya no aportan nada y así se reducen los cálculos necesarios

El problema del contexto en la Inteligencia Artificial

Definir el problema del contexto es difícil ya que sus causas son muchas. De forma intuitiva el problema del contexto es que cuando hablas con otra persona tiene claro dónde y cuándo estás, que os rodea y un montón de información cultural y social aprendida. Además tenemos una capacidad más o menos buena para captar las emociones e intenciones de la otra persona y de aprender cómo es su personalidad con el paso del tiempo. Suma a todo esto nuestra habilidad para comprender el lenguaje, los gestos, los símbolos visuales y el entorno junto con nuestra capacidad de abstracción. Sin ser perfectos, muchas veces ocurren malentendidos, ninguna inteligencia artificial se nos acerca si quiera. Vamos a ver algunas de las causas de forma individual.

Los conocimientos y comportamientos aprendidos se deben a nuestra cultura y sociedad. Son muchos más de los que nos pensamos. Son cosas como las normas de comportamiento, frase hechas, “lo que está de moda” o aquel conjunto de diversos conocimientos que llamamos “culturilla general”. La unica forma de solucionar este problema es aportar ese conocimiento al agente. Por ejemplo, el refrán: “El que a buen árbol se arrima, buena sombra le cobija” no va a ser correctamente interpretado por ninguna I.A. que no conozca su significado previamente. No es un problema de interpretación de lenguaje natural, es un conocimiento que debe ser aprendido. Lo mismo pasa con las señales de tráfico, por ejemplo.

Otro problema del contexto es que el ser humano es perfectamente consciente del entorno que le rodea. Si por ejemplo tu pareja te dice: “¿Puedes mirar en Internet a que hora pasa el bus?”. Y es un martes a las ocho de la mañana seguramente se refiera al bus al trabajo. Si es un sábado y se va al pueblo a ver a sus padres será el bus del pueblo y si es un martes de agosto tiene vacaciones y vais a coger un avión se referirá al bus al aeropuerto. Como humanos no tenemos ningún problema en entender esto. Eso se debe a que integramos la frase en un contexto espacial, temporal y personal. Para que una I.A. haga lo mismo tiene que ser capaz de fusionar varias fuentes de datos: localización, fecha, hora, agenda, costumbres de la persona. Estamos tan acostumbrados a hacerlo de forma automática que nos parece engañosamente facil hacerlo. Sin embargo para un agente saber que fuentes de información son importantes y como fusionarlas es difícil.

Las inteligencias artificiales tampoco son buenas entendiendo figuras como la ironía, el sarcasmo o interpretando las cosas desde el punto de vista de otras personas. No son capaces de las abstracciones necesarias para entender cosas como el arte o incluso distinguir un objeto de su reflejo en un espejo. La incapacidad de ponerse en el lugar de otros causa problemas como que muchos vehículos autónomos causan mareos ya que sus maniobras no están pensadas para la comodidad de los viajeros. En algunos casos sencillos se pueden resolver estos problemas con aprendizaje y realimentación de los humanos.

woman in black shirt facing mirror

Una I.A. no sabria distinguir entre la chica real y la reflejada, diria que en la foto hay dos personas. Photo by Ivan Obolensky on Pexels.com

Saber que señales ignorar y cuáles no. Hace un tiempo iba conduciendo por un calle de dos carriles uno para cada sentido con aparcamientos en batería a los lados. Llegado a un punto uno de los carriles estaba en obras, la solución por la que había optado era que uno de los carriles provisionales pasaba por encima del aparcamiento en batería y el otro usaba el carril que habitualmente circulaba en sentido opuesto. La única señal que había era unas vayas amarillas que más o menos sugerían lo que había que hacer y un cartel de cuidado obras. Tras unos segundo de duda resulto sencillo saber que durante unos metros tendría que hacer caso omiso a las indicaciones viales y circular por encima de las lineas de aparcamiento ya que mi carril estaría ocupado por coches circulando en sentido contrario. El entorno puede estar lleno de señales contradictorias y hay que entender cuáles ignorar en cada momento.

Algunas técnicas que tenemos para tratar de minimizar este problema y que los agentes den la sensación de tener cierta “consciencia” del entorno:

Limitar el ámbito del agente, si haces un agente para consultar sobre mecánica del automóvil nadie se sorprenderá de que por “gato” solo entienda los gatos hidráulicos.

Crear estados o tópicos, es una forma de ampliar el caso anterior. El programador define estados o tópicos que ayudan a crear el contexto. Si por ejemplo el estado es “mecánica del automóvil” es muy probable que gato se refiera al gato hidráulico, pero si el tópico es “mascotas” es más probable que se refiera a un animal. El problema de los tópicos es que al final el número de los mismos está limitado.

Detección de tópicos, en combinación con el punto anterior, es detectar los tópicos de un texto o conversación. Si hablo de un gato saber si me refiero al animal o a la herramienta. Generalmente se extrae relacionándolo con el resto de palabras, si digo “coche”, “rueda”, “maulla”.

Aprendizaje, para adaptarse a cada persona es necesario aprender sus hábitos. Los asistentes actuales ya lo hacen tratando de aprender los hábitos, gustosy costumbres a base de recopilar datos automáticamente,

Interacción con los humanos, a veces la forma más fácil de saber algo es que te lo digan. Es importante la capacidad de preguntar y recibir esa información ya sea de forma natural o a través de una pantalla de configuración.

Detección de emociones, técnicas que van desde el reconocimiento de expresiones faciales a la detección de sentimientos en frases o de ironías.

Extracción de datos del entorno, muchas veces el contexto viene determinado por lo que te rodea. El que agente necesita saber dónde está y que ocurre a su alrededor. Si suena música que música es, si se es viendo una película, cuál es. Si conoce al resto de las personas que pueda haber.

Fusión de datos, no basta con captar todos los datos hay que entenderlos en su conjunto. Para ello hace falta cruzarlos pero también ser capaz de extraer nueva información al cruzar estos datos. Ha de “deducir datos nuevos”. Tiene que trabajar con incertidumbre y ser capaz de “rellenar huecos” con lo más probable. También tiene que ser trabajar de descartar los datos que son correctos pero no aplican ene ese momento, que quizás sea lo más difícil.

¿Con todo esto basta? No, o al menos no con el nivel actual de la tecnología. Aún estamos lejos de lograr agentes que entiendan el contexto completamente. Sin embargo con estas técnicas, en algunos casos, los resultados pueden ser sorprendentes, o al menos parecerlo, por eso a veces los asistentes como Siri o Alexa nos sorprenden con su “comprensión” y otras con su estupidez. Aun queda mucho para lograr que la I.A. entienda el contexto correctamente.

 

Programación Lógica

La programación lógica está inspirada en la lógica de primer orden. El lenguaje más conocido es Prolog y si no lo conocéis os recomiendo que le echéis un ojo. Es una forma de programar bastante diferente a la habitual y aunque para cosas genéricas pueden ser más “cómodos” otros paradigmas de programación para ciertas ramas de la I.A. facilita el desarrollo de forma espectacular.

En programación lógica por lo general hay tres tipos de sentencias:

  • Hechos (facts): Serían los conocimientos de los que se parte. Son sentencias del estilo “Juan es padre de Pepe” que se escribiría como algo así: padre(juan, pepe).
  • Reglas (rules): Calculan nuevos hechos estableciendo relaciones entre ellos.Para ello se utilizan variables. Por ejemplo “Si X es padre de Y e Y es padre de Z entonces X es abuelo de Z” que en Prolog sería: abuelo(X,Z) :- padre(X,Y), padre(Y,Z).
  • Consultas (queries): Se usan para extraer información. Hay de dos tipos, la primera dice si un hecho es verdadero o falso. Por ejemplo “¿Es padre Juan de Pepe?” Que se escribiría (depende el intérprete de Prolog) padre(juan, pepe). El otro tipo son las que tiene que completar un hecho. Por ejemplo “¿Quien es el padre de Pepe?” padre(X, pepe).

Si queréis jugar con él sin tener que instalar nada podéis probar aquí.

Guardando el conocimiento

Supongo que ya os imaginareis como va a aprender este sistema. Convertiremos los datos a un conjunto de hechos y reglas. Para obtener la respuesta de la base de datos usaremos consultas.

¿Qué ventajas tiene este sistema?. Que no solo “aprende” datos, si no que también las relaciones entre ellos y la forma de calcularlas.

En el siguiente ejemplo vemos qué se define el concepto de abuelo y en lugar de añadir abuelo(juan, javi) añadimos la regla genérica para calcularlo.

padre(juan, jose). # juan padre de jose
padre(jose, javi). # jose pare de javi
abuelo(X,Y):-padre(X,Z), padre(Z,Y).

Probamos la query:

abuelo(juan, X)

Se comporta igual que si hubiéramos introducido el dato directamente abuelo(juan, javi).

Otra ventaja de la programación lógica es que es comprensible por los seres humanos, bueno al menos por algunos de ellos.

Usando Prolog desde Javascript

La cosa se complicó en este punto. Si quería que Chispas pudiera usar prolog necesitaba que se pudiera interpretar desde JS. El problema es que no encontré ningún intérprete de programación lógica que encajara con mi idea. O no tenían una sintaxis que me convenciera o no funcionaban bien cuando las reglas se complicaban o lo hacían pero eran muy lentos. Al final el que más me gustaba era el de la página que os he enlazado antes. El único problema es que la web era monolítica y tendría que separar la parte del interprete, encapsularlo y dotarle de una forma de introducir las reglas y leer los resultados que fuera amigable para el desarrollador. Pero eso era fácil de resolverlo programado. Al final el resultado podéis verlo aquí.