twitter y la inteligencia artificial

Me gusta encontrarme algoritmos de inteligencia artificial en aplicaciones comerciales, me sirve para comprobar que tiene sentido la investigación a pesar de que durante años no se han obtenido muchos resultados prácticos. La última que me he encontrado es una nueva parte de twitter, que planea insertar tweets promocionados en los resultados de las búsquedas,  al estilo de lo que hace google en sus resultados de búsquedas. Cómo explica Michael Bernstein en un reportaje de technology review esto supone un gran desafío para twitter: el hecho de limitarse a 140 caracteres hace complicado extraer conocimiento de un texto tan corto. Lo habitual en los algoritmos de extracción de información es utilizar las palabras más relevantes, muchas veces buscando las palabras más frecuentes. Pero con mensajes de 140 caracteres es mucho más complicado obtener información.

Otra aplicación que utiliza algoritmos de inteligencia artificial es hunch, que utiliza técnicas de aprendizaje e inferencia estadística para predecir respuestas en cuestionarios generales. Tiene un juego que analiza tus contactos en twitter, los compara con su base de datos y predice las respuestas que vas a dar a los cuestionarios. El indice de aciertos es sorprendentemente alto (merece la pena probarlo, es divertido), pero creo que el truco está en el tipo de preguntas que realiza. No son tan sencillas como los juguetes que adivinan lo que estás pensando en 20 preguntas, pero tampoco son excesivamente complejas y bastantes están relacionadas entre sí (acertando una de las respuestas, es muy probable saber qué vas a responder en la otra).

Hunch es un ejemplo de lo que creo que va a pasar en tecnología: partiendo de los apis de desarrollo de las diferentes redes sociales y plataformas de internet, deberían aparecer servicios más abstractos y genéricos, que aporten más conocimiento y mejoren la funcionalidad de la aplicación haciendola más inteligente.

internet of things

Parece que el concepto de internet de las cosas (internet of things) está cuajando poco a poco. Últimamente circula un vídeo de IBM sobre este concepto que está bastante bien:

No es un concepto nuevo, según la wikipedia se originó a finales de los 90 en el MIT y fue cuajando poco a poco con la idea de RFID. Ahora no sólo se piensa en etiquetar los objetos sino en añadir microprocesadores para dotarlos de más inteligencia y capacidad de reacción. No sólo conseguir que los objetos hablen si no que interaccionen. Cómo ya he comentado, mi último proyecto personal va en esta línea. Y la parte más importante de todo este mar de datos es la inteligencia artificial, que es la que le daría valor a los datos. Yo me quedo con la interconexión primero, con la capacidad de obtener datos. Después ya vendrá la inteligencia.

¿seres reemplazables?

Una frase que ha aparecido en Microsiervos:

En la sociedad del conocimiento, todo aquel que pueda ser sustituido por una máquina merece serlo.

Paradójicamente, es posible que muchos trabajos considerados de la sociedad del conocimiento sean sustituidos por ordenadores antes que muchos trabajos físicos o mecánicos. Tal y como evoluciona la robótica y la inteligencia artificial, algunas tareas cómo la toma de decisiones sean más automatizables que ciertos trabajos físicos.

Un ejemplo sencillo sencillo de mi cosecha: aunque existen robots capaces de tocar el violin, también existen programas capaces de componer obras musicales automáticamente. Y creo que probablemente se desarrollen más rápidamente los programas de composición que los robots con capacidades fisicas, pero no es más una intuición.

inteligencia artificial en la práctica

¿Qué tienen en común la ineligencia arificial, la semántica y la publicidad? En principio parece que muy poco, son términos que estamos acostumbrados a verlos por separado. Sin embargo como explican en el blog de google adsense la semántica y la publicidad están relacionadas. Y aunque no lo menciona, el análisis de textos para la comprensión semántica es un problema de la inteligencia artificial.

Se puede decir que actualmente es lo suficientemente buena para que la pubicidad contextual funcione, pero no es todo lo buena que podría ser. De forma elegante en esa entrada comentan que la definición de relevancia difiere de a definición humana. ¿Existe una definición de relevancia no humana? Creo que no, el problema es que la relevancia humana es dificil de modelar y por eso los resultados difieren.

En cualquier caso se trata de un problema complejo que está siendo resuelto con técnicas propias de la inteligencia artificial y que es relevante porque una empresa tecnológica como google depende de que su tecnología esté a la vanguardia.


ruby sbn

El segundo elemento que tengo pensado utilizar en mi nuevo proyecto se trata de sbn una librería ruby que permite trabajar con redes bayesianas. Aunque la inferencia está limitada a un algoritmo de resolución aproximado, el Markov Chain Monte Carlo, por lo poco que he probado, esta librería es suficiente para mi proyecto, aunque me gustaría que tuviese algún método de inferencia exacto para poder comparar.

Voy a poner un código sencillo y de paso comento algún detalle de este proyecto sin nombre. Me he decidido a implementar un “adivino del futuro” que funciona de forma aleatoria. La idea es generar un mensaje de texto aleatorio que contiene una serie de variables aleatorias: suerte, amor, salud, riqueza. Hasta ahora he construido una red bayesiana que determina la relación entre estas variables y otras derivadas, para que el mensaje sea coherente (aunque sea aleatorio). Por ejemplo, en el caso del trabajo, si eres afortunado en la riqueza, es posible que que también tengas suerte en el trabajo, pero entonces puede que tu familia te eche de menos y no seas tan afortunado en el amor.

Por ahora he construido una red bayesiana que determina la relación entre una serie de parámetros. La red estará generada “a mano” para que los mensajes que se generen sean divertidos y más o menos coherentes. La descripción de los valores que maneja la red es esta:

  • suerte: es el factor principal de la red, el resto de variables dependen directa o indirectamente de la suerte.
  • amor: todos sabemos lo que es el amor. Por ahora el único hijo del amor es la familia, que depende directamente de nuestra suerte en el amor.
  • salud: fácil de saber qué significa. La salud determina nuestro trabajo, si no tenemos buena salud no podemos trabajar y viceversa.
  • riqueza: determina cúanto dinero y posesiones tenemos. Una parte de la riqueza depende del trabajo y otra del dinero (cómo algo genérico). He supuesto que si te va bien en la riqueza, lo más probable es que te vaya bien en el trabajo o en el dinero (juegos de azar, bolsa, etc) pero es improbable que te vayan bien o mal las dos cosas a la vez (aunque no es imposible).
  • trabajo: depende de la riqueza y de la salud.
  • familia: la más compleja de las variables de este ejemplo, depende del amor y del trabajo, que a su vez depende de la riqueza y de la salud. La idea es que si tenemos mucho trabajo, nuestra familia se resentirá, aunque le vaya bien a nuestra riqueza.

Se trata de un ejemplo muy sencillo, en el que hay que tener en cuenta que no hablo de causalidad, sino de correlación estadística, pero al fín y al cabo es lo que cuenta para “predecir el futuro” y para darle coherencia al mensaje. Una vez generado el mensaje de “suerte”, el siguiente paso es vestirlo con palabras que expresen correlación o causalidad indistitamente. Éste es básicamente el truco que usan los adivinos: te va bien en el trabajo, entonces tu familia no estará muy contenta, veo tu futuro muy negro, no vas a tener suerte, pero en el amor te va a ir bien, porque tu familia te va a apoyar. Lo complicado será generar estas palabras que expresen la relación causal, espero que wordnet me sirva de ayuda.

El código ruby es muy sencillo y prácticamente se trata del ejemplo de uso de sbn adaptado a este caso:

require ‘rubygems’
require ‘sbn’

#puts “Starting: #{Time.now}”

net = Sbn::Net.new(“Predicting your future”)

#main variable
luck = Sbn::Variable.new(net, :luck, [0.5, 0.5])

#base variables
love = Sbn::Variable.new(net, :love)
luck.add_child(love)
love.set_probability(0.55, {:love => :true, :luck => :true})
love.set_probability(0.45, {:love => :false, :luck => :true})
love.set_probability(0.45, {:love => :true, :luck => :false})
love.set_probability(0.55, {:love => :false, :luck => :false})

health = Sbn::Variable.new(net, :health)
luck.add_child(health)
health.set_probability(0.55, {:health => :true, :luck => :true})
health.set_probability(0.45, {:health => :false, :luck => :true})
health.set_probability(0.45, {:health => :true, :luck => :false})
health.set_probability(0.55, {:health => :false, :luck => :false})

wealth = Sbn::Variable.new(net, :wealth)
luck.add_child(wealth)
wealth.set_probability(0.55, {:wealth => :true, :luck => :true})
wealth.set_probability(0.45, {:wealth => :false, :luck => :true})
wealth.set_probability(0.45, {:wealth => :true, :luck => :false})
wealth.set_probability(0.55, {:wealth => :false, :luck => :false})

#derived variables

work = Sbn::Variable.new(net, :work)
wealth.add_child(work)
health.add_child(work)

work.set_probability(0.8, {:work => :true, :wealth => :true, :health => :true})
work.set_probability(0.2, {:work => :false, :wealth => :true, :health => :true})
work.set_probability(0.2, {:work => :true, :wealth => :true, :health => :false})
work.set_probability(0.8, {:work => :false, :wealth => :true, :health => :false})
work.set_probability(0.5, {:work => :true, :wealth => :false, :health => :true})
work.set_probability(0.5, {:work => :false, :wealth => :false, :health => :true})
work.set_probability(0.1, {:work => :true, :wealth => :false, :health => :false})
work.set_probability(0.9, {:work => :false, :wealth => :false, :health => :false})

money = Sbn::Variable.new(net, :money)
wealth.add_child(money)

money.set_probability(0.6, {:money => :true, :wealth => :true})
money.set_probability(0.4, {:money => :false, :wealth => :true})
money.set_probability(0.2, {:money => :true, :wealth => :false})
money.set_probability(0.8, {:money => :false, :wealth => :false})

family = Sbn::Variable.new(net, :family)
love.add_child(family)
work.add_child(family)

family.set_probability(0.8, {:family => :true, :love => :true, :work => :true})
family.set_probability(0.2, {:family => :false, :love => :true, :work => :true})
family.set_probability(0.6, {:family => :true, :love => :true, :work => :false})
family.set_probability(0.4, {:family => :false, :love => :true, :work => :false})
family.set_probability(0.3, {:family => :true, :love => :false, :work => :true})
family.set_probability(0.7, {:family => :false, :love => :false, :work => :true})
family.set_probability(0.1, {:family => :true, :love => :false, :work => :false})
family.set_probability(0.9, {:family => :false, :love => :false, :work => :false})

#generate evidence
luck_value = rand(2) == 1  ? “true”.to_sym : “false”.to_sym

evidence = {:luck => luck_value}

net.set_evidence(evidence)

#lookup derived variables, and calculate a value

love_value = rand(0) < net.query_variable(:love)[:true] ? true : false
health_value = rand(0) < net.query_variable(:health)[:true] ? true : false
wealth_value = rand(0) < net.query_variable(:wealth)[:true] ? true : false
work_value = rand(0) < net.query_variable(:work)[:true] ? true : false
money_value = rand(0) < net.query_variable(:money)[:true] ? true : false
family_value = rand(0) < net.query_variable(:family)[:true] ? true : false

puts “luck: #{luck_value} [love: #{love_value} " + \
"(family: #{family_value}), health: #{health_value}, " + \
"wealth: #{wealth_value} (work: #{work_value}, money: #{money_value})]“

#puts “end: #{Time.now}”