You are on page 1of 151

UNIVERSIDAD POLITÉCNICA SALESIANA

FACULTAD DE INGENIERIAS
SEDE QUITO – CAMPUS SUR

CARRERA DE INGENIERIA DE SISTEMAS

MENCIÓN ROBÓTICA E INTELIGENCIA ARTIFICIAL

Tema:

DISEÑO Y CONSTRUCCIÓN DE UNA RED NEURONAL


ARTIFICIAL DE PROPÓSITO GENERAL

TESIS PREVIA A LA OBTENCIÓN DEL TITULO DE INGENIERO DE SISTEMAS

DANY ANAEL LÓPEZ LOAIZA

DIRECTOR:
ING. NAVAS RUILOVA GUSTAVO

Octubre 2007
Quito-Ecuador
1

DECLARACIÓN

Yo, Danny Anael López Loaiza, declaro bajo juramento que el trabajo aquí
descrito es de mi autoría; que no ha sido previamente presentado para ningún
grado o calificación profesional; y, que hemos consultado las referencias
bibliográficas que se incluyen en este documento.

A través de la presente declaración cedemos nuestros derechos de propiedad


intelectual correspondientes a este trabajo, a la Universidad Politécnica Salesiana,
según lo establecido por la Ley de Propiedad Intelectual, por su reglamento y por
la normatividad institucional vigente.

_______________________

Danny Anael López Loaiza


2

CERTIFICACIÓN

Certifico que el presente trabajo fue desarrollado por Danny Anael López Loaiza,
bajo mi dirección.

_______________________
Ing. Navas Ruilova Gustavo
3

DEDICATORIA

Dedicado a todas aquellas personas que en lugar de ver una nota, un pago o un
premio; vieron la necesidad y gusto de aprender algo, imaginarlo y verlo
funcionar.

A quien no sigue una carrera esperando encontrar trabajo o buen sueldo.

A quien no aspira emplearse, sino ser fuente de empleo.

A quien no ve el reloj para salir de su trabajo.

A quien comprende que el conocimiento no se puede esconder y sabe


compartirlo.

Y a quien, aún estando en desacuerdo, permite al resto hacerlo.


4

AGRADECIMIENTOS

Expresar en pocas lineas de texto el profundo agradecimiento hacia todas las


personas que hacen posible que alguien tenga la oportunidad de escribir esto, me
resulta más complicado que la redacción del trabajo en sí.

Y pues, si somos resultado de todas las experiencias que vivimos, agradecer a


cada una de ellas resultaría una tarea de más complicada.

Así que para hacer un breve resumen puedo agradecer a mis padres por su
cariño, por todas las oportunidades que me regalan, por hacerme ver el mundo de
otra forma, por solo mencionar unas pocas razones.

A quien estuvo alado mio durante todo este camino de aprendizaje.

A mis amigos quienes nunca me faltaron y estuvieron siguiendo mi mismo


camino, u otro que aunque parecía lejano, a la larga resultó la forma de estar más
cerca.

A mis profesores, tutores, guías, senseis y demás, quienes pudieron ejemplificar y


mostrar el conocimiento de libros en un idioma más entendible para mi.

A mi tutor por su gran paciencia, confianza y sinceridad.

Entre muchas, muchas más a quienes no creo que hago justicia en este
agradecimiento; como al viejo pichirilo que entre atentados físicos y velocidades
nunca vistas, me llevo sano y salvo a mi casa todas las noches durante algunos
años.
5

ÍNDICE DE CONTENIDO
Indice :
. DECLARACIÓN................................................................................................................. 1
. CERTIFICACIÓN............................................................................................................... 2
. DEDICATORIA...................................................................................................................3
. AGRADECIMIENTOS....................................................................................................... 4
. ÍNDICE DE CONTENIDO .................................................................................................5
. RESUMEN.........................................................................................................................13
. PRESENTACIÓN.............................................................................................................. 14
1. CAPITULO I: Introducción al Tema de Tesis................................................................. 15
1.1. Titulo:....................................................................................................................... 15
1.2. Planteamiento del problema: ................................................................................... 15
1.3. Objetivos...................................................................................................................17
1.3.1. Objetivo General...............................................................................................17
1.3.2. Objetivos específicos........................................................................................ 17
1.4. Alcance..................................................................................................................... 18
1.5. Importancia y Justificación.......................................................................................19
1.5.1. Importancia....................................................................................................... 19
1.5.2. Justificación...................................................................................................... 19
2. CAPITULO II: Tecnología DotNET................................................................................20
2.1. Introducción: ............................................................................................................20
2.2. .NET Framework:..................................................................................................... 21
2.2.1. CLI (Common Language Infrastructure).......................................................... 23
2.2.2. BCL (Base Class Library):................................................................................25
2.2.3. CLR (Common Language Runtime).................................................................27
2.2.4. RESUMEN....................................................................................................... 29
2.3. IDE (Integrated Development Environment) para .NET:........................................ 31
2.4. Versiones del .NET Framework:.............................................................................. 34
2.4.1. .NET Framework v1.0: .................................................................................... 34
2.4.2. .NET Framework v1.1: .................................................................................... 34
2.4.3. .NET Framework v2.0: .................................................................................... 35
2.4.4. .NET Framework v3.0: .................................................................................... 35
6

2.5. C# (Sharp), El lenguaje predilecto del .NET framework:........................................ 36


2.6. Trabajando con DotNET.......................................................................................... 38
2.6.1. Introducción:..................................................................................................... 38
2.6.2. Motor Gráfico (GDI+):..................................................................................... 39
2.6.2.1. Lienzo (Graphics):.................................................................................... 40
2.6.2.2. Lápices (Pen):............................................................................................41
2.6.2.3. Brochas (Brush):....................................................................................... 41
2.6.2.4. Figuras Básicas:........................................................................................ 42
2.6.2.5. Manejo de Imágenes:................................................................................ 44
2.6.3. Punteros:........................................................................................................... 46
2.6.4. Hilos (Threads):................................................................................................ 49
2.6.5. Creación de Controles de Usuario:................................................................... 51
3. CAPITULO III: Redes Neuronales Artificiales (RNA)................................................... 60
3.1. Introducción:.............................................................................................................60
3.2. Reseña Histórica:...................................................................................................... 61
3.3. Neurona Biológica:...................................................................................................63
3.3.1. Dendritas........................................................................................................... 63
3.3.2. Sinapsis............................................................................................................. 64
3.3.3. Soma................................................................................................................. 64
3.3.4. Axón..................................................................................................................64
3.4. Neurona Artificial:....................................................................................................65
3.5. Perceptrón:................................................................................................................66
3.5.1. Aprendizaje del Perceptrón: .............................................................................67
3.5.2. Problema de Oscilación.................................................................................... 68
3.5.3. Problema de Linealidad ................................................................................... 70
3.6. Perceptrón Multicapa................................................................................................76
3.6.1. Neurona artificial auxiliar (BIAS): .................................................................. 79
3.7. Algoritmo de aprendizaje: BACKPROPAGATION................................................ 81
3.7.1. Introducción:..................................................................................................... 81
3.7.2. Resumen histórico:............................................................................................82
3.7.3. Algoritmo de Aprendizaje:............................................................................... 84
3.7.3.1. Capa de Salida:..........................................................................................87
3.7.3.2. Una Capa Oculta:...................................................................................... 89
3.7.3.3. Generalizar a N capas Ocultas:................................................................. 90
7

4. CAPITULO IV: Análisis .................................................................................................92


4.1. Introducción..............................................................................................................92
4.2. Limitaciones............................................................................................................. 92
4.3. Requisitos................................................................................................................. 93
4.4. Referencias a otros proyectos................................................................................... 97
4.5. Diagramas de Casos de Uso..................................................................................... 98
4.5.1. Diagrama de Casos de Uso Nº 1:...................................................................... 98
4.5.2. Diagrama de Casos de Uso Nº 2:...................................................................... 99
4.5.3. Diagrama de Casos de Uso Nº 3:.................................................................... 100
4.5.4. Diagrama de Casos de Uso Nº 4:.................................................................... 101
4.5.5. Diagrama de Casos de Uso Nº 5:.................................................................... 102
4.5.6. Diagrama de Casos de Uso Nº 6:.................................................................... 103
5. CAPITULO V: Diseño ..................................................................................................104
5.1. Introducción............................................................................................................104
5.2. DISEÑO DEL SOFTWARE (UML)......................................................................105
5.2.1. Diagramas de Clases....................................................................................... 105
5.2.2. Diagramas de Secuencia................................................................................. 108
5.2.2.1. Diagrama de Secuencia Nº 1: Configuración de la RNA........................108
5.2.2.2. Diagrama de Secuencia Nº 2: Cambiar Función Custom...................... 109
5.2.2.3. Diagrama de Secuencia Nº 3: Entrenamiento de la RNA..................... 110
5.2.2.4. Diagrama de Secuencia Nº 4: Uso de la RNA ..................................... 111
5.2.2.5. Diagrama de Secuencia Nº 5: Uso del Visor de la RNA..................... 112
6. CAPITULO VI: Construcción....................................................................................... 113
6.1. Herramientas Usadas: ............................................................................................ 113
6.2. Componente RNA.................................................................................................. 114
6.3. Clase CAPA............................................................................................................119
6.4. Clase CapaColeccion.............................................................................................. 120
6.5. Clase EvaluadorString............................................................................................ 121
6.6. Clase RNA_Visor................................................................................................... 122
7. CAPITULO VII: Ejemplo de Aplicación (OCR Básico)...............................................124
7.1. Introducción............................................................................................................124
7.2. Adquisición de la vocal.......................................................................................... 125
7.3. Red-Neuronal Artificial.......................................................................................... 127
7.4. Conclusiones del OCR............................................................................................129
8

8. CAPITULO VIII: Conclusiones y Recomendaciones....................................................130


8.1. Conclusiones...........................................................................................................130
8.2. Recomendaciones................................................................................................... 133
9. BIBLIOGRAFÍA ...........................................................................................................135
10. ANEXO: Manual de Usuario.................................................................................... 136
10.1. Introducción: ........................................................................................................136
10.2. Agregar los controles de IA_RNA....................................................................... 137
10.3. Configurar la RNA............................................................................................... 139
10.4. Configurar el Visor............................................................................................... 143
10.4.1. Capas.............................................................................................................143
10.4.2. Pesos............................................................................................................. 143
10.4.3. Tamaños........................................................................................................144
10.5. Entrenamiento.......................................................................................................145
10.6. Consulta................................................................................................................ 149
9

Dibujos
. Dibujo 1: .NET FrameWork - ORIGEN: Propia del autor.................................................21
. Dibujo 2: Estructura del FrameWork - ORIGEN: Propia del autor................................... 30
. Dibujo 3: IDE Visual Studio.NET - ORIGEN: Microsoft Visual Studio .NET 2005...... 32
. Dibujo 4: IDE SharpDevelop - ORIGEN: SharpDevelop v2.0..........................................33
. Dibujo 5: Habilitar Código No Seguro - ORIGEN: Visual Studio.NET 2005.................. 47
. Dibujo 6: Flujo de Hilos - ORIGEN: Propia del autor.......................................................50
. Dibujo 7: Nuevo Proyecto Class Library - ORIGEN: Visual Studio.NET 2005............... 52
. Dibujo 8: Nuevos componentes o controles - ORIGEN: Visual Studio.NET 2005...........53
. Dibujo 9: Propiedades en el código - ORIGEN: Propia del autor......................................58
. Dibujo 10: Neurona Biológica - ORIGEN: Propia del autor............................................. 63
. Dibujo 11: Neurona Artificial - ORIGEN: Propia del autor.............................................. 65
. Dibujo 12: Problema de Oscilación - ORIGEN: Propia del autor..................................... 68
. Dibujo 13: Solución Linealidad - ORIGEN: Propia del autor........................................... 69
. Dibujo 14: Compuerta AND - ORIGEN: Propia del autor................................................ 71
. Dibujo 15: Solución C. AND - ORIGEN: Propia del autor............................................... 72
. Dibujo 16: Problema Lineal - ORIGEN: Propia del autor................................................. 73
. Dibujo 17: Compuerta XOR - ORIGEN: Propia del autor................................................ 74
. Dibujo 18: Problema No Lineal - ORIGEN: Propia del autor........................................... 75
. Dibujo 19: Interconexión de capas - ORIGEN: Propia del autor.......................................76
. Dibujo 20: Estructura de una RNA - ORIGEN: Propia del autor...................................... 77
. Dibujo 21: Solución de la C. XOR - ORIGEN: Propia del autor......................................78
. Dibujo 22: Neurona BIAS - ORIGEN: Propia del autor...................................................79
. Dibujo 23: Propagación de errores hacia atrás - ORIGEN: Propia del Autor....................81
. Dibujo 24: David E. Rumelhart - ORIGEN:
http://www.grawemeyer.com/psychology/previous/02.htm................................................ 83
. Dibujo 25: James L McClelland - ORIGEN:
http://www.grawemeyer.com/psychology/previous/02.htm................................................ 83
. Dibujo 26: Caso de uso Nº 1 - ORIGEN: Propia del Autor.............................................. 98
. Dibujo 27: Caso de uso Nº 2 - ORIGEN: Propia del Autor.............................................. 99
. Dibujo 28: Caso de uso Nº 3 - ORIGEN: Propia del Autor............................................ 100
. Dibujo 29: Caso de uso Nº 4 - ORIGEN: Propia del Autor............................................ 101
10

. Dibujo 30: Caso de uso Nº 5 - ORIGEN: Propia del Autor............................................ 102


. Dibujo 31: Caso de uso Nº 6 - ORIGEN: Propia del Autor............................................ 103
. Dibujo 32: Diagrama de Clases - ORIGEN: Propia del Autor.........................................105
. Dibujo 33: Leyenda de Diagramas de Clases - ORIGEN: Propia del Autor................... 105
. Dibujo 34: Diagrama de Clases (Detalle 1) - ORIGEN: Propia del Autor...................... 106
. Dibujo 35: Diagrama de Clases (Detalle 2) - ORIGEN: Propia del Autor...................... 107
. Dibujo 36: Configuración de la RNA - ORIGEN: Propia del Autor.............................. 108
. Dibujo 37: Cambiar Función Custom - ORIGEN: Propia del Autor.............................. 109
. Dibujo 38: Entrenamiento de la RNA - ORIGEN: Propia del Autor..............................110
. Dibujo 39: Uso de la RNA - ORIGEN: Propia del Autor............................................... 111
. Dibujo 40: Uso del Visor de la RNA - ORIGEN: Propia del Autor............................... 112
. Dibujo 41: Clase RNA - ORIGEN: SharpDevelop 2.2.................................................... 116
. Dibujo 42: Propiedades del RNA - ORIGEN: Ayuda Generada con Document!X 5.0...117
. Dibujo 43: Método Evaluar - ORIGEN: SharpDevelop 2.2............................................ 118
. Dibujo 44: Ayuda: Método Evaluar - ORIGEN: Ayuda Generada con Document!X 5.0
............................................................................................................................................ 118
. Dibujo 45: Clase CAPA - ORIGEN: SharpDevelop 2.2..................................................119
. Dibujo 46: Clase CapaCollection - ORIGEN: SharpDevelop 2.2....................................120
. Dibujo 47: Clase EvaluadorString - ORIGEN: SharpDevelop 2.2.................................. 121
. Dibujo 48: Clase RNA_Visor - ORIGEN: SharpDevelop 2.2......................................... 122
. Dibujo 49: Adquisición de la vocal - ORIGEN: Propia del autor....................................125
. Dibujo 50: parametrización de la vocal - ORIGEN: Propia del autor..............................126
. Dibujo 51: Barra de Herramientas - ORIGEN: Propia del Autor, extraído de MS. Visual
Studio 2005........................................................................................................................ 137
. Dibujo 52: Ventana de selección de componentes - ORIGEN: Propia del Autor, extraído
de MS. Visual Studio 2005................................................................................................ 138
. Dibujo 53: Iconos de los componentes - ORIGEN: Propia del Autor, extraído de MS.
Visual Studio 2005............................................................................................................. 138
. Dibujo 54: Propiedades del componente RNA - ORIGEN: Propia del Autor, extraído de
MS. Visual Studio 2005..................................................................................................... 139
. Dibujo 55: Propiedad Ocultas - ORIGEN: Propia del Autor, extraído de MS. Visual
Studio 2005........................................................................................................................ 140
. Dibujo 56: FT Escalón - ORIGEN: Propia del Autor.................................................... 141
. Dibujo 57: FT Lineal - ORIGEN: Propia del Autor.......................................................141
11

. Dibujo 58: FT Sigmoide logarítmica - ORIGEN: Propia del Autor.............................. 141


. Dibujo 59: FT Sigmoide Tangencial - ORIGEN: Propia del Autor...............................142
. Dibujo 60: FT Gauss - ORIGEN: Propia del Autor....................................................... 142
. Dibujo 61: Configurar el RNA_Visor - ORIGEN: Propia del Autor.............................144
. Dibujo 62: Cambiar valores de entrada desde el visor - ORIGEN: Propia del autor.......150
. Dibujo 63: Menú contextual del visor - ORIGEN: Propia del autor................................151
12

Códigos
Código 1: Ejemplo de código escrito en C# - ORIGEN: Propia del Autor..........................37
Código 2: Ejemplo del uso de punteros - ORIGEN: Propia del Autor................................ 48
Código 3: AssemblyInfo - ORIGEN: Propia del autor........................................................ 53
Código 4: Crear una Propiedad - ORIGEN: Propia del autor.............................................. 54
Código 5: Método PAINT - ORIGEN: Propia del autor......................................................54
Código 6: Control sencillo - ORIGEN: Propia del autor..................................................... 55
Código 7: Crear un Evento - ORIGEN: Propia del autor....................................................56
Código 8: Comentarios XML - ORIGEN: Propia del autor................................................57
Código 9: Argumentos documentados - ORIGEN: Propia del autor................................... 58
Código 10: Ejem de entrenamiento - ORIGEN: Propia del autor......................................146
Código 11: Ejem del evento iteración - ORIGEN: Propia del autor.................................. 147
Código 12: Detener el entrenamiento - ORIGEN: Propia del autor...................................147
Código 13: Ejemplo de uso con BDD - ORIGEN: Propia del autor..................................148
Código 14: Ejemplo del uso de fichero - ORIGEN: Propia del autor................................148
Código 15: Ejem de consulta - ORIGEN: Propia del autor............................................... 149
13

RESUMEN

El presente trabajo muestra el diseño y construcción de un control escrito en C#,


que encapsula todas las funcionalidades de una red neuronal multi-perceptrón
con el algoritmo de aprendizaje BackPropagation o propagación para atrás. El
mismo que podrá ser usado para crear aplicaciones usando este tipo de redes en
cualquier lenguaje de programación soportado por la tecnología DotNET de la
versión 2.0 del FrameWork de Microsoft. Para lograrlo, los controles están
encapsulados en un DLL que permite la compatibilidad entre lenguajes.

El componente que encapsula todas las funcionalidades de una red neuronal


artificial se llamará RNA por sus siglas. Pero adicionalmente se creará un control
gráfico llamado RNA_Visor que será una representación e interfaz gráfica de una
RNA, dando así una completa herramienta para el estudio y aplicación de las
redes neuronales.

***
14

PRESENTACIÓN

Dada la realidad económica y tecnológica de nuestro medio, estoy convencido


que el uso de programas comerciales especializados en materias de inteligencia
artificial no es una buena solución, por su alto precio, para la elaboración de
sistemas inteligentes que el medio necesita.

Por esta razón, creo que el uso de software abierto o libre es la mejor alternativa a
la hora de desarrollar una aplicación. En cuanto a sistemas inteligentes, a la hora
de desarrollar el presente trabajo, no existen proyectos de software abierto para
inteligencia artificial. De modo que el diseño y construcción de nuestras propias
herramientas se convierte en un eje indispensable; y así es que el presente
trabajo muestra, no solo como programar una herramienta inteligente que en este
caso es una red neuronal, sino que muestra como crear una herramienta, un
control para ser usado en cualquier aplicación y enfocándola al programador y no
a un usuario final.

***
15

1 CAPITULO I: Introducción al Tema de Tesis


1.1 Titulo:

Diseño y Construcción de una Red Neuronal Artificial (RNA) de


propósito general

1.2 Planteamiento del problema:

Comprendiendo la inmensa necesidad de fomentar la pequeña y mediana


empresa de nuestro país, casi todas las universidades en la actualidad educan
a sus alumnos para competir y desarrollar sus propios bienes y servicios.

Lamentablemente uno de los principales obstáculos que existe es el difícil


acceso a las herramientas de desarrollo que se aprecia más en las
especialidades o áreas vinculadas a la tecnología como es el caso de la
robótica e inteligencia artificial.

En el caso específico de Redes Neuronales Artificiales (RNA) como


herramienta de desarrollo de procesos inteligentes, resulta casi imposible por
los altos costos. Por ejemplo, una herramienta de programación que permita el
uso de las RNA es el paquete LabView v8.20 de la Nacional Instrument que se
puede adquirir por un precio de $2,395 USD 1 ,otro es el paquete de
programación matemático MATLAB de MathWorks que sumado el toolkit de
RNA llegan a un precio de $3,550 USD2 ,y por último el paquete de
programación NEUROIntelligence alcanza un precio de $3,999 USD3 .

1 Precio consultado en agosto del 2006 en: http://www.ni.com/labview/esa/

2 Precio consultado en agosto del 2006 en: http://www.mathworks.com/store/priceListLink.do

3 Precio consultado en agosto del 2006 en: http://www.alyuda.com


16

Dada esta realidad social y económica que hace prácticamente imposible que
una pequeña empresa financie una herramienta de programación de tal
elevados costos, nos encontramos hoy en día con ingenieros que han pasado
a formar parte de otros sectores como operarios, realizando funciones
impropias a las de un ingeniero, que son la investigación y desarrollo de
soluciones; convergiendo en uno de los tantos problemas que nos sitúan como
un país consumista y tercermundista.
17

1.3 Objetivos

1.3.1 Objetivo General.

Diseñar y construir una red neuronal artificial de propósito general que pueda ser
usada en cualquier lenguaje de programación que soporte la tecnología DotNET
v2. (Microsoft FrameWork 2.0)

1.3.2 Objetivos específicos.

● Desarrollar el software en su totalidad en el lenguaje de programación C#


v2.

● Empaquetar el programa en un componente o control .NET (archivo DLL)


para facilitar su uso y portabilidad.

● Construir una interfaz gráfica que muestre la RNA programada y su


funcionamiento.

● Usar estructuras XML (DataSets) para el almacenamiento de los datos


brindándole así la posibilidad de interactuar con cualquier base de datos.

● Usar punteros para el cálculo de pesos y así mejorar la velocidad de


procesamiento.

● Usar programación en hilos para no atascar el flujo de todo el programa en


los procesos largos de la RNA.
18

1.4 Alcance

El software de RNA a desarrollar estará basado en la versión 2 del Framework de


Microsoft y solo alcanza una compatibilidad directa con los programas y entornos
de programación que soporten este framework, tal es el caso de Visual Basic en
su versión 8, C# 2, C++ para .NET2, VBA para Autocad 2007, etc.

El uso de lenguajes de programación que permitan una compatibilidad indirecta


con esta tecnología como es el caso de Delphi 8.NET, Visual Basic 7 / 7.1, C#1,
Linux con su proyecto Go-MONO, LabView, Visual Basic 6 y otros, NO están en el
alcance investigativo de esta tesis aunque en teoría funcionarían sin problema.

La RNA a programarse únicamente soportará el algoritmo de aprendizaje


denominado “BackPropagation”.

Así mismo el software esta sujeto a las limitaciones y alcance que posee la
plataforma FrameWork 2.
19

1.5 Importancia y Justificación.

1.5.1 Importancia.

La herramienta de programación que ofrece el presente trabajo permitirá a


muchos desarrolladores poner en práctica sus conocimientos de RNA de una
forma fácil, rápida y a un costo extremadamente bajo en relación a sus similares,
al distribuirse el control como FreeWare4. Brindando así una gran ayuda a la
formación y crecimiento de la pequeña y mediana empresa que se dedique al
desarrollo de procesos inteligentes.

Además se pretende fomentar el desarrollo a bajos costos de herramientas que


permitan el desarrollo en conjunto del área de robótica e inteligencia artificial que
tiene poca o ninguna acogida en nuestro país.

1.5.2 Justificación.

El presente trabajo nació de una necesidad real en el desarrollo y aplicación de


procesos inteligentes en una pequeña empresa de Quito, así como también en
distintos proyectos o trabajos de tesis presentados contemporáneamente a este.

Por otro lado, dará una alternativa al ofrecer una herramienta que permita estudiar
las RNA de una forma práctica y no solo teórica.

El uso de la tecnología .NET se eligió por su gran avance y acogida, siendo la


plataforma usada por más de 20 lenguajes hoy en día (Visual Basic, Ada, Cobol,
Perl, C++, Java, etc) , siendo C# su lenguaje por excelencia.

Además la extensa documentación que lo sustenta lo hace la mejor opción para


un trabajo de esta naturaleza. Y por último, la visión a corto plazo que plantea
esta tecnología lo hace compatible con diversas plataformas como Linux,
Macintosh, Solaris, etc.

4 Software de distribución gratuita y sin límite de tiempo. http://es.wikipedia.org/wiki/Freeware


20

2 CAPITULO II: Tecnología DotNET

2.1 Introducción:

La creciente demanda de los programadores para desarrollar aplicaciones


multimedia y Web obligaba a plataformas como Windows a desarrollar sobre la
marcha APIs (Application Programming Interface) cada vez más elaborados y
complejos que carecían de documentación detallada y en muchos casos caían en
incompatibilidades y errores.

La solución empezó a dialogarse en las mesas de los ejecutivos de


Microsoft a finales de los 90’s, y así en Julio del 2000, su presidente, Bill Gates
anunciaba al mundo en la Profesional Developer Conference (PDC)5 de Orlando
una vista preliminar de lo que sería una nueva plataforma de desarrollo que
unificaría todos los ámbitos del software, desde aplicaciones de escritorio
pasando por entornos Web, Dispositivos móviles, Bases de Datos, entre otros.

Como era de esperarse, Microsoft copio la idea que tan bien le estaba
funcionando a la empresa Sun Microsystems con su lenguaje JAVA, y decidió
usar un compilador JIT así como un lenguaje hibridado entre C++ y Basic ( C# )6.

Pero no se conformaron solo con eso, pensaron en ir más allá y establecer


un estándar a nivel internacional y lograr que cualquier lenguaje de programación
pueda ser usado con su tecnología, y que esta cubriera todos los ámbitos de
programación existentes: POO, Gráficos, Multimedia, BDD, Web, Dispositivos
móviles, Juegos, etc.

5 http://www.microsoft.com/Presspass/press/2000/jul00/pdcgateskeynotepr.mspx
6 Conclusion propia del autor
21

2.2 .NET Framework:

Dibujo 1: .NET FrameWork - ORIGEN: Propia del autor

El framework, traducido al español como “marco de trabajo” aunque se


recomienda mantener la palabra en inglés por su concepto dedicado, es el
corazón de la tecnología DotNET y aunque fue impulsada por Microsoft, en su
desarrollo intervinieron empresas como: Hewlett-Packard , Intel, IBM, Fujitsu
Software, Plum Hall, la Universidad de Monash e ISE

Generalizando un poco, se puede decir que el .NET Framework es a la


tecnología NET como el Java Virtual Machine, JRE y J2SE es al Java. Es decir,
el framework constituye el vínculo entre el sistema operativo y el programa
generado bajo la tecnología DotNET, dando así una transparencia al código al
resolver el problema de incompatibilidad que se daba al tener que tomar en
cuenta el sistema operativo base, su versión, e incluso su configuración al
programar.

Un dato muy importante que cabe recalcar es que muchos de los elementos
de la tecnología DotNET fueron estandarizados bajo normativas internacionales, y
por lo tanto abiertas a todo el mundo. La normativa que rige al .NET framework es
22

la ECMA-335, ISO/IEC 232717. Basado en esto la versión de Microsoft toma el


nombre de: Microsoft .NET Framework y no es el único existente, hoy en día
existen varios aunque el de Microsoft constituye el más usado y famoso; no
obstante la empresa Ximian y más tarde Novell, ambas encargadas de dar vida a
los programas de código libre entre ellos Linux, empezó con la tarea de crear un
.NET framework para todas los sistemas operativos, y al proyecto lo llamaron:
MONO8, el cual ya esta disponible de forma gratuita en su página web y ha tenido
mucha acogida por programadores de Windows, Linux, Solaris y Mac OS X.

El .NET Framework se divide en las siguientes partes:

● Infraestructura común de lenguajes o CLI

● La Biblioteca de Clases Base o BCL

● Entorno Común de Ejecución para Lenguajes o CLR

7 http://www.microsoft.com/Presspass/press/2000/jul00/pdcgateskeynotepr.mspx
8http://www.mono-project.com
23

2.2.1 CLI (Common Language Infrastructure)

El propósito del CLI es soportar una gran gama de lenguajes de


programación y traducirlos a un lenguaje común propio del framework conocido
como MSIL (Microsoft Intermediate Lenguaje) que será usado luego por el
compilador JIT.

Así, el CLI se encarga de brindar una infraestructura que debe cumplir


todos los lenguajes que quieran funcionar bajo la tecnología .NET, además se
encarga de la validación del mismo y de su respectiva compilación para alcanzar
el código MSIL que será un lenguaje parecido al ensamblador y resultado final del
programa. Es decir un programa realizado en .NET nunca alcanza el lenguaje de
máquina del computador por si solos, sino que queda expresado en este lenguaje
MSIL que cumple la misma funcionalidad que el lenguaje llamado BYTECODE en
Java.

Puesto de esta manera, es posible usar cualquier lenguaje de


programación que cumpla las especificaciones del CLI para poder usar la
tecnología .NET, y es por esto que hoy en día tenemos varios lenguajes a nuestra
disposición. Los ofrecidos por Microsoft son: C#, C++, Visual Basic y J#, no
obstante muchas empresas han brindado a sus propios lenguajes de
programación la compatibilidad con el CLI del .NET framework de Microsoft, y es
así que hoy en día se puede encontrar lenguajes como: Delphi.NET, Perl,
Python, Fortran y Cobol.NET entre otros. Hasta la fecha se han sumado más de
30 lenguajes de programación9 que pueden ser usados en la tecnología .NET.

El CLI posee internamente un compilador para cada uno de los lenguajes a


usarse, y es así que realizar un programa en Visual Basic no va a ser igual que
realizarlo en un C#, las diferencias de velocidad, alcance, entre otras va a seguir
dando las mismas diferencias que siempre. Un lenguaje externo como los
9http://www.dotnetpowered.com/languages.aspx
24

mencionados antes (Delphi, Cobol, Fortran, etc) deben de poseer un compilador


externo, y claramente ser compatible con el CLI y más específicamente con el
CLS (Common Language Specification) que es la parte del CLI donde se
encuentran las reglas a seguir para validar o no un lenguaje, además usar el CTS
(Common Type System) que es el encargado de brindar un sistema de tipos único
para todos los lenguajes de programación, es decir, para todos los lenguajes
basados en .NET las variables como “int, string, long, double” van a tener el
mismo tamaño en bits, y los mismos limites.
25

2.2.2 BCL (Base Class Library):

Esta biblioteca es un conjunto muy bien organizado de clases que abarcan


las funciones más comunes para todo programador.

Están definidas como archivos DLL lo que significa que están en código MSIL y
por lo tanto pueden ser usadas de forma transparente por cualquier lenguaje .NET

Aquí una lista de las principales funcionalidades que se pueden encontrar en esta
biblioteca de clases:

● Interacción con los dispositivos periféricos

● Formularios y componentes para aplicaciones de escritorio (Windows


Forms)

● Manejo de datos (ADO.NET)

● Administración de memoria

● Transmisión y recepción de datos por distintos medios (XML, TCP/IP)

● Administración de componentes Web que corren tanto en el servidor como


en el cliente (ASP.NET)

● Manejo y administración de excepciones

● Manejo del sistema de ventanas

● Herramientas de despliegue de gráficos (GDI+)

● Herramientas de seguridad e integración con la seguridad del sistema


operativo

● Interacción con otras aplicaciones

● Manejo de cadenas de caracteres y expresiones regulares

● Manejo de archivos, ficheros y streams.

● Operaciones aritméticas

● Manipulación de fechas, zonas horarias y periodos de tiempo

● Serialización
26

● Manipulación de archivos de imágenes

● Generación de código

● Manejo de idiomas

● Interacción con el API Win32 o Windows API.


27

2.2.3 CLR (Common Language Runtime)

Es el verdadero núcleo de la tecnología .NET, se encarga de las funciones


principales de un buen motor de ejecución, cumpliendo también las funciones de
depuración, organización de memoria, seguridad y más.

Las funciones que cumple son:

• Carga las diferentes clases de la BCL, recursos y las unifica al programa.

• Maneja la iteración con antiguos componente COM que no son propios de


la tecnología .NET

• Controla todos los recursos de memoria para soportar hilos (threads)

• Verifica y valida los diferentes tipos a usarse

• Controla las excepciones

• Motor de seguridad

• Motor de depuración

• Controlador de código en general

• Recolector de basura (Garbage Colector “GC”)

• Compilador JIT

El Compilador JIT (Just-In-Time) es un motor que corre en tiempo real generando


a partir del código MSIL un lenguaje de máquina propio de cada computador. Este
es en realidad el que otorga a la tecnología .NET la compatibilidad con los
diferentes sistemas.
28

Cuando uno realiza un programa en la tecnología .NET, este programa ya en su


etapa de release, por ejemplo un ejecutable EXE; el .NET framework lo deja
expresado en el código MSIL, cuando es ejecutado el programa, el motor JIT lo
transforma en tiempo real al lenguaje de máquina del computador local. En caso
de que el programa fuese usado en otra computadora con otro sistema operativo
y otro procesador. El programa será interpretado por el motor JIT de la otra
máquina, como el lenguaje MSIL sigue siendo el mismo, el motor JIT del nuevo
computador traducirá en tiempo real el código MSIL a un nuevo lenguaje de
máquina perteneciente a esta nueva computadora. Otorgando así la flexibilidad de
tener un programa que pueda correr en varias computadoras con diferentes
configuraciones, siendo el framework el encargado de realizar los cambios
respectivos, dando al programador total transparencia.
29

2.2.4 RESUMEN

Para simplificar las cosas, podemos decir que el framework es el motor que
corre entre el usuario y el sistema operativo, siendo claramente indispensable
tenerlo instalado en la computadora donde se quiera ejecutar cualquier programa
bajo la tecnología .NET

El framework es un estándar a nivel mundial, siendo Microsoft la empresa


que lo impulso y por lo tanto la pionera en esta tecnología.

El Microsoft .NET Framework es la versión de Microsoft de este framework, y es


completamente gratuito, pudiendo ser descargada desde el Internet. Pero no es el
único framework bajo la tecnología .NET, el proyecto MONO es una alternativa al
framework de Microsoft impulsado por la grande del código libre Novell.

El framework se divide en tres partes fundamentalmente:

• El CLI, encargado de compilar y validar un código escrito en muchos de los


lenguajes de programación existentes para la tecnología .NET y dar como
resultado un código ensambler virtual conocido como MSIL.

• El BCL es la biblioteca de clases en las que se encuentran todas las


funciones más comunes que un programador pueda requerir para una
aplicación.

• El CLR es el motor que ejecuta el código MSIL y lo transforma al código de


máquina requerido de forma diferente en cada computador.
30

C# VB.NET

CLI ( Common Language Infrastructure ) BCL (Base Class Library)

MSIL MSIL

CLR (Common Language Runtime)


Microsoft .NET
Framework

100101101101101110

SISTEMA OPERATIVO

Dibujo 2: Estructura del FrameWork - ORIGEN: Propia del autor


31

2.3 IDE (Integrated Development Environment) para .NET:

Como todos sabemos un IDE es una Entorno Integrado de Desarrollo que


brinda a un programador varias herramientas entre ellas una interfaz gráfica de
usuario (GUI), un intérprete, coloración de sintaxis entre otras; para facilitar el
trabajo a la hora de programar.

El .NET Framework como vimos anteriormente consta internamente de


compiladores para los lenguajes promocionados por Microsoft, entre los que se
encuentran C# y Visual Basic principalmente. Teniendo la posibilidad de realizar
nuestros programas sin pagar un solo centavo por licencias de programas, al ser
como ya dijimos el .NET framework una aplicación freeware que se puede
descargar de Internet.

Pero hay que estar consientes que esto involucra escribir nuestro código en
algún editor de texto que ya dispongamos como el Bloc de Notas, y hacer la
respectiva compilación desde un entorno de consola de comandos (DOS). Así
como no disponer de diseñadores gráficos para las aplicaciones con formularios
lo que resulta un dolor de cabeza.

Dado el mencionado problema, vemos la gran ayuda que significa el uso de


un IDE para la tecnología .NET, y es aquí que Microsoft lanza al mercado el IDE
más usado en el mundo para esta tecnología, conocido como: Microsoft Visual
Studio.NET, que sirve como IDE para todos los lenguajes de Microsoft, no
obstante si se desea un IDE para un lenguaje nada más podemos encontrar uno
dedicado a Visual Basic llamado Microsoft Visual Basic.NET, o para C#
conocido como Microsoft Visual C#.
32

Pero cabe recalcar que el paquete Microsoft Visual Studio.NET es tan solo
un IDE de la tecnología .NET y no el motor indispensable. De ahí que no es el
único IDE existente en el mercado, aunque si el mejor y por lo tanto el más
costoso.

Dibujo 3: IDE Visual Studio.NET - ORIGEN: Microsoft Visual Studio .NET


2005
33

Hace varios años ya, un grupo de personas empezaron la tarea de ofrecer a los
programadores de .NET un IDE freeware y de ahí que hoy podemos descargar de
forma gratuita el tan famoso SharpDevelop
(www.icsharpcode.net/OpenSource/SD) que por menos de 10MB (versión 2.0) ,
podemos tener un IDE de altísimo nivel, igualando en casi todos los aspectos al
IDE de Microsoft.

Dibujo 4: IDE SharpDevelop - ORIGEN: SharpDevelop v2.0

SharpDevelop tuvo tan buena acogida en el mercado de los programadores


a nivel mundial que obligo a Microsoft a hacer algo que hace algunos años
parecía imposible que lo llegue a hacer, me refiero concretamente a su versión
Express del paquete 2005, el cual da a sus usuarios una versión freeware de su
IDE del cual hablaremos más adelante.

Ambos IDEs cumplen los requisitos mínimos que un programador necesita,


entre ellos, un diseñador gráfico de formularios, coloración de sintaxis, coloración
de errores, base de datos de los métodos y propiedades de una clase (lista que
34

aparece indicando los métodos y variables que posee una clase), depuración,
entre otros. No obstante cabe señalar que según mi apreciación personal, la
versión de Microsoft es un poco más rápida y consta de mejores herramientas
que el SD, aunque se debe tomar muy en cuenta que el Visual Studio viene en 2
CDs en comparación a los 10MB del SharpDevelop.

2.4 Versiones del .NET Framework:

Desde el año 2000 cuando fue presentada la idea de la tecnología .NET, se


empezó a trabajar en la construcción de un framework que alcanzara tal nivel de
profundidad que se pueda construir todo un sistema operativo sobre él. Han
pasado casi 7 años desde entonces y las ambiciones de Microsoft se están
materializando.

2.4.1 .NET Framework v1.0:

Su primera versión vio la luz a finales del 2001 y vino de la mano con la salida de
Visual Studio.NET 2002 o v7.0, la que incluía claro la versión 7 de Visual Basic y
la primera versión de C#, este nuevo lenguaje que más adelante le dedicaremos
principal atención.

2.4.2 .NET Framework v1.1:

Poco tiempo después de la salida de su primera versión, los cambios y parches


en el framework eran tan grandes que obligaron a sacar al mercado una versión
1.1 del framework acompañada del Microsoft Visual Studio 2003 que incluía a
Visual Basic 7.1 y a C# 1.1 . Esta versión es por muchos considerada la primera y
dejo completamente descontinuada a la 2002.

La gran acogida de esta tecnología por los programadores de todo el mundo


sorprendió hasta a los mismos ejecutivos de Microsoft, incrementando sus
usuarios en una proporción geométrica jamás vista.

Es aquí cuando SharpDevelop sale al mercado con su versión 1.0


35

2.4.3 .NET Framework v2.0:

Para el 2005, la llegada de la segunda versión rompió todos los esquemas, dando
completa integración a los programas desarrollados en las versiones anteriores,
acompañada por el Microsoft Visual Studio.NET 2005, la que incluía claro la
versión 8 de Visual Basic y la tan esperada segunda versión de C#. Las mejores
son muy considerables a todo nivel y es actualmente la versión más usada en el
mundo para las aplicaciones .NET, integrando cientos de programas escritos en
esta tecnología, por mencionar alguno al propio AutoCAD 2007 de la firma
AutoDesk. SharpDevelop claro, lanzó su segunda versión con este nuevo .NET
Framework.

2.4.4 .NET Framework v3.0:

Actualmente la acogida en el mundo de los programadores de .NET es tan grande


y sobretodo tan creciente que Microsoft decidió jugarse todo por el todo con esta
tecnología, y así la llegada del framework 3.0 en estas fechas (Enero 2007) nos
trae no solo una versión mejorada, sino la gran sorpresa que quedará escrita en
los libros, me refiero concretamente la llegada del nuevo Windows Vista, el primer
sistema operativo escrito en su totalidad en código MSIL, es decir en un lenguaje
de “alto nivel”, rompiendo la tradición de escribirlo en lenguaje de máquina. Las
ventajas de este hecho hace que todo el sistema operativo y por lo tanto todos
programas estarán basados en la tecnología .NET y por lo tanto al hacer una
aplicación en .NET estaremos al mismo nivel que todo, teniendo completo control
y transparencia.

Microsoft ha anunciado el desarrollo de una versión 3.5 del framework,


cuyo IDE está bajo el nombre clave de ORCAS y será la versión 2008 del Visual
Studio.
36

2.5 C# (Sharp), El lenguaje predilecto del .NET framework:

El lenguaje más usado de todos los tiempos sin duda es el C++ por su gran
alcance, sin embargo su inminente dificultad hizo que lenguajes tan “superficiales”
como el Basic llegaran a las manos de todos por su sencillez y sobretodo por su
velocidad de desarrollo.

Java, a finales de los 90, propondría un nuevo lenguaje que hibridara la


sencillez del Basic con la potencialidad del C++, marcando un interesante
equilibrio entre los dos. La acogida de este lenguaje marco la historia, teniendo
hoy en día a Java entre los primeros lenguajes de programación más usados en
el mundo entero.

Así es como Microsoft aposto a la creación de un nuevo lenguaje similar a


Java, y para esto contrato a una leyenda de la programación, encargada de dar
vida al Pascal y a Delphi, me refiero a Anders Hejlsberg10, que fue el arquitecto
de C# y uno de los encargados de dar vida a la tecnología DotNET.

Su sintaxis se apega a una derivación del C, como casi todos los lenguajes
lo han hecho, formando poco a poco en lo que algún día, creo yo, será un
estándar. Esto es la utilización de “;” para el fin de instrucción, el uso de llaves
“{ }”, la distinción entre mayúsculas y minúsculas, por mencionar algunas.

10 http://es.wikipedia.org/wiki/Anders_Hejlsberg
37

public Form1()
{
InitializeComponent();
}

private Stopwatch temporizador;


private const int cuantasCadenas = 20000;
private void btnCalcular_Click(object sender, EventArgs e)
{
btnCalcular.Enabled = false;
btnCalcular.Refresh();
// La prueba de StringBuilder (que tarda menos)
this.txtStringBuilder.Text = “Prueba”
// La prueba de String (que tarde un poco más)
this.txtString.Text = calcularString().ToString();
btnCalcular.Enabled = true;
btnCalcular.Refresh();
}

Código 1: Ejemplo de código escrito en C# - ORIGEN: Propia del Autor

Además el C# constituye el lenguaje clave para la tecnología .NET, de ahí


que todo lo que se pueda hacer con esta tecnología, se podrá hacer desde C#,
siendo el resto de lenguajes los que se deban acoplar.

Por citar un ejemplo, el propio IDE antes mencionado, el SharpDevelop


esta escrito en su totalidad en C#. Teniendo en este lenguaje entre los 10 más
usados en el mundo, lo que es un récord tomando en cuenta que la vida de C# es
de tan solo 5 años con respecto a Java que lleva más de 15 años.
38

2.6 Trabajando con DotNET


2.6.1 Introducción:

Como ya lo había mencionado, dentro de todos los lenguajes que se


pueden usar dentro de la tecnología DotNET, vamos a usar el C# (Sharp) puesto
que es el lenguaje por excelencia de DotNET, es decir, el C# constituye un
lenguaje creado exclusivamente para esta tecnología y por ende resulta el más
compatible y en él se pueden explotar al máximo todas las herramientas que
brinda DotNET.

Al igual que la mayoría de lenguajes de cuarta generación, el C# brinda


una programación estructurada, programación orientada a objetos (POO), y
demás. Pero en el desarrollo del presente trabajo se utilizaron algunas
herramientas poco usuales en cuanto a este lenguaje y tecnología se refiere,
como es:

El motor gráfico GDI+ propio de la tecnología DotNET que nos da la facilidad de


dibujar a un excelente nivel, pudiendo resolver fácilmente los problemas de
parpadeo que aparecen siempre que intentamos realizar algún tipo de animación,
solo por poner un ejemplo.

El uso de punteros que era una tarea casi exclusiva para C++, ahora se
puede hacer desde C#, claro, usando ciertas protecciones para combinar el
código administrado por el motor de la tecnología DotNET (código seguro) y el
código en el que usamos punteros (código no seguro).

A estas herramientas le aumentamos el uso de hilos para poder correr


varios procesos en “paralelo” y una explicación de como crear controles de
usuario encapsulados en una DLL para poder usarlos desde cualquier lenguaje de
esta tecnología y tendremos todas las herramientas que se han usado en el
desarrollo del presente trabajo.
39

2.6.2 Motor Gráfico (GDI+):

El GDI por sus siglas en ingles: Graphics Device Interface11, es el motor


gráfico del sistema operativo windows, y constituye, como todo motor, de un API
programado originalmente en C++ que nos permite usar esta librería. Esta librería
gráfica ha sido modificada constantemente para cubrir los grandes avances de las
presentaciones gráficas, y es así que para windows XP, los desarrolladores de
microsoft re-hicieron toda la librería gráfica dando nacimiento al GDI+, que como
su nombre lo indica es una evolución del mismo.

La tecnología DotNET ha incluido una librería de comunicación directa y en


bajo nivel al GDI+ de windows, dándonos así la posibilidad de usar esta potente
herramienta de forma natural y sencilla desde cualquier lenguaje de DotNET.

El GDI+ se divide en tres partes principalmente:

● Dibujo en 2D: Esta parte permite dibujar lineas, cuadrados, elipses, y


demás figuras en cualquier parte de nuestros controles, incluyendo los
formularios. A esta parte se le ha agregado varias funcionalidades muy
útiles como los degradados, sistema de colores ARGB, es decir incluyendo
el componente de Alfa que da niveles de transparencia; entre otras
mejoras.

● Manejo de imágenes: Con esta parte podemos abrir, manipular y guardar


imágenes que abarcan todos los formatos conocidos, como son el BMP,
JPG, GIF, PNG, entre otros. La manipulación de las mismas se la puede
hacer pixel por pixel, o con matrices de transformación y rotación.

● Manejo de Textos: GDI+ incluye un completo algoritmo para le manejo de


textos en el dibujo, pudiendo usar degradados, estilos de linea y más en la
graficación de textos.

En C#, el uso de esta librería se da por medio del ensamblado: System.Drawing

Que a su vez contiene varios ensamblados y clases como por ejemplo:


Drawing2D, Text, Imaging, etc.

11 http://www.microsoft.com/whdc/archive/GDInext.mspx
40

2.6.2.1 Lienzo (Graphics):

El lienzo, expresado en una clase de nombre Graphics, es la clase base


para poder dibujar cualquier cosa en GDI+. Y pues, igual que un lienzo real, es lo
primero que hay que tener antes de dibujar aun quesea una linea. En DotNET, el
lienzo es de color transparente y puede ser extraído de casi cualquier lado,
teniendo entre las formas más comunes las siguientes:

● Desde una Imagen: Teniendo un objeto de tipo Image o Bitmap que


luego trataremos más a fondo, podemos extraer un lienzo con el siguiente
código:

Graphics g = Graphics.FromImage(imagen);

● Desde un Control: Teniendo cualquier control con interfaz gráfica, como


un formulario, botón, etiqueta, panel, u otro control:

Graphics g = control.CreateGraphics();

● Usando el evento PAINT: Todos los controles poseen un evento


denominado PAINT, que se genera cuando windows requiere volver a
dibujar dicho control. Así podemos capturar este evento y como argumento
del mismo, tenemos a nuestra disposición el lienzo u objeto Graphics con
el que podemos alterar lo dibujado en el control.

private void control_Paint(object sender, PaintEventArgs e)


{
Graphics g = e.Graphics;
}

Existen varias formas más de conseguir un lienzo, pero estas son las más
usadas. Cabe recalcar que cuando se extrae el lienzo de una imagen, todos los
dibujos se quedan intrínsecamente en la imagen y por lo tanto mantiene sus
modificaciones. Pero cuando se extrae el lienzo desde un control directamente,
los dibujos realizados sobre este se ejecutan una única vez, y esto se refleja al
minimizar por ejemplo el formulario, los dibujos se habrán borrado al restaurar el
formulario. Para lograr que el control mantenga sus dibujos siempre, se usa el
evento PAINT, así se dibujara cada vez que se lo solicite.
41

2.6.2.2 Lápices (Pen):

Los lápices son clases que representan el estilo con el que se quiere
dibujar la silueta o contorno de algo. Por ejemplo, para crear un lápiz de color Azul
y de un grosor de 3 se usaría el siguiente código:

Pen p1 = new Pen(Color.Blue,3);

Esta clase es muy completa, puesto que permite crear lapices con distintos
colores, texturas, formas de empezar como una flecha por ejemplo, etc.

2.6.2.3 Brochas (Brush):

Las brochas son clases que sirven para rellenar un dibujo. Principalmente se
puede tener:

● SolidBrush : Es una brocha de un solo color.

SolidBrush sb1 = new SolidBrush(Color.Green);

● HatchBrush : Esta brocha combina dos colores de varias formas


predeterminadas.

HatchBrush b1 = new HatchBrush(HatchStyle.Shingle, Color.Blue, Color.Red);

● LinearGradientBrush : Permite usar una gradiente lineal de varios colores.

LinearGradientBrush lb1 = new LinearGradientBrush


(new Point(0, 50), new Point(100, 50), Color.Blue, Color.Red);

● PathGradientBrush: Esta permite una gradiente de forma circular de varios


colores.

GraphicsPath gp1 = new GraphicsPath();


gp1.AddRectangle(new Rectangle(0,0,100,100));
PathGradientBrush pb1 = new PathGradientBrush(gp1);
42

pb1.CenterColor = Color.LightYellow;
pb1.SurroundColors = new Color[] { Color.LightGreen, Color.LightGreen,
Color.Green, Color.DarkGreen };

● TextureBrush : Con esta brocha podemos usar una imagen como papel
tapiz de nuestro relleno.

TextureBrush tb1=new TextureBrush(Image.FromFile(@"C:\guille.jpg"));

2.6.2.4 Figuras Básicas:

Entre los métodos que encontramos en el lienzo (Graphics), se ven


claramente dos grupos, los llamados DRAW y los llamados FILL, con quienes se
pueden graficar todas las formas básicas de dibujo como son las lineas,
rectángulos, elipses, texto, etc.

Los DRAW están basados en lápices, por lo tanto solo dibuja siluetas o
contornos. Así se puede tener los siguientes códigos:

g.DrawLine(p1, 0, 0, 100, 100); g.DrawRectangle(p2, 100, 100, 200, 200);

g.DrawEllipse(p1, 100, 100, 50, 50); g.DrawEllipse(new Pen(Color.Red), 100, 100,


150, 50);
43

Todos los métodos del tipo DRAW dentro de la clase Graphics son::

DrawArc DrawLine
DrawBezier DrawLines
DrawClosedCurve DrawPath
DrawCurve DrawPie
DrawEllipse DrawPolygon
DrawIcon DrawRectangle
DrawImage DrawRectangles
DrawImageUnscaled DrawString

Por otro lado, cuando usamos los métodos FILL, estos están dirigidos a rellenar
las formas, así tenemos lo siguiente:

g.FillEllipse(sb1, 0, 0, 100, 100); g.FillEllipse(hb1, 0, 0, 100, 100);

g.FillRectangle(pb1, 0, 0, 100, 100); g.FillEllipse(tb1, 0, 0, 300, 300);

Como se ve, en los ejemplos usamos las distintas brochas que creamos
anteriormente.
44

La lista de métodos FILL dentro de la clase Graphics son:

FillRegion

FillRectangle

FillRectangles

FillPolygon

FillPie

FillPath

FillEllipse

FillClosedCurve

2.6.2.5 Manejo de Imágenes:

El manejo de imágenes es muy extenso, y como no se uso el tema en el


presente trabajo, solo daré una breve introducción a lo que a imágenes se refiere.

El GDI+ divide el trato de imágenes en dos grandes clases.

IMAGE: Es la clase que soporta una imágen y está enfocada a tratar la


manipulación de la imagen a un nivel de archivo. Es decir, abrir la imagen, grabar
en un formato establecido, extraer información de la misma, presentarla en un
PcitureBox, etc

Image imagen1 = Image.FromFile(@"C:\guille.jpg");

BITMAP: Esta clase también contiene una imagen pero está enfocada al trato de los
pixeles de la imagen. Es decir, en cuanto a modificar los pixeles se trata, este objeto es el
que lo permite hacer. Además, esta calse permite instanciarse a diferencia de la IMAGE,
creando así una nueva imagen.

Bitmap bm1 = new Bitmap(100, 100);


45

Estas dos clases funcionan casi siempre a la par, puesto que cada una contiene
funcionalidades requeridas a lo largo de un trabajo de procesamiento de
imágenes. Y son 100% compatibles en cuanto a intercambiabilidad se refiere. Es
decir, si se requiere pasar una imagen para que sea un objeto BITMAP o IMAGE,
basta con hacer el debido casting:

imagen1 = (Image)bm1;
bm1 = (Bitmap)imagen1;

Para tratar con cada uno de los pixeles, es necesario tener la imagen en un objeto
BITMAP y usar los métodos:

bm1.GetPixel(x, y);
bm1.SetPixel(x, y, Color.Red);

Donde X,Y son las coordenadas del pixel que se quiere leer o escribir. El pixel
esta representado por un color que es toda una clase que brinda facilidades para
el trato de colores.
46

2.6.3 Punteros:

Normalmente, las variables, objetos o recursos que usamos en nuestros


programas son alojados de forma dinámica en la memoria RAM de nuestro
computador, esto significa que dependiendo de las necesidades del sistema
operativo, este tiene la potestad de mover los espacios de memoria RAM que
usamos. Gracias a esto, conseguimos que nuestros programas no interfieran con
otros que puedan estar corriendo en un computador. No obstante, algunas veces
es necesario alojar un paquete de datos en la memoria RAM y que este no se
mueva de ahí en un tiempo, además, al tenerlo fijo es posible acceder a estos
datos de forma directa. A esto se le conoce como “Atacar directamente a la
memoria RAM”. Las ventajas que se consiguen al hacer esto es principalmente
velocidad.

En C#, el uso de punteros es conocido como “Código NO-SEGURO” o


UnSAFE, puesto que al tener acceso directamente a la memoria RAM de la
computadora, es posible interferir con otros programas y llegar al colapso de
varios de ellos. Por esto hay que tener varias consideraciones, que van desde
usar correctamente las variables o punteros, hasta tener en cuenta el tamaño del
banco de datos que nos perteneces y no sobrepasarlo porque podremos alterar
otros valores de algún otro proceso.

Pasos para escribir un código no seguro en C#.

1. Avisar al compilador que permita el código no seguro. Esto se hace en las


propiedades del proyecto (Clic derecho >> Propiedades), en la pestaña
“BUILD” hay una opción que indica poder habilitar el código no seguro.
Allow unsafe code
47

Dibujo 5: Habilitar Código No Seguro -


ORIGEN: Visual Studio.NET 2005

2. Declarar los métodos que van a contener el código con punteros como
UNSAFE

public unsafe void Procesar(byte[] buff){

3. Fijar o congelar una variable u objeto en la memoria RAM con el comando


FIXED.

fixed (byte* p = buff){

4. Usar los punteros de la misma forma que se hace en C++, esto es, usar el
puntero para indicar la dirección en la memoria RAM. Usar el prefijo
asterisco ( * ) para indicar lo “Especificado por”, es decir, para indicar el
contenido de esa dirección de la RAM.
*Puntero = 55; //Escribir en la dirección indicada por el
puntero el valor de 55
Puntero++; //Auemntar la dirección de la memoria RAM
48

Ejemplo: Método que dado un vector de entrada, rellene todo el vector con el
valor de 100.

public unsafe void Procesar(byte[] buff)


{
fixed (byte* p = buff)
{
byte* pp = p;
for(byte i=0 ; i < buff.Length ; i++)
{
*pp = 100;
pp++;
}
}
}

Código 2: Ejemplo del uso de punteros - ORIGEN: Propia del Autor


49

2.6.4 Hilos (Threads):

Un computador realiza varias tareas “simultáneamente”, por ejemplo,


escuchamos música mientras jugamos solitario y estamos descargándonos algún
archivo del Internet.

Contando los procesos propios del sistema operativo y demás programas,


tenemos cerca de 10 procesos corriendo simultáneamente en nuestro
computador. Pero nosotros sabemos que casi toda computadora tiene
únicamente un procesador, y bueno, ahora se habla de dos procesadores
funcionando en paralelo, pero aun así no son 10 procesadores, 1 para cada
programa. Así que lo que se hace, es dividir todos los procesos en peticiones muy
pequeñas, y estas son enviadas al procesador; trabajo realizado por el sistema
operativo de forma transparente para nosotros. Así el procesador solo efectúa una
única operación a la vez, pero como hace un pedacito de cada uno, este se
aprecia como si lo hiciera todo a la vez.

Cuando nosotros realizamos un programa, este es un proceso más para el


sistema operativo, sin embargo es un proceso casi siempre de un solo hilo. Y así
un hilo no es más que un sub-proceso que corre “independientemente” de los
otros.

Para aclarar mejor la idea, es muy común usar los controles TIMER en nuestros
programas. Estos pueden ser muy fácilmente programados, basta un contador
que llame a un método cuando el tiempo establecido haya finalizado, sin embargo
si lo programáramos de la forma tradicional, mientras el programa realiza el
conteo del timer, no podríamos hacer nada más. Es así que un Timer esta
programado en otro hilo. Esto significa que se ha creado otro proceso
independiente para que realice el conteo, y este está muy aparte del proceso
normal de nuestro programa.
50

Programa Principal

Hilo 1

Conteo del Timer

Hilo 2

Dibujo 6: Flujo de Hilos - ORIGEN: Propia del autor

En DotNET v2, han implementado un control llamado “BackgroundWorker” que es


un completo control que permite empezar un proceso en un hilo nuevo. Este
control nos brinda las facilidades de crear uno o varios procesos en hilos
diferentes para que puedan correr simultáneamente.
51

2.6.5 Creación de Controles de Usuario:

Los controles de usuario nos brindan varias ventajas, entre las más
importantes consta la compatibilidad de ser usada sin problema desde cualquier
lenguaje soportado por DotNET; así un control desarrollado en C# puede ser
usado desde VisualBasic.NET por ejemplo. Además nos brinda protección al
código, puesto que se encuentra compilado y encapsulado en un DLL. Por otro
lado se puede programar el control pensando en una programación de usuario,
esto es, dejando comentarios en XML para que el motor de Visual Studio
encargado de las facilidades de programación como listas, comentarios de
argumentos, entre otros, pueda usar nuestros propios comentarios; además el
uso correcto de propiedades y diseño gráfico nos da la posibilidad de usar nuestro
control en la plantilla de diseño.

Existen dos tipo de controles que se pueden crear, los llamados


CONTROLES propiamente dichos son aquellos que constan de una interfaz de
usuario gráfica, por ejemplo los botones, las etiquetas, formularios, etc. Se
muestran de forma gráfica en nuestro monitor. Por otro lado existen controles que
no tienen interfaz gráfica que toman el nombre de COMPONENTES y entre estos
se encuentran controles como el Timer, SerialPort, DataSets, entre otros. Si bien
el concepto de control o componente puede ajustarse a ambos casos, se usa esta
diferencia para separar ambos casos, puesto que en la parte de diseño, ambos
son tratados de forma diferente.
52

Los pasos a seguir para la creación de un control son:

1. Crear un proyecto nuevo y elegir la plantilla “Class Library”, el nombre del


nombre del proyecto asignado será el nombre del ensamblado y del
archivo DLL generado al final.

Dibujo 7: Nuevo Proyecto Class Library - ORIGEN: Visual Studio.NET 2005

2. Agregar un nuevo Control de Usuario. Para esto basta hacer clic derecho
encima del proyecto en el explorador de soluciones y elegir la opción: “Add
>> New Item” y seleccionar la plantilla: “User Control” para crear un control
y “Component Class” para un componente.
53

Dibujo 8: Nuevos componentes o controles - ORIGEN:


Visual Studio.NET 2005

3. Programar el control o componente con sus respectivos valores,


propiedades, comentarios, interfaz gráfica, etc.

4. Compilar el control ya sea bajo DEBUG o RELEASE. Al hacerlo saldrá un


mensaje avisando que una biblioteca de clases compilada, crea un DLL
pero este no puede ejecutarse de forma independiente. De esta forma,
podemos revisar la carpeta BIN de nuestro proyecto y veremos ahí el
archivo DLL creado.

NOTA.- Se puede abrir el archivo AssemblyInfo.cs que está dentro de la carpeta


Propiedades del proyecto, y modificar los indicadores con que se compila el DLL,
estos indicadores son:

[assembly: AssemblyTitle("MisControles")]
[assembly: AssemblyDescription("Controles propios")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("SILTTEC")]
[assembly: AssemblyProduct("MisControles")]
[assembly: AssemblyCopyright("Danny López-Copyright © 2007")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Código 3: AssemblyInfo - ORIGEN: Propia del autor


54

En la elaboración de un control de usuario existen 4 cosas a tomar en cuenta:

1. Propiedades: Como bien sabemos, las propiedades no son más que


variables encapsuladas, pero en la creación de controles estas son usadas
para acceder desde la ventana de propiedades en tiempo de diseño. Por
ejemplo, si creamos una propiedad llamada “ColorRectangulo” de tipo
COLOR.

private Color colorR = Color.Blue;


public Color ColorRectangulo{
get
{
return colorR;
}
set
{
colorR = value;
}
}

Código 4: Crear una Propiedad - ORIGEN: Propia del autor

2. Método OnPAINT.- Este método está en la clase UserCONTROL 12 de la


cual heredamos nuestra clase, por lo tanto para tener acceso a este
método tenemos que sobre-escribirlo de esta forma:

protected override void OnPaint(PaintEventArgs e)


{
Graphics g = e.Graphics;
//Aquí se ingresa todo el código para graficar en el control
g.DrawRectangle(Pens.Blue, 50, 50, 200, 200);
base.OnPaint(e);
}

Código 5: Método PAINT - ORIGEN: Propia del autor

12 http://msdn2.microsoft.com/en-us/library/ms173038(VS.80).aspx
55

En este ejemplo estamos dibujando un rectángulo de color azul en el


control y este aparecerá incluso en el tiempo de diseño cuando lo coloquemos en
un formulario. De este modo solo basta un buen dote artístico para crear
controles gráficos, por ejemplo un Switch, un LED, u otros.

Combinando las propiedades y este método podemos probar el siguiente


código:

private Color colorR = Color.Blue;


public Color ColorRectangulo
{
get {return colorR;}
set
{
colorR = value;
this.Invalidate();
}
}

protected override void OnPaint(PaintEventArgs e)


{
Graphics g = e.Graphics;
g.DrawRectangle(new Pen(colorR), 50, 50, 200, 200);
base.OnPaint(e);
}

Código 6: Control sencillo - ORIGEN: Propia del autor

Como podemos ver, luego de cambiar el valor de la propiedad


ColorRectangulo, colocamos una llamada al método Invalidate del control, que
obliga a ejecutarse de nuevo el método OnPAINT. Y dentro de este, el color del
rectángulo será el establecido por la propiedad.

Lo interesante de esto es que este código se ejecuta en tiempo de diseño,


así cuando tengamos a nuestro control en un formulario, basta cambiar la
propiedad en la ventana correspondiente y el rectángulo cambiará de color. Y
cabe recalcar una vez más que esto se hace en tiempo de diseño.
56

3. Eventos.- Como se trata de una clase con código cerrado, es


indispensable el uso de eventos para avisar al programa sustentador del
control que se ha efectuado una acción. Todo control de usuario ya posee
por herencia varios eventos tales como el Clic, el Paint, los eventos propios
del Mouse, etc. Pero por ejemplo, si en nuestro control quisiéramos
generar un evento cuando se ha cambiado el color del rectángulo a rojo,
debemos crear el evento nosotros mismos de esta manera:

public delegate void dColor();


public event dColor ColorRojo;

public Color ColorRectangulo


{
get { return colorR; }
set {
colorR = value;
if (colorR.Equals(Color.Red))
{
if (ColorRojo != null) ColorRojo();
}
this.Invalidate();
}
}

Código 7: Crear un Evento - ORIGEN: Propia del autor

Como vemos, el evento se llama ColorRojo y está en la lista de eventos de


la ventana Propiedades del control en tiempo de diseño, y se lo puede usar como
cualquier evento más. Además está usando un delegado sin argumentos, pero
casi siempre los eventos poseen argumentos que deben estar especificados por
el delegado.
57

4. Comentarios XML.- Estos comentarios son muy útiles a la hora de usar el


control, pues son utilizados por el IDE de programación. Los comentarios
se colocan antes de empezar con la declaración de una clase, propiedad o
método y son declarados con tres barras inclinadas “///”. Además en el
caso de las propiedades, también hay como agregar especificaciones para
ser usadas en la ventana de propiedades en tiempo de diseño. Veamos
unos cuantos ejemplos.

/// <summary>
/// Es el color que va a tener el borde del rectángulo
/// </summary>
[DescriptionAttribute("Es el color que va a tener el borde del
rectángulo")]
[BindableAttribute(true)]
[CategoryAttribute("Colores")]
public Color ColorRectangulo
{
.............

Código 8: Comentarios XML - ORIGEN: Propia del autor

Ventana de Propiedades en tiempo de diseño

Ilustración 1: Ventana de Propiedades -


ORIGEN: Propia del autor
58

Comentario de la propiedad al escribir código.

Dibujo 9: Propiedades en el código - ORIGEN: Propia del autor

En el caso de los métodos se puede usar más indicativos como por ejemplo:

/// <summary>
/// Método que suma dos valores
/// </summary>
/// <param name="sumando1">Valor del primer número a sumar</param>
/// <param name="sumando2">Valor del segundo número a sumar</param>
/// <returns>Respuesta de la suma</returns>
public double Sumar(double sumando1, double sumando2)
{
return sumando1 + sumando2;
}

Código 9: Argumentos documentados - ORIGEN: Propia del autor

Usando estos comentarios de forma correcta, podemos hacer uso de las


facilidades que brinda visual studio al navegar por objetos, es decir podemos usar
59

el explorador de objetos, los comentarios en tiempo de diseño, generar reportes


de métodos, ayudas, y muchas cosas más.
60

3 CAPITULO III: Redes Neuronales Artificiales (RNA)

3.1 Introducción:

La inteligencia artificial básicamente trata de dotarle a un sistema computacional


la capacidad de tener inteligencia, y esta en un breve resumen se puede centrar
puntualmente en dos aspectos:

a) Toma de decisiones según el entorno

b) Mejorar sus conocimientos en el transcurso del tiempo (aprendizaje –


evolución).

Para cumplir el primer aspecto señalado, es necesario tener un sistema


retroalimentado que consta básicamente de sensores para poder parametrizar el
entorno, un cerebro que procese la información y tome decisiones, y actuadores
para poder interactuar con el entorno.

En tanto el segundo aspecto se torna un poco más complicado. Para que


un sistema pueda aprender se necesita inevitablemente cambiar la información
que posee, es decir sus reglas del juego, y para conseguir esto es necesario tener
un sistema computacional, puesto que es el único sistema que tiene la capacidad
de cambiar sus datos de forma autónoma.

No obstante, la complejidad de cambiar de forma autónoma un programa


para que este pueda “aprender” nos obliga a buscar una manera de conseguir
una estructura informática estable y que dependa únicamente de DATOS o
valores para su cambio o aprendizaje.

Es así que las redes neuronales artificiales, basadas en el funcionamiento


de las redes neuronales biológicas, cumplen el segundo aspecto de la inteligencia
artificial, constan de un sistema informático estable que depende de valores
fácilmente alterables para su aprendizaje.
61

3.2 Reseña Histórica:

Las redes neuronales artificiales nacieron de la idea de simular o imitar el


funcionamiento de las redes neuronales biológicas, así que para mirar su pasado
debemos empezar mencionando a Platón y Aristóteles quienes fueron los
primeros en plantear teóricamente el funcionamiento del cerebro humano. Claro,
no fue hasta 1936 que Alan Turing miró al cerebro como una forma de ver los
sistemas computacionales, presentando muchos trabajos sobre la inteligencia
artificial, algunos consagrados como el famoso Test de Turing13.

Pero la verdadera cuna de las redes neuronales artificiales como tales,


viene de la mano de Warren McCulloch y Walter Pitts, un neurofisiólogo y un
matemático, respectivamente. Quienes publicaron en 1943 un libro llamado: "A
logical calculus of the ideas immanent in nervous activity" que mostraba un
análisis matemático del funcionamiento del cerebro y además mostraron el primer
modelamiento de una neurona simple, construida con circuitos electrónicos de la
época, al que llamaron Perceptrón.

Pero el gran avance de estos sistemas tendría un golpe muy duro de la


mano de Marvin Minsky14 y Seymour Papert del Instituto Tecnológico de
Massachussets (MIT), que presento el libro Perceptrons en 1969 que mostraba
al perceptrón como una unidad de control muy débil al no poder resolver la
función XOR (OR exclusiva), y así demostrar la linealidad del perceptrón,
característica intolerable en un mundo no-lineal, razón suficiente como para
declarar a la neurona artificial como un elemento de control no apropiado y
caduco.

En el transcurso de la siguiente década muy pocas investigaciones se


hicieron, aunque fue en 1974 cuando se realizo el primer algoritmo de aprendizaje
de propagación para atrás.

13 http://www.fil.ion.ucl.ac.uk/~asaygin/tt/ttest.html
14 http://web.media.mit.edu/~papert/
62

Pero el nuevo renacimiento de las redes neuronales artificiales vendría de


John Hopfield del mismo Instituto Tecnológico de Massachussets15 en 1982 al
publicar el libro “Neural Computation of Decision in Optimization Problems”
que mostraba la idea de conjunto de neuronas, conjunto de perceptrones que al
ser combinados en una estructura podían solucionar problemas no-lineales, y
claro, lo demostraron con el mismo problema que años atrás había destruido al
perceptrón.

Desde entonces las redes neuronales han ido evolucionando


constantemente, teniendo ahora un gran número de alternativas que van desde
un multi-layer perceptrón con Back Propagation, hasta lo conocido como Redes
neuronales difusas.

Y sus aplicaciones hoy están en muchos de los artefactos que usamos a diario.
Entre ellos los más conocidos son: todos los OCR (reconocimiento óptico de
caracteres), reconocedores de voz, TTS16 (Text To Speech) , Reconocedores de
huellas digitales, Controladores Biométricos de personal, correctores de gramática
de procesadores de palabras, etc

15 http://web.mit.edu/
16 http://en.wikipedia.org/wiki/Speech_synthesis
63

3.3 Neurona Biológica:

Al basarse las redes neuronales artificiales en el comportamiento de las redes


neuronales biológicas, es evidente empezar por entender el funcionamiento de
una simple neurona biológica, esta sin entrar en mayor detalle se compone en de
4 partes:

Dibujo 10: Neurona Biológica - ORIGEN: Propia del autor

3.3.1 Dendritas

Son capilares que permiten el ingreso de los impulsos neuronales hacia el núcleo
o SOMA de la neurona. Es decir, las dendritas constituyen las “Entradas” de la
neurona biológica.

Los impulsos neuronales son cargas electro-químicas generadas por el paso de


iones eléctricos de varios componentes químicos como el potasio y sodio.
64

3.3.2 Sinapsis

Es una membrana premiable que se encuentra al extremo de cada dendrita. Esta


sinapsis modifica el impulso eléctrico que ingresa por la dendrita, atenuándolo o
amplificándolo, de tal manera que es visto como la “Ganancia” de una dendrita.

Como veremos posteriormente, la ganancia que la sinapsis le brinda a cada


dendrita es la causante directa del resultado que la neurona genere, de este modo
es considerada a este nivel como la “Memoria” de la neurona, puesto que
depende de la sinapsis para que una neurona se comporte de una forma u otra.

3.3.3 Soma.

Es el núcleo de la neurona, y es aquí donde se procesa todas las señales


procedentes de las dendritas para generar una señal resultado. Este
procesamiento se divide básicamente en dos etapas:

Suma de señales.- Simplemente se suman todas las señales obtenidas de las


dendritas.

Función de Transferencia.- Obtenida la señal sumada, esta pasa por una función
de transferencia propia de cada tipo de neuronas, y genera una señal resultado.

3.3.4 Axón.

Es la salida de la neurona, es decir, la señal resultado que ofrece el SOMA luego


de procesar las señales de las dendritas, es transportada por el axón que puede
extenderse en el caso de los humanos, hasta varios metros ramificándose
llevando esta señal no solo hasta la dendrita una neurona, sino que puede llegar a
dar su señal hasta a 10 000 neuronas, y así, con la conexión de axones y
dendritas, formar lo que se conoce como una Red Neuronal.
65

3.4 Neurona Artificial:

Basándose en el modelo de la neurona biológica, vamos a tener:

Dibujo 11: Neurona Artificial - ORIGEN: Propia del autor

Donde claramente las entradas estarán expresadas con el vector X, las


respectivas ganancias con G, la sumatoria y función de transferencia y finalmente
la respuesta expresada en la señal Y.

Dado este modelo lógico, pasar a un modelo matemático17 es bastante sencillo:

n
I= ∑i= 1
X i ⋅ Wi

Y = f (I )

17Libro: “A logical calculus of the ideas immanent in nervous activity”


66

Donde se ha reemplazado la ganancia “G”, por la “W”, puesto que la


mayoría de autores le tratan a la ganancia de una entrada como PESO de la
entrada, así en inglés sería WIDTH y de ahí que se usa la “W” en lugar de la “G”
para expresar este parámetro.

3.5 Perceptrón:

El perceptrón es uno de los primeros modelos de neurona artificial que existió, y


apareció en 1943. Está basado en el modelamiento matemático antes visto y usa
la función de transferencia ESCALÓN. Es decir, consta únicamente de dos
valores de salida ACTIVADO / DESACTIVADO que puede expresarse de forma
binaria por 1 y 0 lógico. Este valor de salida depende de un umbral (u) el cual casi
siempre tiene el valor de 0; al sobrepasar este umbral, la neurona se activa y al no
pasar el umbral la neurona queda desactivada.

n X1
I= ∑ X i ⋅ Wi W1


i= 1 X2 W2
Y
W3
If I > u : Y = 1 X3
Wn
Else Y = 0 Xn
67

3.5.1 Aprendizaje del Perceptrón:

En 1948, 5 años después de la creación del perceptrón, Donald Hebb


propuso un algoritmo matemático para ajustar los pesos del perceptrón, y con
esto lograr que la neurona responda como se desea al dar unas determinadas
entradas.

El algoritmo de variación de los pesos se basa en el error o diferencia que


existe entre la salida obtenida de la neurona y la salida requerida o deseada; y
multiplicar este error por el valor mismo de la entrada, dando un valor el cual
indicará la diferencia entre el nuevo peso y el antiguo.

E = Yd − Yo
∆ Wi = X i ⋅ E
Wi( t + 1) = Wit + ∆ W

Donde:

Yd : Salida Deseada

Yo : Salida Obtenida

∆ Wi : Significa el Deltha del peso

Wi : Hace referencia al valor del nuevo peso, por eso el (t + 1), que significa
( t + 1)
(Tiempo+1)

Wit : Este entonces sería el peso actual. En el tiempo actual (t)

Los pasos a seguir para enseñar a una neurona a comportarse de la forma


que deseamos, es el siguiente:

Colocamos valores aleatorios en todos los pesos.


68

Vamos colocando un conjunto de entradas y tomando la salida obtenida.

Calculamos el error, que no es más que la diferencia entre la salida deseada y la


obtenida.

Calculamos el dW, es decir, el valor Deltha del peso.

Ahora tomamos un segundo juego de entradas y volvemos a aplicar los pasos 2,3
y 4. Esto lo hacemos para todos los conjuntos de entradas.

Sumamos todos los dW de un peso que obtenemos en los distintos conjuntos de


entradas, para unificar el cambio que queremos darle al peso.

Actualizamos los valores de los pesos según nuestro dW

Con esto terminamos lo que se conoce como UNA ITERACIÓN.

El aprendizaje de una neurona se mide en razón de las iteraciones que le demora


converger en una respuesta. De este modo una neurona logrará converger a una
respuesta en varios miles de iteraciones, claro, dependiendo de la complejidad del
problema a resolver.

3.5.2 Problema de Oscilación.

Este problema se encontró en las iteraciones finales de una neurona al


alcanzar una respuesta. Y no es más que un cambio brusco en los pesos que
hace que la solución no llegue a converger en una respuesta

Respuesta Obtenida

Respuesta Deseada

Iteraciones

Dibujo 12: Problema de Oscilación - ORIGEN: Propia del autor


69

La solución de este problema no es más que atenuar el cambio de los pesos, para
que no cambien tan bruscamente y así pueda converger más rápido. Así nace el
parámetro conocido como Taza de aprendizaje, en inglés Learning Rate
expresado normalmente con las siglas LR o como una constante o coeficiente, es
decir con una letra griega como alpha (α).

Este valor de taza de aprendizaje normalmente toma un valor entre 0 y 1,


siendo un valor cercano a 0 suficiente como para variar muy poco los pesos. Se
usa un valor así de bajo cuando se quiere pulir una respuesta. Por otro lado, un
valor alto cercano a 1 haría que los pesos cambien bruscamente.

Usar un valor alto siempre, hace que la respuesta oscile y no converja en


una respuesta como lo veíamos anteriormente, por otro lado un valor muy
pequeño haría demasiado lento el proceso de entrenamiento. Por eso es
recomendable empezar el entrenamiento con un valor alto de LR, y según vaya
llegando a una respuesta reducir esta variable hasta converger en una respuesta.

Aún sabiendo la funcionalidad exacta de este parámetro LR, no es posible


asignar un algoritmo que lo describa a lo largo del entrenamiento de la neurona.
Así que el valor y la variación del mismo dependerá de la experiencia empírica de
quien entrena la red, así como la complejidad del problema a resolver. En todo
caso, muchos optan por dejar con un valor fijo a este parámetro durante todo el
entrenamiento, el cual casi siempre esta entre 0,5 y 0,6.

Respuesta Obtenida

Respuesta Deseada

Iteraciones

Dibujo 13: Solución Linealidad - ORIGEN: Propia del autor


70

3.5.3 Problema de Linealidad

Para comprender de mejor manera el problema de linealidad de una


neurona, vamos a tomar como ejemplo un perceptrón de dos entradas, el cual se
puede representar en un plano donde el valor de cada entrada toma un valor en
cada uno de los 2 ejes, graficando un punto en el plano, propio de cada conjunto
de entradas.

P Y

Ahora, vamos a entrenar a nuestra neurona para que se comporte como una
compuerta lógica AND, es decir, que responda de acuerdo a la siguiente tabla:

a b Y

0 0 0

0 1 0

1 0 0

1 1 1

Graficando este problema en un plano tendríamos que:


71

Y= 1
1
Y= 0

a
0

0 1

Dibujo 14: Compuerta AND - ORIGEN: Propia del autor

Ahora, si observamos la ecuación que describe el comportamiento del perceptrón


tenemos:

n
I= ∑i= 1
X i ⋅ Wi If I > 0 : Y = 1 :Else Y = 0

Y aplicada al problema de nuestro ejemplo tenemos:

I = a ⋅ W1 + b ⋅ W2
Pues bien, está formula es correspondiente a la ecuación de una recta, en donde:

r = AX + BY + C I = a ⋅ W1 + b ⋅ W2 + 1

A = W1 : B = W2 : X = a : Y=b :C=1

Como sabemos, las constantes que dan forma a una recta son A y B,
correlacionadas a nuestra neurona, vendrían a ser los pesos de la misma. Así es
72

que al modificar los pesos de esta neurona, en realidad estamos creando y


ubicando una recta en el plano.

Una recta que resuelva nuestro problema, se gráfica en el plano a continuación:

b
r
Y= 1
1
Y= 0

a
0

0 1

Dibujo 15: Solución C. AND - ORIGEN: Propia del autor

Recordando a la ecuación de la recta que usualmente usábamos para saber si un


punto (x,y) o en este ejemplo (a,b) se encontraba formando parte de la recta.
Ahora vamos a usar la ecuación para saber a que lado de la recta se encuentra
un punto.

Y esto se logra solo viendo si el resultado es positivo, se encuentra a un lado, y si


es negativo, se encuentra al otro. Claro, tendiendo en 0 que nuestro punto forma
parte de la recta.

De esta forma, los valores constantes que representan a esta recta, serán los
valores de los pesos de nuestra neurona al llegar a la respuesta de este
problema.
73

Visto desde este punto, al inicializar los pesos de forma aleatoria, estamos
colocando una recta cualquiera en el plano, y esta empieza a moverse a medida
que nuestra neurona se entrena, hasta llegar a separar un conjunto de otro.

Si analizamos cualquier otro ejemplo de 2 entradas, podremos graficar los


conjuntos de respuesta en un plano, y graficar una recta que los separe. Dando
así con el valor de los pesos para que un perceptrón resuelva el problema.

Por ejemplo:

Y= 1
a
Y= 0

Dibujo 16: Problema Lineal - ORIGEN: Propia del autor

Si trabajamos con una sola entrada, podemos graficar los valores como puntos
sobre un solo eje, y la “recta” solucionadora quedaría expresada solo como un
punto que separe los do grupos a clasificar.

Si trabajamos con tres entradas nos tocaría graficar los valores en un plano en
tres dimensiones, y la “recta” solucionadora debería ser ahora un plano que
separe un grupo de otro.

De esta forma, si trabajamos con 4 entradas, en teoría se debería graficar los


valores en un plano de 4 dimensiones, lo cual no es posible, al menos por ahora,
74

y la separación estaría dada por un cubo. En todo caso, el modelamiento


matemático sirve para resolver problemas de cualquier número de entradas, así
no sea posible un modelamiento gráfico del mismo.

Ya sea con una, dos o “n” entradas, el Perceptrón solo responde a una respuesta
“lineal” siéndole imposible resolver problemas donde sus respuestas requeridas
no puedan ser separadas por una línea. Y es así que Marvin Minsky y Seymour
Papera del MIT en 1969 mostraban la imposibilidad del perceptrón al tratar de
resolver la operación binaria XOR. Dado que, la tabla de verdad de la XOR y su
respuesta debería ser:

a b Y

0 0 0

0 1 1

1 0 1

1 1 0

Dibujo 17: Compuerta XOR - ORIGEN: Propia del autor

Como se puede apreciar, una recta no podría nunca dar resultado a este
problema. Además, argumentando que los problemas en la naturaleza responden
75

más a una solución desordenada que a una ordenada que demanda una
respuesta no lineal de los sistemas, por ejemplo:

Y= 1
a
Y= 0

Dibujo 18: Problema No Lineal - ORIGEN: Propia del autor

Así es como estos investigadores del MIT recomendaron en su libro


abandonar toda investigación respecto al uso del las neuronas artificiales. Y así
fue que durante 10 años no se hizo mayor investigación al respecto.
76

3.6 Perceptrón Multicapa

En 1982 de se muestra una investigación realizada por el mismo MIT que años
atrás había sepultado al perceptrón, la posibilidad de armar una red con
perceptrones, es decir combinar un conjunto de neuronas artificiales y hacerlas
funcionar a la par para resolver un mismo problema. A esta combinación de
neuronas artificiales se le conoció como Perceptrón Multicapa, y es aquí donde
nace la idea propiamente dicho de Redes Neutrales Artificiales.

Estas redes estarán organizadas por capas, teniendo únicamente dos al


inicio, la capa de entrada y la capa de salida. Y ambas interconectadas teniendo a
todas las neuronas de la capa de salida con una conexión o peso para cada una
de las neuronas de la capa de entrada.

Dibujo 19: Interconexión de capas - ORIGEN: Propia del autor

Este modelo sirvió para combinar varias neuronas artificiales en un mismo


problema, pero seguían siendo perceptrones que respondían a una respuesta
lineal. Es así que se vio la necesidad de expandir este modelo y aumentar una o
77

varias capas más en el medio, conocidas como CAPAS OCULTAS, en inglés


Hides Layers , que pueden ser una única capa o varias.

Dibujo 20: Estructura de una RNA - ORIGEN: Propia del autor

En este ejemplo, se ve una red neuronal con 3 capas ocultas, además de la capa
de entrada y salida.

Como podemos ver gráficamente, las salidas de una neurona vienen a ser las
entradas para cada neurona de la capa siguiente, de la misma forma para la capa
subsiguiente hasta llegar a la capa de salida que ofrece los resultados finales de
la red. Todas las neuronas de las capas ocultas y de salida responden bajo la
misma expresión matemática vista con el perceptrón, en cuanto a la capa de
entrada, esta no efectúa ningún cálculo interno, solo sirve como soporte para la
distribución de las entradas hacia todas las neuronas de la capa subsiguiente. Es
decir, las neuronas de la capa de entrada responden simplemente a una
expresión de paso (Lo que entra, sale).

De esta forma, las redes neuronales logran brindar un resultado NO-LINEAL, y


claro pueden resolver el problema de la XOR sin problemas. A continuación un
ejemplo de una red neuronal de tres capas que logra resolver el mencionado
problema.
78

Dibujo 21: Solución de la C. XOR - ORIGEN: Propia del autor

En cuanto al algoritmo de aprendizaje, las redes neuronales se clasifican en dos


grandes grupos:

● Aprendizaje Supervisado

● Aprendizaje NO-Supervisado

Siendo la primera aquella que necesita saber la salida deseada antes de empezar
el proceso de aprendizaje. Se le conoce como supervisada por el mismo hecho de
tener que ofrecerle las salidas que se buscan, lo que implica inevitablemente
saber las salidas que se quieren, lo cual no siempre es un dato al que tenemos
acceso. En este sistema, se encuentran varios algoritmos teniendo el más usado
y popular al Back-Propagation el cual se explicará en detalle más adelante.

El aprendizaje No-Supervisado es un diseño diferente de redes neuronales donde


la propia red establece cuales son las mejores salidas que puede ofrecer. Esto
representa como en todo, puntos a favor y en contra. Por un lado hace más
dinámico el aprendizaje y logra converger a soluciones de una manera más
natural y más cercana al modelo biológico del cerebro. Pero por otro lado, el no
tener las salidas deseadas, hace imposible calcular una taza de error y por lo
tanto muy complejo saber hasta cuando llevar a cabo el entrenamiento de la
misma. En este tipo de aprendizaje entran modelos de redes como las de Kanon,
Mapas Auto-Organizativos y demás.
79

3.6.1 Neurona artificial auxiliar (BIAS):

El manejo de las redes neuronales de forma empírica ofreció muchos resultados a


los investigadores quienes buscan maneras de hacer el aprendizaje más exacto y
sobretodo rápido. En base a uno de estos estudios empíricos nació la idea de una
neurona artificial auxiliar a la que llamaron Tendencia o por su inglés BIAS, que
no es más que un perceptrón en una capa que siempre tendrá como valor de
entrada la unidad (1), de esta forma no afecta como entrada al sistema, pero sus
pesos si afectan al conjunto. Agregar esta neurona auxiliar demostró en la
práctica mejoras muy significativas en varios problemas, y el uso o no de la
misma aún no está regido a una norma, como muchas cosas en las redes
neuronales, esta depende de la experiencia del diseñador de la red.

La mayoría de autores, muestran a la neurona auxiliar como una neurona de


forma triangular, ubicada como una neurona más en la capa anterior y sin
representar su entrada, puesto que siempre será 1.

Dibujo 22: Neurona BIAS - ORIGEN: Propia del autor


80

Muchas veces el modificar un peso, implicar alterar significativamente la


entrada al que corresponde dicho peso. La neurona auxiliar BIAS nos brinda la
posibilidad de tener pesos, los cuales podemos modificar sin que esto implique
alterar a su entrada, puesto que su entrada siempre será 1 y por lo tanto no
tomada en cuenta, además es una neurona auxiliar, es decir está como sobra del
sistema y por lo tanto no interfiere, pero si nos da varios pesos más que mover y
así converger a un resultado más rápido.
81

3.7 Algoritmo de aprendizaje: BACKPROPAGATION

3.7.1 Introducción:

La creación de redes multicapas resolvía el problema de linealidad como ya vimos


anteriormente, pero plantea un nuevo problema en cuanto al algoritmo de
aprendizaje.

Para usar la regla delta se necesita saber los valores de salida deseados y
compararlos con los valores obtenidos por la red neuronal, sin embargo al tener
una o varias capas ocultas, necesitaríamos conocer los valores que quisiéramos
que dicha capa oculta saque, y esto no es posible. No obstante las salidas
deseadas de la capa de salida si se los tiene, al ser un aprendizaje supervisado y
podemos saber el error general de la red neuronal y en base a este error,
distribuirlo hacia las capas ocultas usando una modificación o generalización de la
regla delta, conocida mejor como algoritmo BackPropagation haciendo énfasis
en la idea de capturar el error en la capa de salida y propagar el error hacia atrás,
llegando a todas las capas ocultas.

Dibujo 23: Propagación de errores hacia atrás - ORIGEN: Propia del Autor
82

3.7.2 Resumen histórico:

En 1974, Paul Verbos, Ph.D. de la Universidad de Harvard, publica el libro “The


Roots of BackPropagation” donde describe un sin número de procesos
matemáticos para propagar el error hacia atrás en cualquier red de modelamiento
paralelo. Dado que las redes neuronales se consideran un tipo especial de redes,
sus colegas científicos tomaron poca o ninguna importancia a sus estudios que
generalizaban este proceso sin darle una utilidad concreta a las redes neuronales.

Libro 1: The Roots of BackPropagation - ISBN: 9780471598978

Doce años después de esto (1986), dos trabajos realizados al mismo tiempo por
David E. Rumelhart, Geoffrey E. Hinton y Ronald J. Williams, David Parker y
Yann Le Cun, mostraban un algoritmo backpropagation mucho más concreto,
estable y dedicado a las redes neuronales; recibiendo mucha acogida por la
comunidad de desarrolladores.

Sin embargo fue gracias al libro que el mismo año publicaron David E Rumelhart y
James L McClelland de la Universidad de California con el título de “Parallel
distributed processing” que hizo del algoritmo uno de los más populares y
usados métodos de aprendizaje hasta nuestros días.
83

Libro 2: Parallel Distributed Processing - ISBN 0262181231

Dibujo 24: David E. Rumelhart - ORIGEN:


http://www.grawemeyer.com/psychology/previous/02.htm

Dibujo 25: James L McClelland - ORIGEN:


http://www.grawemeyer.com/psychology/previous/02.htm
84

3.7.3 Algoritmo de Aprendizaje:

La regla delta generalizada o Backpropagation se puede resumir simplemente


como:

Wt + 1 = Wt − α ∇ E 2
Donde:

Wt + 1 = Nuevo valor del peso

Wt = Valor actual del peso

α = LR (Learning Rate) o taza de aprendizaje: Valor Entre 0 y 1

− ∇ E2 = Gradiente negativa del error medio cuadrático

Entonces la diferencia entre el nuevo y el actual valor del peso esta dado por la
gradiente negativa del error medio cuadrático, atenuado por el LR

El LR o taza de aprendizaje es un valor que va entre 0 y 1, siendo 0 un indicador


que no haría ningún cambio en el peso, y 1 el que deje pasar todo el valor al
nuevo peso. Así un 0,5 atenuaría el cambio del nuevo peso a la mitad.

En posteriores capítulos trataremos de nuevo el valor de la taza de aprendizaje


para entender mejor como afecta en el entrenamiento de la red neuronal.

La gradiente inversa del error se describe como la derivada del error


respecto a todos los pesos de la red.

∂ E2
−∇E = − 2

∂W
85

Para continuar desenvolviendo la derivada hasta llegar a una representación


matemática fácil de interpretar en código, veamos una vez más la nomenclatura
usada para definir todas las partes de una red neuronal.

Para este ejemplo demostrativo, solo veremos una red neuronal con una capa
oculta.

Así:

E1 = Salida de la primera neurona de la capa de entrada

i = Numero de neuronas en la capa de entrada

O1 = Salida de la primera neurona de la capa oculta

j = Numero de neuronas en la capa oculta

S1 = Salida de la primera neurona de la capa de salida

k = Numero de neuronas en la capa de salida

Wij = Peso que conecta a la neurona “i” de la capa de entrada y la neurona “j”
de la capa oculta.
86

Wjk = Peso que conecta a la neurona “j” de la capa oculta y la neurona “k”
de la capa de salida.

Además teniendo implícitamente cada neurona variables tales como:

IE1 = Valor neto de la primera neurona de la capa de entrada

XiOj = Valor de entrada “i” de la neurona “j” de la capa oculta

ISk = Valor neto de la neurona “k” de la capa de salida

Entonces para sacar el error medio cuadrático procedemos a aplicar la


siguiente fórmula18:

1 k
E = ∑ ( Dn − S n ) 2
2

2 n= 1
Donde:

Dn = Salida Deseada de la neurona en la posición “n”

Puesto que en estos momentos no tenemos idea de los valores que tienen
los pesos, por muchos motivos, empezando con que se inicializan con valores
aleatorio; no es posible sacar una derivada numérica del error medio cuadrático
con respecto a los pesos, así que debemos operar la derivada hasta llegar a
expresarla en otro dominio.

18 http://ohm.utp.edu.co/neuronales/Capitulo2/Backpropagation/ReglaB.htm
87

3.7.3.1 Capa de Salida:

Siendo:

∂ E2

∂ W jk
La gradiente inversa del error con respecto a los pesos que corresponden a las
conexiones entre la capa oculta y la capa de salida ( j k ).

Tenemos:

∂ E2 ∂ 1 k  ∂ Sk
− = −  ∑ ( Dn − S n ) 2  = ( Dn − S n ) ×
∂ W jk ∂ W jk  2 n= 1  ∂ W jk

Ahora tenemos a la derivada de las señales de salida con respecto a los pesos.

Entonces sabiendo que la salida es una función directa de la sumatoria interna de


las entradas a la que llamamos ( I ), aplicamos la regla de la cadena:

∂ Sk ∂ Sk ∂ I k
= ×
∂ W jk ∂ I k ∂ W jk
Entonces, reemplazando esta ecuación con la anterior tenemos que:

∂ E2 ∂S ∂ Ik
− = ( Dk − S k ) × k ×
∂ W jk ∂ I k ∂ W jk
88

Recordando que Y = f (I ) tenemos:

∂ E2 ∂ I Sk
− = ( Dk − S k ) × f ' ( I Sk ) ×
∂ W jk ∂ W jk
j
Y recordando también que: Ik = ∑ (X
n= 1
n ⋅ Wnk ) tenemos:

∂ E2
− = ( Dk − S k ) × f ' ( I Sk ) × O j
∂ W jk

Siendo “Oj “ la salida de la capa oculta, y por lo tanto entrada de la capa de


salida.

Entonces volviendo a la fórmula principal de cambio de pesos tenemos que:

W jk ( t + 1) = W jk ( t ) + α × ( Dk − S k ) × f ' ( I Sk ) × O j
Teniendo a mejor expresar como:

∆ W jk = ( Dk − S k ) × f ' ( I Sk ) × O j

W jk( t + 1) = W jk( t ) + α × ∆ W jk

Donde:

∆ W jk = Es la diferencia o cambio a aplicar en el peso Wjk


89

3.7.3.2 Una Capa Oculta:

En cuanto a los pesos de la capa oculta, basta con proyectar la misma fórmula
teniendo en cuenta que ahora la derivada del error a desarrollar y su respectiva
regla de la cadena quedarían así:

∂ Sk ∂ S k ∂ I Sk ∂ O j ∂ I Oj
= × × ×
∂ Wij ∂ I Sk ∂ O j ∂ I Oj ∂ Wij

Resumiendo el proceso, la fórmula final quedaría:

∑ (( D − S k ) × f ' ( I Sk ) × W jk ) × Ei
k
∆ Wij = f ' ( I Oj ) × k
n= 1

Wij( t + 1) = Wij( t ) + α × ∆ Wij


90

3.7.3.3 Generalizar a N capas Ocultas:

Para generalizar la fórmula a N capas ocultas, vamos a pensar en una red


neuronal de las siguientes características:

Donde:

Sk = Neurona “k” en la capa de salida

Oil = Neurona “l” en la capa oculta “i”

O (i + 1) m = Neurona “m” en la capa oculta que le sigue a la capa “i”

O ( i − 1) n = Neurona “n” en la capa oculta anterior a la capa “i”


91

Así, la capa oculta “i”, empezará siendo la última capa, la que se encuentra más
cercana a la capa de salida, donde la capa “i+1” será la capa de salida y la capa
”i-1” la penúltima capa. Luego la capa “i” pasará a ser la que muestra el gráfico y
que antes era la capa “i-1” y la capa “i+1” pasará a ser la que antes era la capa “i”
y así sucesivamente hasta cubrir todas las capas ocultas.

Ahora vamos a definir un nuevo valor que muchos autores denominan

“Sensitividad de la capa” ( δ ) y no es más que la fuerza que tiene el error

propagado en esa capa.

Así, la sensitividad de la capa de salida será:

δ S
k = ( Dk − S k ) × f ' ( I Sk )

Esta sensitividad es la única diferencia a partir de ahora entre una capa de salida
y una capa oculta, siendo la sensitividad de una capa oculta:

(δ )
n
δ Oi
m = f ' ( I Oi m ) × ∑
j= 1
O ( i + 1)
j × Wmj

La generalización de las fórmulas para el cambio de pesos sería entonces:

i
Oi
∆Wo lm =δ m × O ( i − 1) l

i i i
Wo lm( t + 1 ) = Wo lm( t ) + α × ∆Wo lm
92

4 CAPITULO IV: Análisis

4.1 Introducción

En el presente capítulo se detallaran todos los requerimientos y limitaciones que


va a tener la tesis enfocándose en el aspecto técnico. Teniendo toda la teoría a
disposición, el análisis se dará mediante una auto evaluación de las necesidades
que se quiere cubrir, actuando como Usuario Programador (cliente) y
desarrollador al mismo tiempo.

4.2 Limitaciones

Dejando a un lado las limitaciones propias del hardware y software que actúan
como plataforma, en cuanto al sistema se refiere, este tendrá únicamente el
algoritmo de aprendizaje por Backpropagation, usando las fórmulas matemáticas
que se muestran con detalle en el capítulo 3.
93

4.3 Requisitos

● Desarrollar íntegramente el código en C# v2.

● Compilar el código en base al Microsoft FrameWork v2.0

● Crear un componente que permita usar una red neuronal artificial, teniendo
las siguientes características:

○ Número ilimitado* de neuronas en la capa de entrada

○ Número ilimitado* de neuronas en la capa de salida

○ Número ilimitado* de capas ocultas, pudiendo ir desde ninguna hasta


las que se requieran.

○ Número ilimitado* de neuronas en cada capa oculta.

○ Integrar las siguientes funciones de transferencia:

■ Escalón

■ Lineal

■ Sigmoide Logarítmica

■ Sigmoide Tangencial

■ Gauss

○ Incluir una función de transferencia personalizada por el Usuario


Programador, es decir, que pueda escribir directamente la fórmula
matemática que desea como función de transferencia.

○ Poder asignar una función de transferencia por cada capa de forma


independiente.

○ Poder usar opcionalmente la neurona auxiliar “BIAS” por cada capa de


forma independiente.
* Limitado por las capacidades de software y hardware del computador, por ejemplo memoria RAM.
94

○ Incluir una forma de inicializar todos los pesos de la red de forma


aleatoria.

○ Dadas un número de muestras de entradas y salidas deseadas, que


ejecute su debido aprendizaje usando el algoritmo de backpropagation.
Permitiendo, así mismo, elegir los parámetros de aprendizaje como son
la taza de aprendizaje, el momento y el error mínimo para terminar el
proceso de aprendizaje.

○ El proceso de aprendizaje debe reportar su avance mediante un evento


donde indique el error y la iteración llevada a cabo.

○ El proceso de aprendizaje debe correr en otro hilo que el programa


principal. Puesto que dicho proceso es largo, no debe paralizar el
programa principal.

○ Debe permitir consultar a la red neuronal artificial dada un vector de


entradas teniendo como resultado el vector de salida e indicando cual
de ellas es la mayor.

○ Todos los parámetros a modificar por el Usuario Programador deben de


estar como “Propiedades” para poder usar la interfaz de diseño de
nuestro IDE de programación.

○ Poder exportar las configuraciones y pesos de una red hacia una


estructura XML (Objeto DataSET)

○ Poder exportar las configuraciones y pesos de una red hacia una


archivo externo.
95

● Crear un control que permita visualizar la configuración y funcionamiento


del componente de redes neuronales artificiales con las siguientes
características:

○ Poder seleccionar cual objeto del componente se requiere visualizar.

○ Visualizar todas las capas y neuronas de la red.

○ Diferenciar claramente entre la capa de entrada, salida y ocultas en el


caso de existir.

○ Dada la variedad de número de neuronas que puede haber en cada


capa, se requiere poder variar el tamaño del gráfico que represente a
una neurona.

○ Poder cambiar los colores de cada capa.

○ Visualizar los valores numéricos de cada entrada y cada salida de la


red.

○ Visualizar las conexiones o pesos de la red.

○ Representar con un color, el valor numérico del peso en cada una de


las conexiones.

○ Toda el diagrama de la red debe ser auto-escalado dependiendo del


tamaño del control, es decir, si el control cambia de tamaño en alguna
acción como por ejemplo maximizar la ventana, el gráfico se ajusta al
nuevo tamaño.

○ Asignar el número de decimales a mostrar en los valores numéricos de


la capa de salida

○ Poder cambiar el tipo de letra y color del texto mostrado en el visor.


96

○ Permitir en tiempo de diseño y por medio de este control varias tareas


del componente de redes neuronales, como son:

■ Asignar pesos aleatorios

■ Asignar valores a cada una de las entradas de la red

■ Ejecutar una consulta con los valores de entrada actuales

■ Guardar y Restaurar un archivo donde esté la configuración y pesos


de la red.

○ Ingresar en tiempo de ejecución los valores de las entradas de la red.

○ Representar la neurona auxiliar “BIAS”.

○ Usar círculos para la representación de las neuronas, lineas para las


conexiones y triángulos para las neuronas auxiliares “BIAS”.

○ Mostrar gráficamente en el centro de cada neurona, un símbolo que


indique la función de transferencia usada.

● Encapsular ambos controles en un archivo DLL.

● Documentar con comentarios XML el código.


97

4.4 Referencias a otros proyectos

A la fecha de inicio de este proyecto, no existía ningún trabajo sobre redes


neuronales artificiales escritas en el lenguaje de programación C#, que se pueda
encontrar, ya sea en algún libro o en el Internet. El no encontrar ningún trabajo de
este tipo fue una de las razones que impulso el desarrollo de esta tesis.

No obstante, a la fecha de hoy, se puede encontrar más de un trabajo realizado


en C# referente a las redes neuronales artificiales. Proyectos que nunca se
tomaron como referentes para el análisis, ni desarrollo de la tesis actual. Sin
embargo, luego de la culminación del mismo, se ha revisado brevemente algunos
de los trabajos encontrados en Internet y se ha podido ver con satisfacción
diferencias muy grandes entre todos los proyectos.

A continuación se muestra las referencias de los proyectos de redes neuronales


artificiales que se ha podido encontrar en Internet hasta la fecha de hoy.

● Titulo: AI : Neural Network for beginners (Parte 1, 2 y 3 )

Autor: Sacha Barber

Universidad: Sussex University in Information Technology for E-


Commerce (ITEC) Inglaterra

URL: http://www.codeproject.com/cs/algorithms/NeuralNetwork_1.asp

● Titulo: C# Neural network library

Autor: Franck Fleurey (Francia)

URL: http://franck.fleurey.free.fr/NeuralNetwork
98

4.5 Diagramas de Casos de Uso

4.5.1 Diagrama de Casos de Uso Nº 1:

Caso de Uso: Crear Aplicativo para entrenar.


Actores: Programador
Descripción: Es necesario crear un aplicativo para poder entrenar la RNA que se
encuentra en forma de componente en un archivo DLL. Razón por la cual el caso
de uso presente muestra como crear un aplicativo en cualquier lenguaje de
DotNET, por ejemplo VB.NET y muestra también como agregar la referencia del
DLL para usar los componentes.

Dibujo 26: Caso de uso Nº 1 - ORIGEN: Propia del


Autor
99

4.5.2 Diagrama de Casos de Uso Nº 2:

Caso de Uso: Agregar y Configurar una RNA


Actores: Programador
Descripción: El componente RNA que ahora se debe encontrar en la barra de
herramientas del tiempo de diseño de un formulario, se agrega como cualquier
otro componente, es decir arrastrándolo hacia el formulario. Una vez colocado, se
procede a configurarlo mediante la ventana de Propiedades del entorno de
diseño.

Dibujo 27: Caso de uso Nº 2 - ORIGEN: Propia del


Autor
100

4.5.3 Diagrama de Casos de Uso Nº 3:

Caso de Uso: Agregar y Configurar el control RNA_Visor

Actores: Programador

Descripción: El control RNA_Visor que ahora se debe encontrar en la barra de


herramientas del tiempo de diseño de un formulario, se agrega como cualquier
otro componente, es decir arrastrándolo hacia el formulario. Una vez colocado, se
procede a configurarlo mediante la ventana de Propiedades del entorno de diseño
y sirve como visualizador de un componente RNA.

Dibujo 28: Caso de uso Nº 3 - ORIGEN: Propia del


Autor
101

4.5.4 Diagrama de Casos de Uso Nº 4:

Caso de Uso: Entrenar una RNA

Actores: Programador, Estructura XML (DataSet)

Descripción: La etapa de entrenamiento de la red neuronal. Con este proceso se


especializa a la red en una tarea dada.

Dibujo 29: Caso de uso Nº 4 - ORIGEN: Propia del Autor


102

4.5.5 Diagrama de Casos de Uso Nº 5:

Caso de Uso: Consultar una RNA

Actores: Programador, Estructura XML (DataSet)

Descripción: La etapa de consulta es el uso como tal del sistema, una vez
entrenada la red, está lista para ser consultada o usada.

Dibujo 30: Caso de uso Nº 5 - ORIGEN: Propia del Autor


103

4.5.6 Diagrama de Casos de Uso Nº 6:

Caso de Uso: Trabajar con el visor de la RNA

Actores: Programador

Descripción: Se puede visualizar el proceso de una red neuronal mediante este


control, este caso de uso, muestra su utilización.

Dibujo 31: Caso de uso Nº 6 - ORIGEN: Propia del


Autor
104

5 CAPITULO V: Diseño

5.1 Introducción

En el presente capítulo, se analizará el diseño de los controles que permitirán el


uso de redes neuronales artificiales. Teniendo el análisis en el capítulo anterior,
aquí veremos el diseño de las clases y secuencia de operaciones, manteniendo el
modelamiento UML.
105

5.2 DISEÑO DEL SOFTWARE (UML)


5.2.1 Diagramas de Clases

Dibujo 32: Diagrama de Clases - ORIGEN: Propia del Autor

El detalle de las clases se muestra a continuación, representados con la siguiente


simbología:

Dibujo 33: Leyenda de Diagramas de Clases -


ORIGEN: Propia del Autor
106

Dibujo 34: Diagrama de Clases (Detalle 1) - ORIGEN: Propia del Autor


107

Dibujo 35: Diagrama de Clases (Detalle 2) - ORIGEN: Propia del Autor


108

5.2.2 Diagramas de Secuencia

5.2.2.1 Diagrama de Secuencia Nº 1: Configuración de la RNA

Actores: Programador

Dibujo 36: Configuración de la RNA - ORIGEN: Propia del Autor


109

5.2.2.2 Diagrama de Secuencia Nº 2: Cambiar Función Custom

Actores: Programador

Dibujo 37: Cambiar Función Custom - ORIGEN: Propia del Autor


110

5.2.2.3 Diagrama de Secuencia Nº 3: Entrenamiento de la RNA

Actores: Programador

Dibujo 38: Entrenamiento de la RNA - ORIGEN: Propia del Autor


111

5.2.2.4 Diagrama de Secuencia Nº 4: Uso de la RNA

Actores: Programador

Dibujo 39: Uso de la RNA - ORIGEN: Propia del Autor


112

5.2.2.5 Diagrama de Secuencia Nº 5: Uso del Visor de la RNA

Actores: Programador

Dibujo 40: Uso del Visor de la RNA - ORIGEN: Propia del Autor
113

6 CAPITULO VI: Construcción

6.1 Herramientas Usadas:

Como se ha repetido a lo largo de todo el documento, todo el sistema está


programado íntegramente en el lenguaje de programación C#, compilado bajo el
FrameWork de Microsoft en su versión 2.0

El IDE de programación usado es el SharpDevelop v2.2 que se puede descargar


gratuitamente de su página web como se indico en el capítulo 2.

Así mismo, se probó abrir y ejecutar el proyecto desde el IDE de Microsoft Visual
Studio 2005 con todo éxito, ya sea en su versión gratuita (Express) como en la
profesional.

Además, para la creación del control que muestra una representación gráfica, se
uso el motor GDI+ propio de DotNET. Así mismo se usaron punteros y manejo de
hilos. Todos estas herramientas explicadas en el capítulo 2.
114

6.2 Componente RNA

El componente encargado de manifestar todo el comportamiento de la red


neuronal artificial como ya vimos en el diagrama de clases, se llama RNA por sus
siglas. Este componente será una clase heredada de Component que es una
clase propia del BCL del framework y encapsula todas las propiedades y métodos
que le permiten comportarse como un componente de usuario y poder ser usado
como tal en todo el IDE.

Todas las clases usadas estarán dentro de un namespace llamado IA_RNA,


haciendo referencia que es parte de la Inteligencia Artificial. Nombre que llevara
también el ensamblado DLL.

El código de esta clase, como en el resto de clases, está debidamente organizado


utilizando los REGION, que son sentencias ignoradas por el compilador que
sirven para agrupar el código y así ser más fácil organizarlo.

Además, el uso de comentarios XML para documentar el código resulta muy


recomendable puesto que a la hora de compilar, estos comentarios se enlazan
como Metadatos a la aplicación final, siendo en este caso el archivo DLL. De esta
forma un IDE como el SharpDevelop o el Visual Studio pueden mostrar estos
comentarios dinámicamente al Usuario Programador.

Por otro lado, existen muchas herramientas externas como el Document! X de la


empresa innovasys que nos permiten generar todo un documento de ayuda en
base a estos comentarios XML de forma automática. En el transcurso de este
capitulo, presentaremos pedazos de código y muestras del documento de ayuda
generado con esta herramienta externa.
115

Dibujo 41: Clase RNA - ORIGEN: SharpDevelop 2.2

En este gráfico se puede apreciar la organización que nos brinda los REGIONs,
así como un comentario XML, que siempre comienzan con un triple símbolo de
dividido (slash “/” ). En el ejemplo, se muestra un resumen (sumary) de lo que va
a hacer esa clase.

La linea de código que se muestra justo encima de la declaración de la clase,


sirve para asignar un icono al componente y así lograr que este salga en la barra
de herramientas de nuestro IDE.
116

En cuanto al documento de ayuda generado, se puede ver en el siguiente gráfico


una muestra de como nos presenta las propiedades del

Dibujo 42: Propiedades del RNA - ORIGEN: Ayuda Generada con Document!X 5.0

Del mismo modo, estos comentarios XML pueden brindar más información, como
por ejemplo en los métodos, se puede describir los argumentos de entrada, la
salida, e incluso colocar un ejemplo de aplicación. Todo esto exportado al
documento de ayuda.

A continuación se muestra un ejemplo del código de los comentarios XML y del


archivo de ayuda, que adicionalmente deja expresada la declaración en algunos
lenguajes de DotNET.
117

Dibujo 43: Método Evaluar - ORIGEN: SharpDevelop 2.2

Dibujo 44: Ayuda: Método Evaluar - ORIGEN: Ayuda Generada con Document!X 5.0
118

6.3 Clase CAPA

La capa clase contiene todas las funcionalidades de una capa de la red neuronal,
y esta maneja todas las neuronas de una forma global. Es decir, en primera
instancia se piensa en crear una clase NEURONA que contenga el algoritmo de
proceso y aprendizaje, y que un vector de objetos de tipo NEURONA sea una
capa. No obstante en el presente trabajo se decidió usar una clase CAPA que
maneje todas las funcionalidades de proceso y aprendizaje de todas las neuronas
de dicha capa; desapareciendo de cierta forma la individualidad de la neurona.

Dibujo 45: Clase CAPA - ORIGEN: SharpDevelop 2.2


119

6.4 Clase CapaColeccion

Esta capa nace de la necesidad de poder manifestar las capas ocultas, puesto
que estas pueden estar entre 0 o un número alto. Así es que se crea una clase
que, con la ayuda de la clase Collection del BCL del FrameWork, administra todo
lo referente a una lista o colección dinámica, es decir, tener los métodos Add,
Clear, etc.

Cabe recalcar que esta estructura de herencia es nueva, y que al menos hasta
ahora, no se ha visto en otro lenguaje de programación. Y es que no solo se
hereda la clase Collection, sino en la misma declaración de clase, se indica la
clase de la cual se va a hacer la colección, siendo en este caso la clase CAPA.

Dibujo 46: Clase CapaCollection - ORIGEN: SharpDevelop 2.2


120

6.5 Clase EvaluadorString

Esta capa cumple un papel específico y no indispensable en el sistema.

Entre las funciones de transferencia que existen, tenemos la opción CUSTOM,


que se encarga de dar una ventana a que el Usuario Programador para que
pueda personalizar su función de transferencia. Entonces para lograrlo, se crea
esta clase que permite crear una función virtual en tiempo de ejecución. Esto es,
que mientras se está ejecutando el programa, se puede escribir en una cadena de
texto una función, compilarla y usarla.

Gracias a esta clase que permite evaluar como código un String, se puede crear
una función virtual donde se deje espacio para que el Usuario Programador cree
una función matemática a gusto y la ingrese dentro de la propiedad
formula_Custom de la clase CAPA.

Dibujo 47: Clase EvaluadorString - ORIGEN:


SharpDevelop 2.2
121

6.6 Clase RNA_Visor

Es la clase más extensa del sistema, y se encarga de crear una representación


gráfica de la red neuronal. Esta se instancia como un control normal, y entre las
propiedades solicita se indique que red neuronal se desea visualizar. Teniendo
que tener previamente ya una instancia de RNA.

Dibujo 48: Clase RNA_Visor - ORIGEN: SharpDevelop 2.2


122

Este control se hereda de la clase UserControl del BCL del Framework, y


sobrecarga el método OnPaint del mismo para lograr la mejor forma de
graficación. Puesto que el método OnPaint se ejecuta automáticamente cuando el
control requiere dibujarse, dando mucha facilidad de hacerlo al heredar también el
objeto Graphics o Lienzo del control. Toda esta información de como dibujar en un
control s ella puede encontrar en el capítulo 2; donde se especifica la creación de
controles y el manejo del GDI+, puesto que absolutamente todos los gráficos de
este visor, son creados con el GDI+.
123

7 CAPITULO VII: Ejemplo de Aplicación (OCR Básico)

7.1 Introducción

Para poder mostrar el correcto funcionamiento de los controles para redes


neuronales creados en el presente trabajo, es necesario darle un aplicativo real.
Por esta razón, a continuación se presenta un pequeño ejemplo de aplicación de
uno de los más comunes usos de las redes neuronales, que es un OCR
(Reconocimiento Óptico de Caracteres, por sus siglas en inglés).

El uso de redes neuronales para el reconocimiento de caracteres es muy usado


actualmente principalmente por la característica de GENERALIZACIÓN de una
red neuronal, la cual permite ingresar un patrón aproximado a la letra, y la red
determinará el grado de aproximación a cada una de las muestras de
entrenamiento. Esto nos brinda la opción de ingresar un patrón con cierto grado
de error, inevitable a la hora de trabajar con imágenes.

Para una demostración simple, este OCR va a reconocer las cinco vocales del
alfabeto español, es decir: A, E, I, O, U. De una muestra gráfica al carácter ASCII
correspondiente a la letra.
124

7.2 Adquisición de la vocal

Dada la orientación académica-demostrativa de este OCR, la adquisición de la


imagen se da por medio de una WebCAM, conectada al computador, que debe
captar cualquier imagen de una vocal de color negro escrita en mano imprenta en
mayúsculas en fondo blanco.

Luego de capturar una imagen estática de la webcam, se procede a binarizar la


imagen pudiendo seleccionar manualmente el umbral para ajustarse de mejor
manera a la imagen requerida.

Una vez tenida la imagen, se debe separar la letra de entre toda la imagen
capturada.

Teniendo la imagen de la letra lista, se procede a parametrizar la imagen y


obtener así una muestra numérica para la red neuronal.

Dibujo 49: Adquisición de la vocal - ORIGEN: Propia del autor


125

La parametrización de la letra, se da por medio de una matriz 7x5 que se


ajusta a toda la imagen, y dependiendo de los pixeles negros en cada cajón
de la matriz, este toma un valor de 1 para negro, y 0 para blanco, teniendo
al final una matriz de 0 y 1 correspondiente a la imagen. Dicha matriz,
expresa en orden las 35 entradas binarias de la red neuronal a usarse para
el reconocimiento.

Dibujo 50: parametrización de la vocal -


ORIGEN: Propia del autor
126

7.3 Red-Neuronal Artificial

Los pasos a seguir para entrenar una red neuronal para el reconocimiento de
vocales es el siguiente:

● Obtener las muestras de cada vocal parametrizadas como se indica


anteriormente.

Letra A:

01110100011000111111100011000110001

Letra E:

11111100001000011100100001000011111

Letra I:

11111001000010000100001000010011111

Letra O:

01110100011000110001100011000101110

Letra U:

10001100011000110001100011000101110

● Crear un objeto de tipo RNA, y un control RNA_Visor en una aplicación en


C# , tal como muestra el manual de usuario anexo en la presente tesis.

● Fijar como número de entradas de la red 35, puesto que son 35 los
números de la matriz 7x5 resultante de la parametrización.
127

● Fijar como número de salidas de la red neuronal 5, puesto que se requiere


únicamente distinguir 5 tipos de letras, las vocales.

● No fijar ninguna capa oculta, puesto que se debe siempre empezar sin
ninguna capa oculta, y en caso de ser necesarias, ir aumentándolas.

● Dejar el resto de valores por defecto, es decir, sin uso de neuronas


auxiliares BIAS, con la función de transferencia Sigmoide, etc.

● Correr el proceso de entrenamiento tal como muestra el manual de usuario


anexo a la presente tesis, con los valores de:

LR = 0,1

Momento = 0,9

Error Mínimo = 0,0001

En este caso, la red neuronal termina su proceso de entrenamiento fácilmente


luego de 20 000 iteraciones. Por lo cual se da por terminado el OCR, listo para
consultar con cualquier letra parametrizada.
128

7.4 Conclusiones del OCR

● Para hacer un reconocedor de más letras, por ejemplo todas las


consonantes y vocales del alfabeto español, es necesario incrementar la
resolución de la letra, es decir incrementar la matriz de 7x5 a una con
mayor calidad, por ejemplo una 20x15, que daría un número de entradas
de 300.

● El uso de una capa oculta no fue necesario, puesto que la red neuronal
logro converger a una solución con tan solo dos capas. Y esto resulta
lógico, puesto que cada neurona de salida se especializa en un solo patrón
de entradas (letra), sin interferir con las demás.

● En el caso de querer representar la letra reconocida en formato binario,


como el código ASCII, es indispensable usar una o más capas ocultas,
puesto que una letra afecta a varias salidas ahora, y esto hace que la
información de la capa de salida tenga que ser compartida entre sí.

● Para lograr un reconocedor de texto, el principio de reconocer es el mismo,


es decir, letra por letra. La diferencia va a estar en el pre-procesamiento de
la imagen, la cual debe seleccionar automáticamente letra por letra de todo
un texto continuo, siendo este un problema más de visión artificial.
129

8 CAPITULO VIII: Conclusiones y Recomendaciones

8.1 Conclusiones

● El lenguaje de programación C# mostró ser un excelente candidato para el


desarrollo de todo tipo de herramientas, brindando un excelente equilibrio
entre facilidad de sintaxis, velocidad y alcance funcional.

● En el desarrollo de herramientas, la creación de componentes y controles


(clases en DLL) son la mejor forma de trabajar, puesto que nos brinda una
excelente estructura organizativa, una muy buena documentación y
velocidad de desarrollo al usar código reciclado.

● Encapsular los distintos códigos probados en una DLL nos brinda muchas
facilidades como son: protección de código, compatibilidad entre lenguajes,
velocidad de compilación, etc.

● El uso del motor gráfico GDI+ que nos brinda la tecnología DotNET resultó
ser muy liviana y rápida, siendo la mejor forma de mostrar una interfaz
gráfica para nuestros controles. Y así facilitar el uso y comunicación entre
el programador y las herramientas.

● Usar una estructura XML como el objeto DataSet propio de DotNET para
ser de puente universal con todo tipo de almacenamiento de datos, es de
vital importancia cuando se crea una herramienta de propósito general.
Puesto que la tecnología XML se ha convertido en un estándar en cuanto a
portabilidad de datos se refiere.
130

● El uso de punteros es una excelente forma de ganar velocidad en los


procesos, no obstante hay que usarlos con mucho cuidado y no abusar de
los tamaños de memoria que se congelan.

● Cuando de procesos costosos en tiempo se hablan, es indispensable el


uso de hilos (Threads). En la practica, el uso de esta herramienta brinda
una transparencia a la hora de trabajar con normalidad en todo el sistema,
mientras un proceso se sigue ejecutando en otro hilo.

● El traspaso de un modelamiento matemático a uno informático,


específicamente el de programación, resulta bastante complejo de muchas
formas. Puesto que en el transcurso de este trabajo, el traspaso de las
fórmulas matemáticas a código resultaba ambiguo, más que en la fórmula
en sí, en el orden de aplicar uno u otro proceso. Evidenciando una falta de
documentación al respecto, puesto que todos los textos de información de
redes neuronales, muestran el camino o la solución matemática y
aconsejan el uso de software dedicado como el MatLab para su uso
informático.

● La representación gráfica de la red neuronal es eficiente cuando se trabaja


con redes relativamente pequeñas, en donde se pueda apreciar sin ningún
problema las distintas neuronas y las conexiones entre ellas. Si se requiere
usar una red mucho más grande, no se recomienda el uso de la interfaz
gráfica.

● El algoritmo de backpropagation es algo lento para llegar a converger a


una respuesta, no obstante permite alcanzar niveles de agrupación o
separación muy altos y precisos.

● Una adecuada documentación del código usando estructuras XML, resulta


de mucha utilidad a la hora de usar un control o componente. Las distintas
131

ayudas que nos brinda nuestro IDE favorito, nos van mostrando la
documentación de forma dinámica, facilitando significativamente el
desarrollo de un sistema.

● El uso correcto de las propiedades en un control o componente nos


permiten usar la ventana de propiedades de nuestro IDE en tiempo de
diseño, ganando mucha velocidad a la hora desarrollar un sistema.

● Al encapsular un código en una DLL, se pierde todo acceso que no sea


definido al mismo, por este motivo, es de principal importancia dejar todos
los accesos posibles, tanto propiedades y métodos que funcionan como
entradas, así como los eventos que funcionan como salidas o respuestas
del comportamiento de una clase.

● Una red neuronal no siempre llega a un resultado satisfactorio. Este


depende de muchos factores, en especial la configuración de la propia red.
Es decir, número de neuronas, número de capas, función de transferencia,
y demás. Por este motivo, la creación de este control es únicamente la
mitad del camino, de ahí parte toda la ciencia atrás del uso y configuración
de las redes neuronales para la solución de problemas.
132

8.2 Recomendaciones

Enfocado hacia el Usuario Programador:

● La inicialización de los pesos antes de entrenar una red es de vital


importancia. Según algunas pruebas que se hicieron, se aconseja colocar
valores muy cercanos a cero y con cierto equilibrio, es decir, que todos los
pesos estén balanceados sin llegar a que en un lado de la red los pesos
tengan valores muy altos y al otro lado muy bajos.

● Se debe analizar con mucho cuidado la forma de representar las entradas


de una red. Por ejemplo, se puede expresar en una sola neurona un
número grande, o en muchas el mismo número en binario, o en
hexadecimal. Dependiendo de la importancia y variación que este número
va a tener en la red, se debe aprovechar lo mejor posible la información y
desglosarla en varias entradas.

● El número de neuronas de salida también deben ser estudiadas,


analizando la mejor forma de dispersar la información. Así una de las
mejores formas usada casi siempre, es las salidas binarias en conjunto o
en solitario, es decir, en solitario cuando se tiene una neurona por cada
salida deseada, y en conjunto cuando se aplica la combinación binaria
numérica.

● Las capas ocultas resultan lo más complicado de resolver en cuanto a la


configuración se refiere. Se recomienda empezar sin ninguna capa oculta,
para que cada salida este linealmente expresada por una función de todas
las entradas. Si lo vemos desde este punto de vista, la información de cada
salida está completamente separada una de la otra. Pero si se requiere
que la información no trabaje por separado y más bien se busca
combinarlas, es necesario una capa oculta que entrevera la información.

● De la misma manera, el número de neuronas en cada capa oculta es un


dilema cubierto únicamente por la experiencia del diseñador. No obstante
133

se puede aconsejar usar un número medio entre las entradas y salidas de


la red. Consejo en el que coinciden casi todos los autores.

● En cuanto a la función de transferencia se refiere, la que más se usa es la


sigmoide, sea tangencial o logarítmica. No obstante, cuando se requiere
una respuesta proporcional entre las entradas y las salidas, es mejor usar
la función lineal. Y cuando las exigencias del sistema así lo requieran, el
uso de la función gauss nos brinda mucha exactitud pero poca flexibilidad
al ingresar entradas que no han sido entrenadas previamente.

● Se recomienda siempre tener un visor del error mientras la red se entrena.


Esto es de muchísima utilidad a la hora de probar una configuración,
puesto que con la curva del error se puede concluir un valor erróneo de la
taza de aprendizaje, o del momento; así como también se puede ver una
falta de capas ocultas o demás parámetros.
134

9 BIBLIOGRAFÍA
Libros:
● Nikola K. Kasabov, “Foundations of Neural Networks, Fuzzy Systems, and
Knowledge Engineering”, Segunda Edición, 1998, Massachusetts Institute
of Technology, [ ISBN 0585038767 ]

● Rolf Eckmille, Neural networks (Computer science)/ Congresses, 1990,


Universidad de Michigan, [ ISBN 0444884009 ]

● José R. Hilera / Victor J. Martínez, “Redes Neuronales Artificiales.


Fundamentos, modelos y aplicaciones”, 2000, ALFAOMEGA Grupo editor, [
ISBN 9701505719 ]

● R. Rojas. Neural Networks: A Systematic Introduction, Springer, 1996


[ ISBN 3-540-60505-3 ]

URLs:

● http://www.microsoft.com/Presspass/press/2000/jul00/pdcgateskeynotepr.mspx

● http://msdn2.microsoft.com/es-es/netframework/aa569283(en-us).aspx

● http://es.wikipedia.org/wiki/.NET

● http://en.wikipedia.org/wiki/Microsoft_.NET_Framework

● http://www.monografias.com/trabajos12/redneuro/redneuro.shtml

● http://es.wikipedia.org/wiki/Redes_neuronales_artificiales

● http://ohm.utp.edu.co/neuronales/Capitulo2/Backpropagation/ReglaB.htm

● http://es.wikipedia.org/wiki/Red_neuronal

● http://es.wikipedia.org/wiki/Neurona

● http://en.wikipedia.org/wiki/Graphics_Device_Interface

● http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/gdicpp/GDIPlus/aboutGDIPlus.asp

● http://www.elguille.info/colabora/puntoNET/tutGDI/indice.htm
135

10 ANEXO: Manual de Usuario

10.1 Introducción:

El namespace IA_RNA, ofrece dos componentes para el uso de redes


neuronales artificiales. El primer componente RNA, es en sí una red neuronal
artificial multi-perceptrón con el algoritmo de aprendizaje denominado
BackPropagation o Propagación para atrás. Y el componente RNA_Visor es el
encargado de mostrar una forma visual de la RNA, así, en el visor se muestra de
forma gráfica cada una de las neuronas, sus pesos, capas, bias, etc.

Dichos controles se encuentran encapsulados en un archivo DLL, por lo que


resulta indispensable tener un programa que lo use como referencia. Es por este
motivo que el presente trabajo está enfocado a un usuario programador y NO a un
usuario final.
136

10.2 Agregar los controles de IA_RNA

Una vez creado cualquier proyecto bajo la tecnología DotNET, ya sea en


Visual Basic o en C#, siendo estos dos los más conocidos. Vamos a usar la
herramienta gráfica del diseñador de nuestro IDE, como el que nos presenta el
Microsoft Visual Studio 2005. Y seguimos los siguientes pasos:

● En la barra de herramientas en tiempo de diseño, hacer clic derecho y


seleccionar la opción que dice: “Elegir Items” o “Chosee Items”

Dibujo 51: Barra de Herramientas - ORIGEN: Propia del Autor, extraído de MS. Visual
Studio 2005
137

● En la ventana que aparece, podemos elegir cualquier componente o


control del FrameWork .NET o un componente COM. En nuestro caso
debemos seleccionar “Browser....” o “Examinar...”, donde debemos elegir el
archivo: “IA_RNA.dll” y damos clic en OK.

Dibujo 52: Ventana de selección de componentes - ORIGEN: Propia del


Autor, extraído de MS. Visual Studio 2005

● Los tres componentes del IA_RNA.dll se encuentran ahora en nuestra


barra de herramientas con los siguientes gráficos:

Dibujo 53: Iconos de los componentes - ORIGEN: Propia


del Autor, extraído de MS. Visual Studio 2005
138

● Una vez que los controles se encuentran en la barra de herramientas,


basta con arrastrarlas a un formulario para que el diseñador de nuestro
IDE, se encargue del código que referencia el DLL.

10.3 Configurar la RNA

La configuración de la RNA no es más que establecer las propiedades del


mismo, ya sea desde código o desde la barra de propiedades que nos ofrece
cualquier IDE en su etapa de diseño.

Dibujo 54: Propiedades del componente RNA - ORIGEN: Propia del


Autor, extraído de MS. Visual Studio 2005

En el caso de la propiedad Ocultas, la colección de capas se muestra en otra


ventana donde se puede agregar, modificar o eliminar cuantas capas se
requieran.
139

Dibujo 55: Propiedad Ocultas - ORIGEN: Propia del Autor, extraído de MS.
Visual Studio 2005

Detalles de cada propiedad

● CapaEntrada_numero: Es el número de neuronas en la capa de entrada.

● CapaSalida_numero: Es el número de neuronas en la capa de salida.

● CapaSalida_tipoFT: Es el tipo de función de transferencia de las neuronas


de la capa de salida, los cuales están definidos por el enum
FunctionTransfer_Type detallado más adelante.

● CapaSalida_FormulaCustom: Esta propiedad es usada cuando el tipo de


función de transferencia es fijada como CUSTOM, y detalla en forma de
“string” la función de transferencia a usarse, teniendo como argumento, la
suma del producto de todos los pesos y valores de entrada, denominado
por la mayoría de autores con la letra “I”. Por ejemplo:

CapaSalida_FormulaCustom = “Math.Sin(I)”

● CapaSalida_BIAS: Esta propiedad establece si la capa de salida va a


tener una neurona auxiliar denominada BIAS

● NumIteraciones_Evento: Es el número de iteraciones a cumplirse para


que se genere el evento evento_Iteracion del control.
140

● Ocultas: Esta propiedad como ya vimos es una colección de capas, que


permite fijar a su vez propiedades por cada capa oculta que se agregue,
estas propiedades son: Bias, Formula_Custom, TipoFT, NumeroNeuronas;
que son exactamente iguales a las propiedades de la capa de salida, sino
que aplicadas a cada una de las capas ocultas.

FunctionTransfer_Type: Es un enum que describe los tipos de función de


transferencia que se puede aplicar a una capa de neuronas.

● Escalón.- Es la función de transferencia típica, que define una salida


binaria fijada en un umbral que casi siempre es 0.

Dibujo 56: FT Escalón - ORIGEN: Propia


del Autor

● Lineal.- Es la función de transferencia que pasa el valor sin procesar, de


esta forma expresa una proporción directa representada por una linea.

Dibujo 57: FT Lineal - ORIGEN: Propia del


Autor

● Sigmoide Logarítmica.- Es la función de transferencia que nace de la


necesidad de usar el escalón como función continua para ser derivada y
así ser usada en el algoritmo de BackPropagation.

Dibujo 58: FT Sigmoide logarítmica -


ORIGEN: Propia del Autor
141

● Sigmoide Tangencial.- Es una función de transferencia idéntica a la


anterior pero con su límite inferior en menos uno.

Dibujo 59: FT Sigmoide Tangencial - ORIGEN:


Propia del Autor

● Campana de Gauss- Es una función de transferencia que brinda una


salida activa muy exigente gracias a su forma en campana de gauss.

Dibujo 60: FT Gauss - ORIGEN: Propia del


Autor

● Custom.- Es la función de transferencia que permite personalizar la


fórmula.
142

10.4 Configurar el Visor

El control para visualizar una RNA, está heredado de un UserControl y por lo


tanto sus propiedades cubren todos los niveles de herencia del control,
centrándose las particulares de este control en tres grupos de propiedades.
Teniendo por separado a la propiedad Red_Neuronal que es la que establece
cual red neuronal se va a visualizar.

10.4.1 Capas

En este grupo se establecen los colores de las neuronas que van a verse
en cada capa.

■ ColorBIAS: Es el color que va a tomar el triángulo que representa a


la neurona auxiliar BIAS.

■ ColorEntrada: Es el color que va a tomar todas las neuronas de la


capa de entrada

■ ColorOcultas: Es el color que va a tomar todas las neuronas de las


capas ocultas.

■ ColorSalida: Es el color que va a tomar todas las neuronas de la


capa de salida

■ ColorSimbolo: Es el color que va a tomar el símbolo interno de


cada neurona que representa la función de transferencia.

10.4.2 Pesos

Aquí se establecen los parámetros para los pesos o conexiones (lineas),


entre valores máximos y mínimos que se ajustara un gradiente de color.

■ ColorPesoMax: Es el color que va a tomar la conexión cuando el


valor del peso sea mayor o igual a la propiedad ValorPesoMax.

■ ColorPesoMin: Es el color que va a tomar la conexión cuando el


valor del peso sea menor o igual a la propiedad ValorPesoMin.

■ ValorPesoMax: Es el valor tomado como máximo para asignar el


color de la propiedad ColorPesoMax.
143

■ ValorPesoMin: Es el valor tomado como mínimo para asignar el


color de la propiedad ColorPesoMin.

10.4.3 Tamaños

En este grupo de propiedades se establecen los valores de apariencia a


dibujarse.

■ AnchoConexiones: Es el ancho en pixeles de las conexiones


(lineas) a dibujarse, normalmente el valor es 1.

■ ColorFont: Es el color que va a tener el resto del texto, como los


valores de entrada y salida.

■ FuenteTexto: Es la fuente de texto a usarse para mostrar los


valores de entrada y salida.

■ NeuronaTamaño: Es el diámetro en pixeles que tendrá el circulo


que representa a cada una de las neuronas.

■ NúmeroDecimales: Es el número de decimales que van a usarse


para representar los valores de las salidas. Valor entre 0 para
adelante.

Dibujo 61: Configurar el RNA_Visor - ORIGEN: Propia del Autor


144

10.5 Entrenamiento

Una vez teniendo una RNA configurada, sea que esta tenga o no un control
RNA_Visor asociado, se puede empezar con el proceso de entrenamiento.

El entrenamiento de la red neuronal se da por medio de un método del


componente RNA llamado Entrenar, el cual requiere 5 argumentos para trabajar:

● Muestras de entrada

● Muestras de salida

Las muestras, tanto de entradas como de salidas deben ser expresadas en un


doble vector de tipo DOUBLE. Para esto vamos a tener un ejemplo donde la red
neuronal tenga 3 neuronas de entrada y 2 de salida. Y vamos a expresar 4
muestras.

Entrada 1 Entrada 2 Entrada 3 Salida 1 Salida 2


Muestra 1 2 5 7 1 0
Muestra 2 3 4 6 1 0
Muestra 3 5 -4 0 0 1
Muestra 4 4 -9 1 0 1

Donde cada muestra va a ser un vector de tipo DOUBLE, y todas las muestras,
tanto de entradas como de salidas van a estar representadas por un vector de los
vectores de entrada, es decir un doble vector.

● LR (Learning Rate) o Taza de aprendizaje es un valor entre 0 y 1 que


define la velocidad de aprendizaje que va a tener la red neuronal,
generalmente se empieza con un nivel alto, sea un 0.7 o 0.8 y se lo baja
progresivamente a medida que el entrenamiento finalice. O simplemente se
lo deja con un valor medio, sea 0.5 o 0.6

● Momento es un valor que define una tendencia hacia una dirección, este
valor ayuda a que la red neuronal no caiga en un oscilamiento perpetuo.
145

● Mínimo Error es un valor requerido como meta, al cumplirse un error menor


o igual a este, el proceso de entrenamiento se da por finalizado.

double[ ][ ] Muestras_Entrada = new double[4]; //4 Muestras de entrada


double[ ][ ] Muestras_Salida = new double[4]; //4 Muestras de salida

Muestras_Entrada[0] = new double[3] {2, 5, 7}; //Muestra 1


Muestras_Entrada[1] = new double[3] {3, 4, 6}; //Muestra 2
Muestras_Entrada[2] = new double[3] {5, -4, 0}; //Muestra 3
Muestras_Entrada[3] = new double[3] {4, -9, 1}; //Muestra 4

Muestras_Salida[0] = new double[2] { 1, 0 }; //Muestra 1


Muestras_Salida[1] = new double[2] { 1, 0 }; //Muestra 2
Muestras_Salida[2] = new double[2] { 0, 1 }; //Muestra 3
Muestras_Salida[3] = new double[2] { 0, 1 }; //Muestra 4

//Entrenar con un LR = 0.6 , Momento de 0.1 y un Error mínimo a 0.000001


rna1.Entrenar(Muestras_Entrada, Muestras_Salida, 0.6, 0.1, 0.000001);

Código 10: Ejem de entrenamiento - ORIGEN: Propia del autor

El entrenamiento se procesa internamente por medio de un hilo diferente al


proceso de la aplicación, y notifica a este su avance por medio de un evento
llamado evento_Iteracion que se dispara al cumplir cuantas iteraciones se
especifiquen en la propiedad NumIteraciones_Evento del componente RNA.

Dicho evento, entrega en sus argumentos el conteo de las iteraciones y el error


que lleva el proceso de entrenamiento. Esto es clave para poder mostrar de una
forma gráfica el avance del entrenamiento al programador.
146

//Enlazar el evento
rna1.evento_Iteracion += new RNA.delegado_iteracion(this.rna1_evento_Iteracion);

//Evento Iteración
private void rna1_evento_Iteracion(int interac, double error)
{
...........................................
}

Código 11: Ejem del evento iteración - ORIGEN: Propia del autor

Para detener el proceso de entrenamiento, basta con ejecutar el método


CancelarEntrenamiento.

//Cancela el proceso de entrenamiento


rna1.CancelarEntrenamiento( );

Código 12: Detener el entrenamiento - ORIGEN: Propia del autor

Finalmente se puede concluir que el proceso de entrenamiento de una red


neuronal depende en su mayor parte del programador que la esté supervisando,
teniendo a su disposición todas las herramientas para que pueda observar el
comportamiento de su red, y así determinar cambios en los parámetros de
entrenamiento o diseño en la estructura de la red.

Teniendo un resultado satisfactorio del proceso de entrenamiento, es necesario


poder almacenar de alguna forma los pesos de la red neuronal, que después de
todo son los que almacenan la experiencia del entrenamiento, pudiendo decir de
alguna forma que los pesos son la memoria de nuestro pequeño cerebro (RNA).

Para esto, tenemos dos formas de almacenar los pesos:


147

● Objeto DataSet: El componente RNA tiene un método llamado getDataSet


y uno llamado setDataSet, que nos entrega o recibe un objeto DataSet con
los pesos y estructura de la red, dicho objeto es usado en la tecnología
DotNET como una base de datos virtual escrita en el lenguaje XML,
pudiendo ser utilizada para importar o exportar a cualquier base de datos
soportada por DotNET.

DataSet dataset1 = new DataSet();

//Guardar en Base de Datos la estructura y pesos de la RNA


dataset1 = rna1.getDataSet();
SqlDataAdapter1.Update(dataset1);

//Restaurar desde una Base de Datos la estructura y pesos de la RNA


SqlDataAdapter1.Fill(dataset1);
rna1.SetDataSet(dataset1);

Código 13: Ejemplo de uso con BDD - ORIGEN: Propia del autor

● Archivo de almacenamiento: Para no tener que usar obligatoria mente


una base de datos, el componente RNA tiene los métodos Guardar y Abrir,
los cuales guardan y recuperan de un archivo plano toda la estructura y
pesos de una determinada red neuronal.

//Guarda la estructura y pesos de la


//red neuronal en el archivo especificado
rna1.Guardar("C:\\red1.xml");

//Recupera la estructura y pesos de la


//red neuronal del archivo especificado
rna1.Abrir("C:\\red1.xml");

Código 14: Ejemplo del uso de fichero - ORIGEN: Propia del


autor
148

10.6 Consulta

Para el proceso de consulta de la red neuronal, se debe tener ya una instancia de


RNA con su estructura y pesos de entrenamiento, así que se pueden tomar varios
caminos para llegar a este punto. Por ejemplo, se puede consultar en la misma
aplicación del entrenamiento, o se puede guardar los pesos en un archivo o base
de datos y crear otra aplicación de consulta donde únicamente se restaure la red
neuronal previamente entrenada y usarla para consultas, siendo este último la
forma más común de hacerlo.

Independientemente de como se llegue a tener la RNA entrenada, el proceso de


consulta es muy simple, basta con ejecutar el método Evaluar de la RNA,
enviándole como argumento el vector de entradas de tipo DOUBLE.

Por ejemplo, si deseamos consultar a la red neuronal entrenada anteriormente


(ver Código #), se procedería a simplemente definir el vector de la entrada y
ejecutar el método Evaluar, cuyo resultado será el vector de salida. No obstante,
como en la mayoría de los casos, el objetivo de la consulta es tener únicamente
una neurona ganadora, el componente RNA posee una propiedad que se
actualiza después de ejecutar una evaluación o consulta con el índice de la
neurona ganadora.

//Vector de entrada
double[ ] Entrada = new double[3] {2, 5, 7};
//Evaluar
rna1.Evaluar(Entrada);
//Neurona ganadora
int Gandora = rna1.IndexMaxSalida;

Código 15: Ejem de consulta - ORIGEN: Propia del autor

Adicionalmente, es posible hacer una consulta directa por medio del control visor
de redes neuronales, y la consulta se efectúa en tiempo de ejecución en la
interfaz gráfica del visor.
149

Para cambiar los valores de entrada de la red en este modo gráfico, basta en
hacer clic con el ratón encima del valor de entrada y aparecerá un cuadro de
edición donde se puede alterar el valor. Para salir de este modo de edición, basta
con hacer clic fuera del cuadro.

Dibujo 62: Cambiar valores de entrada desde el visor - ORIGEN:


Propia del autor

Una vez cambiados los valores de entrada, se puede acceder al menú contextual
del visor haciendo clic secundario (típicamente derecho) encima del control y
seleccionar la primera opción que dice: “Procesar”. Cabe resaltar que desde este
menú es posible ejecutar varias tareas, como fijar pesos aleatorios, guardar y
restaurar desde un fichero la estructura y pesos de la red asociada al visor, etc.
150

Dibujo 63: Menú contextual del visor - ORIGEN: Propia del autor

Luego de procesar las entradas, el mismo visor se encargará de mostrar las


salidas y sus valores, teniendo siempre de color rojo la salida ganadora. De esta
forma los dos controles, tanto la red como el visor trabajan conjuntamente para
facilitar el trabajo del programador a la hora de entrenar y consultar su red
neuronal.

You might also like