Thot 1.3 Released

Cambié la técnica de escalado de las fuentes.

Radicalmente.

Esto tiene una gran ventaja, que es la generación de conjuntos de datos mucho más homogéneos, y por tanto, una facilidad mucho mayor para las redes neuronales de aprender bajo dichos datos. A la vez, me deshice del problema del Font Padding, que es espacio extra que una fuente utiliza para generar una cadena en pantalla. (Gracias Graphics.MeasureString! No fuiste muy útil pero sí performante).

Sin embargo, con ello viene una gran desventaja, que es el tiempo extra de procesamiento (y claro! lo proceso todo a mano), pero por suerte arreglé el bug de la barra de progreso y algunos detalles más de la aplicación y el deploy.

Download de Thot, aquí.

Soy un zorrinito cambiante.

(Read more →)

OCR con Redes Neuronales en MatLab

Esta es una investigación, a modo de trabajo práctico que me pidieron para la universidad en la que estoy. La idea básica es construir un OCR en MatLab, utilizando redes neuronales. Acá está hecho de una determinada manera, que en conjunto con Thot, se logró un error de alrededor del 56%. Obviamente, no es nada bueno ni aceptable para una aplicación real, pero al menos funciona. Es el comienzo de algo.

Recién hoy que el trabajo fue presentado puedo mostrarlo públicamente. El código es sólo para MatLab 2007. Lo lamento gente, es eso o nada.

Pueden revisar el código o la documentación (a la vez de las diapositivas para las explicaciones que dí de esto) en http://alphagma.googlepages.com/.

Dicho sea de paso, ya se vienen varias mejoras. Pero no digo nada al respecto para que no me apuren. Hoy por hoy es 56% de error y punto.

Soy un zorrinito neuronal.

(Read more →)

Link del día: Introduction to Genetic Algorithms

Link aquí.

No se fijen en la página pedorra. :P

Si bien esto no es demasiado avanzado, es una introducción dentro de todo interesante a los algoritmos genéticos, aquellos algoritmos que evolucionan para lograr un objetivo que se desconoce cómo hacer o para mejorar la forma en que lo hace. El enfoque que acá se da no es tan biológico respecto de la teoría de la evolución (que es el clásicamente abordado cuando se tratan estos temas), sino que tiene un enfoque más matemático y probabilístico… válido también.

Tiene un programita para ver algo así en funcionamiento, pero la verdad no lo probé.

Soy un zorrinito genético.

(Read more →)

Link del día: BrowserShots

El site al que puede acceder aquí, es relativamente conocido.

Lo que hace básicamente es visitar un mismo site con distintos navegadores y distintas opciones (ej: Javascript, Java, Flash activado/desactivado, etc), que permite a un desarrollador web ver qué tan bien o qué tan mal están saliendo sus diseños para otros navegadores aparte de los que dispone él.

Si bien está muy buena la idea, este site anda a medias (sí, lo lamento, si quieren que hable mejor de él tendrán que pagar su cuota), porque a veces las sesiones expiran antes de que salgan las imágenes para todos los navegadores que uno eligió, y al final, tiene que volver a hacerlo.

Pero, en fin, sigue siendo novedoso.

Soy un zorrinito fotografiado.

(Read more →)

Link del día: CSS Sandbox

Link aquí.

Esto seguro le sirva a alguno.

Cuando trabajan con hojas de estilo, a veces no les da por probar a ver qué queda mejor, pero en el medio terminan rompiendo todo lo que hicieron? Bueno, para eso es esta paginita, en la que pueden cambiar las cosas a gusto a ver “qué tal se ve”. En mi opinión le faltan un par de detalles, pero igual está buena.

Soy un zorrinito sandbox.

(Read more →)

Thot 1.2 Released

Ahhhhhhhhhhhh! Esto de las redes neuronales es medio mágico, porque hay cosas que las produce la gracia de la diosa fortuna y otras que son pura intuición y nadie nunca te habría sabido decir si te servía o no (hay un tercer grupo catalogado como “calculable”… pero a nadie le importa, ya hay fórmulas para eso).

Le implementé a Thot un escalado y centrado de las imágenes en el entorno a ser dibujadas… y mi red bajó el error de pruebas desde un 90% a un 70%.

La magia, la magia.

Download de Thot aquí.

Soy un zorrinito mágico.

(Read more →)

Thot 1.0 Released

Para bajar, aquí: http://alphagma.googlepages.com/

Este programa es la fuente de datos para un sistema de redes neuronales a diseñar próximamente, para un trabajo académico sobre OCR.

La idea es que sobre la imagen de una letra se generan perceptores, y en el archivo de salida se indicará para cada letra elegida de cada fuente seleccionada la cantidad de veces que dicho perceptrón cruza la letra. Estos números serán procesados por una fuente neuronal que luego será capaz de reconocer las letras una vez entrenada con estos datos.

Desde ya debo agradecer muchísimo a JF por su ayuda con la implementación de fórmulas y la aproximación de las mismas a nivel pixel, junto con su orientación de manejo de imágenes. También a Gato Gris por su idea en cuanto a la forma de encararlo, que mejoró la performance y permitió la posibilidad de identificar múltiples cruces.

Soy un zorrinito programador.

(Read more →)

Servicios de Presupuesto - Modelo Iteración 1

Como ejercicio para la universidad, tengo que desarrollar un servicio de presupuestación para una empresa ficticia. Voy a ir publicando de a poco lo que voy haciendo, muy probablemente le sea útil a alguien más.

Notesé que vamos (somos dos personas en grupo) a estar trabajando en un sistema iterativo en espiral, por lo que en estas primeras entregas no vamos a tener el sistema terminado, sino que de a poco se irán acercando a la versión final.


Mail mío del 28/06/2007:

XXX,

para los casos de uso que vamos a implementar, tenemos que implementar las siguientes clases del modelo. No son pocas y sus relaciones no son simples, así que lo voy a hacer lo más explicativo que pueda. Cualquier cosa me mandás un mail, me llamás, me mandás un mensaje de texto, me golpeás la puerta de casa, me tirás piedras en el auto, me comprás un sandwich de mortadela, me barrés el piso y me programás el sistema.

Antes que nada, todas las clases que vamos a hacer se denominan de modelo, es decir, son los que representan las entidades persistentes. Luego vamos a tener que implementar otros dos tipos. Las de lógica de negocio (que, para ser ordenados, irán aparte), y las de interfaces (también aparte, solamente para ser ordenados).

Por tanto, todas las clases que explico luego irán en un mismo paquete, denominado com.jarc.presupuestario.model. Por qué el nombre? Es una convención que se sigue, relacionado con la forma en que se ponen los namespaces en XML o la forma inversa a como se hace en .NET… pero bue’, tampoco me quiero ir de tema.

Otro tema es que para cada elemento, los atributos serán de tipo protected. La idea de esto es que sean privados, pero que si la clase es heredada por otra, pueda usarlos también. NINGUN ATRIBUTO ES PúBLICO. Aparte de eso, cada atributo va a tener una operación asociada setter y otra getter, como ya viste. Por ejemplo, atributo String nombreDeUsuario, tendría String getNombreDeUsuario(); y void setNombreDeUsuario(String nombreDeUsuario);. Los casos en donde esto no ocurre son de verdad muy pocos, en cuyo caso lo señalaré. En el resto, TODOS los atributos tienen su correspondiente setter y getter, respetando el mismo orden de mayúsculas y minúsculas también.

Otra consideración general: para todo lo que sea monetario, vamos a usar una clase de Java llamada BigDecimal. La razón de esto es que al usar uno de los tipos predefinidos para decimales, como float o double, nos vamos a comer un bug tremendo que ocurre en la multiplicación y la división, en donde a veces te da un resultado erróneamente redondeado. En realidad no es un problema de Java sino de la representación en memoria del IEEE de los comas flotantes, pero bue’, nosotros usamos _BigDecimal _y punto.

Vamos a la posta:

Dado que vamos a implementar el Login como uno de los casos de uso, vamos a tener que tener los usuarios. Esta es la clase Usuario, que tiene los campos nombreUsuario y password, ambos String.

Una clase heredada de este ** Usuario** es Empresario. Este va a representar al tipo que se loggea como empresario, aunque en las interfaces le digamos que es administrador o algo parecido. Le dejamos ese nombre de clase porque es más significativo para nosotros. Por ahora tiene un solo atributo (no se me ocurrió ninguno, acá podés innovar tranquilo si querés - solo avisame) que es nombreResponsable.

Otra clase que es hija de Usuario es Cliente. Esta representa al tipo que se loggea como cliente, que pide los presupuestos (dado que también vamos a implementar el caso de uso “Solicita Presupuesto”). Los datos del cliente son: nombre, direccion, telefono, email. (Notesé el uso de minúsculas y ninguna cosa rara para emular los acentos).

Un elemento pesadito para nuestro sistema es la clase ** Presupuesto**. Pero antes de esta, vamos a tener que implementar los items, dado que en realidad son estos los que mueven todo el sistema.

Cada tipo de item puede ser uno de tres, como ya sabíamos: un artículo individual, un producto complejo (hecho de artículos individuales) o un servicio.

Por tanto, vamos a tener una clase Item que tiene los siguientes atributos: descripcion, nombre. ** nombre** es el nombre que se le da al ítem y la descripcion es toda la verdura que quiera explicar el empresario al respecto. Una nota IMPORTANTE es que además esta clase contiene dos métodos virtuales llamados getPrecioTotal() y getCostoTotal(). Estos serán implementados en cada uno de las clases que hereden de esta. Así, según el polimorfismo, cada clase resolverá como devuelve el precio total y el costo total de ese item, sin importar si tiene que ver un solo número, o recorrer dos mil.

Ahora, según sea este item en particular, tendremos una de tres clases, correspondientes a los tres tipos de item.

Así, tendremos la clase Articulo. No tiene nada de loco. Tiene su precio y su costo, los asigna y los devuelve. El precio es el precio que se usa para la venta. El costo es el precio al cual el empresario lo compra. Obviamente, getPrecioTotal() va a devolver el precio y

Ahora, la clase ** Servicio** es distinta. Esta clase, además de heredar las correspondientes de Item, va a agregar cuatro atributos. Estos son: ** nombreUnidad, precioPorUnidad, costoPorUnidad, cantidadUnidades. El atributo **cantidadUnidades se refiere a una cantidad entera, por lo que con un tipo ** int** está bien. El motivo de que sea así es poder medir cuestiones que no tienen un precio fijo por unidad, o que no son artículos pero se agregan por alguna razón. Por ejemplo, impuestos, flete, etc. El caso del flete es el más versátil, en donde todo toma sentido. Supongamos que por cada 100 metros recorridos, cueste $10, y se cobre $15. Si para vender un producto complejo se mandó un flete a 2 kms, las variables valdrían costoPorUnidad = 10.00, precioPorUnidad = 15.00, nombreUnidad = “100 metros”, cantidadUnidades = 20. Así, Servicio debe implementar:

  • *getPrecioTotal() **como _precioPorUnidadcantUnidades_
  • *getCostoTotal() **como _costoPorUnidadcantUnidades_

Otro caso es el de los objetos ** ProductoComplejo. Pero antes de hablar de este, voy a hablar de otra clase, una llamada **ListadoItems. Esta clase ListadoItems lo que nos permite es tener encerrado en una clase todo lo necesario para poder manejar múltiples items como uno solo, sean del tipo que sean. Si bien para la funcionalidad que le vamos a dar en este caso de uso, podría usarse muy fácilmente un ArrayList y punto, no lo vamos a hacer así por que esto no nos permitiría tener encerrada esa lógica, por lo que tendría que estar repartida en cualquier otro lugar donde se use (y se va a usar en otros lugares). Entonces, es necesaria.

Esta clase, Sí tendrá dentro suyo un ArrayList de objetos Item, y tendrá los métodos:

  • Item agregarItem(Item item): agrega el item pasado al ArrayList y lo devuelve.
  • removerItem(Item item): remueve el item pasado del ArrayList.
  • Item getItem(int index): devuelve el item que esté en la posición index del ArrayList.
  • int getCantidadItems(): devuelve la cantidad de items que hay en el ArrayList.
  • BigDecimal getPrecioTotal(): devuelve la suma de todos los precios totales del ArrayList.
  • BigDecimal getCostoTotal(): devuelve la suma de todos los costos totales del ArrayList.

Con eso, tenemos lo suficiente para manejar los items, y mantener la lógica de forma cerrada y heredable en caso necesario.

Esta clase será usada por varias otras, entre ellas el ProductoComplejo. Este tendrá, aparte de un atributo itemsFabricadores que será del tipo ListadoItems, un atributo costoFabricacion y un atributo precioAgregado . ProductoComplejo implementará:

  • getPrecioTotal() como itemsFabricadores.getPrecioTotal() + precioAgregado
  • getCostoTotal() como itemsFabricadores.getCostoTotal() + costoFabricacion

Finalmente, tenemos todos los elementos que conformarán a un item, cualquiera que sea. Sea lo que sea, podrá ser contenido por una clase Item.

Así, estamos en condiciones de ver nuestra clase Presupuesto. Esta clase va a tener tres atributos. ** cliente, de tipo **Cliente (el cliente que pidió ese presupuesto), ordenDeCompra de tipo OrdenDeCompra (IMPORTANTE: no tenés que implementarlo. Pone en el código que falta ese atributo y comentale la línea. Es para que no falte en el futuro). Y un último atributo llamado estado, que será de tipo EstadoPresupuesto.

Notesé que EstadoPresupuesto no será una clase, sino simplemente un Enum global. Para esto hacé una clase estática y hacé un tipo Enum ahí suelto, que quede separado del resto en una clase estática donde vamos a meter toda la mierda que no va instanciada en ningún lado. Acordate que los valores que forman parte de ese enum son: Solicitado, Preparado, Rechazado, Aceptado, y EnProduccion.

PD: Te mando una imagen con un diagrama de estas clases. En lugar de ayudarte te va a complicar más y te acerca en un 0.05% a la embolia cerebral. Pero es un problema que resuelve tu instancia, no la mía. xD

PD 2: Me olvidé de decir que la clase Presupuesto es hija de la clase ListadoItems. Esto es porque debe tener toda la funcionalidad que tiene un listado de items. De hecho, es básicamente un listado con un poco más de funcionalidad. Me olvidé de mencionarlo pero en el diagrama está indicado.

Soy un zorrinito diseñador.

(Read more →)

Gerenciamiento difuso

Muchas veces nos hemos encontrado con el problema de querer decidir las cosas por simple democracia. El proceso es simple. Se da un problema, se proponen soluciones, cada uno pone su voto por una y solo una solución, y la solución con más votos es la llevada a cabo por el grupo. A pesar de que muchos no estén de acuerdo, es lo que la mayoría quiere y por tanto es lo que mejor se cree en general que se puede hacer.

Como ejemplo ilustrativo, supongamos que los votantes son las personas P1, P2, P3, P4 y P5. Se plantea un problema y se presentan tres soluciones: S1, S2 y S3.

Si P1 pone su voto por S1, P2 y P3 lo ponen por S2, y P4 y P5 lo ponen por S3, entonces al hacer el recuento de votos nos encontraremos en la siguiente situación:

Solución Cantidad de votos
S1 1
S2 2
S3 2

En este caso, el problema obvio es que no se puede decidir por una solución inmediatamente, puesto que no hay una definida en donde la mayoría haya decidido. En estos casos, muy comúnmente se apela a una segunda vuelta, en donde las soluciones que de seguro no serán elegidas por la mayoría son descartadas. En nuestro ejemplo, podemos ver que S1 no será elegida como la última solución, de modo que quedará descartada. Se volverá a hacer una votación, y el proceso se repetirá varias veces si es necesario, hasta que haya una solución “ganadora”.

Podemos suponer que en este caso, al ser descartada la solución S1, P1 deberá elegir otra de las opciones, a pesar de que no sea su favorita. Este es el caso conocido vulgarmente como la votación por el “menos peor”, por lo que elige de las otras soluciones la que más satisface sus necesidades o expectativas.

Solución Cantidad de votos
S2 3
S3 2

Si en nuestro ejemplo, P1 se decidió por S2, entonces habrá una clara mayoría en las votaciones, y puede definirse a S2 como la ganadora.

Este sistema de votación, tan básico y directo, es el sistema utilizado en muchas naciones como sistema de elección político. También suele utilizarse en la administración de negocios para la toma de decisiones en un grupo, o incluso suele hacerse así en una reunión entre amigos decidiendo qué comer.

Sin embargo, existe un grave problema en estas situaciones. Supongamos que P1 nunca hubiese formado parte del grupo, y que por tanto, S2 y S3 solo hubiesen obtenido 2 votos cada una. ¿De qué manera se resuelve cuál es la mayoría?

Muchas veces se supone que eso nunca va a ocurrir (como en las elecciones políticas), muchas veces se resuelve por medio del azar (como arrojando una moneda al aire entre amigos), o muchas veces se coloca una ponderación sobre los votos (como en los grupos dirigentes de empresas - si el director de la empresa eligió S2 entonces ante la indecisión, se sigue ese camino).


Hace poco se me pidió que diseñe un sistema de votación para un grupo reducido (par - pueden haber empates), en donde no puede haber ponderación de votos, y el azar no es un método fiable por los medios que este grupo maneja.

Durante un tiempo lo pensé sin muchas soluciones, pero luego tuve la inspiración de atacar a las constantes del sistema para cambiarlo. Es decir, ¿cómo surgían las tres alternativas que planteé hasta recién?

La del suponer que eso nunca ocurrirá, en el caso de las elecciones políticas, surge por la improbabilidad del caso. Supongamos que quizás las personas de un país no sólo son de un número par (posibilidad: 50%), sino que es prácticamente imposible que en la votación a dos candidatos, exactamente la mitad elija a uno, y exactamente la mitad elija a otro. Eso es el cambio de una constante: las reglas de votación suponen la posibilidad de que exista este empate ideal… esa posibilidad, esa “constante” (valor que existe por la forma de las reglas) existe. Nosotros la cambiamos, hacemos que no exista simplemente al no tenerla en cuenta por la baja posibilidad del caso.

En el sistema ponderado, como el del grupo dirigente de la empresa, se cambia otra constante. Todos los votos valen iguales, por ejemplo, “1 voto”, como unidad de medida. Con otro criterio, los votos de otros (grupo superior, líder de la empresa, accionista o quién fuera) valen más, por ejemplo “1.2 votos”. En caso de un empate de “cantidad”, estos votos ponderados serán los que hagan desaparecer la posibilidad de empate. Se cambia, en pocas palabras, el valor constante de cada voto.

En el último ejemplo que nombré, el de los amigos, la constante que se cambia es la cantidad de votantes. Al haber un empate, debe crearse una forma en la que un elemento externo introduzca una variación en ese sistema “equilibrado” entre la cantidad de gente que elige una solución y la gente que elige otra. Tanto una moneda, como un dado, como cualquier elemento que esté fuera del control de los involucrados (si es que se va a hacer de una forma “justa”). De esta forma, se cambia la constante de la cantidad de votantes.

En mi caso particular, tuve la idea de cambiar otra constante… aunque son dos en realidad: la cantidad de votos por votante, junto con la ponderación de la votación.

Inspirado en los sistemas difusos, se me ocurrió la posibilidad de que cada votante otorgara una puntuación a cada solución posible.

Supongamos el caso anterior, en donde los votantes son P1, P2, P3, P4 y P5. Las soluciones son S1, S2 y S3. A continuación, veremos una posible situación en donde cada votante vota las soluciones con un puntaje del 1 al 10.

Votante Solución Puntaje Otorgado
P1 S1 10
  S2 7
  S3 2
P2 S1 4
  S2 7
  S3 2
P3 S1 4
  S2 9
  S3 1
P4 S1 6
  S2 2
  S3 10
P5 S1 4
  S2 4
  S3 8

En letra cursiva podemos apreciar como, al igual que en el primer ejemplo, P1 tiene preferencia por S1, P2 y P3 tienen preferencia por S2 y por último, P4 y P5 tienen preferencia por S3. Esto se manifiesta en que esas opciones recibieron más puntajes que las demás. El resto de las opciones recibió también un puntaje, y a la vez la solución elegida tampoco tiene por qué recibir el puntaje máximo (como es el caso de P5 decidiéndose por S3 o P3 decidiéndose por S2).

En este sistema, la solución elegida sería la que obtuviera mayor puntuación. En este ejemplo:

     
S1: ∑ S1(Pi) =  
  = S1(P1) + S1(P2) + S1(P3) + S1(P4) + S1(P5) =  
  = 10 + 4 + 4 + 6 + 4 = 28
S2: ∑ S2(Pi) =  
  = S2(P1) + S2(P2) + S2(P3) + S2(P4) + S2(P5) =  
  = 7 + 7 + 9 + 2 + 4 = 29
S3: ∑ S3(Pi) =  
  = S3(P1) + S3(P2) + S3(P3) + S3(P4) + S3(P5) =  
  = 2 + 2 + 1 + 10 + 8 = 23

Siguiendo el anterior ejemplo, podríamos ver que si P1 no está en el grupo para votar, los resultados serían de la siguiente forma:

     
S1: ∑ S1(Pi) =  
  = S1(P2) + S1(P3) + S1(P4) + S1(P5) =  
  = 4 + 4 + 6 + 4 = 18
S2: ∑ S2(Pi) =  
  = S2(P2) + S2(P3) + S2(P4) + S2(P5) =  
  = 7 + 9 + 2 + 4 = 22
S3: ∑ S3(Pi) =  
  = S3(P2) + S3(P3) + S3(P4) + S3(P5) =  
  = 2 + 1 + 10 + 8 = 21

En el caso hipotético en que las soluciones resultantes tuvieran igual puntuación, se puede implementar la teoría del método Delphi. Este método habla de hacer sucesivas rondas. En la primera ronda, cada uno hace una ponderación de las opciones, sin conocer la puntuación que los demás otorgan. Al no ser satisfactoria la solución, se hace una segunda ronda. Obviamente, al haber visto los puntajes de los demás, algunos considerarán que algunas ponderaciones propias no eran del todo correctas y las variarán.

Si luego de la segunda o tercera ronda de hacer estos cambios, aún no se llega a una determinación satisfactoria, cada integrante explica las razones de su propias puntuaciones, detallando los pro y los contra que le llevó a poner un determinado puntaje a una determinada solución. Luego de esto, se hace otra ronda más, en donde cada integrante pone una nueva puntuación a cada una de las soluciones propuestas, pensando en todos los pros y los contras expuestos.


Con este sistema, no sólo se hace mucho más difícil el problema que tiene la “democracia par”, que es el de los empates y su resolución, sino que además no se descartan soluciones sino que se tienen en cuenta según el grado de aceptación que estas tienen, que es lo más administrativamente correcto para poder llevar un buen manejo de las decisiones tomadas.

Soy un zorrinito gerencial.

(Read more →)