【MQL5】ArrayToFP8関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク

ArrayToFP8関数の働き・役割

ArrayToFP8関数は、float型またはdouble型配列をFP8(8ビット浮動小数点)形式の配列に変換してコピーするために使用されます。この関数は、指定されたフォーマットに従い、元の数値配列(floatまたはdouble)をuchar型配列に変換して格納します。FP8形式は、メモリ効率と計算速度が重要な場面で用いられるデータ形式であり、特にONNXモデルでの操作時に使用されます。

FP8形式では、8ビットの中で符号、指数、仮数に数値を分割するため、精度とメモリ使用量のバランスが取れた形式を提供します。このため、大量のデータを処理する際にメモリを節約しつつ、高速な演算を行うことが可能です。

ArrayToFP8関数の引数について

ArrayToFP8関数は、float型配列double型配列の両方に対応するために、2つのオーバーロードが用意されています。オーバーロードとは、同じ関数名でありながら異なるデータ型を扱えるようにした関数です。ArrayToFP8関数では、float型とdouble型配列をFP8形式に変換する際に、それぞれのオーバーロードが使用されます。

float型配列を扱う場合の書式

bool ArrayToFP8(
  const uchar& dst_array[],      // 変換結果を格納する配列
  const float& src_array[],      // 変換元のfloat型配列
  ENUM_FLOAT8_FORMAT fmt         // FP8のフォーマット
);

引数の説明

第1引数: dst_array[]
この配列は、変換後のデータが格納される場所です。float型配列がFP8形式に変換され、uchar型配列として保存されます。

第2引数: src_array[]
変換元となるfloat型の配列を指定します。この配列に含まれる数値がFP8形式に変換されます。

第3引数: fmt
ENUM_FLOAT8_FORMAT列挙型を使用して、どのFP8形式で変換するかを指定します。


double型配列を扱う場合の書式

bool ArrayToFP8(
  const uchar& dst_array[],      // 変換結果を格納する配列
  const double& src_array[],     // 変換元のdouble型配列
  ENUM_FLOAT8_FORMAT fmt         // FP8のフォーマット
);

引数の説明

第1引数: dst_array[]
変換後のデータが格納されるuchar型配列です。double型配列をFP8形式に変換し、その結果をこの配列にコピーします。

第2引数: src_array[]
変換元となるdouble型配列です。この配列の数値がFP8形式に変換されます。

第3引数: fmt
変換に使用するFP8形式を指定します。ENUM_FLOAT8_FORMAT列挙型から適切な形式を選びます。

ENUM_FLOAT8_FORMATについて

ENUM_FLOAT8_FORMAT列挙型は、MQL5でfloat型やdouble型の数値を8ビット浮動小数点形式(FP8)に変換する際に使用するフォーマットを定義しています。FP8は、符号、指数、仮数の3つの要素で数値を表現し、メモリ効率と計算速度を高める目的で使用されるデータ形式です。この形式は、特に機械学習や人工知能(AI)といった大規模なデータセットを扱う場面で有効です。

FP8の形式には4種類のフォーマットがあり、それぞれ異なる用途に合わせて使い分けられます。

FLOAT_FP8_E4M3FN

FLOAT_FP8_E4M3FNは、8ビットの中で4ビットが指数部、3ビットが仮数部に割り当てられた浮動小数点形式です。符号ビットは1ビットです。この形式は、通常、係数として使用されるデータに適しています。

FLOAT_FP8_E4M3FNUZ

FLOAT_FP8_E4M3FNUZも同様に指数部が4ビット、仮数部が3ビットに割り当てられますが、FLOAT_FP8_E4M3FNとの違いはNaN(Not a Number)をサポートする点にあります。ただし、負のゼロや無限大(Inf)はサポートしません。こちらも係数として使用されることが多いフォーマットです。

  • 指数部: 4ビット
  • 仮数部: 3ビット
  • サポート: NaNサポート、負のゼロおよびInfはサポートされない
  • 用途: 係数としての使用

FLOAT_FP8_E5M2FN

FLOAT_FP8_E5M2FNは、指数部が5ビット、仮数部が2ビットに割り当てられた形式です。このフォーマットはNaNおよび無限大(Inf)をサポートしており、主に勾配(gradient)の計算に使用されます。指数部が5ビットであるため、より広い範囲の数値を表現できるのが特徴です。

  • 指数部: 5ビット
  • 仮数部: 2ビット
  • サポート: NaNおよびInfサポート
  • 用途: 勾配の計算に使用

FLOAT_FP8_E5M2FNUZ

FLOAT_FP8_E5M2FNUZは、指数部が5ビット、仮数部が2ビットに割り当てられる形式で、NaNをサポートしますが、負のゼロや無限大(Inf)はサポートされません。このフォーマットも主に勾配の計算に使用されます。

  • 指数部: 5ビット
  • 仮数部: 2ビット
  • サポート: NaNサポート、負のゼロおよびInfはサポートされない
  • 用途: 勾配の計算に使用

これらのFP8形式は、特に機械学習のモデル処理において使用されることが多く、データを圧縮しつつも十分な計算精度を維持するために活用されています。FP8のコンパクトな表現は、大規模なデータセットを効率的に処理できるため、メモリ節約と計算効率の向上が期待されます。

ArrayToFP8関数の戻り値について

ArrayToFP8関数戻り値は、変換が成功したかどうかを示すブール型です。具体的には、以下のような動作を行います。

  • true
    変換が正常に終了し、float型またはdouble型配列が指定されたFP8形式に正しく変換され、dst_arrayにコピーされた場合に返されます。
  • false
    変換中にエラーが発生した場合や、指定したENUM_FLOAT8_FORMAT形式に対応した変換が行われなかった場合に返されます。この場合、エラーコードを取得するためには、GetLastError関数を使用することが推奨されます。

この戻り値を使用することで、変換処理が正しく行われたかどうかを確認し、エラー処理を行うことができます。

ArrayToFP8関数を使う際の注意点

  1. 配列サイズの整合性
    変換元の配列(float型またはdouble型の配列)と変換先の配列uchar型配列)のサイズが正しく設定されていることを確認する必要があります。サイズが一致していないと、正しく変換が行われず、エラーが発生する可能性があります。
  2. ENUM_FLOAT8_FORMATの選択
    選択するENUM_FLOAT8_FORMATによって、変換の精度や対応する数値範囲が異なります。用途に応じて適切なフォーマットを選ぶ必要があります。たとえば、FP8形式の中にはNaNやInfをサポートしないものもあるため、計算精度が重要な場合は特定のフォーマットを避けるべきです。
  3. エラーハンドリングの実装
    ArrayToFP8関数は、変換が失敗した場合にfalseを返します。エラーが発生した際は、GetLastError関数を用いて詳細なエラー情報を取得し、適切なエラーハンドリングを実装することが求められます。
  4. ONNXモデルとの連携
    ArrayToFP8関数は、主にONNXモデルでの操作に使用されるため、この関数で生成したFP8データを正しくONNXモデルに渡す準備が整っていることを確認する必要があります。ONNXモデルを使用しない場合、この関数を使用する場面は少ないかもしれません。
  5. データの精度に関する注意
    FP8形式は、メモリ効率のために精度が低くなる場合があります。特にFP8_E4M3FNなど、仮数部が少ない形式を使用する場合は、数値の精度が低下し、結果に影響を与える可能性があります。そのため、精度が求められる場面ではFP8形式の使用に十分注意が必要です。

ArrayToFP8関数を使った公式リファレンスのサンプルコード

//+------------------------------------------------------------------+
//| RunCastFloat8Float                                               |
//| この関数は、指定されたFP8形式に基づいて、float型配列をFP8形式に変換し、   |
//| さらにONNXモデルを使用して、FP8形式のデータをfloat型に戻す処理を行います。 |
//+------------------------------------------------------------------+
bool RunCastFloat8ToFloat(long model_handle,const ENUM_FLOAT8_FORMAT fmt)
 {
  // 関数のテスト開始のメッセージをエキスパートログに出力します。
  PrintFormat("TEST: %s(%s)",__FUNCTION__,EnumToString(fmt));

  //--- 変換対象となるfloat型のテストデータを15個用意します。
  float test_data[15]   = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

  //--- 変換後のFP8形式のデータを格納するuchar型の配列を用意します。
  uchar data_float8[15] = {};

  //--- float型データをFP8形式に変換し、結果をdata_float8に格納します。
  if(!ArrayToFP8(data_float8,test_data,fmt))
    {
    // エラー発生時の処理。エラー内容とエラーコードをエキスパートログに出力し、
    // モデルを解放して関数を終了します。
    Print("error in ArrayToFP8. error code=",GetLastError());
    OnnxRelease(model_handle);
    return(false);  // エラー発生のためfalseを返します。
    }

  //--- FP8形式のデータを入力として扱う配列を用意します。
  U<uchar> input_float8_values[3*5];

  //--- モデル実行後に取得するfloat型の出力値を格納する配列を用意します。
  U<float> output_float_values[3*5];

  //--- float型に戻す際の一時変数を用意します。
  float   test_data_float[];

  //--- FP8形式からfloat型にデータを変換します。
  if(!ArrayFromFP8(test_data_float,data_float8,fmt))
    {
    // エラー発生時の処理。エラー内容とエラーコードをエキスパートログに出力し、
    // モデルを解放して関数を終了します。
    Print("error in ArrayFromFP8. error code=",GetLastError());
    OnnxRelease(model_handle);
    return(false);  // エラー発生のためfalseを返します。
    }

  //--- 変換されたデータをエキスパートログに出力します。
  for(uint i=0; i<data_float8.Size(); i++)
    {
    // FP8形式の各データを16進数の文字列として出力し、値と比較します。
    input_float8_values[i].value = data_float8[i];
    PrintFormat("%d input value =%f  Hex float8 = %s  ushort value=%d", 
                i, test_data_float[i], 
                ArrayToHexString(input_float8_values[i].uc), 
                input_float8_values[i].value);
    }

  //--- ONNXモデルに渡す入力データとしてFP8データをエキスパートログに出力します。
  Print("ONNX input array: ",ArrayToString(input_float8_values));

  //--- ONNXモデルを実行し、FP8形式のデータをfloat型に変換します。
  if(!OnnxRun(model_handle,ONNX_NO_CONVERSION, input_float8_values, output_float_values))
    {
    // エラー発生時の処理。エラー内容とエラーコードをエキスパートログに出力し、
    // モデルを解放して関数を終了します。
    PrintFormat("error in OnnxRun. error code=%d",GetLastError());
    OnnxRelease(model_handle);
    return(false);  // エラー発生のためfalseを返します。
    }

  //--- ONNXモデルの出力データをエキスパートログに出力します。
  Print("ONNX output array: ",ArrayToString(output_float_values));

  //--- ONNXモデルの出力結果とFP8から変換した結果を比較し、誤差を計算します。
  double sum_error = 0.0;
  for(uint i=0; i<test_data.Size(); i++)
    {
    //--- 各データの差分(誤差)を計算し、合計誤差に加算します。
    double delta = test_data_float[i] - (double)output_float_values[i].value;
    sum_error += MathAbs(delta);
    //--- 各出力値の詳細と差分をエキスパートログに出力します。
    PrintFormat("%d output float %f = %s difference=%f", 
                i, output_float_values[i].value, 
                ArrayToHexString(output_float_values[i].uc), delta);
    }

  //--- 最終的な合計誤差をエキスパートログに出力します。
  PrintFormat("%s(%s): sum_error=%f\n", __FUNCTION__, EnumToString(fmt), sum_error);
  
  //--- 正常終了の場合はtrueを返します。
  return(true);
 }

コンパイルエラーに関する注意

上記のサンプルコードは、ONNXモデルを使用してfloat型配列をFP8形式に変換し、再度float型に戻して誤差を確認する内容となっています。

しかし、このコードには、MQL5標準のライブラリに存在しないデータ型関数が使用されています。具体的には、U<uchar>U<float>という未定義の型、およびArrayToString関数やArrayToHexString関数が含まれており、これらはそのままではコンパイルエラーを引き起こします。

Uの文法的役割は、何らかのユーザー定義型またはテンプレートとして使用されることが意図されていた可能性があります。例えば、FP8形式のデータをuchar型やfloat型で管理したり、それらを操作するためのカスタムクラスであることが考えられますが、このコード内では明示的な定義がないため、エラーが発生します。

また、ArrayToStringおよびArrayToHexString関数も標準ライブラリには含まれていないため、これらの関数は別途実装が必要です。

したがって、これらの未定義な型や関数を適切に修正、または定義する必要があることを念頭に置いてください。

サンプルコード解説1

//+------------------------------------------------------------------+
//| RunCastFloat8Float                                               |
//| この関数は、指定されたFP8形式に基づいて、float型配列をFP8形式に変換し、   |
//| さらにONNXモデルを使用して、FP8形式のデータをfloat型に戻す処理を行います。 |
//+------------------------------------------------------------------+
bool RunCastFloat8ToFloat(long model_handle,const ENUM_FLOAT8_FORMAT fmt)
 {
  // 関数のテスト開始のメッセージをエキスパートログに出力します。
  PrintFormat("TEST: %s(%s)",__FUNCTION__,EnumToString(fmt));

  //--- 変換対象となるfloat型のテストデータを15個用意します。
  float test_data[15]   = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

  //--- 変換後のFP8形式のデータを格納するuchar型の配列を用意します。
  uchar data_float8[15] = {};

このセクションでは、サンプルコードの冒頭部分を解説します。このコードは、float型のデータをFP8形式に変換し、ONNXモデルを使用してfloat型に再変換する処理の一部です。

関数の目的

RunCastFloat8ToFloat関数は、指定されたFP8形式に基づいて、float型の配列をFP8形式に変換し、さらにONNXモデルを使ってそのデータを再びfloat型に変換する処理を行います。この関数は、FP8形式でのデータ操作がONNXモデルで正しく行われているかを確認するために使用されます。

PrintFormat関数の役割

この部分では、PrintFormat関数を使用して、エキスパートログにテスト開始のメッセージを出力しています。__FUNCTION__は現在実行中の関数名を示し、EnumToString関数を使ってENUM_FLOAT8_FORMATの値を文字列に変換してログに表示します。これにより、関数がどのFP8形式を使って実行されているかを確認できます。

float型配列の準備

この部分では、テストデータとして15個のfloat型の数値が格納された配列test_dataが定義されています。この配列は、FP8形式に変換するための元データとして使用されます。このように、あらかじめデータが用意されていることで、後の処理で変換対象となるデータが明確になります。

uchar型配列の準備

ここでは、FP8形式に変換された結果を受け取るためのuchar型配列のdata_float8が定義されています。この配列のサイズは、変換前のfloat型配列と同じ15要素です。uchar型は、8ビット単位のデータを格納する型で、FP8形式に変換されたデータを効率よく保存するために使用されます。

この時点で、test_data配列のfloat型の数値が後にFP8形式に変換され、その結果がdata_float8に格納される準備が整っています。

サンプルコード解説2

  //--- float型データをFP8形式に変換し、結果をdata_float8に格納します。
  if(!ArrayToFP8(data_float8,test_data,fmt))
    {
    // エラー発生時の処理。エラー内容とエラーコードをエキスパートログに出力し、
    // モデルを解放して関数を終了します。
    Print("error in ArrayToFP8. error code=",GetLastError());
    OnnxRelease(model_handle);
    return(false);  // エラー発生のためfalseを返します。
    }

このセクションでは、float型データをFP8形式に変換する部分と、エラーハンドリングの処理について解説します。

FP8形式への変換処理

ここでは、float型の配列をFP8形式に変換しています。ArrayToFP8関数は、float型またはdouble型配列をFP8形式のuchar型配列に変換し、その結果を指定された配列に格納します。この場合、test_dataに格納されたfloat型の数値をFP8形式に変換し、その結果をdata_float8配列に格納しています。

ArrayToFP8関数が正常に実行されると、変換されたFP8形式のデータがdata_float8配列に格納されます。

エラーハンドリング

ArrayToFP8関数がfalseを返した場合、何らかの理由で変換が失敗したことを示します。以下のように、変換が失敗した際には、GetLastError関数を使ってエラーコードを取得し、エキスパートログにエラー内容を出力します。

エラーが発生すると、まずログにエラー内容とエラーコードを出力し、次にOnnxRelease関数を使ってモデルを解放します。最後に、falseを返して関数を終了します。このように、エラーが発生した場合の処理を明確に定義することで、予期しない動作を防ぎ、プログラムの信頼性を高めることができます。

この部分では、float型データのFP8形式への変換が正しく行われなかった場合に備えて、エラーハンドリングが実装されています。

サンプルコード解説3

  //--- FP8形式のデータを入力として扱う配列を用意します。
  U<uchar> input_float8_values[3*5];

  //--- モデル実行後に取得するfloat型の出力値を格納する配列を用意します。
  U<float> output_float_values[3*5];

  //--- float型に戻す際の一時変数を用意します。
  float   test_data_float[];

このセクションでは、FP8形式のデータを処理するための配列と、モデル実行後に取得するfloat型のデータを格納する配列の準備について解説します。

FP8形式のデータを入力として扱う配列の準備

まず、FP8形式のデータを保持するためにU型の配列input_float8_valuesが用意されています。

ここで注意が必要なのは、Uという型はMQL5標準には存在しないため、このコードはそのままではコンパイルエラーを引き起こします。Uが何らかのユーザー定義型やテンプレートとして使用されることを意図している可能性があります。したがって、この部分を使用するには、Uの定義を追加するか、別の型に変更する必要があります。

FP8形式のデータは8ビット(1バイト)で表されるため、uchar型(符号なしの1バイト整数型)が使われています。この配列は、FP8形式に変換されたデータをONNXモデルに入力として渡すために使用されます。

モデル実行後のfloat型データを格納する配列の準備

次に、ONNXモデルの実行結果として得られるfloat型のデータを格納するためにU型の配列output_float_valuesが用意されています。
UはMQL5標準の型ではないため、この部分もコンパイルエラーを引き起こします。適切な定義を追加するか、標準のデータ型を使うように修正する必要があります。

この配列には、ONNXモデルを実行した結果として得られるfloat型の数値データが格納されます。

一時変数の準備

最後に、float型データをFP8形式から再びfloat型に戻す際に、一時的に使用する変数としてtest_data_floatが宣言されています。この変数に変換されたfloat型のデータが格納され、その後の処理で使用されます。ONNXモデルの実行結果と比較するために、ここで一時的なfloat型配列を使用してデータを保持します。

サンプルコード解説4

  //--- FP8形式からfloat型にデータを変換します。
  if(!ArrayFromFP8(test_data_float,data_float8,fmt))
    {
    // エラー発生時の処理。エラー内容とエラーコードをエキスパートログに出力し、
    // モデルを解放して関数を終了します。
    Print("error in ArrayFromFP8. error code=",GetLastError());
    OnnxRelease(model_handle);
    return(false);  // エラー発生のためfalseを返します。
    }

このセクションでは、FP8形式のデータを再度float型に変換する部分と、その際のエラーハンドリングについて解説します。

FP8形式からfloat型への変換処理

この部分では、FP8形式に変換されたデータを再度float型に戻す処理が行われています。ArrayFromFP8関数を使用して、data_float8に格納されているFP8形式のデータをtest_data_floatというfloat型の配列に変換しています。

ArrayFromFP8関数は、FP8形式のデータを指定されたフォーマット(fmt)に従ってfloat型に変換し、結果をtest_data_floatに格納します。これにより、変換されたデータを再度float型として利用できるようになります。

エラーハンドリング

ArrayFromFP8関数がfalseを返した場合、FP8形式からfloat型への変換が失敗したことを示します。この場合、エラー処理が行われ、以下の手順でエラーハンドリングが実施されます。

  1. GetLastError関数を使用して、エラーコードを取得します。
  2. エキスパートログにエラー内容とエラーコードを出力します。これにより、何が原因でエラーが発生したのかを確認できるようにしています。
  3. OnnxRelease関数を呼び出して、モデルを解放します。これにより、リソースを適切に管理し、無駄なメモリ使用を防ぎます。
  4. 最終的にfalseを返し、関数を終了します。これにより、エラーが発生した場合は適切に処理が中断されます。

このエラーハンドリングによって、変換処理が正しく行われなかった際の対策が講じられており、プログラムが予期しない動作を引き起こすのを防ぐことができます。

サンプルコード解説5

  //--- 変換されたデータをエキスパートログに出力します。
  for(uint i=0; i<data_float8.Size(); i++)
    {
    // FP8形式の各データを16進数の文字列として出力し、値と比較します。
    input_float8_values[i].value = data_float8[i];
    PrintFormat("%d input value =%f  Hex float8 = %s  ushort value=%d", 
                i, test_data_float[i], 
                ArrayToHexString(input_float8_values[i].uc), 
                input_float8_values[i].value);
    }

  //--- ONNXモデルに渡す入力データとしてFP8データをエキスパートログに出力します。
  Print("ONNX input array: ",ArrayToString(input_float8_values));

このセクションでは、FP8形式に変換されたデータをログに出力し、ONNXモデルに渡すデータの確認を行う部分について解説します。

変換されたデータのログ出力

FP8形式に変換されたデータを確認するために、エキスパートログに出力する処理が行われています。ここでは、forループを使って、FP8形式に変換された各データを16進数表記で出力しています。

まず、data_float8配列に格納されたFP8形式のデータが、input_float8_valuesにコピーされ、その後ログに出力されます。ArrayToHexString関数を使って、FP8形式のデータを16進数文字列として出力していますが、この関数MQL5標準の関数ではないため、別途実装する必要があります。

ログ出力される情報は以下の通りです:

  • 変換後のfloat型のデータ
  • そのデータのFP8形式での16進数表現
  • ushort(符号なしの整数)としてのFP8値

これにより、変換されたFP8データと、その対応するfloat型データを比較し、どのように変換が行われたかを詳細に確認できます。

ONNXモデルに渡すデータのログ出力

FP8形式のデータをONNXモデルに渡す際、そのデータの内容をエキスパートログに出力して確認します。Print関数を使用して、input_float8_values配列全体をログに出力しています。

ArrayToString関数が使われていますが、この関数MQL5標準の関数ではないため、実装する必要があります。この出力により、ONNXモデルに渡す前に、入力データが正しく準備されているかを確認することができます。

サンプルコード解説6

  //--- ONNXモデルを実行し、FP8形式のデータをfloat型に変換します。
  if(!OnnxRun(model_handle,ONNX_NO_CONVERSION, input_float8_values, output_float_values))
    {
    // エラー発生時の処理。エラー内容とエラーコードをエキスパートログに出力し、
    // モデルを解放して関数を終了します。
    PrintFormat("error in OnnxRun. error code=%d",GetLastError());
    OnnxRelease(model_handle);
    return(false);  // エラー発生のためfalseを返します。
    }

  //--- ONNXモデルの出力データをエキスパートログに出力します。
  Print("ONNX output array: ",ArrayToString(output_float_values));

このセクションでは、ONNXモデルを実行してFP8形式のデータをfloat型に変換する部分と、その結果をログに出力する処理について解説します。

ONNXモデルの実行

まず、OnnxRun関数を使用して、ONNXモデルを実行しています。この処理では、input_float8_valuesに格納されたFP8形式のデータをモデルに渡し、出力としてoutput_float_valuesにfloat型のデータを格納します。OnnxRun関数は、指定されたモデルハンドルを用いてモデルを実行し、FP8形式からfloat型への変換を行います。

ONNX_NO_CONVERSIONというフラグを使用して、入力データの形式変換を行わないよう指定しています。これにより、FP8形式のデータがそのままONNXモデルに渡され、float型に変換されることが想定されています。

エラーハンドリング

もしOnnxRun関数がfalseを返した場合、モデルの実行が失敗したことを意味します。この場合、以下のようにエラーハンドリングが行われます。

  1. GetLastError関数を使用してエラーコードを取得し、エキスパートログにエラー内容を出力します。
  2. OnnxRelease関数を呼び出して、モデルを解放します。これにより、モデル実行後にメモリやリソースが適切に管理されます。
  3. 最終的にfalseを返して関数を終了し、モデル実行が失敗したことを呼び出し元に伝えます。

ONNXモデルの出力データのログ出力

ONNXモデルの実行が成功すると、output_float_valuesにモデルの出力結果としてfloat型のデータが格納されます。これらのデータをエキスパートログに出力するために、Print関数を使用しています。

この部分では、ArrayToString関数を使用してoutput_float_values配列全体を文字列としてログに出力しますが、この関数MQL5標準の関数ではないため、別途実装が必要です。ログ出力によって、ONNXモデルが正しく実行され、期待通りのfloat型データが出力されているかを確認できます。

このセクションでは、ONNXモデルの実行結果を確認し、正しくfloat型に変換されたデータをログに出力することで、モデルの実行が成功したかどうかをチェックしています。

サンプルコード解説7

  double sum_error = 0.0;
  for(uint i=0; i<test_data.Size(); i++)
    {
    //--- 各データの差分(誤差)を計算し、合計誤差に加算します。
    double delta = test_data_float[i] - (double)output_float_values[i].value;
    sum_error += MathAbs(delta);
    //--- 各出力値の詳細と差分をエキスパートログに出力します。
    PrintFormat("%d output float %f = %s difference=%f", 
                i, output_float_values[i].value, 
                ArrayToHexString(output_float_values[i].uc), delta);
    }

このセクションでは、ONNXモデルの実行結果で得られたfloat型のデータと、元のデータ(test_data_float)の差分(誤差)を計算し、その結果をエキスパートログに出力する部分について解説します。

誤差の計算

まず、sum_errorという変数を使って、全体の誤差の合計を管理しています。この変数初期値として0.0に設定され、各データごとの誤差が加算されます。

forループを使って、test_data_float配列とoutput_float_values配列の各要素を比較しています。各データの差分、すなわち誤差は、output_float_valuesの値からtest_data_floatの値を引くことで計算され、その結果がdeltaという変数に格納されます。

誤差の絶対値をMathAbs関数を使って計算し、それをsum_errorに加算することで、全体の誤差の合計を求めています。このように、各データ間の誤差を積み上げることで、モデルがどれだけ正確にデータを再現したかを把握します。

各データの出力と差分のログ出力

各データの差分(誤差)が計算された後、PrintFormat関数を使って詳細をエキスパートログに出力しています。ログには、以下の情報が出力されます:

  • 現在処理しているデータのインデックス
  • output_float_values配列に格納されたfloat型データの値
  • そのデータのFP8形式における16進数表現
  • test_data_floatとoutput_float_valuesの差分(誤差)

ここで、ArrayToHexString関数を使ってoutput_float_valuesのFP8形式を16進数表記で出力していますが、この関数MQL5標準には含まれていないため、別途実装が必要です。

この処理により、各データごとの誤差を詳細に確認でき、ONNXモデルがどの程度正確にデータを処理しているかを把握することが可能になります。

サンプルコード解説8

 //--- 最終的な合計誤差をエキスパートログに出力します。
  PrintFormat("%s(%s): sum_error=%f\n", __FUNCTION__, EnumToString(fmt), sum_error);
  
  //--- 正常終了の場合はtrueを返します。
  return(true);
 }

このセクションでは、ONNXモデルの実行結果で計算された合計誤差をログに出力し、関数が正常に終了する処理について解説します。

合計誤差のログ出力

誤差の合計値(sum_error)は、各データ間の誤差を累積した結果です。この合計誤差をエキスパートログに出力することで、モデル全体の精度を確認します。

PrintFormat関数を使用して、関数名、FP8のフォーマット(fmt)、および合計誤差(sum_error)をログに出力しています。これにより、どのフォーマットで実行されたか、そして全体の誤差がどの程度であったかを確認できます。特に、複数のフォーマットで処理を試す場合、このログが重要になります。
EnumToString関数は、enum列挙型文字列に変換するために使用されます。fmtというENUM_FLOAT8_FORMAT列挙型の値を文字列に変換し、どのFP8形式で処理が行われたかをログに記録します。

正常終了時の処理

最後に、関数が正常に終了したことを示すためにtrueを返しています。このreturn文により、呼び出し元の処理が関数の結果に基づいて次の処理を行うことが可能になります。

この部分では、エラーが発生しなかった場合の最終的な処理が完了し、モデルの実行結果が正しく取得されたことを確認するための終着点となっています。ログ出力によって合計誤差が記録され、呼び出し元へ成功の結果を返す重要な部分です。

タイトルとURLをコピーしました