Creating a Kohonen Self-Organizing Network in Fore.NET

The example shows how one should classify countries according to the assigned set of characteristics, using a Kohonen network. Data about countries is implemented by the Country class.

Imports Prognoz.Platform.Interop.NN;
Imports System.Collections.Generic;

Class Country
    Public Name: String;
    Public GDP: double;
    Public Population: double;
    Public PopulationGrowthRate: double;
    Public AreaLand: double;
    Public AreaWater: double;
    Public IrrigatedLand: double;
    
    Public Constructor Create(_Name: String; _GDP: Double; _Population: Double; _PopulationGrowthRate: double; _AreaLand: Double; _AreaWater: Double; _IrrigatedLand: Double);
    Begin
        Name := _Name;
        GDP := _GDP;
        Population := _Population;
        PopulationGrowthRate := _PopulationGrowthRate;
        AreaLand := _AreaLand;
        AreaWater := _AreaWater;
        IrrigatedLand := _IrrigatedLand;
    End Constructor Create;
    
    Public Constructor CreateEmpty();
    Begin
    End Constructor CreateEmpty;
    
    Public Override Function ToString(): string;
    Begin
        Return
        "Name=" + Name +
        " GDP=" + GDP.ToString() +
        " Population=" + Population.ToString() +
        " PopulationGrowthRate=" + PopulationGrowthRate.ToString() +
        " AreaLand=" + AreaLand.ToString() +
        " AreaWater=" + AreaWater.ToString() +
        " IrrigatedLand=" + IrrigatedLand.ToString();
    End Function ToString;
End Class Country;

// Method for initialization of the network
Friend Sub NetworkInitialize(Neuro: NeuralNetwork);
Var
    numberOfClusters: integer = 3;
    numberOfNeurons: array[] Of integer = New integer[1];
    arr: System.Array;
Begin
    numberOfNeurons[0] := numberOfClusters;
    arr := numberOfNeurons;
    Neuro.CreateNetworkEx(16Var arr, 0.53);
    Neuro.InitSynapsesConvex();
End Sub NetworkInitialize;


// Method for the assignment of the initial values
Friend Function GenerateCountries(): List < Country >;
Var
    Countries: List < Country >;
Begin
    Countries := New List < Country > (18);
    Countries.Add(New Country.Create("Algeria"3.9311939171.74238174005550));
    Countries.Add(New Country.Create("Argentina", -3369551821.1627366903020017000));
    Countries.Add(New Country.Create("Brazil"0.81728603700.9484565105545528000));
    Countries.Add(New Country.Create("Canada"3.6312810921.0292209707551707100));
    Countries.Add(New Country.Create("China"712618324820.99326410270550498720));
    Countries.Add(New Country.Create("India"5.510140038171.582973190314400480000));
    Countries.Add(New Country.Create("Indonesia"02247842101.6318264409300045970));
    Countries.Add(New Country.Create("Iran"1656196360.8316360001200094000));
    Countries.Add(New Country.Create("Kazakhstan"1.716733227, -0.0526698004750022000));
    Countries.Add(New Country.Create("Libya"251154502.42175954004700));
    Countries.Add(New Country.Create("Mexico"3.71003497661.5319230404951061000));
    Countries.Add(New Country.Create("Mongolia"3.526509521.5415650000800));
    Countries.Add(New Country.Create("Niger"2100755112.751266700300660));
    Countries.Add(New Country.Create("Peru"2.4270128991.751280000522012800));
    Countries.Add(New Country.Create("Russia"3.2146001176, -0.38169958007940040000));
    Countries.Add(New Country.Create("Saudi Arabia"1.6220235063.28196058204350));
    Countries.Add(New Country.Create("Sudan"3350798142.84237600012981019460));
    Countries.Add(New Country.Create("United States"4.12755626730.919158960470131207000));
    Return Countries;
End Function GenerateCountries;
    
Friend Function GetMaxCountry(Countries: List < Country >): Country;
Var
    Result, Cur: Country;
Begin
    Result := New Country.CreateEmpty();
    For Each Cur In Countries Do
        Result.GDP := System.Math.Max(Result.GDP, Cur.GDP);
        Result.Population := System.Math.Max(Result.Population, Cur.Population);
        Result.PopulationGrowthRate := System.Math.Max(Result.PopulationGrowthRate, Cur.PopulationGrowthRate);
        Result.AreaLand := System.Math.Max(Result.AreaLand, Cur.AreaLand);
        Result.AreaWater := System.Math.Max(Result.AreaWater, Cur.AreaWater);
        Result.IrrigatedLand := System.Math.Max(Result.IrrigatedLand, Cur.IrrigatedLand);
    End For;
    Return Result;
End Function GetMaxCountry;
    
Friend Function NormailizeCountries(Countries: List < Country >): List < Country >;
Var
    Result: List < Country >;
    MaxCountry: Country = GetMaxCountry(Countries);
    Cur, Normalized: Country;
Begin
    Result := New List < Country > (18);
    For Each Cur In Countries Do
        Normalized := New Country.Create(Cur.Name, Cur.GDP / MaxCountry.GDP, Cur.Population / MaxCountry.Population,
            Cur.PopulationGrowthRate / MaxCountry.PopulationGrowthRate, Cur.AreaLand / MaxCountry.AreaLand,
            Cur.AreaWater / MaxCountry.AreaWater, Cur.IrrigatedLand / MaxCountry.IrrigatedLand);
        Result.Add(Normalized);
    End For;
    Return Result;
End Function NormailizeCountries;


//  Method to learn the network
Friend Sub TeachNeuro(Neuro: NeuralNetwork; Countries: List < Country >);
Var
    Epoch: integer;
    Alfa: double;
    Cur: Country;
    Inputs: array[0..5Of double = New double[0..5];
    arr: System.Array;
    learnRate: Double;
    learnRadius: Integer;
Begin
    For Epoch := 1 To 300 Do
        For Each Cur In Countries Do
            inputs[0] := Cur.GDP;
            inputs[1] := Cur.Population;
            inputs[2] := Cur.PopulationGrowthRate;
            inputs[3] := Cur.AreaLand;
            inputs[4] := Cur.AreaWater;
            inputs[5] := Cur.IrrigatedLand;
            Alfa := epoch / 100.0;
            arr := Inputs;
            Neuro.SetInputValuesConvex(Var arr, Alfa);
            learnRate := 0.6 * ((300 - epoch) / 300.0);
            learnRadius := System.Convert.ToInt32(System.Math.Round(3 * ((300 - epoch) / 350.0)));
            Neuro.SetLearnRadius(learnRadius);
            Neuro.SetLearnRate(learnRate);
            Neuro.PropagateSOFM();
            Neuro.LearnSOFM();
        End For;
    End For;
End Sub TeachNeuro;


// Method to classify values 
Friend Function IdentifyCountry(Neuro: NeuralNetwork; Country: Country): integer;
Var
    Alfa: double;
    Inputs: array[0..5Of double = New double[0..5];
    arr: System.Array;
Begin
    inputs[0] := Country.GDP;
    inputs[1] := Country.Population;
    inputs[2] := Country.PopulationGrowthRate;
    inputs[3] := Country.AreaLand;
    inputs[4] := Country.AreaWater;
    inputs[5] := Country.IrrigatedLand;
    Alfa := 1;
    arr := Inputs;
    Neuro.SetInputValuesConvex(Var arr, Alfa);
    Neuro.PropagateSOFM();
    Return Neuro.GetClosestNeuron();
End Function IdentifyCountry;

Friend Sub TipaMain();
Var
    countries: List < Country >;
    Neuro: NeuralNetwork;
    Country: Country;
Begin
    System.Diagnostics.Debug.WriteLine("===<BEGIN>===");
// Create a network 
    Neuro := New NeuralNetwork();
// Initialize network  
    NetworkInitialize(Neuro);
    countries := NormailizeCountries(GenerateCountries());
// Learn network 
    TeachNeuro(Neuro, countries);

// Test input values   
    For Each Country In countries Do
        System.Diagnostics.Debug.WriteLine(Country.Name + ". Class: " + IdentifyCountry(Neuro, Country).ToString());
    End For;
    System.Diagnostics.Debug.WriteLine("===< END >===");
// Delete network  
    Neuro.DeleteNetwork();
End Sub TipaMain;

After executing the example each country, which data is tested, is related to one of the three classes. Results are displayed in the console window.

See also:

Examples