Utilizar redes neuronales para resolver un captcha

Aquí tienen una unit llamada CaptchaTrainer que se utiliza para resolver un captcha . Para ello utilizamos la biblioteca open source FANN http://leenissen.dk/fann/wp/ que sirve para implementar redes neuronales artificiales multicapa.

FANN ha sido traducido a 15 lenguajes de programación diferentes, entre ellos no podía faltar Delphi (http://leenissen.dk/fann/wp/language-bindings/ )

Una red neuronal se compone de unidades llamadas neuronas y esta formada por tres capas:
1) Capa de entrada (input layer) que recibe las señales del entorno
2) Capa oculta (hidden layer)
3) Capa de salida (ouput layer)
Cada neurona recibe una o varias entradas y tiene una o varias salidas que viene dada por una serie de funciones:
- Función de propagación: (también conocida como función de excitación), que por lo general consiste en la entrada (suma de todas las señales de entrada) multiplicada por el peso de su interconexión.
- Función de activación, que modifica a la anterior. Puede no existir, siendo en este caso 
Función de transferencia, que se aplica al valor devuelto por la función de activación. 
Se utiliza para acotar la salida de la neurona. Algunas de las más utilizadas son la función sigmoide (genera outputs de valores en el intervalo [0,1]) y la tangente hiperbólica (genera outputs de valores en el intervalo [-1,1])

El número de neuronas de entrada se selecciona en función de las variables de entrada del problema que queramos predecir.
Número de capas ocultas: Las capas ocultas proporcionarán a la red la capacidad de generalizar. En la práctica, se suelen usar redes neuronales con una o dos capas ocultas. Sin embargo, no hay un criterio natural acerca de la fórmula de selección óptima del número de neuronas ocultas. Baily y Thompson (1990) sugieren que el número de neuronas ocultas en una red neuronal de tres capas debe ser de 75% del número de neuronas de entrada mientras que Ersoy (1990) propone duplicar el número de neuronas ocultas hasta que el rendimiento de la red comience a deteriorarse.

Bien, después de esta introducción a las redes neuronales pasamos a comentar lo que hace esta unit:
Inicialmente se crea la red neuronal definiendo el número de entradas en las  3 capas:  entrada, salida y oculta. 
Como la entrada de la red es el bitmap del captcha, el número de neuronas de la entrada sería el tamaño del bitmap bitmapWidth * bitmapHeight.
Hay que tener en cuenta que los valores de cada una de las entradas / salidas siempre serán 1 o 0 (  fInputs[i]:= [1/0]     fOutputs[i]:= [1/0]   )  

Después necesitamos entrenar la red y para ello utilizamos la función Learn que tiene 2 parámetros de entrada: el captcha en formato bitmap y el número que representa y cuando terminemos el entrenamiento utilizaremos la función Guess  para probar la precisión de ese reconocimiento.

Otro aspecto a comentar es la línea 
 result := FANN.Train(fInputs, fOutputs);
del procedimiento Learn, y es que la variable result representa el error cuadrático medio del valor obtenido por la red respecto del valor esperado, por lo que debemos intentar que este error sea lo más pequeño posible para hacer que la red sea lo más precisa posible.


unit CaptchaTrainer;

interface

uses
  SysUtils, Graphics, FannNetwork;

type
  TCaptchaTrainer = class
  private
    fInputs, fOutputs: array of single;
  public
    FANN: TFannNetwork;
    constructor Create;
    procedure CreateNN(numInputs, numOutputs: integer); overload;
    procedure CreateNN(bitmapWidth, bitmapHeight, numOutputs: integer); overload;
    procedure LoadNN(fileName: string);
    procedure SaveNN(fileName: string);
    function Learn(bitmap: TBitmap; value: integer): single;
    function Guess(bitmap: TBitmap): integer;
    destructor Destroy; override;
  end;

implementation

{ TCaptchaTrainer }

function MaxValueIndex(const Data: array of Single): integer;
var I: Integer;
    maxvalue: single;
begin
  maxvalue := Data[Low(Data)];
  result := Low(Data);
  for I := Low(Data) + 1 to High(Data) do
    if maxvalue < Data[I] then
    begin
      maxvalue := Data[I];
      result := I;
    end;
end;

constructor TCaptchaTrainer.Create;
begin
  FANN := TFannNetwork.Create(nil);
  with FANN do
  begin
    ActivationFunctionHidden := afFANN_SIGMOID;
    ActivationFunctionOutput := afFANN_SIGMOID;
    TrainingAlgorithm := taFANN_TRAIN_RPROP;
    ConnectionRate := 1;
    LearningRate := 0.1;
  end;
end;

procedure TCaptchaTrainer.CreateNN(numInputs, numOutputs: integer);
begin
  SetLength(fInputs, numInputs);
  SetLength(fOutputs, numOutputs);
  with FANN.Layers do
  begin
    Add(IntToStr(numInputs));
    Add(IntToStr(50));
    Add(IntToStr(numOutputs));
  end;
  FANN.Build;
end;

procedure TCaptchaTrainer.CreateNN(bitmapWidth, bitmapHeight,
  numOutputs: integer);
begin
  SetLength(fInputs, bitmapWidth * bitmapHeight);
  SetLength(fOutputs, numOutputs);
  with FANN.Layers do
  begin
    Add(IntToStr(bitmapWidth * bitmapHeight));
    Add(IntToStr(50));
    Add(IntToStr(numOutputs));
  end;
  FANN.Build;
end;

destructor TCaptchaTrainer.Destroy;
begin
  FANN.UnBuild;
  FANN.Free;
  inherited;
end;

function TCaptchaTrainer.Guess(bitmap: TBitmap): integer;
var x,y,i: integer;
begin
  i:=0;
  for x:=0 to bitmap.Width-1 do
    for y:=0 to bitmap.Height-1 do
    begin
      if bitmap.Canvas.Pixels[x,y]=$00000000 then fInputs[i]:=1 else fInputs[i]:=0;
      inc(i);
    end;
  FANN.Run(fInputs, fOutputs);
  result := MaxValueIndex(fOutputs);
end;

function TCaptchaTrainer.Learn(bitmap: TBitmap; value: integer): single;
var x,y,i: integer;
begin
  i:=0;
  for x:=0 to bitmap.Width-1 do
    for y:=0 to bitmap.Height-1 do
    begin
      if bitmap.Canvas.Pixels[x,y]=$00000000 then fInputs[i]:=1 else fInputs[i]:=0;
      inc(i);
    end;
  for i:=0 to high(fOutputs) do if i=value then fOutputs[i]:=1 else fOutputs[i]:=0;
  result := FANN.Train(fInputs, fOutputs);
end;

procedure TCaptchaTrainer.LoadNN(fileName: string);
begin
  FANN.LoadFromFile(fileName);
end;

procedure TCaptchaTrainer.SaveNN(fileName: string);
begin
  FANN.SaveToFile(fileName);
end;

end.


Te puede interesar:
Red neuronal backpropagation 
Redes neuronales con delphi
Crear un captcha con delphi

Pulsa aquí si quieres un buen libro sobre redes neuronales. 



Ver el patrón de interferencia de dos fuentes de radiación coherentes.


En física, una interferencia es un fenómeno en el que dos ondas se superponen para formar otra nueva, que será de mayor o menor amplitud. Si ambas ondas tienen la misma frecuencia  entonces la onda resultante variará en función de la fase.

Young.gif
El siguiente programa muestra el patrón de interferencia de dos fuentes de radiación coherentes.
Para hacerlo visible tenéis que hacer un clic mantenido  sobre la imagen y a continuación mover el ratón en cualquier dirección. 
La fuente 1 será la posición inicial del clic y la fuente 2 será la posición del ratón en la que dejéis de hacer clic.

Ejemplos:

La fuente 1 y la fuente 2 están en la misma posición, en el centro de la imagen:



Ambas fuentes están ligeramente desplazadas.


La separación es aún mayor.



Enlace | Codigo fuente



Autor:
 Podsekin Igor aka WondeRu 
  wonderu@mail.ru
  www.wonderu.h12.ru

Escuchar la radio por streaming


Con este programa podrán escuchar emisoras de radio que difundan su programación en streaming por internet. Viene con varias emisoras pre-programadas, aunque como se tiene acceso al código fuente se puede cambiar por la que queramos.
Aquí tienen algunas: 


http://www.sky.fm/mp3/the80s.pls
http://www.sky.fm/mp3/bebop.pls
http://www.sky.fm/mp3/christmas.pls
http://www.sky.fm/mp3/christian.pls
http://www.sky.fm/mp3/jazzclassics.pls
http://www.sky.fm/mp3/lovemusic.pls
http://www.sky.fm/mp3/pianojazz.pls
http://www.sky.fm/mp3/smoothjazz.pls

Utiliza la librería bass.dll que se descarga desde aquí http://www.un4seen.com/ , de todas formas ya la incluyo en el código fuente en el link de abajo.


Codigo fuente

Relacionados

Vumetro con delphi
Visualizar el espectro de frecuencias de sonido
Reproducir archivo MIDI en piano virtual 
Tutorial - utilizar el componente Media Player
Simular teclado de un piano 


Si quieres profundizar más en la tecnología streaming de vídeo y audio pulsa aquí