Bot 機械学習・データサイエンス

開発記録#119(2024/10/26)ML bot開発「GAとLSTM」

2024年10月26日

前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。

今回はGA(Genetic Algorithm, 遺伝的アルゴリズム)とLSTMを組み合わせたbotを作ってみました。

Yodaka

今回もプログラムの雛形とあわせて解説していきます。

解決したかったこと

・GAの概念を理解する

・GAとLSTMを組み合わせたプログラムの雛形を作る

・GAとLSTMの組み合わせの優位性と課題を理解する

・課題解決のアプローチを知る

GAとは

遺伝的アルゴリズム(Genetic Algorithm, GA)は、自然界の進化の仕組みを模倣した最適化アルゴリズムの一種です。GAは、特定の問題に対して「最適解」や「最適なパラメータセット」を見つけるために使用されます。主に、探索空間が広大で、従来の最適化手法では解が見つけにくい問題に対して効果を発揮します。

遺伝的アルゴリズムの基本概念

遺伝的アルゴリズムは、以下のステップで動作します。

  1. 個体(Individual):
    • 解の候補を「個体」と呼びます。それぞれの個体は、特定のパラメータセットを持っています。この個体は「遺伝子」とも呼ばれるデータ構造で表されます。
    • 例えば、LSTMの隠れ層の数やニューロンの数、学習率などが個体の遺伝子情報に相当します。
  2. 集団(Population):
    • 複数の個体からなるグループを「集団」と呼びます。GAは、この集団全体を使って最適化を進めます。
    • 初期集団はランダムに生成され、すべての個体が異なるパラメータセットを持っています。
  3. 適応度(Fitness):
    • 各個体の「適応度」は、その個体がどれだけ「良い解」かを評価するための指標です。GAの目的は、この適応度を最大化または最小化することです。
    • 例えば、LSTMのモデルでは、テストデータに対する予測精度(MSEなど)が適応度になります。適応度が良いほど、より精度の高い予測ができるということです。
  4. 選択(Selection):
    • 次世代に進むために、適応度の高い個体を選び出します。この選択は「自然淘汰」に相当し、強い(良い)個体が生き残る仕組みです。
    • 一般的な選択方法としては「ルーレット選択」や「トーナメント選択」などがあります。
  5. 交叉(Crossover):
    • 選択された個体同士を組み合わせて、新しい個体(子孫)を生成します。これを「交叉」または「クロスオーバー」と呼びます。
    • 交叉により、親の遺伝子を引き継いだ子供が生成され、より良い特徴を組み合わせて新たな解を生み出すことが期待されます。
  6. 突然変異(Mutation):
    • 新しい個体を生成する際、わずかに遺伝子を変更することを「突然変異」と呼びます。これにより、集団に多様性が生まれ、局所解に陥るのを防ぎます。
    • 例えば、LSTMの隠れ層の数が突然変異で1層から2層に変わることがあるかもしれません。
  7. 世代交代(Generation):
    • 交叉や突然変異を経て生成された新しい個体で次の世代の集団を作ります。これを繰り返していくことで、世代ごとにより良い解に進化していきます。

GAのアルゴリズムの流れ

  1. 初期集団の生成:
    • ランダムに複数の個体を生成し、初期集団とします。
  2. 適応度の評価:
    • 各個体の適応度を計算し、どれが良い解かを評価します。
  3. 選択:
    • 適応度の高い個体を選び出し、次世代に向けて親となる個体を決定します。
  4. 交叉と突然変異:
    • 親同士を交叉し、新しい個体を生成。さらに、いくつかの個体に突然変異を加えます。
  5. 新しい世代の生成:
    • 交叉と突然変異を経た新しい個体で次の世代の集団を作成します。
  6. 適応度の確認と終了条件のチェック:
    • 一定の基準を満たすまで、世代交代を繰り返します(例えば、目標の適応度に到達する、一定世代に到達するなど)。

GAの応用例

  • 機械学習モデルのハイパーパラメータ最適化:
    • 遺伝的アルゴリズムは、SVMやニューラルネットワークなどのハイパーパラメータを最適化するためによく使用されます。
  • 自動化された設計やロボット制御:
    • ロボットの行動パターンや設計パラメータの最適化に利用されています。
  • ファイナンス:
    • 自動取引システムの最適化やポートフォリオ最適化に使用されることもあります。

GAのメリットとデメリット

メリット:

  • 探索空間が大きく、複雑な問題に対して有効。
  • 多様な解を生成することで、局所解に陥りにくい。
  • 他の最適化手法と組み合わせやすい。

デメリット:

  • 計算コストが高くなることがある。
  • 解の収束に時間がかかる場合がある。

GAは非常に汎用的なアルゴリズムで、幅広い最適化問題に対応できますが、適切なパラメータ設定と実装が必要です。上記のLSTMの最適化例でも、GAを使用することで効率的により良いモデル構造を見つけることが可能になります。

アプローチの優位性

GA(遺伝的アルゴリズム)とLSTM(Long Short-Term Memory)を組み合わせて仮想通貨の価格予測を行う自動取引ボットを運用する場合の優位性課題、そしてその課題を解決するための方法について解説します。

優位性

  1. ハイパーパラメータの自動最適化:
    • GAはLSTMモデルのハイパーパラメータ(層の数、ニューロンの数、学習率など)を自動的に最適化できます。これにより、手動で調整する必要がなくなり、効率的に最適なモデル構造を見つけることができます。
    • 特に、複数のパラメータが相互に影響を与える複雑なケースでも、GAは広範囲の探索を行い、最適な組み合わせを見つけることができます。
  2. 価格予測の精度向上:
    • LSTMは時系列データを扱うのが得意であり、特に価格のパターンやトレンドを捉える能力に優れています。GAを組み合わせることで、LSTMモデルの精度をさらに向上させることが可能です。
    • これにより、より正確な予測ができ、自動取引ボットのパフォーマンスが向上します。
  3. 自動化された進化的アプローチ:
    • GAを使用することで、トレード戦略を進化的に最適化し、継続的に改善することが可能です。これにより、ボットの性能が市場の変動に適応しやすくなります。
    • 市場の条件が変化しても、GAを使って新しい環境に適応するモデルを見つけることができます。

課題とその解決方法

  1. 計算コストが高い:
    • GAは多くの世代にわたって個体を評価し、交叉や突然変異を繰り返すため、計算コストが非常に高くなる可能性があります。特にLSTMのトレーニングは時間がかかるため、GAの評価プロセスが全体の速度を遅くすることがあります。
    解決方法:
    • 並列処理や分散処理を利用することで、GAの計算プロセスを効率化できます。例えば、クラウドサービスや分散コンピューティング環境を使用して、複数の個体を同時に評価することができます。
    • また、LSTMモデルのトレーニングにGPUを活用することで、トレーニング時間を大幅に短縮することができます。
  2. 過適合(Overfitting)のリスク:
    • GAが非常に最適化されたLSTMモデルを作り出すことはありますが、それが過剰に学習してしまい、過去のデータに適合しすぎる(過適合)可能性があります。これは、テストデータや実際の運用環境でのパフォーマンスが期待通りにならない原因になります。
    解決方法:
    • 適応度の評価時に、交差検証やフォワード検証を導入し、より堅牢な評価を行うことで過適合のリスクを減らします。また、GAの進化プロセス中に評価セットをランダムに変更することで、汎化性能を高めることができます。
    • さらに、ドロップアウトなどの正則化手法をLSTMに取り入れて、モデルの汎化能力を向上させることができます。
  3. リアルタイム取引への応答速度:
    • 仮想通貨市場は非常に変動が激しく、リアルタイムでの対応が求められます。GAを使って最適化されたLSTMモデルを使う場合でも、モデルの予測と取引決定が迅速に行われなければ、機会を逃したり、誤った取引を行うリスクがあります。
    解決方法:
    • モデルのトレーニングはリアルタイムで行わず、事前にトレーニングしたモデルを使用し、定期的にGAを実行してモデルをアップデートする形にします。リアルタイムの取引では、事前にトレーニングされたモデルが即座に予測できるようにしておき、必要に応じてGAで新しいモデルを用意する、という運用が効果的です。
    • また、予測に基づくトリガーを設定して、予測結果が大きな変動を示した場合のみ取引を行うようにすることで、取引の頻度を減らし、応答速度の低下を防ぐことができます。
  4. 市場のダイナミクスに対する適応性:
    • 仮想通貨市場は急激な価格変動が頻繁に起こるため、これに適応できないと予測の精度が落ち、取引戦略が有効でなくなるリスクがあります。
    解決方法:
    • 遺伝的アルゴリズムの一部として、継続的な最適化を行い、GAが常に最新の市場データに基づいて進化できるようにします。これにより、市場のダイナミクスに適応したモデルを維持できます。
    • また、異なる市場状況に対応する複数のモデルをGAで生成し、各モデルの適応度に応じて使い分けるアプローチも考えられます。

まとめ

GAとLSTMを組み合わせた仮想通貨の自動取引ボットは、ハイパーパラメータの最適化や市場の変動に対する適応能力を高めるという点で優れたアプローチです。しかし、計算コストや過適合、リアルタイム性の問題が課題となります。これらの課題は、並列処理や分散処理の利用、正則化やフォワード検証の導入、事前トレーニングされたモデルの活用などによって効果的に解決できます。

このアプローチにより、継続的に進化し続ける最適なモデルを維持することで、市場の変動に柔軟に対応し、より精度の高い予測と利益の向上を目指すことが可能です。

プログラムの雛形1

遺伝的アルゴリズム(GA)を使用してLSTMの構造やハイパーパラメータを最適化するためのPythonコードの例です。このコードでは、DEAPという進化的アルゴリズムのライブラリを用いてGAを実装します。また、LSTMモデルのトレーニングにはKerasを使用します。

import random
import numpy as np
from deap import base, creator, tools, algorithms
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.optimizers import Adam
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# データの準備
def generate_data():
    # 仮想的なデータを生成(実際のデータセットを読み込むことを推奨)
    X = np.random.rand(1000, 10, 1)
    y = np.random.rand(1000, 1)
    return train_test_split(X, y, test_size=0.2)

X_train, X_test, y_train, y_test = generate_data()

# 遺伝的アルゴリズムの設定
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)

# ハイパーパラメータの範囲
PARAMS_BOUND = {
    'n_layers': (1, 3),  # 隠れ層の数
    'n_neurons': (16, 128),  # 各層のニューロン数
    'learning_rate': (0.0001, 0.01)  # 学習率
}

# 個体の生成
def create_individual():
    return [
        random.randint(*PARAMS_BOUND['n_layers']),
        random.randint(*PARAMS_BOUND['n_neurons']),
        random.uniform(*PARAMS_BOUND['learning_rate'])
    ]

toolbox = base.Toolbox()
toolbox.register("individual", tools.initIterate, creator.Individual, create_individual)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

# モデルの評価関数
def evaluate(individual):
    n_layers, n_neurons, learning_rate = individual
    model = Sequential()
    
    # LSTM層の追加
    for _ in range(n_layers):
        model.add(LSTM(n_neurons, activation='tanh', return_sequences=True))
    model.add(LSTM(n_neurons, activation='tanh'))
    model.add(Dense(1))
    
    optimizer = Adam(learning_rate=learning_rate)
    model.compile(optimizer=optimizer, loss='mse')
    
    # モデルのトレーニング
    model.fit(X_train, y_train, epochs=10, batch_size=32, verbose=0)
    
    # 評価
    predictions = model.predict(X_test)
    mse = mean_squared_error(y_test, predictions)
    
    return (mse,)

toolbox.register("evaluate", evaluate)
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutUniformInt, low=[1, 16, 0], up=[3, 128, 1], indpb=0.2)
toolbox.register("select", tools.selTournament, tournsize=3)

# 遺伝的アルゴリズムの実行
def run_ga():
    population = toolbox.population(n=10)
    ngen = 10  # 世代数
    cxpb = 0.5  # 交叉確率
    mutpb = 0.2  # 突然変異確率
    
    result = algorithms.eaSimple(population, toolbox, cxpb, mutpb, ngen, verbose=True)
    
    best_individual = tools.selBest(population, 1)[0]
    print(f"Best Individual: {best_individual}")
    print(f"Best Score: {evaluate(best_individual)}")

run_ga()

コードの説明

  1. データ生成: 仮想的なデータセットを用意していますが、実際のデータを使用する場合は適宜変更してください。
  2. 遺伝的アルゴリズム設定: DEAPを使用して遺伝的アルゴリズムのフレームワークを構築しています。
  3. 評価関数: 個体(モデル設定)ごとにLSTMモデルを作成し、評価しています。損失関数にはMSEを使用し、モデルのトレーニングと評価が行われます。
  4. GA実行: 指定された世代数、交叉確率、突然変異確率に従ってGAが進行します。最適なハイパーパラメータを見つけます。

このコードはシンプルな例なので、パフォーマンス向上のためにモデル評価の部分に工夫が必要です(例えば、トレーニングのエポック数を増やすなど)。また、計算量が多い場合、GPUを使用してトレーニングを行うと良いでしょう。

プログラムの雛形2

bybitのビットコイン価格を予測し、予測に基づいて自動取引を行うプログラムのコードのプロトタイプです。ccxtライブラリを使用してbybitからデータを取得し、価格予測の結果に基づいて売買を行う簡単な例を示します。

import random
import numpy as np
import ccxt
from deap import base, creator, tools, algorithms
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.optimizers import Adam
from sklearn.metrics import mean_squared_error

# BybitのAPIクライアント設定
bybit = ccxt.bybit({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_API_SECRET',
})

# データの取得
def fetch_bybit_data():
    ohlcv = bybit.fetch_ohlcv('BTC/USDT', timeframe='1m', limit=1000)
    data = np.array([x[4] for x in ohlcv])  # 終値のみ取得
    X = []
    y = []
    for i in range(len(data) - 10):
        X.append(data[i:i + 10])
        y.append(data[i + 10])
    X = np.array(X).reshape(-1, 10, 1)
    y = np.array(y).reshape(-1, 1)
    return X, y

X, y = fetch_bybit_data()
X_train, X_test, y_train, y_test = X[:-200], X[-200:], y[:-200], y[-200:]

# 遺伝的アルゴリズムの設定
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)

# ハイパーパラメータの範囲
PARAMS_BOUND = {
    'n_layers': (1, 3),  # 隠れ層の数
    'n_neurons': (16, 128),  # 各層のニューロン数
    'learning_rate': (0.0001, 0.01)  # 学習率
}

# 個体の生成
def create_individual():
    return [
        random.randint(*PARAMS_BOUND['n_layers']),
        random.randint(*PARAMS_BOUND['n_neurons']),
        random.uniform(*PARAMS_BOUND['learning_rate'])
    ]

toolbox = base.Toolbox()
toolbox.register("individual", tools.initIterate, creator.Individual, create_individual)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

# モデルの評価関数
def evaluate(individual):
    n_layers, n_neurons, learning_rate = individual
    model = Sequential()
    
    # LSTM層の追加
    for _ in range(n_layers):
        model.add(LSTM(n_neurons, activation='tanh', return_sequences=True))
    model.add(LSTM(n_neurons, activation='tanh'))
    model.add(Dense(1))
    
    optimizer = Adam(learning_rate=learning_rate)
    model.compile(optimizer=optimizer, loss='mse')
    
    # モデルのトレーニング
    model.fit(X_train, y_train, epochs=5, batch_size=32, verbose=0)
    
    # 評価
    predictions = model.predict(X_test)
    mse = mean_squared_error(y_test, predictions)
    
    return (mse,)

toolbox.register("evaluate", evaluate)
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutUniformInt, low=[1, 16, 0], up=[3, 128, 1], indpb=0.2)
toolbox.register("select", tools.selTournament, tournsize=3)

# 遺伝的アルゴリズムの実行
def run_ga():
    population = toolbox.population(n=10)
    ngen = 10  # 世代数
    cxpb = 0.5  # 交叉確率
    mutpb = 0.2  # 突然変異確率
    
    result = algorithms.eaSimple(population, toolbox, cxpb, mutpb, ngen, verbose=True)
    
    best_individual = tools.selBest(population, 1)[0]
    print(f"Best Individual: {best_individual}")
    print(f"Best Score: {evaluate(best_individual)}")

    return best_individual

# 最適なハイパーパラメータでモデルをトレーニングし、予測に基づいて取引を行う
def trade():
    best_params = run_ga()
    n_layers, n_neurons, learning_rate = best_params
    
    # 最適化されたモデル構築
    model = Sequential()
    for _ in range(n_layers):
        model.add(LSTM(n_neurons, activation='tanh', return_sequences=True))
    model.add(LSTM(n_neurons, activation='tanh'))
    model.add(Dense(1))
    
    optimizer = Adam(learning_rate=learning_rate)
    model.compile(optimizer=optimizer, loss='mse')
    model.fit(X_train, y_train, epochs=10, batch_size=32, verbose=0)
    
    # 最新の価格データを用いて予測
    current_data = fetch_bybit_data()[0][-1].reshape(1, 10, 1)
    prediction = model.predict(current_data)
    print(f"Predicted Price: {prediction[0][0]}")

    # 簡単な売買ルール
    last_price = bybit.fetch_ticker('BTC/USDT')['last']
    if prediction[0][0] > last_price:
        print("Buying BTC")
        bybit.create_market_buy_order('BTC/USDT', 0.01)  # 0.01 BTC購入(例)
    else:
        print("Selling BTC")
        bybit.create_market_sell_order('BTC/USDT', 0.01)  # 0.01 BTC売却(例)

trade()

コードの説明

  1. データ取得: ccxtライブラリを使用してbybitからビットコインの価格データを取得しています。これにより、実際のトレードに使用可能なデータをリアルタイムで収集できます。
  2. GA設定とモデル最適化: 先ほどの遺伝的アルゴリズムの例を用いて、LSTMモデルの構造とハイパーパラメータを最適化します。
  3. 自動取引の実行: GAで最適化されたモデルを使用し、bybitの最新のデータを予測。予測された価格に基づいて、簡単な売買ルールを適用し、自動的に取引を行います。

注意: APIキーとシークレットキーを適切に設定し、取引量などの設定も適宜変更してください。また、リアル取引を行う場合は、ペーパートレードモードや小額の取引から始めることを強く推奨します。

追記:このアプローチへの批判的な検討

GA(遺伝的アルゴリズム)とLSTMを組み合わせた仮想通貨価格予測および自動取引ボットのアプローチには、いくつかの数学的・論理的観点からの問題点があります。これらを批判的に検討すると、以下のような指摘ができます。

1. 遺伝的アルゴリズムによるハイパーパラメータ最適化の問題

局所最適解と収束の問題

  • 問題: GAは初期条件や遺伝子多様性に依存するため、探索空間内で局所最適解に収束しやすい傾向があります。特に、GAは解空間全体の正確な形状を知らずに最適化を進めるため、必ずしも全体の最適解を見つけられるわけではありません。
  • 批判的視点: 一般的な勾配ベースの最適化手法と比べて、GAは収束の速さや効率が劣る可能性が高く、特に多次元で連続的な解空間を探索する場合には、非常に非効率な手法と見なされる場合があります。また、仮想通貨の価格予測では、適応度関数が多峰性(複数の山のような構造)であるため、局所最適に留まってしまうリスクが高まります。

収束速度の遅さと計算コスト

  • 問題: GAは進化的プロセスを経るため、収束速度が遅い上に、多くの試行錯誤が必要です。個体数、世代数が増加すると、計算量は指数関数的に増加し、コストが膨大になることがあります。
  • 批判的視点: GAは、多次元の連続的なハイパーパラメータの最適化には、従来の勾配降下法やベイズ最適化といった手法と比べて非効率的です。計算資源が限られる場合、収束速度が遅くなるため、理論的には実運用に適さない可能性があります。

2. LSTMモデルの適用限界

長期依存性のキャプチャに対する数学的限界

  • 問題: LSTMは短期的なパターンを捉えるのに適していますが、仮想通貨市場のように長期的かつランダム性が高いデータに対しては、情報が劣化してしまいます。これにより、LSTMが予測モデルとしての限界を示す可能性があり、適応度の向上が難しくなる場合があります。
  • 批判的視点: 金融市場の時系列は、必ずしもLSTMが前提とする自己相関的なデータ(過去のパターンが将来にある程度反映される)ではありません。数学的には、ランダムウォークに近い動きをする価格変動を扱う場合、LSTMのような自己相関モデルでは十分な精度が出ないことが証明されています。

過剰適合と汎化性能

  • 問題: 遺伝的アルゴリズムによってLSTMのハイパーパラメータを最適化した場合、過剰適合(オーバーフィッティング)のリスクが高まります。適応度関数がトレーニングデータに依存しすぎるため、実際の取引環境では機能しない可能性が高いです。
  • 批判的視点: 金融データは極めてノイズが多く、過剰適合が頻発する性質があります。理論的には、トレーニングデータで良好な適応度を示しても、未知のデータ(テストデータ)で同様の性能を発揮するとは限りません。この問題は過剰適合が原因であり、数学的には一般化エラーが非常に大きくなる可能性が指摘されます。

3. 市場のランダム性と予測限界

金融市場の予測可能性に関する統計的限界

  • 問題: 多くの研究により、金融市場、特に仮想通貨市場は非効率かつノイズが多く、予測が困難なランダムウォーク性を持つとされています。このため、LSTMでの予測精度が低下する場合があります。
  • 批判的視点: 仮想通貨市場のデータは多くの場合、定常性や自己相関性がないため、数学的には予測が不可能に近いものです。LSTMが「学習」していると認識しているデータの大部分が、実はノイズである可能性が高いことが、数学的にも統計的にも示唆されています。この場合、GAとLSTMの組み合わせによる予測は理論的に無意味とされる場合もあります。

ボラティリティへの非対応

  • 問題: 仮想通貨市場の価格はボラティリティ(変動性)が高く、外的要因による急激な変動が頻繁に起こります。これに対してLSTMは対応が難しいため、予測精度に大きなばらつきが生じやすいです。
  • 批判的視点: 高ボラティリティ時には、過去データから予測したモデルが急激な市場変動に適応できないことが数学的に証明されています。特に、外的要因(例えば政策変更や経済ショック)により価格が急変する際、GAとLSTMの組み合わせでは正確な予測が難しいという限界があります。

4. 適応度関数の不安定性と評価基準の問題

適応度関数の定義の難しさ

  • 問題: GAにおける適応度関数(フィットネス関数)は、モデルの予測性能や取引の利益に基づいていますが、これがボットの実際のパフォーマンスを正確に表すとは限りません。金融市場では、特に適応度関数が非線形な関数になる場合が多いため、最適化が困難です。
  • 批判的視点: 金融取引の利益や損失は、数学的には非線形かつ不規則で、変動性が高い関数です。したがって、GAで定義された適応度関数が真のパフォーマンスを正確に反映しない場合、最適化結果が意味を持たないことがあります。

評価基準の歪み

  • 問題: 一部のトレード戦略が適応度関数において一時的に高評価を得た場合、その後の環境変化に対応できなくなるリスクがあります。例えば、ボットが特定の市場状況(上昇トレンドや下降トレンド)に過度に適応すると、逆のトレンドに対して脆弱になります。
  • 批判的視点: 時系列分析においては、評価基準の偏りが予測の妥当性を低下させることが数学的に示されています。このため、特定の評価基準が、GAによる最適化において市場のダイナミクスに適応できるとは限りません。

結論

GAとLSTMの組み合わせは一見すると有望に見えるものの、上記のような数学的な観点からの限界や批判が存在します。特に、局所最適への収束、計算コスト、過剰適合、非線形性による適応度評価の歪み、ランダムウォーク性の高い市場での予測不可能性が主な課題です。

理論的には、こうした問題に対して、GAの代わりにより効率的な探索手法を用いる、もしくはLSTMの代わりにランダム性を許容した統計モデルや確率的モデルの併用を検討することが有効と考えられます。

まとめ

今回はGAとLSTMの組み合わせについて紹介しました。

実際に稼働させるための雛形に基づいて、botの構造を理解できるようになってきたように感じます。

Yodaka

この戦略もこれまで試してきたアプローチと比較して優位性を検証していきます。

今後もこの調子で開発の状況をまとめていきます。

-Bot, 機械学習・データサイエンス