English Русский 中文 Español Deutsch Português
preview
取引におけるニューラルネットワーク:適応的なエージェント行動のための階層的スキル発見(HiSSD)

取引におけるニューラルネットワーク:適応的なエージェント行動のための階層的スキル発見(HiSSD)

MetaTrader 5トレーディングシステム |
15 1
Dmitriy Gizlyk
Dmitriy Gizlyk

はじめに

近年、協調型マルチエージェント強化学習(MARL, Multi-Agent Reinforcement Learning)への関心が急速に高まっています。この概念は、ゲーム、自動運転、物流、社会動態、そして特に金融市場など、幅広い分野で応用されています。複数の戦略やエージェントが協調して行動することが求められる場面では、従来の手法では十分に対応できないことが少なくありません。そのような状況において、MARLは優れた性能を示しています。

しかしながら、依然としていくつかの課題が残されています。高精度なシミュレータの構築や、環境との継続的なオンライン相互作用には多大な計算資源が必要です。また、実環境では、参加エージェント数の変化、目的の変更、環境パラメータの変動など、状況が絶えず変化します。そのため、追加コストをできる限り抑えながら、異なるタスク間で知識を効率よく転移し、新しい環境へ適応できる学習システムへの関心が高まっています。

従来は、あるタスクでエージェントを学習させ、その後、別のタスク向けにファインチューニングを行う方法が一般的でした。しかし、この手法にはいくつかの問題があります。第一に、新しい環境との相互作用を再度行う必要があり、そのためのコストが大きくなります。第二に、固定されたエージェント数を前提として学習したモデルは拡張性に乏しく、エージェント構成やタスク条件が変化すると性能が低下してしまいます。

こうした課題に対処するため、近年ではTransformerベースのアーキテクチャが広く採用されるようになりました。Transformerは高い柔軟性を備えており、モデルを固定されたエージェント数に依存させることなく、新しい環境へ適応させることができます。これにより、異なるタスク間で再利用可能な、汎用的な協調行動パターン(スキル)を学習するという考え方を発展させる基盤が築かれました。

このようなスキルを実現するため、これまでにもさまざまな手法が提案されています。たとえば、まず汎用的な協調パターンを抽出し、その後に方策を学習する二段階学習を採用する手法や、オフライン学習とオンライン学習を組み合わせることで、新しい環境への適応を高速化する手法などがあります。

これらの手法は、関連タスクへのモデル転移コストを大幅に削減するという点で大きな成果を挙げています。しかし、その一方で限界もあります。汎用スキルは多くの場面で有効ですが、特定のタスクで求められる固有の特性を十分に反映できないことがあります。実際には、そのような細かな違いこそが成功を左右することも少なくありません。また、多くの既存手法では、エージェント間の相互作用が持つ時間的構造が十分に考慮されていません。協調行動は瞬間的に成立するものではなく、時間をかけて形成されます。そのため、行動の順序や協調の一貫性は極めて重要な要素となります。

これらの課題を解決するために、論文Learning Generalizable Skills from Offline Multi-Task Data for Multi-Agent Cooperationでは、HiSSD(Hierarchical and Separable Skill Discovery)フレームワークが提案されています。HiSSDは、汎用スキルとタスク固有スキルを恣意的に切り分けたり厳格な制約を設けたりすることなく、両者を同時に学習できる新しいアーキテクチャです。階層構造の中で、2種類の知識は並行して学習・発展します。

汎用スキルは、協調行動に共通する汎用的なパターンを学習します。これにより、未知の環境においてもエージェントは協調的に行動できるようになります。これらのスキルは、多様な状況に適用可能な基本的な行動様式として機能します。一方、タスク固有スキルは、それぞれのタスクに特化した知識を学習します。目的や環境条件に応じて行動を細かく調整し、個々のタスクに最適化された振る舞いを実現します。

HiSSDの中核となる考え方は、これら2種類のスキルを階層的かつ同時に学習することです。このアプローチにより、エージェント間相互作用の時間的側面と、各タスク固有の文脈の両方を深く理解できるようになります。その結果、エージェントの行動品質が向上するだけでなく、学習済み戦略を新しい環境へ高い信頼性で転移できるようになります。

フレームワークの著者らは、代表的なベンチマークであるSMACおよびMuJoCoを用いて評価実験をおこないました。その結果、HiSSDによって学習したエージェントは、未知のタスクに対しても高い協調性能を示しました。また、その戦略は柔軟性、精度、および頑健性のいずれの点においても優れた性能を発揮することが確認されています。


HiSSDアルゴリズム

HiSSD (Hierarchical and Separable Skill Discovery)アルゴリズムは、マルチエージェント環境におけるエージェントの学習を目的とした革新的な手法であり、分散型設定において頑健な行動を維持しながら、異なるタスク間でスキルを転移できるよう設計されています。このアルゴリズムの中核となる考え方は、各エージェントの行動を階層的に2つの主要な要素へ分解することにあります。1つは、エージェント間およびタスク間で共有される共通スキル、もう1つは、特定の役割や目的に応じて行動を適応させるタスク固有スキルです。

HiSSDと既存手法との大きな違いの1つは、モデルを構成するすべてのコンポーネントを同時に学習できる点です。従来のような段階的あるいは逐次的な学習ではなく、プランナー(Planner)、コントローラ(Controller)、各種エンコーダ、および状態価値モデルを含むすべてのモジュールを一括して最適化します。この同期的な学習プロセスにより、階層間の不整合が低減され、より一貫性があり効果的なエージェント行動を獲得できます。

学習には、オフラインデータセットDT = {Di}を使用します。ここで、各Diは個別のタスクに対応しています。各時刻において、エージェントkは観測値ot,kを受け取ります。この観測に基づいて、プランナーは共通スキルct,kを生成します。

このスキルは、高レベルの意図および行動全体の戦略的な計画を表します。続いて、タスク固有スキルエンコーダgωは、同じ観測値からタスク固有スキルzt,kを生成します。

生成された共通スキルとタスク固有スキルはコントローラへ入力され、現在の観測と組み合わせることで、エージェントの行動を決定します。

環境価値モデルは、マルチエージェント環境向けに拡張した暗黙的なQ学習(IQL, Implicit Q-Learning)を用いて学習されます。状態価値は、すべてのエージェントが共同で獲得した報酬を基に推定されます。

ここで、切断二乗誤差(truncated squared error)を用います。

価値モデルによる推定結果を基に、プランナーを学習します。その主な目的は、将来的に最も望ましい状態へ到達できる高レベルスキルを選択することです。このために、次状態の価値と予測状態の尤度の両方を考慮した損失関数を最小化します。

また、指数形式の損失関数を使用することもできます。

コントローラおよびタスク固有スキルエンコーダは、行動表現を学習するための変分オートエンコーダ(VAE)によって学習されます。基本的な考え方は、タスクの潜在構造を考慮しながら、デモンストレーションから得られた行動をコントローラが再現できるよう学習することです。損失関数には、行動の対数尤度に加えて、KLダイバージェンスによる正則化項が含まれます。

さらに、エージェントがタスクごとに真に異なるスキルを獲得できるよう、対照学習を導入します。エンコーダは、各タスクについて、表現gω(q)が同一タスクに属する正例k+に近く、他のタスクに属する負例k-から遠くなるように学習されます。

ここで、σは温度係数を表し、gω†は学習の安定化のために使用される指数移動平均版のエンコーダを表します。

最終的なコントローラの損失関数は、行動再現項と対照学習項を組み合わせたものです。

このように、HiSSDは、戦略的な計画から低レベルの戦術に至るまで、行動のあらゆる階層を統一的に学習し、分散制御環境においても効果的に機能する強力なシステムを構成しています。

HiSSDフレームワークの概要を示した著者らの図を以下に示します。


MQL5での実装

HiSSDフレームワークの理論的基盤を確認したところで、本稿の実践編に進みます。ここでは、提案手法をMQL5を用いて独自に実装していきます。

モデル設計の基本原則


実装の詳細に入る前に、本稿で採用するソリューションの基盤となるいくつかの重要な設計原則について説明します。

まず、HiSSDフレームワークはマルチエージェント学習を前提として設計されている点に注意する必要があります。これは、単一の金融商品に対する売買方策の学習を目的とする本稿の課題とは異なります。しかし、このパラダイムは、実際の金融市場が持つマルチタスク性を考えると大きな可能性を秘めています。本記事では、提案されている階層構造を拡張し、それぞれが市場情報の特定のサブセットを分析・予測する複数の独立したエージェントを学習させます。そして、最終的な意思決定をより一貫性があり効果的なものにするため、各エージェントからの提案を統合し、最適な戦略を選択する上位レベルのマネージャモデルを導入します。このようなマルチタスクシステムは人工知能分野では広く用いられており、金融市場へ適用することで、多様な市場要因やリスクを効率的に扱うことが可能になります。

2つ目の重要な点は、 HiSSDフレームワークでは各エージェントがローカルな観測情報に基づいて行動を決定することです。しかし、金融市場では価格データ、出来高、各種テクニカル指標などが互いに強く依存しているため、この前提には工夫が必要です。そこで、本記事では各エージェントに対して、市場環境を表すマルチモーダル時系列データから抽出した専用の単変量系列を入力として与えます。一方で、市場変数同士には高い相関が存在します。たとえば、ある銘柄の価格変動が他の銘柄へ影響を及ぼすことは珍しくありません。この問題に対応するため、市場全体の状態に関する共有知識を各エージェントが利用できるようにするデータ拡充機構を導入します。これにより、各エージェントはより多くの情報に基づいた意思決定を行えるようになります。

最後に、HiSSDフレームワークの中核となる設計思想であるモジュール化について述べます。この設計は、複雑なマルチタスクシステムとの親和性が非常に高いものです。アーキテクチャは複数の独立したコンポーネントへ分割でき、それぞれが個別の問題を担当します。このモジュール構造により、各コンポーネントを効率的に最適化できるだけでなく、市場環境の変化に応じてシステムを柔軟に適応させることも可能になります。金融市場は極めて動的な環境であるため、モデルの一部だけを迅速に改良・置き換えられることは、実運用において大きな利点となります。

スキルエンコーダ


最初に実装するモジュールは、スキルエンコーダです。ここで、HiSSDフレームワークの重要なアーキテクチャ上の特徴を確認しておきます。共通スキルとタスク固有スキルは、いずれも同じ情報源から生成されます。その情報源とは、各エージェントが取得する局所的な観測情報です。本記事では、これは環境状態を表すマルチモーダル時系列データから抽出した単変量系列に相当します。

この特徴を踏まえ、本稿では両方のサブタスクに対して共通のアーキテクチャを採用しました。この設計にはいくつかの利点があります。まず、モデル設計およびデバッグを簡素化できます。次に、特徴量の品質を一貫した手法で評価できるようになります。さらに、アーキテクチャコンポーネントを再利用することで開発コストを削減でき、新しいタスクや金融商品へモデルを拡張する際のスケーラビリティも向上します。

スキルエンコーダは、CNeuronSkillsEncoderオブジェクトとして実装されています。その構造を以下に示します。

class CNeuronSkillsEncoder   :  public CNeuronSoftMaxOCL
  {
protected:
   CNeuronCATCH               cCrossObservAttention;
   CNeuronTransposeOCL        cTranspose;
   CNeuronConvOCL             cSkillsProjection[2];
   CNeuronBaseOCL             cPrevSkillsConcat;
   //---
   virtual bool               feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool               updateInputWeights(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool               calcInputGradients(CNeuronBaseOCL *prevLayer) override;

public:
                              CNeuronSkillsEncoder(void) {};
                             ~CNeuronSkillsEncoder(void) {};
   //---
   virtual bool               Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                                   uint time_step, uint variables, uint skills,
                                   uint window, uint step, uint window_key, uint heads,
                                   ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int                Type(void) override const   {  return defNeuronSkillsEncoder;   }
   //---
   virtual bool               Save(int const file_handle) override;
   virtual bool               Load(int const file_handle) override;
   //---
   virtual bool               WeightsUpdate(CNeuronBaseOCL *source, float tau) override;
   virtual void               SetOpenCL(COpenCLMy *obj) override;
  };

この構造には、それぞれ異なる役割を担う複数の内部コンポーネントが含まれています。それぞれの機能については、クラスメソッドの実装を進める中で詳しく説明します。現時点で重要なのは、すべてのオブジェクトがstaticとして宣言されているという点です。クラスのコンストラクタおよびデストラクタは空のままとしています。すべての内部オブジェクトの初期化はInitメソッドでおこなわれます。

bool CNeuronSkillsEncoder::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                                uint time_step, uint variables, uint skills,
                                uint window, uint step, uint window_key, uint heads,
                                ENUM_OPTIMIZATION optimization_type, uint batch)
  {
   if(!CNeuronSoftMaxOCL::Init(numOutputs, myIndex, open_cl, variables * skills,
                               optimization_type, batch))
      return false;
   SetHeads(variables);

Initメソッドは、構築されるオブジェクトのアーキテクチャを一意に定義する一連の定数を受け取ります。これらのパラメータの多くはこれまでの説明ですでに登場しているため、ここでは詳しく説明しません。

メソッド本体では、まず親クラスに対応するメソッドを呼び出します。このメソッドには、最小限必要な制御ポイントの実装に加え、継承されたコンポーネントやインターフェースの初期化処理がすでに実装されています。

親クラスとしてSoftMax関数レイヤーを使用します。これにより、各エージェントのスキルエンコーダが出力する値を正規化し、互いに比較可能なスケールへ変換できます。各エージェントが持つスキル数はskillsパラメータによって定義されます。そのため、本モジュールは各エージェントに対してこの長さの出力ベクトルを生成し、それぞれの要素が対応するスキルの重要度を表します。

本実装では、エージェント数はマルチモーダル時系列を構成する単変量系列の数に対応します。そのため、この値はSoftMax正規化ヘッド数として使用されます。

親クラスの初期化が正常に完了した後、新たに導入した内部コンポーネントの初期化を行います。最初に初期化するのは、単変量系列間で情報交換を行うモジュールです。本実験では、この役割を以前実装したCATCHフレームワークのコンポーネントが担います。

int index = 0;
if(!cCrossObservAttention.Init(0, index, OpenCL, time_step, variables, window,
                               step, window_key, heads, optimization, iBatch))
   return false;

前述したように、このモジュールは周波数領域において単変量系列を整列させます。スペクトル分解は複数のセグメントに分割され、それぞれの周波数帯域ごとに解析されます。このアプローチにより、市場シグナルの挙動をより柔軟に表現できます。周波数スペクトル全体を一括して解析するのではなく、特定の周波数帯域に着目します。これは金融市場において特に重要です。高周波成分と低周波成分は、本質的に異なる情報を含んでいるためです。一般に、高周波成分は短期的なボラティリティやノイズを反映し、一方で低周波成分はトレンドや長期的な市場パターンを捉えます。

この仕組みにより、同期性、位相シフト、相関関係などの共通パターンを発見し、それらをスキル形成時の追加情報として利用できます。

重要なのは、情報交換が直接行われるのではなく、マスク付きアテンション機構を介して実施される点です。これにより、エージェント同士が互いに過度な影響を与えることを防ぎ、分散性を維持できます。その結果、各エージェントは自身の単変量系列を処理しながら、市場全体のグローバルなパターンも取り入れることができます。

CATCHモジュールの出力は、クロスチャネル依存性が付加されたマルチモーダル時系列です。

続いて、各エージェントは対応する単変量系列を受け取ります。このデータをより扱いやすい表現へ変換するため、転置レイヤーを適用します。

index++;
if(!cTranspose.Init(0, index, OpenCL, time_step, variables, optimization, iBatch))
   return false;

その後、各エージェントのスキルベクトルを生成するために、独立したヘッドを用います。ここでは2層の畳み込み層を直列に配置しています。

解析対象となる系列長は大きく変動する可能性がある点にも注意が必要です。そのため、系列全体を一度に処理すると計算コストが非常に高くなる場合があります。この問題に対応するため、まず系列を複数のセグメントへ分割し、最初の畳み込み層で次元を調整します。

   uint count = (time_step - window + step - 1) / step;
   if(count <= 1)
     {
      window = time_step;
      count = 1;
     }
//---
   index++;
   if(!cSkillsProjection[0].Init(0, index, OpenCL, window, step, window_key, count,
                                 variables, optimization, iBatch))
      return false;
   cSkillsProjection[0].SetActivationFunction(SoftPlus);

続く2番目の畳み込み層では、各単変量系列に属するすべてのセグメントを集約し、各エージェントにつき1つのスキルベクトルを生成します。このことは、系列長が「1」となっていることからも分かります。

index++;
if(!cSkillsProjection[1].Init(0, index, OpenCL, window_key * count, window_key * count,
                              skills, 1, variables, optimization, iBatch))
   return false;
cSkillsProjection[1].SetActivationFunction(None);

ここで強調しておきたいのは、畳み込み層のパラメータが、モデルによって処理される独立した単変量系列の数を明示的に定義していることです。これにより、各エージェントは固有の重みを持つ独立した畳み込みネットワークを保持できます。同時に、それぞれがマルチモーダル時系列の異なる局所情報のみを解析します。

言い換えれば、エージェントは単に異なるデータを観測しているだけではありません。それぞれが情報全体の限られた部分にのみアクセスし、その範囲で意思決定をおこないます。この構成は、実際の金融市場に近い状況を再現しています。実際のトレーダー(本研究ではエージェント)は、それぞれ異なる情報源を利用し、それに基づいて売買判断を行うからです。

その結果、本モデルは単なる並列実行器の集合ではなく、それぞれが独自の環境で学習し、市場に対する独自の表現を形成し、独自の行動戦略を発展させる協調的な専門エージェント群となります。この設計により、システム全体の頑健性が向上し、行動の多様性が高まり、不確実性の高い市場環境において局所戦略を組み合わせながら、効率的かつ適応的なトレードを実現できるようになります。

続いて、補助オブジェクトを初期化します。このオブジェクトのサイズは出力テンソルの2倍です。その役割については、後述する誤差勾配分配メソッドの実装時に説明します。

   index++;
   if(!cPrevSkillsConcat.Init(0, index, OpenCL, 2 * Neurons(), optimization, iBatch))
      return false;
   cPrevSkillsConcat.SetActivationFunction((ENUM_ACTIVATION)cSkillsProjection[1].Activation());
//---
   return true;
  }

すべての内部オブジェクトを初期化した後、Initメソッドは終了し、呼び出し元のプログラムに論理的な成功ステータスを返します。

次にfeedForwardメソッドにおける順伝播アルゴリズムを実装します。予想どおり、この処理は比較的単純で逐次的な流れとなっています。

bool CNeuronSkillsEncoder::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
   if(!cCrossObservAttention.FeedForward(NeuronOCL))
      return false;

このメソッドは、マルチモーダル入力データオブジェクトへのポインタを受け取ります。この入力は、まず内部のクロスチャネル依存性解析モジュールへ渡されます。

if(!cTranspose.FeedForward(cCrossObservAttention.AsObject()))
   return false;

その出力は転置され、スキルテンソル生成ブロックへ渡されます。

if(!cSkillsProjection[0].FeedForward(cTranspose.AsObject()))
   return false;

ここで重要な点があります。2番目の畳み込み層の順伝播を実行する前に、中間結果を保持しているバッファのポインタを入れ替えています。この単純な操作によって、前回計算された出力を保持できます。この処理が重要である理由については、逆伝播の実装時に詳しく説明します。

   if(!cSkillsProjection[1].SwapOutputs() ||
      !cSkillsProjection[1].FeedForward(cSkillsProjection[0].AsObject()))
      return false;
//---
   return CNeuronSoftMaxOCL::feedForward(cSkillsProjection[1].AsObject());
  }

最後に、生成されたスキルテンソルは親クラスによって確率空間へ写像されます。その後、メソッドは処理結果を示す論理値を呼び出し元へ返して終了します。

次に、逆伝播アルゴリズムを実装します。この処理は次の2つの段階で構成されます。

  • calcInputGradients:すべての内部コンポーネントへ誤差勾配を分配する
  • updateInputWeights:損失を最小化するようにパラメータを更新する

まずはcalcInputGradientsから説明します。このメソッドは、最終出力への寄与度に応じて、内部モジュール全体へ誤差勾配を伝播する役割を担います。この構造についてはすでに触れましたが、ここではその詳細を説明し、モデル学習においてなぜ重要なのかを見ていきます。

このメソッドは、順伝播で使用された入力データオブジェクトへのポインタを受け取ります。ただし今回は、入力が最終出力へ与えた影響に応じて、その入力へ誤差勾配を逆方向に伝播させる必要があります。

bool CNeuronSkillsEncoder::calcInputGradients(CNeuronBaseOCL *prevLayer)
  {
   if(!prevLayer)
      return false;

当然ながら、有効なオブジェクトに対してのみデータを渡すことができます。そのため、メソッドの冒頭で受け取ったポインタの妥当性を直ちに確認します。ポインタがnullである、あるいは無効である場合は、それ以上の計算は意味を持たないため、処理を即座に終了します。このような検証は、アルゴリズムを安全に実行し、学習中の予期しない障害を防ぐための基本的な安全対策です。

検証が正常に完了すると、次の段階である誤差勾配の分配へ進みます。ここから、処理に関わるすべてのオブジェクト間で勾配が順次伝播されます。それぞれのコンポーネントはモデル内で固有の役割を担っており、私たちの目的は、その役割に応じて誤差勾配を適切なモジュールへ段階的に伝播することです。

この仕組みは極めて重要です。各ブロックが最終的な誤差に基づいて自身のパラメータを調整できるよう、内部フィードバックループを提供するからです。まさにこの機構によって、モデルは損失関数を最小化する最適なパラメータを学習していきます。

最初の段階では、親クラスが提供する機能を利用して、後続レイヤーから受け取った誤差勾配をオブジェクトの外部インターフェースまで伝播し、最終的なエージェントのスキルテンソル生成層へ到達させます。

if(!CNeuronSoftMaxOCL::calcInputGradients(cSkillsProjection[1].AsObject()))
   return false;

この処理は、タスクに本当に有用なスキルを生成できるようモデルを学習させるうえで重要な役割を果たします。勾配が順次伝播されることで、モデルはこれまでの行動や判断がどの程度適切であったかという直接的なフィードバックを受け取ります。

しかし、私たちの目的は単に有用なスキルを生成できるエージェントを学習させることだけではありません。エージェント同士が協調して行動し、それぞれが異なる方向へ能力を発揮することで、システム全体として最大限の性能を発揮できるようにすることも重要です。つまり、各エージェントを独立に学習させるだけではなく、それらの間にシナジーを生み出すことを目指しています。

この目的を実現するために、対照学習のアルゴリズムを利用し、各エージェントが生成するスキルテンソルに多様性を導入します。重要なのは、この多様化が単一時刻における異なるエージェント間だけではなく、異なる時刻で生成されたスキル間にも適用される点です。これにより、状態表現の分離性がさらに高まります。

その結果、各エージェントは自身のスキルの独自性を認識するだけではなく、過去の行動によって形成されたコンテキストも考慮するようになります。これにより、エージェントはより複雑で連続性のある行動戦略を獲得し、市場環境の変化へ適応しやすくなります。

金融市場では、市場環境が急速に変化することが少なくありません。そのため、過去の行動や状態の違いを考慮できる能力は非常に重要です。スキルの多様化と履歴情報を組み合わせることで、高いボラティリティや不確実性の下でも、より頑健で適応性の高い戦略を構築できます。

対照学習アルゴリズムは、これらの違いを生み出す中心的な役割を果たします。これにより、エージェントはさまざまな状況をより適切に識別・解釈し、各時点でより合理的な意思決定を行えるようになります。

順伝播時には、新しいスキルテンソルを生成する前に、前回の順伝播結果を保存しておきました。ここでは、それら2つの環境状態の出力を1つのテンソルへ連結します。

if(!Concat(cSkillsProjection[1].getOutput(), cSkillsProjection[1].getPrevOutput(),
           cPrevSkillsConcat.getOutput(), cSkillsProjection[1].GetFilters(),
           cSkillsProjection[1].GetFilters(), iHeads))
   return false;

その後、スキル部分空間内で各ベクトルを可能な限り分離することを目的とした多様化メソッドを呼び出します。

if(!DiversityLoss(cPrevSkillsConcat.AsObject(), 2 * iHeads, cSkillsProjection[1].GetFilters(), false))
   return false;

得られた誤差勾配は、その後、対応する各系列(各出力列)へ再分配されます。

if(!DeConcat(cPrevSkillsConcat.getOutput(), cPrevSkillsConcat.getPrevOutput(),
             cPrevSkillsConcat.getGradient(), cSkillsProjection[1].GetFilters(),
             cSkillsProjection[1].GetFilters(), iHeads))
   return false;

続いて、現在時刻のスキルに対する誤差勾配を、それまで蓄積されていた勾配へ加算します。

if(!SumAndNormilize(cSkillsProjection[1].getGradient(), cPrevSkillsConcat.getOutput(),
                    cSkillsProjection[1].getGradient(), cSkillsProjection[1].GetFilters(),
                    false, 0, 0, 0, 1))
   return false;

以降の処理は逐次的です。まず、スキル生成ブロックへ誤差勾配を伝播します。

if(!cSkillsProjection[0].calcHiddenGradients(cSkillsProjection[1].AsObject()))
   return false;

得られた勾配は転置され、その後クロスチャネル依存性解析モジュールへ渡されます。

if(!cTranspose.calcHiddenGradients(cSkillsProjection[0].AsObject()))
   return false;
if(!cCrossObservAttention.calcHiddenGradients(cTranspose.AsObject()))
   return false;

最後に、入力データが最終出力へ与えた寄与に応じて、誤差勾配を入力データオブジェクトまで逆伝播させます。

 return prevLayer.calcHiddenGradients(cCrossObservAttention.AsObject());
}

メソッドは処理の論理結果を呼び出し元に返して終了します。

パラメータ更新をおこなうupdateInputWeightsメソッドは非常に単純です。内部コンポーネントに対して対応する更新メソッドを順番に呼び出すだけです。なお、すべての内部モジュールが学習可能なパラメータを持っているわけではありません。そのため、この更新処理に参加するのは一部のモジュールのみです。

bool CNeuronSkillsEncoder::updateInputWeights(CNeuronBaseOCL *NeuronOCL)
  {
   if(!cCrossObservAttention.UpdateInputWeights(NeuronOCL))
      return false;
   if(!cSkillsProjection[0].UpdateInputWeights(cTranspose.AsObject()))
      return false;
   if(!cSkillsProjection[1].UpdateInputWeights(cSkillsProjection[0].AsObject()))
      return false;
//---
   return true;
  }

最後に、モデルの保存と復元についても触れておきます。すでにお気付きかもしれませんが、2回の連続した順伝播結果を連結するコンポーネントには学習可能なパラメータは存在しません。このコンポーネントは、異なる処理経路から得られた出力を結合する補助的な役割のみを担っています。ただし、この連結オブジェクトは、エンコーダの出力テンソルの2倍のサイズを持つデータバッファを保持しています。しかし、これらのバッファは中間計算の一時保存にのみ使用されるため、モデルの動作そのものには本質的な影響を与えません。したがって、学習済みモデルを保存する際には、これらのバッファを保存対象から除外することで、ディスク使用量を削減できます。

bool CNeuronSkillsEncoder::Save(const int file_handle)
  {
   if(!CNeuronSoftMaxOCL::Save(file_handle))
      return false;
   if(!cCrossObservAttention.Save(file_handle))
      return false;
   if(!cTranspose.Save(file_handle))
      return false;
   for(uint i = 0; i < cSkillsProjection.Size(); i++)
      if(!cSkillsProjection[i].Save(file_handle))
         return false;
//---
   return true;
  }

モデルを復元する際には、スキルエンコーダの出力テンソルのサイズは既知であるため、この連結コンポーネントは容易に再初期化できます。

bool CNeuronSkillsEncoder::Load(const int file_handle)
  {
   if(!CNeuronSoftMaxOCL::Load(file_handle))
      return false;
   if(!LoadInsideLayer(file_handle, cCrossObservAttention.AsObject()))
      return false;
   if(!LoadInsideLayer(file_handle, cTranspose.AsObject()))
      return false;
   for(uint i = 0; i < cSkillsProjection.Size(); i++)
      if(!LoadInsideLayer(file_handle, cSkillsProjection[i].AsObject()))
         return false;
//---
   if(!cPrevSkillsConcat.Init(0, 4, OpenCL, 2 * Neurons(), optimization, iBatch))
      return false;
   cPrevSkillsConcat.SetActivationFunction((ENUM_ACTIVATION)cSkillsProjection[1].Activation());
//---
   return true;
  }

以上で、スキルエンコーダの実装についての説明を終わります。ここで紹介したオブジェクトおよび各メソッドの完全なソースコードは、添付ファイルに収録されています。

本記事では大きく実装を進めることができましたが、記事の分量も限界に近づいてきました。そのため、ここでいったん区切りとし、続きは次回の記事で紹介します。



結論

本記事では、HiSSDフレームワークの理論的基盤について解説しました。HiSSDは、マルチエージェント環境においてエージェントを学習させるための、強力かつ柔軟なフレームワークです。各エージェントは、システム内の他のエージェントと密接に相互作用しながら、それぞれ独自の行動方策を学習します。このように、共有スキル学習とタスク固有のスキル学習を組み合わせることで、不確実かつ動的な環境下でも効果的に機能する、より適応性と頑健性に優れた戦略を構築できます。

さらに、HiSSDはモジュール構造を採用しており、対照学習や変分的行動コーディングといった複数の学習メカニズムを統合しています。そのため、マルチエージェントシステムにおけるさまざまな課題へ柔軟に対応できる、有望なフレームワークとなっています。

記事の実践的な部分では、このアプローチをMQL5で実現するための実装を開始しました。具体的には、汎用的なスキルエンコーダの実装を紹介しました。次回の記事では、この実装をさらに発展させ、実際の過去市場データを用いて、実装した手法の有効性を検証していきます。


参照文献


記事で使用されたプログラム

# 名前 種類 詳細
1 Research.mq5 EA サンプル収集用EA
2 ResearchRealORL.mq5
EA
Real-ORL法を用いたサンプル収集用EA
3 Study.mq5 EA モデル学習用EA
4 Test.mq5 EA モデルテスト用EA
5 Trajectory.mqh クラスライブラリ システム状態とモデルアーキテクチャ記述構造
6 NeuroNet.mqh クラスライブラリ ニューラルネットワークを作成するためのクラスのライブラリ
7 NeuroNet.cl コードライブラリ OpenCLプログラムコード


MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/17729

添付されたファイル |
MQL5.zip (2621.73 KB)
最後のコメント | ディスカッションに移動 (1)
DrStone007
DrStone007 | 18 7月 2026 において 11:22
取引におけるニューラルネットワーク:適応型エージェント行動のための階層的スキル発見(最終章) 取引におけるニューラルネットワーク:適応型エージェント行動のための階層的スキル発見(最終章)
アルゴリズム取引への適用を目的としたHiSSDフレームワークの実装について解説します。スキル階層と適応的なアーキテクチャを活用して、安定的に機能する取引戦略を構築する方法を説明します。
取引におけるニューラルネットワーク:周波数領域での異常検知(最終回) 取引におけるニューラルネットワーク:周波数領域での異常検知(最終回)
フーリエ変換と周波数パッチングの仕組みを組み合わせ、市場の異常を高精度に検出するCATCHフレームワークの実装を続けます。提案されたアプローチに対する独自の実装を完成させるとともに、新しいモデルを実際の市場履歴データで検証します。
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
コード、涙、そしてAlgo Forge コード、涙、そしてAlgo Forge
プログラムコードや記事の添付ファイルを、より快適に公開・管理するための新しい方法として、MQL5 Algo Forgeへの移行について紹介します。従来のZIPアーカイブ形式でソースコードを添付する方法の代わりにリポジトリを使用することで、プロジェクトを常に最新の状態に保ち、素早く編集し、読者とよりプロフェッショナルな形で関わることができるようになります。MetaEditorインターフェースを通じて、開発したものをクラウド環境へ素早く移行するための推奨方法についても説明します。