FANN(Fast Artificial Neural Network Library)を使う ~Delphiでお手軽プログラミング
- 当サイトで他にFANNを使用しているページ
- FANNを使って最高気温をAIに予測させる
- FANNを使って手書き数字(0~9)をAIに認識させる
- FANNを使って手書き数字(0~9)の画像データセットMNISTを利用してみる
- FANNを使って2つの1桁の整数の足し算を行わせる
FANNを使用する為のファイルの準備
FANNライブラリ、FANNライブラリ(fannfloat.dll 32Bit版)をDelphiから使用するfann.pas、fannライブラリを クラスとして使用できるライブラリファイル(MamFann.pas)を、本ページ下部からダウンロードします。Delphiを起動して新規作成を行い、必要なコンポーネントをドラッグ&ドロップする
Delphi起動⇒ファイル⇒新規作成⇒WindowsVCLアプリケーション を選択します。TButton 4個、 TLabel 1個、 TMemo 1個、 TImage 1個をフォームへドラッグ&ドロップします。
Image1のプロパティ[Proportional]をTrueに、プロパティ[Stretch]をTrueにします。
プロジェクトフォルダ内にダウンロードしたfann.pas、MamFann.pasファイルを配置します。
fannfloat.dllファイル(32Bit版)をパスの通ったフォルダ(c:\Windows等)に入れます。
ソースコードを記述する
Form1のイベントOnCreateイベント、OnDestroyイベント、、 Button1のOnClickイベント、Button2のOnClickイベント、Button3のOnClickイベント、Button4のOnClickイベント、等に 以下ソースコードを記述します。unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, fann, MamFann ; type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; Memo1: TMemo; Button2: TButton; Button3: TButton; Button4: TButton; Image1: TImage; Label2: TLabel; procedure Button1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private 宣言 } MamFann: TMamFann; public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var NeuronNumInLayer:array of Cardinal; begin //TMamFannクラスのインスタンス化 if Assigned(MamFann) then FreeAndNil(MamFann); setlength(NeuronNumInLayer,3);//レイヤー(層)の数 NeuronNumInLayer[0]:=2; //入力層のニューロン数 NeuronNumInLayer[1]:=3; //中間層のニューロン数 NeuronNumInLayer[2]:=1; //出力層のニューロン数 MamFann:=TMamFann.Create(NeuronNumInLayer); Button2.Enabled:=true; Button3.Enabled:=false; Button4.Enabled:=true; ShowMessage('ANNの初期設定完了'); end; // procedure TForm1.Button2Click(Sender: TObject); var inputs: array [0..1] of TFann_type; outputs: array [0..0] of TFann_type; epoch:Integer; //一連の学習の実施回数 i,j: Integer; Mse: single; //誤差分散 begin //一連の学習を3万回実施 for epoch:=1 to 30000 do begin inputs[0]:=0; inputs[1]:=0; outputs[0]:=trunc(inputs[0]) Xor trunc(inputs[1]); MamFann.Train(inputs,outputs); inputs[0]:=1; inputs[1]:=0; outputs[0]:=trunc(inputs[0]) Xor trunc(inputs[1]); MamFann.Train(inputs,outputs); inputs[0]:=0; inputs[1]:=1; outputs[0]:=trunc(inputs[0]) Xor trunc(inputs[1]); MamFann.Train(inputs,outputs); inputs[0]:=1; inputs[1]:=1; outputs[0]:=trunc(inputs[0]) Xor trunc(inputs[1]); MamFann.Train(inputs,outputs); if epoch mod 100 = 0 then begin //誤差分散の表示 Mse:=MamFann.GetMSE; Label1.Caption:=Format('%.8f',[mse]); Application.ProcessMessages; end; end; //学習結果をファイルに保存 //ロード[NN.LoadFromFile('abc.net');]すれば学習結果を使用できる MamFann.SaveToFile('a.net'); //ニューロンネットワーク図の描画 MamFann.CreateNeuronBmp(Image1.Picture.Bitmap); Button2.Enabled:=true; Button3.Enabled:=true; Button4.Enabled:=true; ShowMessage('トレーニング終了'+#13#10+'学習ファイル保存'); end; procedure TForm1.Button3Click(Sender: TObject); var i,j: integer; outputs: array [0..0] of TFann_type; inputs : array [0..1] of TFann_type; begin //XORのANN実行 Memo1.Lines.Clear; inputs[0]:=0; inputs[1]:=0; MamFann.Run(inputs,outputs); Memo1.Lines.Add( Format('%1.0f XOR %1.0f = %f',[inputs[0],inputs[1],Outputs[0]]) ); inputs[0]:=1; inputs[1]:=0; MamFann.Run(inputs,outputs); Memo1.Lines.Add( Format('%1.0f XOR %1.0f = %f',[inputs[0],inputs[1],Outputs[0]]) ); inputs[0]:=0; inputs[1]:=1; MamFann.Run(inputs,outputs); Memo1.Lines.Add( Format('%1.0f XOR %1.0f = %f',[inputs[0],inputs[1],Outputs[0]]) ); inputs[0]:=1; inputs[1]:=1; MamFann.Run(inputs,outputs); Memo1.Lines.Add( Format('%1.0f XOR %1.0f = %f',[inputs[0],inputs[1],Outputs[0]]) ); end; procedure TForm1.Button4Click(Sender: TObject); begin if Assigned(MamFann) then FreeAndNil(MamFann); if not FileExists('a.net') then exit; //学習済みファイルの読み込み MamFann:=TMamFann.Create('a.net'); Button2.Enabled:=true; Button3.Enabled:=true; Button4.Enabled:=true; showmessage('ANNファイルの読み込み完了'); end; procedure TForm1.FormCreate(Sender: TObject); begin Image1.Proportional:=True; Image1.Stretch:=True; Button2.Enabled:=false; Button3.Enabled:=false; Button4.Enabled:=true; end; procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(MamFann) then FreeAndNil(MamFann); end; end.
実行する
実行ボタンを押して実行します。(デバッグ実行でもOK)fann.pasソースコード
unit fann; interface uses system.types; Const FANN_DLLFILE = 'fannfloat.dll'; type TFann_type = Single; PFann_Type = ^TFann_type; PPFann_Type = ^PFann_type; Fann_Type_Array = array[word] of TFann_type; PFann_Type_Array = ^Fann_Type_Array; PPFann_Type_Array = ^PFann_Type_Array; //struct _iobuf{ // char *_ptr; int _cnt; char *_base; int _flag; // int _file; int _charbuf; int _bufsiz; char *_tmpfname; //}; typedef struct _iobuf FILE; _iobuf = packed record _ptr: PChar; _cnt: Integer; _base: PChar; _flag: Integer; _file: Integer; _charbuf: Integer; _bufsiz: Integer; _tmpfname: PChar; end; TFile = _iobuf; PFile = ^TFile; TEnumType=Cardinal; TFann_activationfunc_enum=( FANN_LINEAR, //閾値アクティブ化、0又は1の出力 FANN_THRESHOLD, //閾値アクティブ化、-1又は1の出力 FANN_THRESHOLD_SYMMETRIC, //シグモイド活性化、最も使用される、0~1の出力 FANN_SIGMOID, //シグモイド段階的線形近似、シグモイドより高速で精度は劣る、0~1の出力 FANN_SIGMOID_STEPWISE, //対称シグモイド活性化関数、最も使用される、-1~1の出力 FANN_SIGMOID_SYMMETRIC, //対称シグモイド段階的線形近似、対称シグモイドより高速で精度は劣る、-1~1の出力 FANN_SIGMOID_SYMMETRIC_STEPWISE, FANN_GAUSSIAN, FANN_GAUSSIAN_SYMMETRIC, FANN_GAUSSIAN_STEPWISE, FANN_ELLIOT, FANN_ELLIOT_SYMMETRIC, FANN_LINEAR_PIECE, FANN_LINEAR_PIECE_SYMMETRIC, FANN_SIN_SYMMETRIC, FANN_COS_SYMMETRIC, FANN_SIN, FANN_COS ); PFann_activationfunc_enum = ^Tfann_activationfunc_enum; TFann_Neuron = packed record first_con: Cardinal; last_con : Cardinal; sum: TFann_type; value: TFann_type; activation_steepness: TFann_type; activation_function: Cardinal ; end; PFann_Neuron = ^TFann_Neuron; PPFann_Neuron = ^PFann_Neuron; TFann_Layer = packed record first_neuron: PFann_Neuron; last_neuron : PFann_Neuron; end; PFann_Layer = ^TFann_Layer; TFann_nettype_enum = TEnumType; TFann_errno_enum = TEnumType; TFann_train_enum =( //重みが1つのエポックで何度も更新されるバックプロパゲーションアルゴリズム。 //非常に速くトレーニングするが、高度な問題はうまくトレーニングしません。 FANN_TRAIN_INCREMENTAL, //0 //重みはエポック中に1回だけ更新されるので、トレーニングが遅くなります。 //平均二乗誤差はより正確に計算され、FANN_TRAIN_INCREMENTALより良い。 FANN_TRAIN_BATCH, //1 //適応型の為learning_rateを使用しません。iRPROPアルゴリズム FANN_TRAIN_RPROP, //2 //learning_rateを使用する、より高度なアルゴリズム。 FANN_TRAIN_QUICKPROP, //3 //SARPROPアルゴリズム FANN_TRAIN_SARPROP //4 ); TFann_errorfunc_enum=TEnumType; TFann_stopfunc_enum=TEnumType; PFann_Train_Data = ^TFann_Train_Data; TFann_Train_Data = packed record errno_f: TFann_errno_enum; erro_log: PFile; errstr: PChar; num_data: Cardinal; num_input: Cardinal; num_ouput: Cardinal; input: PPFann_Type_Array; output: PPFann_Type_Array; end; PFann = ^TFann; TFann_callback = function( ann: PFann; train: PFann_Train_Data; max_epochs: Cardinal; epochs_between_reports: Cardinal; desired_error: Single; epochs: Cardinal): Integer; stdcall; TUser_Function = procedure( num: Cardinal; num_input: Cardinal; num_output: Cardinal; input: PFann_Type; output: PFann_Type); stdcall; TFann = packed record errno_f: TFann_errno_enum; error_log: PFile; errstr: PChar; learning_rate: Single; learning_momentum: Single; connection_rate: Single; network_type: TFann_nettype_enum; first_layer: PFann_Layer; last_layer: PFann_Layer; total_neurons: Cardinal; num_input: Cardinal; num_output: Cardinal; weights: PFann_Type; connections: PPFann_Neuron; train_errors: PFann_Type; training_algorithm: TFann_train_enum; total_connections: Cardinal; output: PFann_Type; num_MSE: Cardinal; MSE_value: Single; num_bit_fail: Cardinal; bit_fail_limit: TFann_type; train_error_function: TFann_errorfunc_enum; train_stop_function: Tfann_stopfunc_enum; callback: TFann_callback; user_data: Pointer; cascade_output_change_fraction: single; cascade_output_stagnation_epochs: Cardinal; cascade_candidate_change_fraction: single; cascade_candidate_stagnation_epochs: Cardinal; cascade_best_candidate: Cardinal; cascade_candidate_limit: TFann_type; cascade_weight_multiplier: TFann_type; cascade_max_out_epochs: Cardinal; cascade_max_cand_epochs: Cardinal; cascade_activation_functions: TFann_activationfunc_enum; cascade_activation_functions_count: Cardinal; cascade_activation_steepnesses: PFann_Type; cascade_activation_steepnesses_count: Cardinal; cascade_num_candidate_groups: Cardinal; cascade_candidate_scores: PFann_Type; total_neurons_allocated: Cardinal; total_connections_allocated: Cardinal; quickprop_decay: single; quickprop_mu: single; rprop_increase_factor: single; rprop_decrease_factor: single; rprop_delta_min: single; rprop_delta_max: single; rprop_delta_zero: single; sarprop_temperature:single; sarprop_epoch: Cardinal; train_slopes: PFann_Type; prev_steps: PFann_Type; prev_train_slopes: PFann_Type; prev_weights_deltas: PFann_Type; end; TFann_Connection = packed record from_neuron: Cardinal; to_neuron: Cardinal; weight: TFann_type; end; PFann_Connection = ^TFann_Connection; TFann_Error = packed record errno_f: TFann_errno_enum; error_log: PFile; errstr: PChar; end; PFann_Error = ^TFann_Error; Const //_Fann_Error_Func FANN_ERRORFUNC_LINEAR = 0; FANN_ERRORFUNC_TANH = 1; //_Fann_ErroNo FANN_E_NO_ERROR = 0; FANN_E_CANT_OPEN_CONFIG_R = 1; FANN_E_CANT_OPEN_CONFIG_W = 2; FANN_E_WRONG_CONFIG_VERSION = 3; FANN_E_CANT_READ_CONFIG = 4; FANN_E_CANT_READ_NEURON = 5; FANN_E_CANT_READ_CONNECTIONS = 6; FANN_E_WRONG_NUM_CONNECTIONS = 7; FANN_E_CANT_OPEN_TD_W = 8; FANN_E_CANT_OPEN_TD_R = 9; FANN_E_CANT_READ_TD = 10; FANN_E_CANT_ALLOCATE_MEM = 11; FANN_E_CANT_TRAIN_ACTIVATION = 12; FANN_E_CANT_USE_ACTIVATION = 13; FANN_E_TRAIN_DATA_MISMATCH = 14; FANN_E_CANT_USE_TRAIN_ALG = 15; FANN_E_TRAIN_DATA_SUBSET = 16; FANN_E_INDEX_OUT_OF_BOUND = 17; FANN_E_SCALE_NOT_PRESENT = 18; //_Fann_Stop_Func FANN_STOPFUNC_MSE = 0; FANN_STOPFUNC_BIT = 1; //_Fann_Net_Type FANN_NETTYPE_LAYER = 0; FANN_NETTYPE_SHORTCUT = 1; function fann_create_standard(num_layers: Cardinal): PFann; stdcall; function fann_create_sparse( connection_rate: single; num_layers: Cardinal):PFann; stdcall; function fann_create_shortcut(connection_rate: single): PFann; stdcall; function fann_create_standard_array( num_layers: Cardinal; const layers: PCardinal): PFann; stdcall; function fann_create_sparse_array( connection_rate: single; num_layers: Cardinal; const layers: PCardinal): PFann; stdcall; function fann_create_shortcut_array( num_layers: cardinal;const layers: Pcardinal): PFann; stdcall; procedure fann_destroy(Ann: PFann); stdcall; function fann_run(ann: PFann; input: PFann_Type): Pfann_type_array; stdcall; procedure fann_randomize_weights( Ann: PFann; Min_weight: TFann_type; Max_weight: TFann_type); stdcall; procedure fann_init_weights( Ann: PFann; train_data: PFann_Train_Data); stdcall; procedure fann_print_connections(ann: PFann);stdcall; procedure fann_print_parameters(ann: PFann);stdcall; function fann_get_num_input(Ann: PFann): cardinal;stdcall; function fann_get_num_output(Ann: PFann): cardinal;stdcall; function fann_get_total_neurons(Ann: PFann): cardinal; stdcall; function fann_get_total_connections(Ann: PFann): cardinal; stdcall; function fann_get_network_type(Ann: PFann): cardinal; stdcall; function fann_get_connection_rate(Ann: PFann): single; stdcall; function fann_get_num_layers(Ann: PFann): cardinal; stdcall; procedure fann_get_layer_array(Ann: PFann; layers: PCardinal); stdcall; procedure fann_get_bias_array(Ann: PFann; bias: PCardinal);stdcall; procedure fann_get_connection_array( Ann: PFann; connections: PFann_Connection);stdcall; procedure fann_set_weight_array(Ann: PFann; connections: PFann_Connection; num_connection: Cardinal);stdcall; procedure fann_set_weight(Ann: PFann; from_neuron: Cardinal; to_neuron: Cardinal; weight: TFann_type);stdcall; procedure fann_set_user_data(Ann: PFann; user_data: Pointer);stdcall; function fann_get_user_data(Ann: PFann): Pointer; stdcall; function fann_create_from_file( const configuration_file: PAnsiChar): PFann; stdcall; procedure fann_save(Ann: PFann; Const Configuration_File: PAnsiChar);stdcall; function fann_save_to_fixed( Ann: PFann; Const Configuration_File: PChar): integer;stdcall; procedure fann_train( Ann: PFann; Input: PFann_Type; Desired_Output: PFann_Type);stdcall; function fann_test( Ann: PFann; Input: PFann_Type; Desired_Output: Pfann_Type): Pfann_type_array;stdcall; function fann_get_MSE(Ann: PFann): single;stdcall; function fann_get_bit_fail(Ann: PFann): Cardinal;stdcall; procedure fann_reset_MSE(Ann: Pfann); stdcall; procedure fann_train_on_data( Ann: PFann; Data: PFann_Train_Data; max_epochs: cardinal;epochs_between_reports: cardinal; desired_error: single);stdcall; procedure fann_train_on_file( Ann: PFann; Filename: PAnsiChar;max_epochs: cardinal; epochs_between_reports: cardinal; desired_error: single); stdcall; function fann_train_epoch( Ann: PFann; data: PFann_Train_Data): single; stdcall; function fann_test_data(Ann: PFann; data: PFann_Train_Data): single; stdcall; function fann_read_train_from_file( const filename: PChar): PFann_Train_Data; stdcall; function fann_create_train_from_callback( num_data: Cardinal; num_input: Cardinal; num_output: Cardinal; user_function: TUser_Function): PFann_Train_Data; stdcall; procedure fann_destroy_train(train_data: PFann_Train_Data); stdcall; procedure fann_shuffle_train_data(Train_Data: PFann_Train_Data);stdcall; procedure fann_scale_train(Ann: PFann; data: PFann_Train_Data);stdcall; procedure fann_descale_train(Ann: PFann; data: PFann_Train_Data);stdcall; function fann_set_input_scaling_params( Ann: PFann; const data: PFann_Train_Data; new_input_min: single; new_input_max: single): integer;stdcall; function fann_set_output_scaling_params( Ann: PFann; const data: PFann_Train_Data; new_output_min: single; new_output_max: single): integer;stdcall; function fann_set_scaling_params( Ann: PFann; const data: PFann_Train_Data; new_input_min: single; new_input_max: single; new_output_min: single; new_output_max: single): integer; stdcall; function fann_clear_scaling_params(Ann: PFann): integer; stdcall; procedure fann_scale_input(Ann: PFann; input_vector: PFann_type); stdcall; procedure fann_scale_output(Ann: PFann; output_vector: PFann_type); stdcall; procedure fann_descale_input(Ann: PFann; input_vector: PFann_type); stdcall; procedure fann_descale_output(Ann: PFann; output_vector: PFann_type); stdcall; procedure fann_scale_input_train_data( Train_Data: PFann_Train_Data; new_min: TFann_type; new_max: TFann_type); stdcall; procedure fann_scale_output_train_data( Train_Data: PFann_Train_Data; new_min: TFann_type; new_max: TFann_type); stdcall; procedure fann_scale_train_data( Train_Data: PFann_Train_Data; new_min: TFann_type; new_max: TFann_type); stdcall; function fann_merge_train_data( Data1: PFann_Train_Data; Data2: PFann_Train_Data): PFann_Train_Data; stdcall; function fann_duplicate_train_data( Data: PFann_Train_Data): PFann_Train_Data;stdcall; function fann_subset_train_data( data: PFann_Train_Data; pos: Cardinal; length: Cardinal): PFann_Train_Data; stdcall; function fann_length_train_data( data: PFann_Train_Data): Cardinal; stdcall; function fann_num_input_train_data( data: PFann_Train_Data): Cardinal; stdcall; function fann_num_output_train_data( data: PFann_Train_Data): Cardinal; stdcall; function fann_save_train( Data: PFann_train_Data; const Filename: PChar):integer;stdcall; function fann_save_train_to_fixed( Data: PFann_train_Data; const FileName: Pchar; decimal_point: cardinal): integer;stdcall; function fann_get_training_algorithm(Ann: Pfann):Cardinal;stdcall; procedure fann_set_training_algorithm( Ann: PFann; Training_Algorithm: Cardinal);stdcall; function fann_get_learning_rate(Ann: PFann): single;stdcall; procedure fann_set_learning_rate( Ann: PFann; Learning_Rate: Single); stdcall; function fann_get_learning_momentum(Ann: PFann): single;stdcall; procedure fann_set_learning_momentum( Ann: PFann; learning_momentum: Single); stdcall; function fann_get_activation_function( Ann: PFann; layer: integer; neuron: integer): TFann_activationfunc_enum; stdcall; procedure fann_set_activation_function( Ann: PFann; activation_function: Cardinal; layer: integer; neuron: integer); stdcall; procedure fann_set_activation_function_layer( Ann: PFann; activation_function: Cardinal; layer: integer); stdcall; procedure fann_set_activation_function_hidden( Ann: PFann; activation_function: Cardinal); stdcall; procedure fann_set_activation_function_output( Ann: PFann; activation_function: Cardinal); stdcall; function fann_get_activation_steepness( Ann: PFann; layer: integer; neuron: integer): TFann_type; stdcall; procedure fann_set_activation_steepness( Ann: PFann; steepness: TFann_type; layer: integer; neuron: integer); stdcall; procedure fann_set_activation_steepness_layer( Ann: PFann; steepness: TFann_type; layer: integer); stdcall; procedure fann_set_activation_steepness_hidden( Ann: PFann; steepness: TFann_type); stdcall; procedure fann_set_activation_steepness_output( Ann: PFann; steepness: TFann_type); stdcall; function fann_get_train_error_function(Ann: PFann): cardinal;stdcall; procedure fann_set_train_error_function( Ann: PFann; Train_Error_Function: cardinal); stdcall; function fann_get_train_stop_function(Ann: PFann): Cardinal; stdcall; procedure fann_set_train_stop_function( Ann: PFann; train_stop_function: cardinal); stdcall; function fann_get_bit_fail_limit(Ann: PFann): TFann_type; stdcall; procedure fann_set_bit_fail_limit( Ann: PFann; bit_fail_limit: TFann_type); stdcall; procedure fann_set_callback(Ann: PFann; callback: TFann_Callback); stdcall; function fann_get_quickprop_decay(Ann: PFann): single;stdcall; procedure fann_set_quickprop_decay( Ann: Pfann; quickprop_decay: Single);stdcall; function fann_get_quickprop_mu(Ann: PFann): single;stdcall; procedure fann_set_quickprop_mu(Ann: PFann; Mu: Single);stdcall; function fann_get_rprop_increase_factor(Ann: PFann): single;stdcall; procedure fann_set_rprop_increase_factor( Ann: PFann;rprop_increase_factor: single);stdcall; function fann_get_rprop_decrease_factor( Ann: PFann): single;stdcall; procedure fann_set_rprop_decrease_factor( Ann: PFann;rprop_decrease_factor: single); stdcall; function fann_get_rprop_delta_min(Ann: PFann): single; stdcall; procedure fann_set_rprop_delta_min( Ann: PFann; rprop_delta_min: Single); stdcall; function fann_get_rprop_delta_max(Ann: PFann): single;stdcall; procedure fann_set_rprop_delta_max( Ann: PFann; rprop_delta_max: Single); stdcall; function fann_get_rprop_delta_zero(Ann: PFann): single;stdcall; procedure fann_set_rprop_delta_zero( Ann: PFann; rprop_delta_zero: Single); stdcall; procedure fann_set_error_log(errdat: PFann_Error; Log_File: PFile);stdcall; function fann_get_errno(errdat: PFann_Error): cardinal;stdcall; procedure fann_reset_errno(errdat: PFann_Error);stdcall; procedure fann_reset_errstr(errdat: PFann_Error);stdcall; function fann_get_errstr(errdat: PFann_Error): PChar;stdcall; procedure fann_print_error(Errdat: PFann_Error);stdcall; procedure fann_cascadetrain_on_data( Ann: PFann; data: PFann_Train_Data; max_neurons: Cardinal; neurons_between_reports: Cardinal; desired_error: single); stdcall; procedure fann_cascadetrain_on_file(Ann: PFann; const filename: PChar; max_neurons: Cardinal; neurons_between_reports: Cardinal; desired_error: single); stdcall; function fann_get_cascade_output_change_fraction( Ann: PFann): single; stdcall; procedure fann_set_cascade_output_change_fraction( Ann: PFann; cascade_output_change_fraction: single); stdcall; function fann_get_cascade_output_stagnation_epochs( Ann: PFann): cardinal; stdcall; procedure fann_set_cascade_output_stagnation_epochs( Ann: PFann; cascade_output_stagnation_epochs: cardinal); stdcall; function fann_get_cascade_candidate_change_fraction( Ann: PFann): single; stdcall; procedure fann_set_cascade_candidate_change_fraction( Ann: PFann; cascade_candidate_change_fraction: single); stdcall; function fann_get_cascade_candidate_stagnation_epochs( Ann: PFann): cardinal; stdcall; procedure fann_set_cascade_candidate_stagnation_epochs( Ann: PFann; cascade_candidate_stagnation_epochs: cardinal); stdcall; function fann_get_cascade_weight_multiplier( Ann: PFann): TFann_type; stdcall; procedure fann_set_cascade_weight_multiplier( Ann: PFann; cascade_weight_multiplier: TFann_type); stdcall; function fann_get_cascade_candidate_limit( Ann: PFann): TFann_type; stdcall; procedure fann_set_cascade_candidate_limit( Ann: PFann; cascade_candidate_limit: TFann_type); stdcall; function fann_get_cascade_max_out_epochs(Ann: PFann): cardinal; stdcall; procedure fann_set_cascade_max_out_epochs( Ann: PFann; cascade_max_out_epochs: cardinal); stdcall; function fann_get_cascade_max_cand_epochs( Ann: PFann): cardinal; stdcall; procedure fann_set_cascade_max_cand_epochs( Ann: PFann; cascade_max_cand_epochs: cardinal); stdcall; function fann_get_cascade_num_candidates( Ann: PFann): cardinal; stdcall; function fann_get_cascade_activation_functions_count( Ann: PFann): cardinal; stdcall; function fann_get_cascade_activation_functions( Ann: PFann): PCardinal; stdcall; procedure fann_set_cascade_activation_functions(Ann: PFann; cascade_activation_functions: PCardinal; cascade_activation_functions_count: Cardinal); stdcall; function fann_get_cascade_activation_steepnesses_count( Ann: PFann): cardinal; stdcall; function fann_get_cascade_activation_steepnesses( Ann: PFann): pfann_type; stdcall; procedure fann_set_cascade_activation_steepnesses( Ann: PFann; cascade_activation_steepnesses: PFann_Type; cascade_activation_steepnesses_count: Cardinal); stdcall; function fann_get_cascade_num_candidate_groups(Ann: PFann): cardinal; stdcall; procedure fann_set_cascade_num_candidate_groups( Ann: PFann; cascade_num_candidate_groups: cardinal); stdcall; implementation function fann_create_standard; external FANN_DLLFILE; function fann_create_sparse; external FANN_DLLFILE; function fann_create_shortcut; external FANN_DLLFILE; function fann_create_standard_array; external FANN_DLLFILE name '_fann_create_standard_array@8'; function fann_create_sparse_array; external FANN_DLLFILE name '_fann_create_sparse_array@12'; function fann_create_shortcut_array; external FANN_DLLFILE; procedure fann_destroy(Ann: PFann); external FANN_DLLFILE name '_fann_destroy@4'; function fann_run; external FANN_DLLFILE name '_fann_run@8'; procedure fann_randomize_weights; external FANN_DLLFILE name '_fann_randomize_weights@12'; procedure fann_init_weights; external FANN_DLLFILE; procedure fann_print_connections; external FANN_DLLFILE; procedure fann_print_parameters; external FANN_DLLFILE; function fann_get_num_input; external FANN_DLLFILE; function fann_get_num_output; external FANN_DLLFILE; function fann_get_total_neurons; external FANN_DLLFILE; function fann_get_total_connections; external FANN_DLLFILE name '_fann_get_total_connections@4'; function fann_get_network_type; external FANN_DLLFILE; function fann_get_connection_rate; external FANN_DLLFILE name '_fann_get_connection_rate@4'; function fann_get_num_layers; external FANN_DLLFILE name '_fann_get_num_layers@4'; procedure fann_get_layer_array; external FANN_DLLFILE name '_fann_get_layer_array@8'; procedure fann_get_bias_array; external FANN_DLLFILE name '_fann_get_bias_array@8'; procedure fann_get_connection_array; external FANN_DLLFILE name '_fann_get_connection_array@8'; procedure fann_set_weight_array; external FANN_DLLFILE; procedure fann_set_weight; external FANN_DLLFILE; procedure fann_set_user_data; external FANN_DLLFILE; function fann_get_user_data; external FANN_DLLFILE; function fann_create_from_file; external FANN_DLLFILE name '_fann_create_from_file@4'; procedure fann_save; external FANN_DLLFILE name '_fann_save@8'; function fann_save_to_fixed; external FANN_DLLFILE; procedure fann_train; external FANN_DLLFILE name '_fann_train@12'; function fann_test; external FANN_DLLFILE; function fann_get_MSE; external FANN_DLLFILE name '_fann_get_MSE@4'; function fann_get_bit_fail; external FANN_DLLFILE; procedure fann_reset_MSE; external FANN_DLLFILE name '_fann_reset_MSE@4'; procedure fann_train_on_data; external FANN_DLLFILE name '_fann_train_on_data@20'; procedure fann_train_on_file; external FANN_DLLFILE name '_fann_train_on_file@20'; function fann_train_epoch; external FANN_DLLFILE; function fann_test_data; external FANN_DLLFILE; function fann_read_train_from_file; external FANN_DLLFILE; function fann_create_train_from_callback; external FANN_DLLFILE; procedure fann_destroy_train; external FANN_DLLFILE; procedure fann_shuffle_train_data; external FANN_DLLFILE; procedure fann_scale_train; external FANN_DLLFILE; procedure fann_descale_train; external FANN_DLLFILE; function fann_set_input_scaling_params; external FANN_DLLFILE; function fann_set_output_scaling_params; external FANN_DLLFILE; function fann_set_scaling_params; external FANN_DLLFILE; function fann_clear_scaling_params; external FANN_DLLFILE; procedure fann_scale_input; external FANN_DLLFILE; procedure fann_scale_output; external FANN_DLLFILE; procedure fann_descale_input; external FANN_DLLFILE; procedure fann_descale_output; external FANN_DLLFILE; procedure fann_scale_input_train_data; external FANN_DLLFILE; procedure fann_scale_output_train_data; external FANN_DLLFILE; procedure fann_scale_train_data; external FANN_DLLFILE; function fann_merge_train_data; external FANN_DLLFILE; function fann_duplicate_train_data; external FANN_DLLFILE; function fann_subset_train_data; external FANN_DLLFILE; function fann_length_train_data; external FANN_DLLFILE; function fann_num_input_train_data; external FANN_DLLFILE; function fann_num_output_train_data; external FANN_DLLFILE; function fann_save_train; external FANN_DLLFILE; function fann_save_train_to_fixed; external FANN_DLLFILE; function fann_get_training_algorithm; external FANN_DLLFILE name '_fann_get_training_algorithm@4'; procedure fann_set_training_algorithm; external FANN_DLLFILE name '_fann_set_training_algorithm@8'; function fann_get_learning_rate; external FANN_DLLFILE name '_fann_get_learning_rate@4'; procedure fann_set_learning_rate; external FANN_DLLFILE name '_fann_set_learning_rate@8'; function fann_get_learning_momentum; external FANN_DLLFILE name '_fann_get_learning_momentum@4'; procedure fann_set_learning_momentum; external FANN_DLLFILE name '_fann_set_learning_momentum@8'; function fann_get_activation_function; external FANN_DLLFILE; procedure fann_set_activation_function; external FANN_DLLFILE name '_fann_set_activation_function@16'; procedure fann_set_activation_function_layer; external FANN_DLLFILE; procedure fann_set_activation_function_hidden; external FANN_DLLFILE name '_fann_set_activation_function_hidden@8'; procedure fann_set_activation_function_output; external FANN_DLLFILE name '_fann_set_activation_function_output@8'; function fann_get_activation_steepness; external FANN_DLLFILE; procedure fann_set_activation_steepness; external FANN_DLLFILE name '_fann_set_activation_steepness@16'; procedure fann_set_activation_steepness_layer; external FANN_DLLFILE name '_fann_set_activation_steepness_layer@12'; procedure fann_set_activation_steepness_hidden; external FANN_DLLFILE name '_fann_set_activation_steepness_hidden@8'; procedure fann_set_activation_steepness_output; external FANN_DLLFILE name '_fann_set_activation_steepness_output@8'; function fann_get_train_error_function; external FANN_DLLFILE; procedure fann_set_train_error_function; external FANN_DLLFILE; function fann_get_train_stop_function; external FANN_DLLFILE; procedure fann_set_train_stop_function; external FANN_DLLFILE; function fann_get_bit_fail_limit; external FANN_DLLFILE; procedure fann_set_bit_fail_limit; external FANN_DLLFILE; procedure fann_set_callback; external FANN_DLLFILE; function fann_get_quickprop_decay; external FANN_DLLFILE; procedure fann_set_quickprop_decay; external FANN_DLLFILE; function fann_get_quickprop_mu; external FANN_DLLFILE; procedure fann_set_quickprop_mu; external FANN_DLLFILE; function fann_get_rprop_increase_factor; external FANN_DLLFILE; procedure fann_set_rprop_increase_factor; external FANN_DLLFILE; function fann_get_rprop_decrease_factor; external FANN_DLLFILE; procedure fann_set_rprop_decrease_factor; external FANN_DLLFILE; function fann_get_rprop_delta_min; external FANN_DLLFILE; procedure fann_set_rprop_delta_min; external FANN_DLLFILE; function fann_get_rprop_delta_max; external FANN_DLLFILE; procedure fann_set_rprop_delta_max; external FANN_DLLFILE; function fann_get_rprop_delta_zero; external FANN_DLLFILE; procedure fann_set_rprop_delta_zero; external FANN_DLLFILE; procedure fann_set_error_log; external FANN_DLLFILE; function fann_get_errno; external FANN_DLLFILE; procedure fann_reset_errno; external FANN_DLLFILE; procedure fann_reset_errstr; external FANN_DLLFILE; function fann_get_errstr; external FANN_DLLFILE; procedure fann_print_error; external FANN_DLLFILE; procedure fann_cascadetrain_on_data; external FANN_DLLFILE; procedure fann_cascadetrain_on_file; external FANN_DLLFILE; function fann_get_cascade_output_change_fraction; external FANN_DLLFILE; procedure fann_set_cascade_output_change_fraction; external FANN_DLLFILE; function fann_get_cascade_output_stagnation_epochs; external FANN_DLLFILE; procedure fann_set_cascade_output_stagnation_epochs; external FANN_DLLFILE; function fann_get_cascade_candidate_change_fraction; external FANN_DLLFILE; procedure fann_set_cascade_candidate_change_fraction; external FANN_DLLFILE; function fann_get_cascade_candidate_stagnation_epochs; external FANN_DLLFILE; procedure fann_set_cascade_candidate_stagnation_epochs; external FANN_DLLFILE; function fann_get_cascade_weight_multiplier; external FANN_DLLFILE; procedure fann_set_cascade_weight_multiplier; external FANN_DLLFILE; function fann_get_cascade_candidate_limit; external FANN_DLLFILE; procedure fann_set_cascade_candidate_limit; external FANN_DLLFILE; function fann_get_cascade_max_out_epochs; external FANN_DLLFILE; procedure fann_set_cascade_max_out_epochs; external FANN_DLLFILE; function fann_get_cascade_max_cand_epochs; external FANN_DLLFILE; procedure fann_set_cascade_max_cand_epochs; external FANN_DLLFILE; function fann_get_cascade_num_candidates; external FANN_DLLFILE; function fann_get_cascade_activation_functions_count; external FANN_DLLFILE; function fann_get_cascade_activation_functions; external FANN_DLLFILE; procedure fann_set_cascade_activation_functions; external FANN_DLLFILE; function fann_get_cascade_activation_steepnesses_count; external FANN_DLLFILE; function fann_get_cascade_activation_steepnesses; external FANN_DLLFILE; procedure fann_set_cascade_activation_steepnesses; external FANN_DLLFILE; function fann_get_cascade_num_candidate_groups; external FANN_DLLFILE; procedure fann_set_cascade_num_candidate_groups; external FANN_DLLFILE; end.
MamFann.pasソースコード
unit MamFann; interface uses fann, System.Classes, System.SysUtils, VCL.Graphics,System.Types; Type TMamFann=class private FFann:PFann; FConnectionRate: Single;//接続割合 FLearningRate: Single; //学習割合 FLearningMomentum: Single; FActivationFunctionHidden:TFann_activationfunc_enum; FActivationFunctionOutput:TFann_activationfunc_enum; FTrainingAlgorithm:TFann_train_enum; //学習慣性 procedure SetLearningMomentum(Const Value: Single); //学習割合 procedure SetLearningRate(Const Value:Single); //学習アルゴリズム procedure SetTrainingAlgorithm(Const Value:TFann_train_enum); //非表示レイヤーのアクティベーション関数を設定 procedure SetActivationFunctionHidden(Const Value: TFann_activationfunc_enum); //出力層のアクティベーション関数を設定 procedure SetActivationFunctionOutput(Const Value: TFann_activationfunc_enum); protected public //コンストラスター(接続割合,各層のニューロン数) // 接続割合: // 1だと完全に接続されたネットワーク(fann_create_standard_array) // 1未満だと完全に接続されないネットワーク(fann_create_sparse_array) // 各層のニューロン数:各層のニューロン数を与える constructor Create(NeuronNumInLayer: array of Cardinal; ConnectionRate:Single=1.0);overload; //コンストラクター(ファイル名) // fann_create_from_fileを使用する場合 constructor Create(LoadFromFileName:String);overload; destructor Destroy();override; //誤差分散の取得 function GetMSE():Single; //誤差分散のリセット procedure ResetMse(); //トレーニング procedure Train(Inputs,Outputs: array of TFann_type); procedure TrainOnFile(FileName: String; MaxEpochs: Cardinal; DesiredError: Single); //ANN実行 procedure Run(Inputs: array of TFann_type; var Outputs: array of TFann_type); procedure SaveToFile(FileName: String); //ファイルからANNを読み込む procedure LoadFromFile(Filename: string); //ネットワーク接続数を取得する function GetTotalConnections():Cardinal; //ネットワーク接続を取得する procedure GetConnectionArray(pcns:PFann_Connection); //レイヤーの数を取得する function GetNumLayers():Cardinal; procedure GetLayerArray(pc:PCardinal); //バイアスを取得する procedure GetBiasArray(pc:PCardinal); //ニューロンネットワーク図の作成 procedure CreateNeuronBmp(bmp:TBitmap); function GetTrainingAlgorithm():Cardinal; //学習慣性(デフォルト0.0、与える場合は0.9程度らしい) property LearningMomentum:Single read FLearningMomentum write SetLearningMomentum; property LearningRate:single read FLearningRate write SetLearningRate; property TrainingAlgorithm:TFann_train_enum read FTrainingAlgorithm write SetTrainingAlgorithm; property ActivationFunctionHidden:TFann_activationfunc_enum read FActivationFunctionHidden write setActivationFunctionHidden; property ActivationFunctionOutput:TFann_activationfunc_enum read FActivationFunctionOutput write setActivationFunctionOutput; end; implementation { TMamFann } constructor TMamFann.Create( NeuronNumInLayer: array of Cardinal;ConnectionRate:Single=1.0); var LayerNum: Cardinal; //レイヤーの数 begin if Length(NeuronNumInLayer)<2 then raise Exception.Create('2レイヤー以上が必要です'); FConnectionRate :=ConnectionRate;//接続割合 FLearningRate :=0.7;//学習割合 FLearningMomentum:=0.0;//学習慣性 //全ての非表示レイヤーのアクティベーション関数の設定 FActivationFunctionHidden:=TFann_activationfunc_enum.FANN_SIGMOID; //全ての出力レイヤーのアクティベーション関数の設定 FActivationFunctionOutput:=TFann_activationfunc_enum.FANN_SIGMOID; //練習アルゴリズム FTrainingAlgorithm:=TFann_train_enum.FANN_TRAIN_RPROP; LayerNum:=Length(NeuronNumInLayer); if(FConnectionRate<1) then FFann:=fann_create_sparse_array( FConnectionRate,LayerNum,@NeuronNumInLayer[0]) else FFann:=fann_create_standard_array(LayerNum,@NeuronNumInLayer[0]); fann_randomize_weights(FFann,-0.5,0.5); fann_set_learning_rate(FFann,FLearningRate); fann_set_learning_momentum(FFann,FLearningMomentum); fann_set_activation_steepness_hidden(FFann,0.5); fann_set_activation_steepness_output(FFann,0.5); fann_set_activation_function_hidden( FFann,Cardinal(ord(FActivationFunctionHidden))); fann_set_activation_function_output( FFann,Cardinal(ord(FActivationFunctionOutput))); fann_set_training_algorithm( FFann,Cardinal(ord(FTrainingAlgorithm))); self.ResetMse; end; constructor TMamFann.Create(LoadFromFileName: String); begin self.LoadFromFile(LoadFromFileName); end; procedure TMamFann.CreateNeuronBmp(bmp: TBitmap); //ニューロンネットワーク図の作成 Type TNeuron=record x,y:integer; isBias:Boolean; end; var ConnectionNum: Cardinal;//ネットワークの接続数 Connections: array of TFann_Connection;//ネットワークの接続 LayerNum: Cardinal;//レイヤー(層)数 NeuronNums:array of Cardinal; //各レイヤー(層)ごとのニューロン数 BiasNums:array of Cardinal; //各レイヤー(層)ごとのバイアスの数 Neurons:array of TNeuron; NeuronCount:integer; i,j:integer; max_x,max_y:integer; FromPoint,ToPoint:TPoint; ConWeight:integer; ConColor:TColor; const span:integer=100; begin //ネットワークの接続数を取得 ConnectionNum:=Self.GetTotalConnections(); SetLength(Connections,ConnectionNum); //ネットワーク内の接続を取得します Self.GetConnectionArray(@Connections[0]); //レイヤー数の取得(バイアス含まず) LayerNum:=Self.GetNumLayers(); SetLength(NeuronNums, LayerNum); SetLength(BiasNums , LayerNum); //各レイヤーのニューロン数を取得(バイアス含まず) Self.GetLayerArray(@NeuronNums[0]); //各レイヤーのバイアス数を取得 Self.GetBiasArray(@BiasNums[0]); NeuronCount:=0; for i := 0 to LayerNum-1 do begin for j := 0 to NeuronNums[i]-1 do begin inc(NeuronCount); setLength(Neurons,NeuronCount); Neurons[NeuronCount-1].x:=j; Neurons[NeuronCount-1].y:=i; Neurons[NeuronCount-1].isBias:=false; end; for j := 0 to BiasNums[i]-1 do begin inc(NeuronCount); setLength(Neurons,NeuronCount); Neurons[NeuronCount-1].x:=NeuronNums[i]+j; Neurons[NeuronCount-1].y:=i; Neurons[NeuronCount-1].isBias:=True; end; end; max_y:=LayerNum; max_x:=0; for i := 0 to Length(Neurons)-1 do begin if max_x<Neurons[i].x then max_x:=Neurons[i].x; end; inc(max_x); if not Assigned(bmp) then bmp:=TBitmap.Create; bmp.Width :=max_x*span; bmp.Height:=max_y*span; bmp.Canvas.Brush.Color:=$FFFFFF; bmp.Canvas.Brush.Style:=TBrushStyle.bsSolid; bmp.Canvas.FillRect(Rect(0,0,bmp.Width,bmp.Height)); for i := 0 to ConnectionNum-1 do begin FromPoint.X:=Neurons[Connections[i].from_neuron].x; FromPoint.Y:=Neurons[Connections[i].from_neuron].y; ToPoint.X :=Neurons[Connections[i].to_neuron].x; ToPoint.Y :=Neurons[Connections[i].to_neuron].y; ConWeight :=trunc(Connections[i].weight); if ConWeight>0 then ConColor:=$000000 else ConColor:=$0000FF; ConWeight:=ABS(ConWeight); if ConWeight=0 then ConWeight:=1; bmp.Canvas.Pen.Color:=ConColor; bmp.Canvas.Pen.Width:=ConWeight; bmp.Canvas.MoveTo( FromPoint.X*span + span div 2, FromPoint.Y*span + span div 2); bmp.Canvas.LineTo( ToPoint.X *span + span div 2, ToPoint.Y *span + span div 2); end; for i := 0 to NeuronCount-1 do begin if Neurons[i].isBias then ConColor:=$0099FF else ConColor:=$FF0000; bmp.Canvas.Pen.Color:=ConColor; bmp.Canvas.Brush.Color:=ConColor; bmp.Canvas.Ellipse( Neurons[i].x*span + span div 2 - span div 8, Neurons[i].y*span + span div 2 - span div 8, Neurons[i].x*span + span div 2 + span div 8, Neurons[i].y*span + span div 2 + span div 8 ); end; end; destructor TMamFann.Destroy; begin fann_destroy(FFann); inherited; end; procedure TMamFann.GetBiasArray(pc: PCardinal); begin fann_get_bias_array(FFann,pc); end; procedure TMamFann.GetConnectionArray(pcns: PFann_Connection); begin fann_get_connection_array(FFann,pcns); end; procedure TMamFann.GetLayerArray(pc: PCardinal); begin fann_get_layer_array(FFann,pc); end; function TMamFann.GetMSE: Single; begin result:=fann_get_MSE(FFann); end; function TMamFann.GetNumLayers: Cardinal; begin result:=fann_get_num_layers(FFann); end; function TMamFann.GetTotalConnections: Cardinal; begin result:=fann_get_total_connections(FFann); end; function TMamFann.GetTrainingAlgorithm: Cardinal; begin result:=fann_get_training_algorithm(FFann); end; procedure TMamFann.LoadFromFile(Filename: string); begin if Assigned(FFann) then fann_destroy(FFann); FFann:=fann_create_from_file(PAnsiChar(AnsiString(Filename))); end; procedure TMamFann.ResetMse; begin fann_reset_mse(FFann); end; procedure TMamFann.Run( Inputs: array of TFann_type;var Outputs: array of TFann_type); var out_array: Pfann_type_array; i: Integer; begin out_array:=fann_run(FFann,@Inputs[0]); for i:=0 to High(outputs) do begin Outputs[i]:=out_array[i]; end; end; procedure TMamFann.SaveToFile(FileName: String); begin fann_save(FFann,PAnsiChar(AnsiString(Filename))); end; procedure TMamFann.SetActivationFunctionHidden( const Value: TFann_activationfunc_enum); begin FActivationFunctionHidden:=Value; fann_set_activation_function_hidden( FFann,Cardinal(ord(FActivationFunctionHidden))); end; procedure TMamFann.SetActivationFunctionOutput( const Value: TFann_activationfunc_enum); begin FActivationFunctionOutput := Value; fann_set_activation_function_output( FFann,Cardinal(ord(FActivationFunctionOutput))); end; procedure TMamFann.SetLearningMomentum(const Value: Single); begin FLearningMomentum:=Value; fann_set_learning_momentum(FFann,FLearningMomentum); end; procedure TMamFann.SetLearningRate(const Value: Single); begin FLearningRate:=Value; fann_set_learning_rate(FFann,FLearningRate); end; procedure TMamFann.SetTrainingAlgorithm(const Value: TFann_train_enum); begin FTrainingAlgorithm:=Value; fann_set_training_algorithm( FFann,Cardinal(ord(FTrainingAlgorithm)) ); end; procedure TMamFann.Train(Inputs,Outputs: array of TFann_type); begin fann_train(FFann, @Inputs[0], @Outputs[0]); end; procedure TMamFann.TrainOnFile(FileName: String; MaxEpochs: Cardinal; DesiredError: Single); begin fann_train_on_file( FFann,PAnsiChar(AnsiString(FileName)),MaxEpochs,1000,DesiredError); end; end.