はじめに
システムトレードで使用するアルゴリズムの中でも「ロジスティック回帰」は、初心者でも学びやすく、幅広く活用されています。この記事では、ロジスティック回帰の基本を初学者に向けてわかりやすく解説していきます。
ロジスティック回帰とは?
ロジスティック回帰とは、ある事象が起きる確率を予測するための統計モデルです。特に「2つの選択肢」のどちらかを選ぶような場面で威力を発揮します。たとえば、「明日株価が上がるか下がるか」を予測するシステムトレードに適しています。
具体例:株価の予測 株価を例に考えてみましょう。ある株価が上がるか下がるかを予測したい場合、次のようなデータを使います:
- 前日比上昇率
- 出来高
ロジスティック回帰は、これらのデータをもとに次に「株価が上がる確率」を計算します。
ロジスティック回帰とシステムトレード
- 価格の上下を2値で表現できるシステムトレードでは、当然「買い」と「売り」の2つの判断が多く求められます。ロジスティック回帰は、これを次のようにモデル化します:
- 1:買い
- 0:売り
- 確率で判断する柔軟性 ロジスティック回帰では、「買い」や「売り」を単なる判断ではなく、確率(たとえば70%の確率で買いが有利)として出力します。この確率をもとに判断基準を柔軟に変更できます。
シグモイド関数とは?
シグモイド関数とは、入力データを0から1の範囲に変換する関数で、確率として解釈できる値を出力します。これにより、ロジスティック回帰ではある事象が発生する確率を計算できます。
シグモイド関数は、次のような形をしています:
y = 1 / (1 + e^(-z))
ここでは、
y:予測される確率
z:入力データを元に計算された値
をそれぞれ表しています。
自然対数とは?
自然対数とは、底がe(約2.718)である対数のことです。これは数学や統計学でよく使われ、成長や減衰を表すのに適しています。たとえば、複利計算や人口増加などの現象で登場します。
対数とは?
対数とは、特定の数値を得るために底を何乗するかを示す数学的な概念です(logで表されます)。例えば、2を3乗して8になる場合、8の対数(底が2)は3となります。つまり、log2(8) = 3 という形式で表されます。
シグモイド関数の具体的な計算例
たとえば、z = 2 の場合、シグモイド関数は次のように計算されます:
y = 1 / (1 + e^(-2))
まず、e^(-2) を計算します。e の値は約 2.718 ですので:
e^(-2) = 1 / (2.718^2) ≈ 1 / 7.389 ≈ 0.135
次に、1 + e^(-2) を計算します:
1 + 0.135 = 1.135
最後に、y を求めます:
y = 1 / 1.135 ≈ 0.88
したがって、z = 2 の場合、シグモイド関数の出力 y は約 0.88 となります。これは、確率として解釈できます。
ロジスティック回帰のステップ
システムトレードにロジスティック回帰を導入する際の基本ステップを解説します。
- データを準備する
まず、株価や通貨ペアの過去の価格データを用意します。たとえば、株価の「前日比上昇率」や「出来高」などです。これらのデータは、市場の動きや価格の変化を理解するのに役立ちます。具体的には以下のようなデータを準備します: - 特徴量を選ぶ
特徴量とは、モデルが判断に使う情報(データ)のことです。たとえば、「過去3日間の平均価格」や「出来高の増加率」が特徴量になり得ます。特徴量を選ぶことは、モデルの性能を左右する重要な作業です。
適切な特徴量を選ぶことで、モデルが効率的に学習し、より正確な予測を行えるようになります。 - モデルを訓練する
次に、Pythonなどのプログラミング言語を使って、ロジスティック回帰モデルを訓練します。モデルを訓練するというのは、過去のデータを使ってパターンを学び、将来のデータを予測できるようにすることです。訓練には次の手順を踏みます:
Pythonでの実装例
次に、Pythonを使った簡単なロジスティック回帰の実装を紹介します。
# 必要なライブラリをインポート
import pandas as pd # データ操作用ライブラリ
from sklearn.model_selection import train_test_split # データを訓練用とテスト用に分割するための関数
from sklearn.linear_model import LogisticRegression # ロジスティック回帰モデルを提供するクラス
from sklearn.metrics import accuracy_score # 予測精度を計算するための関数
# データの準備(仮のデータ)
data = { # 株価や出来高を模擬的に作成
"price_change": [0.1, -0.2, 0.3, -0.1, 0.05, -0.3], # 前日比の上昇率(小数値で表現)
"volume": [100, 150, 200, 120, 80, 60], # 出来高(その日の取引量)
"up_down": [1, 0, 1, 0, 1, 0] # 上昇(1:株価が上がった)か下落(0:株価が下がった)
}
# データをpandasのDataFrame形式に変換
# DataFrameとは、表形式のデータ構造で、行と列を持ち、データ分析に便利
df = pd.DataFrame(data) # 辞書型データをDataFrameに変換
# 特徴量(入力データ)とラベル(出力データ)に分ける
# 特徴量:モデルが予測に使用するデータ
# ラベル:予測したい結果
X = df[["price_change", "volume"]] # 特徴量として、前日比上昇率と出来高を使用
y = df["up_down"] # ラベルとして、株価の上昇(1)or下落(0)を使用
# 訓練データとテストデータに分割
# 訓練データ:モデルを学習させるためのデータ
# テストデータ:モデルの性能を確認するためのデータ
X_train, X_test, y_train, y_test = train_test_split( # train_test_split関数で分割
X, y, # 特徴量とラベルを入力
test_size=0.2, # データの20%をテストデータにする
random_state=42 # 乱数の種を固定して、再現性を確保
)
# ロジスティック回帰モデルの作成
# LogisticRegressionクラスを使用してモデルをインスタンス化
model = LogisticRegression() # ロジスティック回帰モデルのインスタンスを作成
# 訓練データでモデルを学習させる
# fitメソッド:訓練データ(特徴量とラベル)を入力してモデルを訓練
model.fit(X_train, y_train) # 訓練データ(X_train, y_train)で学習
# テストデータで予測を行う
# predictメソッド:入力データ(X_test)を元に予測値を出力
y_pred = model.predict(X_test) # テストデータ(X_test)に対する予測を実施
# 予測精度の計算
# accuracy_score関数:実際のラベル(y_test)と予測値(y_pred)を比較して正解率を計算
accuracy = accuracy_score(y_test, y_pred) # 精度を計算してaccuracyに代入
# 予測精度を画面に表示
# print関数:計算した精度を小数点以下2桁まで表示
print(f"予測精度: {accuracy:.2f}") # f文字列で精度を整形して出力
Pythonコードの解説
ライブラリのインポート
Pythonでは、特定の機能を使うために「ライブラリ」をインポートする必要があります。ライブラリは、他のプログラマが作った便利な道具箱のようなものです。今回使用するライブラリは以下の4つです。
pandas
- データを扱いやすい形(表形式)にするためのライブラリです。表計算ソフト(例:Excel)のように、データを行と列で整理できます。
- このコードでは、データを「DataFrame」という形式で管理します。
※DataFrameとは、行と列で構成された表形式のデータ構造で、Excelの表のようにデータを容易に整理可能にした形式の事を言います。
import pandas as pd # pandasライブラリをインポートし、「pd」という短い名前で使えるようにする
train_test_split
- scikit-learnという機械学習ライブラリの中の関数です。
- データを「訓練用」と「テスト用」に分ける役割があります。
- 訓練用データはモデルを学習させるために使い、テスト用データはモデルの性能を確認するために使います。
from sklearn.model_selection import train_test_split
LogisticRegression
from sklearn.linear_model import LogisticRegression
accuracy_score
from sklearn.metrics import accuracy_score
データの準備
データはプログラムにとっての「材料」です。このプログラムでは仮のデータを用意しています。
辞書型データの作成
Pythonの辞書型は、{}で囲み、キーと値のペアでデータを管理します。辞書型は、名前(キー)とその内容(値)をセットで保存するデータ形式です。
data = {
"price_change": [0.1, -0.2, 0.3, -0.1, 0.05, -0.3],
"volume": [100, 150, 200, 120, 80, 60],
"up_down": [1, 0, 1, 0, 1, 0]
}
price_change
: 前日比上昇率を示します。volume
: 出来高(その日の取引量)です。up_down
: 株価が上がった場合は1、下がった場合は0で記録しています。
辞書をDataFrameに変換
pandas.DataFrame
を使って、データを表形式(行と列を持つ形)に変換します。これにより、列名を指定してデータにアクセスできるようになります。
df = pd.DataFrame(data) # 辞書型データをDataFrameに変換
特徴量とラベルの分割
- 特徴量(入力データ)の選択
※特徴量は、モデルが予測のために利用する入力データのことです。例えば、「前日比上昇率」や「出来高」など、予測に関連する情報を指します。
※ラベルは、モデルが予測する対象(結果)のことです。例えば、「株価が上がるか下がるか」といった予測結果そのものを指します。
訓練とテストデータの分割
モデルを正しく評価するためには、データを「訓練用」と「テスト用」に分ける必要があります。
- 分割する理由
訓練データだけでモデルを評価すると、「そのデータだけに特化したモデル」になり、未知のデータに対応できない可能性があります。これを防ぐため、データの一部をテスト用に取っておきます。 train_test_split
の使い方train_test_split(X, y, test_size=0.2, random_state=42)
は、データを80%:20%に分割します。test_size=0.2
でテストデータを20%に設定しています。random_state=42
を設定すると、毎回同じ結果が得られるようになります。
- 分割結果
X_train
とy_train
は訓練用データです。X_test
とy_test
はテスト用データです
モデルの訓練
予測と精度計算
- 予測の実行
- 精度の計算
accuracy = accuracy_score(y_test, y_pred)
で、実際の値(y_test
)と予測値(y_pred
)を比較し、正解率を計算します。- 正解率は、予測が正しかった割合を示します。
- 結果の出力
print(f"予測精度: {accuracy:.2f}")
で、精度を小数点以下2桁まで表示します。f
文字列を使うと、変数を文字列の中に埋め込むことができます
ロジスティック回帰の限界と対策
1. 線形分離しかできない
ロジスティック回帰の限界:データを直線で分ける性質
ロジスティック回帰は、「線形分離」が可能なデータに対して非常に効果的です。しかし、データの分布が複雑で、直線(または平面)では分けられない場合には十分に対応できません。
線形分離とは?
「線形分離」とは、データを1本の直線や平面で明確に分けられる状態を指します。具体的に言うと、以下のようなイメージです:
例1:線形分離が可能な場合
イメージとしては、以下のように赤い点(クラス0)と青い点(クラス1)が1本の直線で分けられる状態を考えます。
● ● ● ● ● ← クラス0(赤い点)
------------------ ← 分類境界線
▲ ▲ ▲ ▲ ▲ ← クラス1(青い点)
この場合、ロジスティック回帰は、直線を引くことでデータを簡単に分離できます。
例2:線形分離が不可能な場合
一方、データが以下のように配置されている場合を考えます。
● ▲ ● ▲ ● ← クラス0とクラス1が混在
▲ ● ▲ ● ▲
具体例:株価データを使った線形分離の説明
線形分離が可能なケース
例えば、以下の条件で株価の動きを予測する場合を考えます:
データが以下のような単純な場合、線形分離が可能です:
前日比上昇率 (%) | 出来高 (100株単位) | 結果 (ラベル) |
---|---|---|
5.0 | 200 | 1 |
4.5 | 180 | 1 |
-1.0 | 150 | 0 |
-2.5 | 100 | 0 |
このデータでは「前日比上昇率」と「出来高」の間に1本の直線を引くことで、結果を0と1に分類できます。
線形分離が難しいケース
しかし、以下のようにデータが複雑化すると直線では分類できません:
前日比上昇率 (%) | 出来高 (100株単位) | 結果 (ラベル) |
---|---|---|
5.0 | 200 | 1 |
-2.0 | 220 | 0 |
3.5 | 100 | 1 |
-1.5 | 180 | 0 |
この場合、データが交差しており、複雑な境界が必要です。ロジスティック回帰はこの状況では不適切です。
2. データ量に依存する
訓練データが少ないと、モデルの性能が低下します。また、データの質も重要です。
限界への対策
- 非線形モデルを使用する ニューラルネットワークやサポートベクターマシン(SVM)を使用することで、非線形データも適切に分類できます。これらのモデルは直線に限定されず、曲線や複雑な形状でデータを分けることが可能です。
- 特徴量を工夫する 非線形の関係を持つ特徴量を導入することで、データを線形に変換できる場合があります。たとえば、株価の「二乗変化率」や「移動平均差分」を特徴量に追加するなどです。
まとめ
ロジスティック回帰はデータが単純で線形分離可能な場合に非常に効果的です。しかし、複雑なパターンを含むデータには非線形モデルを検討する必要があります。データの特性に応じた手法選択が重要です。