Õppiv tehisnärvivõrk lihtsaks tehtud

Tegelikult ei tee ma midagi lihtsaks, ma ei ole õpetaja, LVQ on Kohoneni tehisnärvivõrk ja ehituselt üks lihtsamaid. Kusjuures neist LVQ-dest on antud kood ka üks lihtsamaid, see on Kohoneni SOM võrgu eellane. Antud võrgus on kaks kihti, nagu joonisel. Põhimõtteliselt iteratiivne meetod, mis lõpuks leiab mingi lahenduse, mis ei pruugi olla parim. Hea on, et võrk jääb hästi meelde ja tõenäoliselt võib seda peast kirjutada. Võrgu tundma õppimine on ka suhteliselt lihtne, sest väga keerulist matemaatikat ei ole vaja ja kõik tundub väga intuitiivne. Seda tänu õppimise funktsioonile, mis on ainult korrutamine ja liitmine põhimõtteliselt. Reaalselt on rohkem spetsialiseerunud VQ meetodid kasutusel.

joonis

lvq.jpg

Kaalutud summaator funktsioon on sum( wM,i * xi), kus x on sisendvektor. M on nende kaalude maatrix.

Neid kaale uuendatakse sellise funktsiooniga: wM,i = wM,i + p(xi – wM,i), kus p on õppimise kiirus. Siin on p konstantne.

Kõigepealt on lõplik arv vektoreid, mis on sisendvektoritega sama suurused. Neile määratakse klassid, kuhu nad kuuluvad.
Võrk on otsesuunatud, võitja-võtab-kõik tüüpi lähenemisega valitakse väikseima aktiveeritusega väljund, mis esindab lähimat vektorit.

Kood on otse raamatu(Artificial Intelligence A systems approach)CD-lt võetud.

Kusjuures see SCALE(x) funktsioon ei ole kellegi hulluks ajamiseks, vaid arvude normaliseermiseks vahemikku 0.1 – 0.9 ,mis antud juhul toimib. Kood algab initialize_vector-iga, mis teeb suvalisi vektoreid. Initialize_network võtab esimesed n vektorit oma koodiraamatu(codebook) vektoriteks. Edasi tuleb tsükkel update-e, kuni enam muutusi ei toimu. Mis võib olla väga pikk aeg. Lõpuks on need koefitsient-kaalud õppinud sisendite keskmise väärtuse. Õppimise kiiruse väärtust võib muuta, rohkem kruttida midagi ei saa eriti.

#include <stdio.h>
#include "maths.h"
#include "rand.h"

/*
 * Features and Feature Vector Symbolic Constants and Types
 */

#define MAX_FEATURE_VECTORS	40
#define MAX_FEATURES		3

/* Feature List */
#define COLOR	0
#define TEXTURE	1
#define SHAPE	2

/* Color */
#define RED		0
#define BLUE		1
#define BLACK		2

/* Texture */
#define SMOOTH		0
#define ROUGH		1
#define DIMPLED		2

/* Shape */
#define BOX		0
#define SPHERE		1
#define CYLINDER	2

typedef struct {
  int class;
  int features[MAX_FEATURES];
} feature_vector_t;

feature_vector_t fvec[MAX_FEATURE_VECTORS];

char *feature_strings[MAX_FEATURES][MAX_FEATURES]={
  {"RED  " ,   "BLUE ",    "BLACK"},
  {"SMOOTH ",  "ROUGH  ",  "DIMPLED"},
  {"BOX     ", "SPHERE  ", "CYLINDER"}
};

/*
 * Neural Network Representation for Vector Quantization
 */
#define OUTPUT_NODES	3	/* Unique classes */
#define CLASSES		OUTPUT_NODES

double outputs[OUTPUT_NODES];

double weights[OUTPUT_NODES][MAX_FEATURES];

#define LEARNING_RATE		((double)0.01)

#define SCALE(x)	(((double)(x+1) * 0.2) + 0.1)

int changes = 0;

void initialize_vectors( void )
{
  int vector, feature;

  RANDINIT();

  for (vector = 0 ; vector < MAX_FEATURE_VECTORS ; vector++) {

    for (feature = 0 ; feature < MAX_FEATURES ; feature++) {

      fvec[vector].features[feature] = RANDMAX(MAX_FEATURES);

    }

  }

  return;
}

void updateNetwork( int feature_vector, int class )
{
  int weight;

  for (weight = 0 ; weight < MAX_FEATURES ; weight++) {

    /*  */
    weights[class][weight] += LEARNING_RATE *
            ( SCALE(fvec[feature_vector].features[weight]) -
               weights[class][weight] );

  }

  return;
}

void initialize_network( void )
{
  int class;

  /* Force the first N feature vectors to a separate class (where
   * N is the number of classes).  Since the feature vectors are
   * random, this is a random sampling.
   */

  for (class = 0 ; class < CLASSES ; class++) {

    updateNetwork( class, class );

  }

  return;
}

int feed_forward( int feature_vector )
{
  int output, weight, best;
  double best_value;

  /* Compute each output node activation for the current
   * prototype vector.
   */
  for (output = 0 ; output < CLASSES ; output++) {

    outputs[output] = 0.0;

    /*  */
    for (weight = 0 ; weight < MAX_FEATURES ; weight++) {

      outputs[output] +=
           weights[output][weight] *
              SCALE(fvec[feature_vector].features[weight]);

    }

  }

  /* Set the current best to class 0 */
  best = 0;
  best_value = outputs[0];

  /* Iterate through the remaining classes to identify which was best. */
  for (output = 1 ; output < CLASSES ; output++) {

    if (outputs[output] < best_value) {       best = output;       best_value = outputs[output];     }   }   /* Keep track of when a prototype vector changes classes, for use as    * a termination criteria.    */   if (best != fvec[feature_vector].class) {     changes++;     fvec[feature_vector].class = best;   }   return best; } int main() {   int i, j;   int sample = CLASSES;   int class;   changes = 0;   /* Initialize the feature vectors */   initialize_vectors();   /* Initialize the neural network */   initialize_network();   /* Continue to run while feature vectors change classes */   while (changes > 0) {

    if (sample >= MAX_FEATURE_VECTORS) {
      /* Reset the sample index */
      sample = 0;

      /* If no changes occurred in the last iteration, the exit,
       * otherwise, reset the changes counter to zero and continue.
       */
      if (changes == 0) break;
      else changes = 0;
    }

    /* Feed the sample prototype vector through the network. */
    class = feed_forward( sample );    

    /* Update the weights for the winning output node (class). */
    updateNetwork( sample, class );

    /* Next sample */
    sample++;

  }

  for (class = 0 ; class < CLASSES ; class++) {

    printf("Class %d contains:\n\n", class);

    /* Show classification */
    for (i = 0 ; i < MAX_FEATURE_VECTORS ; i++) {

      if (feed_forward(i) == class) {

        printf("\t%2d [", i);

        for (j = 0 ; j < MAX_FEATURES ; j++) {

          printf("%s ", feature_strings[j][fvec[i].features[j]]);

        }

        printf("]\n");

      }

    }

    printf("\n");

  }

  return 0;
}

//------------ rand.h faili kood
#include <stdlib.h>
#include <time.h>

#define RANDINIT()	srand(time(NULL))

#define RANDOM()	((float)rand() / (float)RAND_MAX)

#define RANDMAX(x)	(int)((float)(x)*rand()/(RAND_MAX+1.0))

//-------------- math.h faili kood
#include <math.h>

#define MIN(x, y)	(((x) < (y)) ? x : y) #define MAX(x, y)	(((x) > (y)) ? x : y)

#define PI	(double)3.1415926

double sqr( double x );

 

Advertisements