Red neuronal en SAP ABAP IV

6 Sep 2013

Las aplicaciones técnicas de la inteligencia artificial cada vez están más y más extendidas. En nuestro día a día, como usuarios de múltiples gadgets, aplicaciones, herramientas... hacemos uso de esta tecnología sin ser realmente conscientes de ello.

Sin embargo, a pesar de la creciente aplicación de la inteligencia artificial, en algunos ámbitos de desarrollo de aplicaciones todavía sigue pareciendo algo lejano, como de ciencia ficción y difícilmente alcanzable.

Uno de los objetivos de este artículo es quitar ese halo de misterio que a veces rodea estos temas. El otro, es mostrar un ejemplo sencillo de una red neuronal implementada en un sistema poco común para estos menesteres como es SAP / ABAP IV y que sin embargo en este ámbito de gestión empresarial podría tener muchas aplicaciones de gran utilidad.

Vamos al detalle

La red se organiza en dos capas. La primera capa está compuesta por tres neuronas de dos entradas y una salida. Todas ellas reciben la misma entrada, coordenada X y coordenada Y y suministran una salida que se envía a la segunda capa. La segunda capa está formada por una única neurona de tres entradas y una salida. Cada entrada recibe la salida de una neurona de la capa anterior y la salida proporciona el resultado final de la red.

 

Utilizamos la red para detectar en un espacio de coordenadas X, Y si un determinado punto está dentro de una figura o área. En el ejemplo del presente artículo, enseño a la red reconocer la letra "F" mayúscula sin embargo con otro entrenamiento distinto sería capaz de reconocer cualquier otro patrón o letra. Para mí, aquí es donde radica la magia de estos sistemas. A diferencia de un paradigma convencional de programación en el que realizamos un algoritmo para resolver un problema concreto, en el caso de las redes neuronales lo que hacemos es enseñar al sistema a resolver ese problema

*&------------------------------------*
*&  Include  ZRN_NEURONA
*&------------------------------------*

* Declaración de tablas BBDD
* ========================

  TABLES: ZRN_DATOS.

* Declaración de variables y tablas internas.
* =====================================

* Tabla con los valores de entrenamiento.

  DATA: BEGIN OF IT_VALORES OCCURS 0,
          X1           TYPE ZDEC2_3,
          X2           TYPE ZDEC2_3,
          TARGET       TYPE FLAG,
          SELECCIONADO TYPE FLAG,
        END   OF IT_VALORES.

* Muestras reservadas para entrenamiento.

  DATA: BEGIN OF IT_ENTRENAMIENTO OCCURS 0,
          X1     TYPE ZDEC2_3,
          X2     TYPE ZDEC2_3,
          TARGET TYPE FLAG,
        END   OF IT_ENTRENAMIENTO.

* Muestras reservadas para validación

  DATA: BEGIN OF IT_VALIDACION OCCURS 0,
          X1     TYPE ZDEC2_3,
          X2     TYPE ZDEC2_3,
          TARGET TYPE FLAG,
        END   OF IT_VALIDACION.

* Muestras reservadas para test.

  DATA: BEGIN OF IT_TEST OCCURS 0,
          X1     TYPE ZDEC2_3,
          X2     TYPE ZDEC2_3,
          TARGET TYPE FLAG,
        END   OF IT_TEST.

* Tabla para almacenar los resultados de ejecución.

  DATA: IT_RESULTADOS TYPE TABLE OF ZRN_DATOS WITH HEADER LINE.

* Neuronas.

  CLASS NEURONA_2E DEFINITION DEFERRED.
  CLASS NEURONA_3E DEFINITION DEFERRED.

  DATA: N1 TYPE REF TO NEURONA_2E,
        N2 TYPE REF TO NEURONA_2E,
        N3 TYPE REF TO NEURONA_2E,
        N4 TYPE REF TO NEURONA_3E.

* Salidas.

  DATA: Y1   TYPE ZDEC2_3,
        Y2   TYPE ZDEC2_3,
        Y3   TYPE ZDEC2_3,
        YSAL TYPE ZDEC2_3.

* Varios.

  DATA: PARAR_TEST TYPE FLAG,
        PARAR_VAL  TYPE FLAG.

  DATA: FACTOR_APRENDIZAJE TYPE ZDEC2_3.

  DATA: FICHERO LIKE RLGRAP-FILENAME.

  DATA: NUM_EPOCA TYPE INT4.

  DATA: ERR_CUADRATICO_MEDIO_TEST TYPE ZDEC2_3,
        ERR_CUADRATICO_MEDIO_VAL  TYPE ZDEC2_3.

  DATA: WA_PORC_ENT TYPE NUMC2,
        WA_PORC_VAL TYPE NUMC2,
        WA_PORC_TES TYPE NUMC2.

* Definición de Clases.
* =================

* Neurona de 2 Entradas.

CLASS NEURONA_2E DEFINITION.

  PUBLIC SECTION.

    METHODS: INIT_PESOS,

             INIT_SESGO,

             SET_ENTRADAS IMPORTING E1 TYPE ZDEC2_3
                                    E2 TYPE ZDEC2_3,

             SET_PESOS    IMPORTING P1 TYPE ZDEC2_3
                                    P2 TYPE ZDEC2_3,

             SET_SESGO    IMPORTING S1 TYPE ZDEC2_3,

             GET_PESOS    EXPORTING P1 TYPE ZDEC2_3
                                    P2 TYPE ZDEC2_3,

             GET_SESGO    EXPORTING S1 TYPE ZDEC2_3,

             GET_SALIDA   EXPORTING S  TYPE ZDEC2_3.

  PRIVATE SECTION.

  DATA: ENTRADA1 TYPE ZDEC2_3,
        ENTRADA2 TYPE ZDEC2_3,
        PESO1    TYPE ZDEC2_3,
        PESO2    TYPE ZDEC2_3,
        SESGO    TYPE ZDEC2_3,
        SALIDA   TYPE ZDEC2_3.

ENDCLASS.

CLASS NEURONA_2E IMPLEMENTATION.

* Inicializa los pesos con valores aleatorios entre-0.5 y 0.5.

  METHOD INIT_PESOS.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = PESO1.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = PESO2.

  ENDMETHOD.

* Inicializa el sesgo con un valor aleatorio entre -0.5 y 0.5.

  METHOD INIT_SESGO.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = SESGO.

  ENDMETHOD.

* Establece los valores de entrada de la neurona.

  METHOD SET_ENTRADAS.

    ENTRADA1 = E1.
    ENTRADA2 = E2.

  ENDMETHOD.

* Establece el valor de los pesos.

  METHOD SET_PESOS.

    PESO1 = P1.
    PESO2 = P2.

  ENDMETHOD.

* Establece el valor para el sesgo.

  METHOD SET_SESGO.

    SESGO = S1.

  ENDMETHOD.

* Obtiene el valor de los pesos.

  METHOD GET_PESOS.

    P1 = PESO1.
    P2 = PESO2.

  ENDMETHOD.

* Obtiene el valor del sesgo.

  METHOD GET_SESGO.

    S1 = SESGO.

  ENDMETHOD.

  METHOD GET_SALIDA.

    DATA: VALOR TYPE ZDEC2_3.

    VALOR = ( ENTRADA1 * PESO1 ) + ( ENTRADA2 * PESO2 ) +
            ( SESGO    * 1     ).

      CALL FUNCTION 'ZRN_ACTIVACION'
        EXPORTING
          valor       = VALOR
       IMPORTING
         RESULTADO    = SALIDA.

    S = SALIDA.

  ENDMETHOD.

ENDCLASS.

* Neurona de 3 Entradas.

CLASS NEURONA_3E DEFINITION.

  PUBLIC SECTION.

    METHODS: INIT_PESOS,

             INIT_SESGO,

             SET_ENTRADAS IMPORTING E1 TYPE ZDEC2_3
                                    E2 TYPE ZDEC2_3
                                    E3 TYPE ZDEC2_3,

             SET_PESOS    IMPORTING P1 TYPE ZDEC2_3
                                    P2 TYPE ZDEC2_3
                                    P3 TYPE ZDEC2_3,

             SET_SESGO    IMPORTING S1 TYPE ZDEC2_3,

             GET_PESOS    EXPORTING P1 TYPE ZDEC2_3
                                    P2 TYPE ZDEC2_3
                                    P3 TYPE ZDEC2_3,

             GET_SESGO    EXPORTING S1 TYPE ZDEC2_3,

             GET_SALIDA   EXPORTING S  TYPE ZDEC2_3.

  PRIVATE SECTION.

  DATA: ENTRADA1 TYPE ZDEC2_3,
        ENTRADA2 TYPE ZDEC2_3,
        ENTRADA3 TYPE ZDEC2_3,
        PESO1    TYPE ZDEC2_3,
        PESO2    TYPE ZDEC2_3,
        PESO3    TYPE ZDEC2_3,
        SESGO    TYPE ZDEC2_3,
        SALIDA   TYPE ZDEC2_3.

ENDCLASS.

CLASS NEURONA_3E IMPLEMENTATION.

* Inicializa los pesos con valores aleatorios entre-0.5 y 0.5.

  METHOD INIT_PESOS.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = PESO1.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = PESO2.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = PESO3.

  ENDMETHOD.

* Inicializa el sesgo con un valor aleatorio entre -0.5 y 0.5.

  METHOD INIT_SESGO.

      CALL FUNCTION 'ZRN_PESO_ALEATORIO'
       IMPORTING
         VALOR    = SESGO.

  ENDMETHOD.

* Establece los valores de entrada de la neurona

  METHOD SET_ENTRADAS.

    ENTRADA1 = E1.
    ENTRADA2 = E2.
    ENTRADA3 = E3.

  ENDMETHOD.

* Establece los pesos para cada entrada.

  METHOD SET_PESOS.

    PESO1 = P1.
    PESO2 = P2.
    PESO3 = P3.

  ENDMETHOD.

* Establece el valor del sesgo.

  METHOD SET_SESGO.

    SESGO = S1.

  ENDMETHOD.

* Obtiene el valor de los pesos.

  METHOD GET_PESOS.

    P1 = PESO1.
    P2 = PESO2.
    P3 = PESO3.

  ENDMETHOD.

* Obtiene el valor del sesgo.

  METHOD GET_SESGO.

    S1 = SESGO.

  ENDMETHOD.

  METHOD GET_SALIDA.

    DATA: VALOR TYPE ZDEC2_3.

    VALOR = ( ENTRADA1 * PESO1 ) + ( ENTRADA2 * PESO2 ) +
            ( ENTRADA3 * PESO3 ) + ( SESGO    * 1     ).

      CALL FUNCTION 'ZRN_ACTIVACION'
        EXPORTING
          valor       = VALOR
       IMPORTING
         RESULTADO    = SALIDA.

    S = SALIDA.

  ENDMETHOD.

ENDCLASS.

* Elementos de datos necesarios para la carga del fichero excel.
* =====================================================

TYPES: BEGIN OF TE_ITAB,
          X1     TYPE ZDEC2_3,
          X2     TYPE ZDEC2_3,
          TARGET TYPE FLAG,
       END   OF TE_ITAB.

TYPES: TT_ITAB TYPE TE_ITAB OCCURS 0.

DATA: IT_DATOS_FICHERO TYPE TT_ITAB WITH HEADER LINE.

*------------------------------------------------------------------*
*   CLASS lcl_file DEFINITION
*------------------------------------------------------------------*
CLASS lcl_file DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor    IMPORTING i_path        TYPE char128,
             build_file,
             rellena_salida.

    DATA: tabla_salida TYPE tt_itab.

  PRIVATE SECTION.
    METHODS: upload_file,
             transform_data.

    DATA: g_path    TYPE rlgrap-filename,
          gt_itab   TYPE tt_itab,
          gt_excel  TYPE TABLE OF alsmex_tabline.
ENDCLASS.

CLASS lcl_file IMPLEMENTATION.
*------------------------------------------------------------------*
*   Constructor : Inicializando Variables Privadas
*------------------------------------------------------------------*
  METHOD constructor.
* Inicializando Variables: pasamos la ruta del archivo excel
    g_path = i_path.
  ENDMETHOD.
*------------------------------------------------------------------*
*   Levantando archivo excel a tabla interna
*------------------------------------------------------------------*
  METHOD build_file.
* Levantando el archivo Excel
    CALL METHOD upload_file.
* Transformando la informacion
    CALL METHOD transform_data.
  ENDMETHOD.

*------------------------------------------------------------------*
*   Copio la tabla interna a una tabla publica
*------------------------------------------------------------------*

  METHOD rellena_salida.

    DATA: WA_ITAB TYPE TE_ITAB.

    REFRESH: TABLA_SALIDA.

    LOOP AT ME->gt_itab INTO WA_ITAB.

       APPEND WA_ITAB TO ME->TABLA_SALIDA.

    ENDLOOP.

  ENDMETHOD.

*------------------------------------------------------------------*
*   Levantando archivo excel a tabla interna
*------------------------------------------------------------------*
  METHOD upload_file.
* Variables Locales
    DATA: l_start_col TYPE i VALUE 1,
          l_start_row TYPE i VALUE 1,
          l_end_col   TYPE i VALUE 3,
          l_end_row   TYPE i VALUE 65536.

    CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
        EXPORTING
            filename                = me->g_path
            i_begin_col             = l_start_col
            i_begin_row             = l_start_row
            i_end_col               = l_end_col
            i_end_row               = l_end_row
        TABLES
            intern                  = me->gt_excel
        EXCEPTIONS
            inconsistent_parameters = 1
            upload_ole              = 2
            others                  = 3.

    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDMETHOD.
*------------------------------------------------------------------*
*   Transformando la informacion levantada
*------------------------------------------------------------------*
  METHOD transform_data.
* Variables Locales
    DATA: l_cont TYPE i.
    FIELD-SYMBOLS: <fs_excel> LIKE LINE OF me->gt_excel,
                   <fs_itab>  LIKE LINE OF me->gt_itab,
                   <fs>       TYPE any.

* Aqui agrupamos cada celda del excel y llenamos la tabla interna
    LOOP AT me->gt_excel ASSIGNING <fs_excel>.
      AT NEW row.
        APPEND INITIAL LINE TO me->gt_itab ASSIGNING <fs_itab>.
      ENDAT.
      l_cont = <fs_excel>-col.
      ASSIGN COMPONENT l_cont OF STRUCTURE <fs_itab> TO <fs>.
      <fs> = <fs_excel>-value.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.