Создание самоорганизующейся сети Кохонена на Fore.NET

В примере демонстрируется, как можно классифицировать страны по заданному набору характеристик, используя сеть Кохонена. Данные стран реализованы классом Country.

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;

// Метод для инициализации сети
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(1, 6, Var arr, 0.5, 3);
    Neuro.InitSynapsesConvex();
End Sub NetworkInitialize;


// Метод для задания начальных значений
Friend Function GenerateCountries(): List < Country >;
Var
    Countries: List < Country >;
Begin
    Countries := New List < Country > (18);
    Countries.Add(New Country.Create("Algeria", 3.9, 31193917, 1.74, 2381740, 0, 5550));
    Countries.Add(New Country.Create("Argentina", -3, 36955182, 1.16, 2736690, 30200, 17000));
    Countries.Add(New Country.Create("Brazil", 0.8, 172860370, 0.94, 8456510, 55455, 28000));
    Countries.Add(New Country.Create("Canada", 3.6, 31281092, 1.02, 9220970, 755170, 7100));
    Countries.Add(New Country.Create("China", 7, 1261832482, 0.9, 9326410, 270550, 498720));
    Countries.Add(New Country.Create("India", 5.5, 1014003817, 1.58, 2973190, 314400, 480000));
    Countries.Add(New Country.Create("Indonesia", 0, 224784210, 1.63, 1826440, 93000, 45970));
    Countries.Add(New Country.Create("Iran", 1, 65619636, 0.83, 1636000, 12000, 94000));
    Countries.Add(New Country.Create("Kazakhstan", 1.7, 16733227, -0.05, 2669800, 47500, 22000));
    Countries.Add(New Country.Create("Libya", 2, 5115450, 2.42, 1759540, 0, 4700));
    Countries.Add(New Country.Create("Mexico", 3.7, 100349766, 1.53, 1923040, 49510, 61000));
    Countries.Add(New Country.Create("Mongolia", 3.5, 2650952, 1.54, 1565000, 0, 800));
    Countries.Add(New Country.Create("Niger", 2, 10075511, 2.75, 1266700, 300, 660));
    Countries.Add(New Country.Create("Peru", 2.4, 27012899, 1.75, 1280000, 5220, 12800));
    Countries.Add(New Country.Create("Russia", 3.2, 146001176, -0.38, 16995800, 79400, 40000));
    Countries.Add(New Country.Create("Saudi Arabia", 1.6, 22023506, 3.28, 1960582, 0, 4350));
    Countries.Add(New Country.Create("Sudan", 3, 35079814, 2.84, 2376000, 129810, 19460));
    Countries.Add(New Country.Create("United States", 4.1, 275562673, 0.91, 9158960, 470131, 207000));
    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;


//  Метод для обучения сети
Friend Sub TeachNeuro(Neuro: NeuralNetwork; Countries: List < Country >);
Var
    Epoch: integer;
    Alfa: double;
    Cur: Country;
    Inputs: array[0..5] Of 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;


// Метод для классификации значений 
Friend Function IdentifyCountry(Neuro: NeuralNetwork; Country: Country): integer;
Var
    Alfa: double;
    Inputs: array[0..5] Of 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>===");
// Создаем сеть 
    Neuro := New NeuralNetwork();
// Инициализируем сеть  
    NetworkInitialize(Neuro);
    countries := NormailizeCountries(GenerateCountries());
// Обучаем сеть 
    TeachNeuro(Neuro, countries);

// Тестируем входные значения   
    For Each Country In countries Do
        System.Diagnostics.Debug.WriteLine(Country.Name + ". Класс: " + IdentifyCountry(Neuro, Country).ToString());
    End For;
    System.Diagnostics.Debug.WriteLine("===< END >===");
// Уничтожаем сеть  
    Neuro.DeleteNetwork();
End Sub TipaMain;

После выполнения примера каждая страна, данные которой тестируются, будет отнесена к одному из трех классов. Результаты будут выведены в окно консоли.

См. также:

Примеры