SNeuronCount = 'Неправильно указано количество нейронов';
SOutFieldCount = 'Неправильно установлено количество выходных полей';
SOutNeuronCount = 'Неправильно установлено количество выходных нейронов';
SOutVectorCount = 'Неправильно установлена размерность выходного вектора';
SPatternRangeIndex = 'Выход за границы массива примеров %d';
SStreamCannotRead = 'Ошибка чтения из потока';
SWeightRangeIndex = 'Неправильно указан номер веса %d';
SWrongFileName = 'Неправильно указано имя файла %s';
SCannotBeNumber = 'Ошибка, выражение %s невозможно привести к числовому типу';
SBPStopCondition = 'Не задано условие останова процесса обучения';
type
TVectorInt = array of integer;
TVectorFloat = array of double;
TVectorString = array of string;
TMatrixInt = array of array of integer;
TMatrixFloat = array of array of double;
TNormalize = (nrmLinear, nrmSigmoid, nrmAuto, nrmNone,
nrmLinearOut, nrmAutoOut);
TNeuroFieldType = (fdInput, fdOutput, fdNone);
implementation
end.
Листинг 4 Основной файл проекта NeroSys
unit NeroSys;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, PumpData, NeuralBaseTypes, IniFiles, Math;
type
// Классы исключений
EInOutDimensionError = class(Exception);
ENeuronCountError = class(Exception);
ENeuronNotEqualFieldError = class(Exception);
EBPStopCondition = class(Exception);
// Процедурные типы
TActivation = function (Value: double): double of object;
// Упреждающее объявление классов
TNeuron = class;
TLayer = class;
// Базовый класс нейрона
TNeuron = class(TObject)
private
FOutput: double;
// Вектор весов
FWeights: TVectorFloat;
// Указатель на слой в котором находится нейрон just in case
Layer: TLayer;
function GetWeights(Index: integer): double;
procedure SetWeights(Index: integer; Value: double);
procedure SetWeightCount(const Value: integer);
public
constructor Create(ALayer: TLayer); virtual;
destructor Destroy; override;
// Инициализация весов
procedure InitWeights; virtual;
// Взвешенная сумма
procedure ComputeOut(const AInputs: TVectorFloat); virtual;
property Output: double read FOutput write FOutput;
property WeightCount: integer write SetWeightCount;
property Weights[Index: integer]: double read GetWeights write SetWeights;
end;
// Класс нейрона для сети back-propagation
TNeuronBP = class(TNeuron)
private
// Локальная ошибка
FDelta: double;
// Значение скорости обучения на предыдущей эпохе
FLearningRate: TVectorFloat;
// Значение частной производной на предыдущей эпохе
FPrevDerivative: TVectorFloat;
// Значение коррекции веса на предыдущей эпохе
FPrevUpdate: TVectorFloat;
// Функция активации
FOnActivationF: TActivation;
// Производная функции активации
FOnActivationD: TActivation;
function GetPrevUpdate(Index: integer): double;
function GetPrevDerivative(Index: integer): double;
function GetLearningRate(Index: integer): double;
function GetPrevUpdateCount: integer;
procedure SetPrevDerivative(Index: integer; const Value: double);
procedure SetPrevDerivativeCount(const Value: integer);
procedure SetDelta(Value: double);
procedure SetPrevUpdate(Index: integer; Value: double);
procedure SetPrevUpdateCount(const Value: integer);
procedure SetLearningRate(Index: integer; const Value: double);
procedure SetLearningRateCount(const Value: integer);
public
destructor Destroy; override;
procedure ComputeOut(const AInputs: TVectorFloat); override;
property Delta: double read FDelta write SetDelta;
property LearningRate[Index: integer]: double read GetLearningRate write SetLearningRate; // Delta-Bar-Delta, SuperSAB
property LearningRateCount: integer write SetLearningRateCount;
property PrevDerivativeCount: integer write SetPrevDerivativeCount;
property PrevDerivative[Index: integer]: double read GetPrevDerivative write SetPrevDerivative; // QuickProp, Delta-Bar-Delta, SuperSAB
property PrevUpdateCount: integer read GetPrevUpdateCount write SetPrevUpdateCount;
property PrevUpdate[Index: integer]: double read GetPrevUpdate write SetPrevUpdate;
property OnActivationF: TActivation read FOnActivationF write FOnActivationF;
property OnActivationD: TActivation read FOnActivationD write FOnActivationD;
end;
// Базовый класс слоя
TLayer = class(TPersistent)
private
FNumber: integer;
// Размерность NeuronCount
FNeurons: array of TNeuron;
function GetNeurons(Index: integer): TNeuron;
function GetNeuronCount: integer;
procedure SetNeurons(Index: integer; Value: TNeuron);
procedure SetNeuronCount(Value: integer);
public
constructor Create(ALayerNumber: integer; ANeuronCount: integer); virtual;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
property Neurons[Index: integer]: TNeuron read GetNeurons write SetNeurons;
property NeuronCount: integer read GetNeuronCount write SetNeuronCount;
end;
// Класс слоя для сети back-propagation
TLayerBP = class(TLayer)
private
function GetNeuronsBP(Index: integer): TNeuronBP;
procedure SetNeuronsBP(Index: integer; Value: TNeuronBP);
public
constructor Create(ALayerNumber: integer; ANeuronCount: integer); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
property NeuronsBP[Index: integer]: TNeuronBP read GetNeuronsBP write SetNeuronsBP;
end;
// Базовый класс сети
TNeuralNet = class(TComponent)
private
// Массив слоев
FLayers: array of TLayer;
// Число выборок
FPatternCount: integer;
// Размерность FPatternCount, InputNeuronCount
FPatternsInput: TMatrixFloat;
// Размерность FPatternCount, OutputNeuronCount
FPatternsOutput: TMatrixFloat;
function GetLayers(Index: integer): TLayer;
function GetOutputNeuronCount: integer;
function GetPatternsOutput(PatternIndex: integer; OutputIndex: integer): double;
function GetPatternsInput(PatternIndex: integer; InputIndex: integer): double;
procedure SetLayers(Index: integer; Value: TLayer);
procedure SetPatternsInput(PatternIndex: integer; InputIndex: integer; Value: double);
procedure SetPatternsOutput(PatternIndex: integer; InputIndex: integer; Value: double);
protected
function GetLayerCount: integer; virtual;
function GetInputNeuronCount: integer; virtual;
procedure Clear; virtual;
procedure ResizeInputDim; virtual;
procedure ResizeOutputDim; virtual;
procedure SetPatternCount(const Value: integer); virtual;
procedure SetLayerCount(Value: integer); virtual;
property PatternCount: integer read FPatternCount write SetPatternCount;
public
destructor Destroy; override;
procedure AddLayer(ANeurons: integer); virtual; abstract;
procedure AddPattern(const AInputs: TVectorFloat; const AOutputs: TVectorFloat); overload; virtual;
procedure DeleteLayer(Index: integer); virtual; abstract;
procedure DeletePattern(Index: integer); virtual;
procedure Init(const ANeuronsInLayer: TVectorInt); overload; virtual;
property InputNeuronCount: integer read GetInputNeuronCount;
property LayerCount: integer read GetLayerCount write SetLayerCount;
property Layers[Index: integer]: TLayer read GetLayers write SetLayers;
property OutputNeuronCount: integer read GetOutputNeuronCount;
property PatternsInput[PatternIndex: integer; InputIndex: integer]: double read GetPatternsInput write SetPatternsInput;
property PatternsOutput[PatternIndex: integer; InputIndex: integer]: double read GetPatternsOutput write SetPatternsOutput;
procedure ResetPatterns; virtual;
end;
// Класс сети back-propagation
TNeuralNetBP = class(TNeuralNet)
private
// Коэффициент крутизны пороговой сигмоидальной функции
FAlpha: double;
// Флаг автоинициализации топологии сети
FAutoInit: boolean;
// Флаг продолжения обучения
FContinueTeach: boolean;
// Желаемый выход нейросети размерность OutputNeuronCount
FDesiredOut: TVectorFloat;
// Флаг остановки при достижении FEpochCount
FEpoch: boolean;
// Счетчик эпох (предъявление сети всех примеров из обучающей выборки)
FEpochCount: integer;
// Номер текущей эпохи
FEpochCurrent: integer;
// Значение ошибки, при которой пример считается распознанным
FIdentError: double;
// Значение максимальной ошибки на обучающем множестве
FMaxTeachResidual: double;
// Значение максимальной ошибки на тестовом множестве
FMaxTestResidual: double;
// Значение средней ошибки на обучающем множестве
FMidTeachResidual: double;
// Значение средней ошибки на тестовом множестве
FMidTestResidual: double;
// Ошибка на обучающем множестве
FTeachError: double;
// Коэффициент инерционности
FMomentum: double;
// Количество нейронов в слоях
FNeuronsInLayer: TStrings;
// Событие после инициализации
FOnAfterInit: TNotifyEvent;
FOnAfterNeuronCreated: TNotifyEvent;
// Событие после обучения
FOnAfterTeach: TNotifyEvent;
// Событие до инициализации
FOnBeforeInit: TNotifyEvent;
// Событие до начала обучения
FOnBeforeTeach: TNotifyEvent;
// Событие после прохождения одной эпохи
FOnEpochPassed: TNotifyEvent;
// Число примеров в обучающем множестве
FPatternCount: integer;
// Массив содержащий псевдослучайную последовательсность
FRandomOrder: TVectorInt;
// Счетчик распознанных примеров на обучающем множестве
FRecognizedTeachCount: integer;
// Счетчик распознанных примеров на обучающем множестве
FRecognizedTestCount: integer;
// Флаг остановки обучения
FStopTeach: boolean;
FTeachStopped: boolean;
// Коэффициент скорости обучения - величина градиентного шага
FTeachRate: double;
// Число примеров в тестовом множестве
FTestSetPatternCount: integer;
// Размерность FTestSetPatternCount, InputNeuronCount
FTestSetPatterns: TMatrixFloat;
// Размерность FTestSetPatternCount, InputNeuronCount
FTestSetPatternsOut: TMatrixFloat;
function GetDesiredOut(Index: integer): double;
function GetLayersBP(Index: integer): TLayerBP;
function GetTestSetPatterns(InputIndex, PatternIndex: integer): double;
function GetTestSetPatternsOut(InputIndex, PatternIndex: integer): double;
procedure NeuronCountError;
procedure NeuronsInLayerChange(Sender: TObject);
procedure SetAlpha(Value: double);
procedure SetDesiredOut(Index: integer; Value: double);
procedure SetEpochCount(Value: integer);
procedure SetLayersBP(Index: integer; Value: TLayerBP);
procedure SetMomentum(Value: double);
procedure SetTeachRate(Value: double);
procedure SetTestSetPatternCount(const Value: integer);
procedure SetTestSetPatterns(InputIndex, PatternIndex: integer; const Value: double);
procedure SetTestSetPatternsOut(InputIndex, PatternIndex: integer; const Value: double);
// Перетасовка набора данных
procedure Shuffle;
protected
function GetLayerCount: integer; override;
function GetOutput(Index: integer): double; virtual;
// Активационная функция
function ActivationF(Value: double): double; virtual;
// Производная активационной функции
function ActivationD(Value: double): double; virtual;
// Средняя квадратичная ошибка
function QuadError: double; virtual;
// Подстройка весов
procedure AdjustWeights; virtual;
// Рассчитывает локальную ошибку - дельту
procedure CalcLocalError; virtual;
// Проверка сети на тестовом множестве
procedure CheckTestSet; virtual;
procedure DoOnAfterInit; virtual;
procedure DoOnAfterNeuronCreated(ALayerIndex, ANeuronIndex: integer); virtual;
procedure DoOnAfterTeach; virtual;
procedure DoOnBeforeInit; virtual;
procedure DoOnBeforeTeach; virtual;
procedure DoOnEpochPassed; virtual;
// Инициализация весов сети псевдослучайными значениями
procedure InitWeights; virtual;
// Предъявление сети входных значений примера
procedure LoadPatternsInput(APatternIndex :integer); virtual;
// Предъявление сети входных значений примера
procedure LoadPatternsOutput(APatternIndex :integer); virtual;
// Распространяет сигнал в прямом направлении
procedure Propagate; virtual;
// Установка значений по умолчанию
procedure SetDefaultProperties; virtual;
procedure SetPatternCount(const Value: integer); override;
// Встряска сети
procedure ShakeUp; virtual;
property TeachStopped: boolean read FTeachStopped write FTeachStopped;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure AddLayer(ANeurons: integer); override;
procedure Compute(AVector: TVectorFloat); virtual;
procedure DeleteLayer(Index: integer); override;
procedure Init; reintroduce; overload;
procedure ResetLayers; virtual;
procedure TeachOffLine; virtual;
property DesiredOut[Index: integer]: double read GetDesiredOut write SetDesiredOut;
property EpochCurrent: integer read FEpochCurrent;
property IdentError: double read FIdentError write FIdentError;
property LayersBP[Index: integer]: TLayerBP read GetLayersBP write SetLayersBP;
property LayerCount: integer read GetLayerCount write SetLayerCount;
property Output[Index: integer]: double read GetOutput;
property StopTeach: boolean read FStopTeach write FStopTeach;
property TeachError: double read FTeachError;
property MaxTeachResidual: double read FMaxTeachResidual;
property MaxTestResidual: double read FMaxTestResidual;
property MidTeachResidual: double read FMidTeachResidual;
property MidTestResidual: double read FMidTestResidual;
property RecognizedTeachCount: integer read FRecognizedTeachCount;
property RecognizedTestCount: integer read FRecognizedTestCount;
property TestSetPatternCount: integer read FTestSetPatternCount write SetTestSetPatternCount;
property TestSetPatterns[InputIndex: integer; PatternIndex: integer]: double read GetTestSetPatterns write SetTestSetPatterns;
property TestSetPatternsOut[InputIndex: integer; PatternIndex: integer]: double read GetTestSetPatternsOut write SetTestSetPatternsOut;
published
property Alpha: double read FAlpha write SetAlpha;
property AutoInit: boolean read FAutoInit write FAutoInit;
property ContinueTeach: boolean read FContinueTeach write FContinueTeach;
property Epoch: boolean read FEpoch write FEpoch;
property EpochCount: integer read FEpochCount write SetEpochCount;
property Momentum: double read FMomentum write SetMomentum;
property NeuronsInLayer: TStrings read FNeuronsInLayer write FNeuronsInLayer;
property OnAfterInit: TNotifyEvent read FOnAfterInit write FOnAfterInit;
property OnAfterNeuronCreated: TNotifyEvent read FOnAfterNeuronCreated write FOnAfterNeuronCreated;
property OnAfterTeach: TNotifyEvent read FOnAfterTeach write FOnAfterTeach;
property OnBeforeInit: TNotifyEvent read FOnBeforeInit write FOnBeforeInit;
property OnBeforeTeach: TNotifyEvent read FOnBeforeTeach write FOnBeforeTeach;
property OnEpochPassed: TNotifyEvent read FOnEpochPassed write FOnEpochPassed;
property PatternCount: integer read FPatternCount write SetPatternCount;
property TeachRate: double read FTeachRate write SetTeachRate;
end;
// Класс сети back-propagation TNeuralNetExtended }
TNeuralNetExtended = class(TNeuralNetBP)
private
// Файл данных
FNeuroDataSource: TNeuroDataSource;
// Имя файла данных *.txt
FSourceFileName: TFileName;
// Имя конфигурационного файла *.nnw
FFileName: TFileName;
// Конфигурационный файл
FNnwFile: TIniFile;
// Поля
FFields: TNeuroFields;
// Количество доступных полей
FAvailableFieldsCount: integer;
FMaxTeachError: boolean;
FMaxTeachErrorValue: double;
FMaxTestError: boolean;
FMaxTestErrorValue: double;
FMidTeachError: boolean;
FMidTeachErrorValue: double;
FMidTestError: boolean;
FMidTestErrorValue: double;
FOptions: string;
FSettingsLoaded: boolean;
FTestAsValid: boolean;
FTeachIdent: boolean;
FTeachIdentCount: integer;
FTestIdent: boolean;
FTestIdentCount: integer;
FUseForTeach: integer;
FIdentError: double;
FRealOutputIndex: TVectorInt;
FRealInputIndex: TVectorInt;
function GetFields(Index: integer): TNeuroField;
function GetInputFieldCount: integer;
function GetOutputFieldCount: integer;
function GetRealInputIndex(Index: integer): integer;
function GetRealOutputIndex(Index: integer): integer;
procedure SetFields(Index: integer; Value: TNeuroField);
procedure SetFileName(Value: TFilename);
procedure SetAvailableFieldsCount(Value: integer);
procedure SetUseForTeach(const Value: integer);
procedure SetTeachIdentCount(const Value: integer);
procedure SetRealOutputIndex(Index: integer; const Value: integer);
procedure SetRealOutputIndexCount(const Value: integer);
procedure SetRealInputIndex(Index: integer; const Value: integer);
procedure SetRealInputIndexCount(const Value: integer);
protected
function GetOutput(Index: integer): double; override;
procedure DoOnBeforeTeach; override;
procedure DoOnEpochPassed; override;
procedure SetDefaultProperties; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ComputeUnPrepData(AVector: TVectorFloat);
// Загружает данные из текстового файла
procedure LoadDataFrom;
// Загружает настройки сети
procedure LoadNetwork;
// Загружает настройки сети
procedure LoadPhase1;
// Загружает настройки сети
procedure LoadPhase2;
// Загружает настройки сети
procedure LoadPhase4;
// Нормализует набор данных
procedure NormalizeData;
// Сохраняет настройки сети
procedure SaveNetwork;
// Сохраняет настройки сети
procedure SavePhase1;
// Сохраняет настройки сети
procedure SavePhase2;
// Сохраняет настройки сети
procedure SavePhase4;
// Обучение нейронной сети
procedure Train;
property AvailableFieldsCount: integer read FAvailableFieldsCount write SetAvailableFieldsCount;
property Fields[Index: integer]: TNeuroField read GetFields write SetFields;
property InputFieldCount: integer read GetInputFieldCount;
property OutputFieldCount: integer read GetOutputFieldCount;
property SettingsLoaded: boolean read FSettingsLoaded write FSettingsLoaded;
property RealOutputIndex[Index: integer]: integer read GetRealOutputIndex write SetRealOutputIndex;
property RealOutputIndexCount: integer write SetRealOutputIndexCount;
property RealInputIndex[Index: integer]: integer read GetRealInputIndex write SetRealInputIndex;
property RealInputIndexCount: integer write SetRealInputIndexCount;
property NnwFile: TIniFile read FNnwFile write FNnwFile;
published
property FileName: TFileName read FFileName write SetFileName;
property IdentError: double read FIdentError write FIdentError;
property MaxTeachError: boolean read FMaxTeachError write FMaxTeachError;
property MaxTeachErrorValue: double read FMaxTeachErrorValue write FMaxTeachErrorValue;
property MaxTestError: boolean read FMaxTestError write FMaxTestError;
property MaxTestErrorValue: double read FMaxTestErrorValue write FMaxTestErrorValue;
property MidTeachError: boolean read FMidTeachError write FMidTeachError;
property MidTeachErrorValue: double read FMidTeachErrorValue write FMidTeachErrorValue;
property MidTestError: boolean read FMidTestError write FMidTestError;
property MidTestErrorValue: double read FMidTestErrorValue write FMidTestErrorValue;
property Options: string read FOptions write FOptions;
property SourceFileName: TFileName read FSourceFileName write FSourceFileName;
property TestAsValid: boolean read FTestAsValid write FTestAsValid;
property TeachIdent: boolean read FTeachIdent write FTeachIdent;
property TeachIdentCount: integer read FTeachIdentCount write SetTeachIdentCount;
property TestIdent: boolean read FTestIdent write FTestIdent;
property TestIdentCount: integer read FTestIdentCount write FTestIdentCount;
property UseForTeach: integer read FUseForTeach write SetUseForTeach;
end;
implementation
{$R *.RES}
{ TNeuron }
constructor TNeuron. Create(ALayer: TLayer);
begin
inherited Create;
// указатель на слой в котором находится нейрон
Layer := ALayer;
end;
destructor TNeuron. Destroy;
begin
WeightCount := 0;
FWeights := nil;
Layer := nil;
inherited;
end;
procedure puteOut(const AInputs: TVectorFloat);
var
i: integer;
begin
FOutput := 0;
// Подсчитывается взвешенная сумма нейрона
for i := Low(AInputs) to High(AInputs) do
FOutput := FOutput + FWeights[i] * AInputs[i];
end;
function TNeuron. GetWeights(Index: integer): double;
begin
try
Result := FWeights[Index];
except
on E: ERangeError do
raise E. CreateFmt(SWeightRangeIndex, [Index])
end;
end;
procedure TNeuron. InitWeights;
var
i: integer;
begin
// Инициализация весов нейрона
for i := Low(FWeights) to High(FWeights) do
FWeights[i] := Random
end;
procedure TNeuron. SetWeightCount(const Value: integer);
begin
SetLength(FWeights, Value);
end;
procedure TNeuron. SetWeights(Index: integer; Value: double);
begin
try
FWeights[Index] := Value;
except
on E: ERangeError do
raise E. CreateFmt(SWeightRangeIndex, [Index])
end;
end;
{ Конец описания TNeuron }
{ TNeuronBP }
destructor TNeuronBP. Destroy;
begin
FOnActivationF := nil;
FOnActivationD := nil;
PrevUpdateCount := 0;
FPrevUpdate := nil;
inherited;
end;
function TNeuronBP. GetLearningRate(Index: integer): double;
begin
Result := FLearningRate[Index];
end;
function TNeuronBP. GetPrevDerivative(Index: integer): double;
begin
Result := FPrevDerivative[Index];
end;
function TNeuronBP. GetPrevUpdateCount: integer;
begin
Result := High(FPrevUpdate) + 1;
end;
function TNeuronBP. GetPrevUpdate(Index: integer): double;
begin
Result := FPrevUpdate[Index];
end;
procedure puteOut(const AInputs: TVectorFloat);
begin
inherited;
// Задает смещение нейрона
FOutput := FOutput + Weights[High(AInputs) + 1];
FOutput := OnActivationF(FOutput);
end;
procedure TNeuronBP. SetDelta(Value: double);
begin
FDelta := Value;
end;
procedure TNeuronBP. SetLearningRate(Index: integer; const Value: double);
begin
FLearningRate[Index] := Value;
end;
procedure TNeuronBP. SetLearningRateCount(const Value: integer);
begin
SetLength(FLearningRate, Value)
end;
procedure TNeuronBP. SetPrevUpdate(Index: integer; Value: double);
begin
FPrevUpdate[Index] := Value;
end;
procedure TNeuronBP. SetPrevUpdateCount(const Value: integer);
begin
SetLength(FPrevUpdate, Value)
end;
procedure TNeuronBP. SetPrevDerivative(Index: integer; const Value: double);
begin
FPrevDerivative[Index] := Value;
end;
procedure TNeuronBP. SetPrevDerivativeCount(const Value: integer);
begin
SetLength(FPrevDerivative, Value)
end;
{ Конец описания TNeuronBP }
{ TLayer }
procedure TLayer. Assign(Source: TPersistent);
var
i: integer;
begin
FNumber := (Source as TLayer).FNumber;
NeuronCount := (Source as TLayer).NeuronCount;
// Создаются нейроны
for i := 0 to NeuronCount - 1 do
FNeurons[i] := TNeuron. Create(Self);
end;
constructor TLayer. Create(ALayerNumber: integer; ANeuronCount: integer);
var
i: integer;
begin
inherited Create;
FNumber := ALayerNumber;
NeuronCount := ANeuronCount;
for i := 0 to ANeuronCount - 1 do
FNeurons[i] := TNeuron. Create(Self);
end;
destructor TLayer. Destroy;
var
i: integer;
begin
for i := 0 to NeuronCount - 1 do
FNeurons[i].Free;
NeuronCount := 0;
FNeurons := nil;
inherited;
end;
function TLayer. GetNeuronCount: integer;
begin
Result := High(FNeurons) + 1;
end;
function TLayer. GetNeurons(Index: integer): TNeuron;
begin
Result := FNeurons[Index];
end;
procedure TLayer. SetNeuronCount(Value: integer);
begin
if Value <> High(FNeurons) + 1 then
SetLength(FNeurons, Value);
end;
procedure TLayer. SetNeurons(Index: integer; Value: TNeuron);
begin
try
FNeurons[Index] := Value;
except
on E: ERangeError do
raise E. CreateFmt(SNeuronRangeIndex, [Index])
end;
end;
{ TNeuralNetBP }
constructor TNeuralNetBP. Create(AOwner: TComponent);
var
i: integer;
begin
inherited;
FNeuronsInLayer := TStringList. Create;
for i := 0 to DefaultLayerCount do
AddLayer(DefaultNeuronCount);
TStringList(FNeuronsInLayer).OnChange := NeuronsInLayerChange;
AutoInit := True;
StopTeach := False;
TeachStopped := False;
NeuronsInLayerChange(Self);
SetDefaultProperties;
end;
destructor TNeuralNetBP. Destroy;
begin
FNeuronsInLayer. Free;
SetLength(FRandomOrder, 0);
FRandomOrder := nil;
SetLength(FDesiredOut, 0);
FDesiredOut := nil;
SetLength(FTestSetPatterns, 0, 0);
FTestSetPatterns := nil;
SetLength(FTestSetPatternsOut, 0, 0);
FTestSetPatternsOut := nil;
FOnAfterInit := nil;
FOnAfterTeach := nil;
FOnBeforeInit := nil;
FOnBeforeTeach := nil;
FOnEpochPassed := nil;
inherited;
end;
function TNeuralNetBP. GetLayersBP(Index: integer): TLayerBP;
begin
Result := FLayers[Index] as TLayerBP;
end;
function TNeuralNetBP. GetLayerCount: integer;
begin
Result := High(FLayers) + 1;
end;
function TNeuralNetBP. GetDesiredOut(Index: integer): double;
begin
Result := FDesiredOut[Index];
end;
function TNeuralNetBP. GetOutput(Index: integer): double;
begin
try
Result := LayersBP[LayerCount - 1].NeuronsBP[Index].Output;
except
on E: ERangeError do
raise E. CreateFmt(SNeuronRangeIndex, [Index])
end;
end;
function TNeuralNet. GetPatternsOutput(PatternIndex: integer; OutputIndex: integer): double;
begin
Result := FPatternsOutput[PatternIndex, OutputIndex];
end;
function TNeuralNetBP. QuadError: double;
var
i: integer;
begin
// рассчитывает среднеквадратичную ошибку
Result := 0;
for i := 0 to OutputNeuronCount - 1 do
Result := Result + sqr(LayersBP[LayerCount - 1].NeuronsBP[i].Output - DesiredOut[i]);
Result := Result/2;
end;
function TNeuralNetBP. ActivationF(Value: double): double;
begin
// Активационная функция - сигмоид
Result := 1/( 1 + exp(-FAlpha * Value) )
end;
function TNeuralNetBP. ActivationD(Value: double): double;
begin
// Производная сигмоиды
Result := FAlpha * Value * (1 - Value)
end;
function TNeuralNetBP. GetTestSetPatterns(InputIndex, PatternIndex: integer): double;
begin
Result := FTestSetPatterns[InputIndex, PatternIndex];
end;
function TNeuralNetBP. GetTestSetPatternsOut(InputIndex, PatternIndex: integer): double;
begin
Result := FTestSetPatternsOut[InputIndex, PatternIndex];
end;
procedure TNeuralNetBP. AddLayer(ANeurons: integer);
begin
if ANeurons < DefaultNeuronCount then
NeuronCountError
else
NeuronsInLayer. Add(IntToStr(ANeurons));
end;
procedure TNeuralNetBP. AdjustWeights;
var
i, j, k: integer;
xCurrentUpdate: double;
begin
// Подстройка весов начиная с первого слоя
for i := 1 to LayerCount - 1 do
for j := 0 to LayersBP[i].NeuronCount - 1 do
begin
for k := 0 to LayersBP[i-1].NeuronCount do
with LayersBP[i].NeuronsBP[j] do
begin
// корректирует вес соединяющий j-нейрон слоя i
// с k-нейроном слоя i-1: произведением дельта j-нейрона
// на выход k-нейрона слоя i-1
if k = LayersBP[i-1].NeuronCount then
// если это нейрон задающий смещение
xCurrentUpdate := - TeachRate * Delta + Momentum * PrevUpdate[k]
else
xCurrentUpdate := - TeachRate * Delta *
LayersBP[i-1].NeuronsBP[k].Output + Momentum * PrevUpdate[k];
Weights[k]:= Weights[k] + xCurrentUpdate;
PrevUpdate[k] := xCurrentUpdate;
end;
end
end;
procedure TNeuralNetBP. CalcLocalError;
var
i, j, k: integer;
begin
// Дельта-правило с последнего слоя до первого
for i := LayerCount - 1 downto 1 do
// для последнего слоя
if i = LayerCount - 1 then
for j := 0 to LayersBP[i].NeuronCount - 1 do
LayersBP[i].NeuronsBP[j].Delta := (LayersBP[i].NeuronsBP[j].Output-DesiredOut[j])
* ActivationD(LayersBP[i].NeuronsBP[j].Output)
else
for j := 0 to LayersBP[i].NeuronCount - 1 do
with LayersBP[i].NeuronsBP[j] do
begin
Delta := 0;
// Суммирует произведение локальной ошибки k-нейрона слоя i+1
// на вес соединяющий k-нейрон слоя i+1 с j-нейроном слоя i
for k := 0 to LayersBP[i+1].NeuronCount - 1 do
Delta := Delta + LayersBP[i+1].NeuronsBP[k].Delta *
LayersBP[i+1].NeuronsBP[k].Weights[j];
Delta := Delta * ActivationD(Output)
end;
end;
procedure TNeuralNetBP. CheckTestSet;
var
i, j: integer;
xArray: TVectorFloat;
xFirstTestSample: boolean;
xQuadError: double;
// функция рассчитывает среднеквадратичную ошибку
function QuadError(APatternCount: integer): double;
var
i: integer;
begin
Result := 0;
for i := 0 to OutputNeuronCount - 1 do
Result := Result + sqr(LayersBP[LayerCount - 1].NeuronsBP[i].Output - TestSetPatternsOut[APatternCount, i]);
Result := Result/2;
end;
begin
SetLength(xArray, InputNeuronCount);
xFirstTestSample := True;
FRecognizedTestCount := 0;
FMidTestResidual := 0;
FMaxTestResidual := 0;
for i := 0 to TestSetPatternCount - 1 do
begin
for j := 0 to InputNeuronCount - 1 do
xArray[j] := TestSetPatterns[i, j];
Compute(xArray);
xQuadError := QuadError(i);
// проверка - распознан ли пример из тестового множества
if xQuadError < IdentError then
Inc(FRecognizedTestCount);
FMidTestResidual := FMidTestResidual + xQuadError;
// максимальная ошибка на тестовом множестве
if xFirstTestSample then
begin
FMaxTestResidual := xQuadError;
xFirstTestSample := False;
end
else
if FMaxTestResidual < xQuadError then
FMaxTestResidual := xQuadError;
end;
// средняя ошибка на тестовом множестве
FMidTestResidual := FMidTestResidual/TestSetPatternCount;
SetLength(xArray, 0);
xArray := nil;
end;
procedure pute(AVector: TVectorFloat);
var
i: integer;
begin
if InputNeuronCount <> High(AVector)+ 1 then
raise EInOutDimensionError. Create(SInNeuronCount);
for i := Low(AVector) to High(AVector) do
LayersBP[SensorLayer].NeuronsBP[i].Output := AVector[i];
Propagate;
end;
procedure TNeuralNetBP. DoOnAfterInit;
begin
if Assigned(FOnAfterInit) then
FOnAfterInit(Self);
end;
procedure TNeuralNetBP. DoOnAfterNeuronCreated(ALayerIndex, ANeuronIndex: integer);
var
i: integer;
begin
with LayersBP[ALayerIndex].NeuronsBP[ANeuronIndex] do
for i := 0 to PrevUpdateCount - 1 do
PrevUpdate[i] := 0;
if Assigned(FOnAfterNeuronCreated) then
FOnAfterNeuronCreated(Self);
end;
procedure TNeuralNetBP. DoOnAfterTeach;
begin
if Assigned(FOnAfterTeach) then
FOnAfterTeach(Self);
end;
procedure TNeuralNetBP. DoOnBeforeInit;
begin
if Assigned(FOnBeforeInit) then
FOnBeforeInit(Self);
end;
procedure TNeuralNetBP. DoOnBeforeTeach;
begin
if Assigned(FOnBeforeTeach) then
FOnBeforeTeach(Self);
end;
procedure TNeuralNetBP. DoOnEpochPassed;
begin
if Assigned(FOnEpochPassed) then
FOnEpochPassed(Self);
end;
procedure TNeuralNetBP. DeleteLayer(Index: integer);
var
i: integer;
begin
try
NeuronsInLayer. Delete(Index);
for i := Index to LayerCount - 2 do
LayersBP[i].Assign(LayersBP[i + 1]);
FLayers[LayerCount - 1].Free;
LayerCount := LayerCount - 1;
except
on E: ERangeError do
raise E. CreateFmt(SLayerRangeIndex, [Index])
end;
end;
procedure TNeuralNetBP. Init;
var
i, j: integer;
begin
DoOnBeforeInit;
if NeuronsInLayer. Count > 0 then
begin
LayerCount := NeuronsInLayer. Count;
// FLayers[0] нулевой слой, используется только поле Output
FLayers[0] := TLayerBP. Create(0, StrToInt(NeuronsInLayer. Strings[0]));
// для нулевого слоя не нужны весовые коэффициенты
for i := 1 to LayerCount - 1 do
begin
FLayers[i] := TLayerBP. Create(i, StrToInt(NeuronsInLayer. Strings[i]));
for j := 0 to StrToInt(NeuronsInLayer. Strings[i]) - 1 do
with LayersBP[i].NeuronsBP[j] do
begin
// задает количество элементов в векторе весов + смещение
WeightCount := LayersBP[i-1].NeuronCount + BiasNeuron;
// задает количество в векторе содержащем предыдущую коррекцию
// элементов + смещение
PrevUpdateCount := LayersBP[i-1].NeuronCount + BiasNeuron;
PrevDerivativeCount := LayersBP[i-1].NeuronCount + BiasNeuron; // для быстрых алгоритмов
LearningRateCount := LayersBP[i-1].NeuronCount + BiasNeuron; // для быстрых алгоритмов
OnActivationF := ActivationF;
OnActivationD := ActivationD;
Randomize;
DoOnAfterNeuronCreated(i, j);
end
end;
// устанавливает размерность массива выходов
// число нейронов в последнем слое = числу выходов
SetLength(FDesiredOut, OutputNeuronCount);
end;
DoOnAfterInit;
end;
procedure TNeuralNetBP. InitWeights;
var
i, j: integer;
begin
Randomize;
// Инициализация весов
for i := 1 to LayerCount - 1 do
for j := 0 to LayersBP[i].NeuronCount - 1 do
LayersBP[i].NeuronsBP[j].InitWeights;
end;
procedure TNeuralNetBP. LoadPatternsInput(APatternIndex :integer);
var
i: integer;
begin
for i := 0 to InputNeuronCount - 1 do
LayersBP[SensorLayer].NeuronsBP[i].Output := PatternsInput[APatternIndex, i];
end;
procedure TNeuralNetBP. LoadPatternsOutput(APatternIndex :integer);
var
i: integer;
begin
for i := 0 to OutputNeuronCount - 1 do
DesiredOut[i] := PatternsOutput[APatternIndex, i];
end;
procedure TNeuralNetBP. NeuronsInLayerChange(Sender: TObject);
begin
if AutoInit then
Init;
end;
procedure TNeuralNetBP. NeuronCountError;
begin
raise ENeuronCountError. Create(SNeuronCount)
end;
procedure TNeuralNetBP. Propagate;
var
i, j, xIndex: integer;
xArray: TVectorFloat;
begin
// Распространение сигнала в прямом направлении с первого слоя
for i := 1 to LayerCount - 1 do
begin
// формирование массива входов из выходов предыдущего слоя
SetLength(xArray, LayersBP[i-1].NeuronCount);
for xIndex := 0 to LayersBP[i-1].NeuronCount - 1 do
xArray[xIndex] := LayersBP[i-1].NeuronsBP[xIndex].Output;
// вычисление выхода нейрона
for j := 0 to LayersBP[i].NeuronCount - 1 do
with LayersBP[i].NeuronsBP[j] do
ComputeOut(xArray);
for xIndex := 0 to LayersBP[i-1].NeuronCount - 1 do
xArray[xIndex] := 0;
end;
SetLength(xArray, 0);
xArray := nil;
end;
procedure TNeuralNetBP. ResetLayers;
begin
Clear;
FNeuronsInLayer. Clear;
end;
procedure TNeuralNetBP. SetDesiredOut(Index: integer; Value: double);
begin
FDesiredOut[Index] := Value;
end;
procedure TNeuralNetBP. SetLayersBP(Index: integer; Value: TLayerBP);
begin
FLayers[Index] := Value as TLayerBP;
end;
procedure TNeuralNetBP. SetAlpha(Value: double);
begin
if (Value > 10) or (Value < 0.01) then
FAlpha := DefaultAlpha
else
FAlpha := Value;
end;
procedure TNeuralNetBP. SetTeachRate(Value: double);
begin
if (Value > 1) or (Value <= 0) then
FTeachRate := DefaultTeachRate
else
FTeachRate := Value;
end;
procedure TNeuralNetBP. SetTestSetPatterns(InputIndex, PatternIndex: integer; const Value: double);
begin
FTestSetPatterns[InputIndex, PatternIndex] := Value;
end;
procedure TNeuralNetBP. SetTestSetPatternsOut(InputIndex, PatternIndex: integer; const Value: double);
begin
FTestSetPatternsOut[InputIndex, PatternIndex] := Value;
end;
procedure TNeuralNetBP. SetTestSetPatternCount(const Value: integer);
begin
FTestSetPatternCount := Value;
SetLength(FTestSetPatterns, FTestSetPatternCount, InputNeuronCount);
SetLength(FTestSetPatternsOut, FTestSetPatternCount, OutputNeuronCount);
end;
procedure TNeuralNetBP. SetMomentum(Value: double);
begin
if (Value > 1) or (Value < 0) then
FMomentum := DefaultMomentum
else
FMomentum := Value;
end;
procedure TNeuralNetBP. SetEpochCount(Value: integer);
begin
if Value < 1 then
FEpochCount := 1
else
FEpochCount := Value;
end;
procedure TNeuralNetBP. ShakeUp;
var
i, j, k: integer;
begin
Randomize;
for i := 1 to LayerCount - 1 do
for j := 0 to LayersBP[i].NeuronCount - 1 do
for k := 0 to LayersBP[i-1].NeuronCount do
with LayersBP[i].NeuronsBP[j] do
Weights[k]:= Weights[k] + Random*0.1-0.05;
end;
procedure TNeuralNetBP. Shuffle;
var
i, j, xNewInd, xLast: integer;
xIsUnique : boolean;
begin
xNewInd := 0;
FRandomOrder[0] := Round(Random(FPatternCount));
xLast := 0;
for i := 1 to PatternCount - 1 do
begin
xIsUnique := False;
while not xIsUnique do
begin
xNewInd := Round((Random(FPatternCount)));
xIsUnique := True;
for j := 0 to xLast do
if xNewInd = FRandomOrder[j] then
xIsUnique := False;
end;
FRandomOrder[i] := xNewInd;
xLast := xLast +1;
end;
end;
procedure TNeuralNetBP. TeachOffLine;
var
j: integer;
xQuadError: double;
xNewEpoch: boolean;
begin
DoOnBeforeTeach;
if not ContinueTeach then
begin
// веса инициализируются, если сеть обучается с "нуля"
InitWeights;
FEpochCurrent := 1;
end;
Randomize;
SetLength(FRandomOrder, FPatternCount);
TeachStopped := False;
while (FEpochCurrent <= EpochCount) do
begin
FTeachError := 0;
FMaxTeachResidual := 0;
FRecognizedTeachCount := 0;
xNewEpoch := True;
Shuffle;
for j := 0 to PatternCount - 1 do
begin
LoadPatternsInput(FRandomOrder[j]);
LoadPatternsOutput(FRandomOrder[j]);
Propagate;
xQuadError := QuadError;
// проверка - распознан ли пример из обучающего множества
if xQuadError < IdentError then
Inc(FRecognizedTeachCount);
FTeachError := FTeachError + xQuadError;
// максимальная ошибка на обучающем множестве
if xNewEpoch then
begin
FMaxTeachResidual := xQuadError;
xNewEpoch := False;
end
else
if MaxTeachResidual < xQuadError then
FMaxTeachResidual := xQuadError;
CalcLocalError;
AdjustWeights;
end;
// средняя ошибка на обучающем множестве
FMidTeachResidual := TeachError/PatternCount;
// проверка сети на обобщение
if TestSetPatternCount > 0 then
CheckTestSet;
DoOnEpochPassed;
if StopTeach then
begin
TeachStopped := True;
Exit;
end;
Inc(FEpochCurrent);
end;
DoOnAfterTeach;
end;
procedure TNeuralNetBP. SetPatternCount(const Value: integer);
begin
FPatternCount := Value;
inherited;
end;
procedure TNeuralNetBP. SetDefaultProperties;
begin
// параметры устанавливаемые по умолчанию
Alpha := DefaultAlpha;
ContinueTeach := False;
Epoch := True;
EpochCount := DefaultEpochCount;
Momentum := DefaultMomentum;
TeachRate := DefaultTeachRate;
ResizeInputDim;
ResizeOutputDim;
end;
end.
Исходный код скрипта подключения библиотеки ActiveX к системе “1C:Предприятие”
//Нейросеть - начало
Если флNero=1 Тогда
Если ПустоеЗначение(Нейросеть)=1 Тогда
Если ЗагрузитьВнешнююКомпоненту("NeroNet. dll")=0 Тогда
Возврат;
КонецЕсли;
НейроСеть=СоздатьОбъект("AddIn. NeroNet");
КонецЕсли;
НейроСеть. НачатьОпределениеКолонок();
Для с=1 по СписокГруппировок. РазмерСписка() Цикл
Идент=СписокГруппировок. ПолучитьЗначение(с);
НейроСеть. НоваяКолонка(Идент);
КонецЦикла;
НейроСеть. НоваяКолонка("Количество","Количество","Число");
НейроСеть. НоваяКолонка("Стоимость","Стоимость","Число");
НейроСеть. НоваяКолонка("Наименование товара"," Наименование товара ","Число");
НейроСеть. НоваяКолонка("Дата"," Дата "," Дата ");
НейроСеть. ЗавершитьОпределениеКолонок();
Прогресс="=>";
Загрузить_Данные_В_НейроСеть(1);
НейроСеть. Показать("Прогноз продажи по товарам");
Возврат;
КонецЕсли;
//НейроСеть – конец
Основные элементы интерфейса пользователя системы

Рис. 1 Главное окно программы и экранная форма вызова внешнего отчета

Рис. 2 Основная экранная форма с элементами настройки

Рис. 3 Форма отчета прогноза
[1] Информационные технологии – совокупность методов, производственных процессов и программно-технических средств, объединенных в технологическую цепочку, обеспечивающую сбор, обработку, хранение, распространение (транспортировку) и отображение информации с целью снижения трудоемкости процессов использования информационного ресурса, а также повышения их надежности и оперативности.
[2] Data Mining – в переводе с английского означает "добыча данных". Альтернативное название – knowledge discovery in databases ("обнаружение знаний в базах данных" или "интеллектуальный анализ данных").
[3] Документ, позволяющий обосновать целесообразность разработки, производства, и сбыта продукции в условиях конкуренции.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 |



