Delphiでお手軽プログラミング

Delphiでお手軽プログラミングメニュー

DelphiでFANN(Fast Artificial Neural Network Library)を使って最高気温をAIに予測させる


FANNを使用する為のファイルの準備

https://mam-mam.net/delphi/fann.html からfannfloat.dll、fann.pas、MamFann.pasをダウンロードする。

トレーニングの為のCSVファイルをz気象庁のHPからダウンロードする

気象庁のHP(https://www.data.jma.go.jp/gmd/risk/obsdl/index.php)から 「大阪府大阪市」の「日別の日最高気温」の「2010/1/1~2019/12/31」のデータ仕様「年月日などに分けて格納」としてCSVファイルをダウンロードします。
ダウンロードしたdata.csvファイルを編集して項目を「年」「月」「日」「最高気温」のみに編集して保存します。

Delphiを起動して新規作成を行い、必要なコンポーネントをドラッグ&ドロップする

Delphi起動⇒ファイル⇒新規作成⇒WindowsVCLアプリケーション を選択します。
TButton 2個、 TImage 1個、 TChart 1個をフォームへドラッグ&ドロップします。

Image1のプロパティ[Proportional]をTrueに、プロパティ[Stretch]をTrueにします。
Chart1をダブルクリックして、「Editing Chart1」ウィンドウを表示させます。「Add...」ボタンをクリックします。

左上の「Line」を選択して「OK」ボタンを押します。


「すべて保存ボタン」を押して、プロジェクトとユニットを保存します。
プロジェクトフォルダ内にダウンロードしたfann.pas、MamFann.pasファイルを配置します。
fannfloat.dllファイル(32Bit版)をパスの通ったフォルダ(c:\Windows等)に入れます。
data.csvをプロジェクトフォルダ内に入れます。

ソースコードを記述する

Form1のOnDestroyイベント、、 Button1のOnClickイベント、Button2のOnClickイベント、等に以下ソースコードを記述します。
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.ExtCtrls, Vcl.StdCtrls,
  VCLTee.TeEngine, VCLTee.TeeProcs, VCLTee.Chart, VclTee.TeeGDIPlus,
  VCLTee.Series,
  System.DateUtils,fann, MamFann;

type
  TForm1 = class(TForm)
    Chart1: TChart;
    Button1: TButton;
    Button2: TButton;
    Image1: TImage;
    Series1: TLineSeries;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(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;
    stl,stll:TStringList;
    i:integer;
    inputs : array [0..2] of TFann_type;//入力層(年,月,日)
    outputs: array [0..0] of TFann_type;//出力層(最高気温)

    epoch:integer;//トレーニングの反復
begin
  if Assigned(MamFann) then FreeAndNil(MamFann);
  
  setlength(NeuronNumInLayer,3);//レイヤー(層)の数
  NeuronNumInLayer[0]:=3;       //入力層のニューロン数(年,月,日)
  NeuronNumInLayer[1]:=3;       //中間層のニューロン数
  NeuronNumInLayer[2]:=1;       //出力層のニューロン数(最高気温)
  //TMamFannクラスのインスタンス化
  MamFann:=TMamFann.Create(NeuronNumInLayer);

  //CSVファイル(年,月,日,最高気温)の読み込み
  stl:=TStringList.Create;
  stl.LoadFromFile('..\..\data.csv');
  stll:=TStringList.Create;
  stll.QuoteChar:='"';
  stll.Delimiter:=',';
  stll.StrictDelimiter:=True;

  //FANNのトレーニングを開始(100反復)
  for epoch := 1 to 100 do
    for i := 1 to stl.Count-1 do
    begin
      stll.DelimitedText:=stl[i];
      //年を正規化 0(2000年)~1(2100年)
      inputs[0]:=(StrToFloat(stll[0])-2000)/100;
      //月を正規化 0(1月)~1(12月)
      inputs[1]:=(StrToFloat(stll[1])-1)/11;
      //日を正規化 0(1日)~1(31日)
      inputs[2]:=(StrToFloat(stll[2])-1)/30;
      //最高気温を正規化 0(-20℃)~1(+50℃)
      outputs[0]:=(StrToFloat(stll[3])+20)/70;
      MamFann.Train(inputs,outputs);
    end;
  stll.Free;
  stl.Free;

  //ニューロンネットワーク図の描画
  MamFann.CreateNeuronBmp(Image1.Picture.Bitmap);
end;

procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
    dt:TDate;
    inputs : array [0..2] of TFann_type;//入力層(年,月,日)
    outputs: array [0..0] of TFann_type;//出力層(最高気温)
begin
  if not Assigned(MamFann) then exit;

  dt:=Date();

  Series1.XValues.DateTime:=True;
  Chart1.BottomAxis.DateTimeFormat:='yyyy/mm/dd';
  Chart1.Legend.Visible:=False;
  Chart1.Title.Text.Text:=
    FormatDateTime('yyyy/mm/dd',dt)+'~1年間の最高気温予想';

  //システム日付から365日間の最高気温を予想させてグラフ表示を行う
  for i := 0 to 365 do
  begin
    inputs[0]:=(YearOf(dt)-2000)/100;
    inputs[1]:=(MonthOf(dt)-1)/11;
    inputs[2]:=(DayOf(dt)-1)/30;
    MamFann.Run(inputs,outputs);
    Series1.AddXY(dt,outputs[0]*70-20);
    dt:=dt+1;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(MamFann) then
    FreeAndNil(MamFann);
end;

end.

実行する

実行ボタンを押して実行します。(デバッグ実行でもOK)

Button1をクリックすると、トレーニングが開始され、ニューロンネットワーク図が描画されます。
Button2をクリックすると、今から1年間の最高気温予測がグラフ表示されます。



Copyright 2020 Mam