はじめに
システムトレードや機械学習の分野では、「損失関数」が使われます。
損失関数は、モデルがどれだけ間違っているかを数値で表すために使用されます。この記事では、損失関数の基礎についてわかりやすく解説します。
損失関数とは?
損失関数とは、モデルが出した予測と本当の値(正解)との差を測るための指標です。この差が大きいほど、モデルの予測が正確ではないことを意味します。
※モデルとは、機械学習においてデータから規則性を学習し、新たなデータに対して予測や判断を行う仕組みを指します。システムトレードでは、株価の動きや経済データの予測などに使用されます。
例えば、テストの点数を予測するモデルが80点と予測したものの、実際は70点だった場合、10点のズレがあります。このズレを表すのが損失関数です。
システムトレードで損失関数が重要な理由
システムトレードでは、未来の値動きやパフォーマンスを予測するモデルを使うことが一般的です。このモデルの精度を評価し、改善するために、損失関数が役立ちます。
例えば、システムトレードのモデルが来週の株価が100円上がると予測したのに、実際は50円しか上がらなかった場合、そのズレを損失関数を使って数値化し、改善の指針とすることができます。
損失関数の種類
損失関数には多くの種類があります。ここでは回帰問題向け、分類問題向け、特殊な損失関数の例を紹介します。
回帰問題とは
回帰問題とは、数値を予測する問題です。例えば、明日の気温や家の価格を予測することが回帰問題にあたります。入力に対して連続的な値(例えば「25.3度」や「300万円」といったような数値)を出力するのが目的です。
分類問題とは
一方、分類問題とは、入力データをいくつかのグループに分ける問題です。例えば、犬か猫かを判別することや、テストの点数から「合格」か「不合格」かを決めることが分類問題です。このとき、出力するのは「犬」「猫」「合格」「不合格」といった離散的なラベル(まとまった選択肢から選ぶもので、値が連続していないもの)です。
回帰問題向けの損失関数
平均二乗誤差(Mean Squared Error, MSE)
平均二乗誤差は、予測と実際の値の差を二乗してその平均を求めたものです。ズレが大きいほど二乗によってその影響が増幅されるため、大きな誤差を重視する特性があります。
計算方法
- 予測値と実際の値の差を求めます。
- 差を二乗します。
- 全ての二乗した差を足し、その合計をデータの数で割ります。
例えば、予測値が80、70、90で、実際の値が70、60、85の場合、差は10、10、5となります。これを二乗して合計すると100 + 100 + 25 = 225。データ数3で割ると平均二乗誤差は75になります。
平均絶対誤差(Mean Absolute Error, MAE)
平均絶対誤差は、予測と実際の値の差の絶対値を取り、その平均を求めたものです。二乗を行わないため、MSEよりも大きなズレに敏感ではありません。
計算方法
例えば、予測値が80、70、90で、実際の値が70、60、85の場合、差の絶対値は10、10、5となります。これを合計すると10 + 10 + 5 = 25。データ数3で割ると平均絶対誤差は8.33になります。
絶対値とは
絶対値とは、ある数の「大きさ」を示すもので、その数がプラスかマイナスかに関係なく、常に正の値で表されます。例えば、+5の絶対値は5、-3の絶対値も3です。絶対値を取ることで、数値がどれだけ離れているか、その「距離」だけを考えることができます。
ハバーバ損失(Huber Loss)
ハバーバ損失は、平均二乗誤差(Mean Squared Error, MSE)と平均絶対誤差(Mean Absolute Error, MAE)の良いところを組み合わせた損失関数です。誤差が小さいときはMSEのように振る舞い、誤差が大きくなるとMAEのように振る舞います。
計算方法
- 誤差が設定した閾値(基準となる数値)より小さい場合は、二乗誤差を使用します。
- 誤差が閾値を超える場合は、絶対誤差を使用します。
ハバーバ損失は、閾値をパラメータとして調整することで、外れ値の影響を適切にコントロールします。
対数誤差(Log-Cosh Loss)
対数誤差は、平均二乗誤差(Mean Squared Error, MSE)に似ていますが、大きなズレに対しては平均絶対誤差(Mean Absolute Error, MAE)のように振る舞います。これにより、外れ値の影響を抑えつつ、精度を保つことができます。
計算方法
- 誤差の絶対値を計算します。
- log(cosh(誤差)) を適用します。
具体例
例えば、予測値が50で実際の値が45の場合、誤差は 50 – 45 = 5 となります。
- 誤差の絶対値を取ります:
|5| = 5
。 - log(cosh(5)) を計算します。
ここで、coshは「ハイパボリックコサイン」という関数で、cosh(x) = (e^x + e^(-x)) / 2 という式で表されます。
まず cosh(5) を計算します:
cosh(5) = (e^5 + e^(-5)) / 2
e^5 の値は約 148.413、e^(-5) の値は約 0.0067 なので、
cosh(5) ≈ (148.413 + 0.0067) / 2 = 74.20985。
次に log(cosh(5)) を求めます:
log(74.20985) ≈ 4.305。
したがって、この場合の対数誤差は約 4.305 になります。
※対数とは何か?
対数とは、ある数を何回かけると別の数になるかを示すものです。例えば、log(100)
は「10を何回かけると100になるか」を意味し、その答えは2です(10^2 = 100
)。対数を使うことで、大きな数を扱いやすくしたり、数の増え方を理解しやすくすることができます。
クロスエントロピー損失(Cross-Entropy Loss)
クロスエントロピー損失は、分類問題でよく使われる損失関数です。分類問題とは、例えば「犬、猫、鳥の中からどれかを予測する他クラス分類」や、「買いか売りかを予測する2値分類」のようなものです。この損失関数は、予測の確率が正しいクラスに近づくほど損失が小さくなるように設計されています。
クロスエントロピーという名前の由来は、情報理論で使われる「エントロピー」という概念からきています。エントロピーは情報の不確実さを表し、クロスエントロピーはその不確実さを比較することにより、予測の良し悪しを判断します。
計算方法
- 正解クラスに対応する確率を取り出します。
- その確率の対数を取り、マイナスを掛けます。
- 全データの平均を取ります。
具体例
例えば、あるモデルが「犬」「猫」「鳥」という3つのクラスから1つを予測するとします。実際の正解は「猫」であり、モデルの予測は次のような確率を出しています:
- 犬: 0.1
- 猫: 0.7
- 鳥: 0.2
この場合、正解クラスである「猫」に対応する確率は 0.7
です。
- 正解クラスの確率:
P = 0.7
- その確率の対数を取り、マイナスを掛けます:
損失 = -log(P) = -log(0.7)
ここで、log(0.7) を計算すると、約 -0.1549 になります。
したがって、損失は次のようになります:
損失 = -(-0.1549) = 0.1549
これが1つのデータに対するクロスエントロピー損失です。
もし全てのデータに対する損失を求める場合には、全ての損失を合計し、データの数で割って平均を取ります。
クロスエントロピーの仕組み
クロスエントロピー損失が小さくなるほど、モデルの予測が正解クラスに近づいていることを意味します。例えば、正解が「猫」である場合、モデルの「猫」と予測する確率が高いほど、損失は小さくなります。逆に、間違ったクラスに高い確率を割り当ててしまうと損失が大きくなります。このようにして、モデルが正しいクラスを選ぶように学習を進めることができます。
サンプルコード:Pythonで損失関数を計算する
# 必要なライブラリをインポート
import numpy as np
# 実際の値(正解)と予測値
actual = np.array([70, 60, 85]) # 実際のデータ
predicted = np.array([80, 70, 90]) # モデルの予測値
# 差を計算
differences = predicted - actual # 予測値と実際値の差を計算
# 差の二乗
squared_differences = differences ** 2 # 差の二乗を計算
# 平均二乗誤差を計算
mse = np.mean(squared_differences) # 二乗した差の平均を計算
# 結果を表示
print("平均二乗誤差:", mse) # 結果をコンソールに出力
サンプルコードの解説
ライブラリのインポート
最初に numpy ライブラリをインポートしています。numpy は数値計算を効率的に行うためのライブラリで、配列(複数のデータを一括で扱うデータ構造)や数学関数をサポートします。
import 文は外部のライブラリやモジュールを使用するために使います。この場合、import numpy as np という形式でインポートしていますが、ここで as np
は numpy を短縮して np
という名前で使うことを意味します。これにより、コード内で numpy
と書く代わりに、np
と短く書けるようになります。例えば、numpy.array()
の代わりに np.array() と書くことで、コードが読みやすくなり、入力も楽になります。
データの設定
actual には実際の値、predicted にはモデルが予測した値を設定しています。それぞれ np.array を使い、数値データの配列として定義しています。
np.array メソッドの役割
np.array は、リストやタプルなどのデータを「配列(複数のデータを効率的に扱うためのデータ構造)」に変換するためのメソッドです。この配列は、数学的な計算やデータの操作を効率的に行えるよう設計されています。
例えば、リスト [70, 60, 85] をそのまま使うと、計算を行う際にループを使う必要がありますが、np.array
に変換すれば一括で計算が可能になります。
np.array の引数について
np.array
は以下のように使用されます。
np.array(data, dtype=None)
- data
配列の元となるデータを指定します。リストやタプルなどの形式でデータを渡します。
例:[70, 60, 85]
や(80, 70, 90)
が該当します。 - dtype(データ型、オプション)
配列内のデータ型を指定します。例えば、整数ならint
、浮動小数点ならfloat
を指定します。指定しない場合、データに基づいて自動的に設定されます。
例: dtype=int は整数型の配列、dtype=float
は小数型の配列を作ります。
使用例の解説
次のコードで、np.array
の使い方を見てみます。
actual = np.array([70, 60, 85]) # 実際の値をリスト形式で渡して配列に変換
predicted = np.array([80, 70, 90]) # モデルの予測値を同様に配列に変換
- actual
実際の値[70, 60, 85]
をnp.array
で配列に変換しています。この配列は数値計算用に効率化され、例えば、他の配列との演算が可能になります。 - predicted
モデルの予測値[80, 70, 90]
を同様にnp.array
で配列に変換しています。これにより、予測値と実際の値を直接計算(例えば引き算)できるようになります。
差の計算
differences = predicted – actual の部分では、predicted
(予測値の配列)と actual
(実際の値の配列)の差を計算しています。この差は損失関数を計算する際の基本となるデータです。
具体的な動作
配列の引き算は要素ごとに行われます。例えば、次のようなデータの場合を考えます。
actual = np.array([70, 60, 85])
predicted = np.array([80, 70, 90])
それぞれの要素を引き算すると以下の結果になります。
differences = [80 - 70, 70 - 60, 90 - 85]
= [10, 10, 5]
この操作は、各データポイントごとに予測値と実際の値の差を算出し、それを配列として保存するものです。
差の二乗
differences ** 2
の計算では、差の値を要素ごとに2乗します。これにより、正負に関わらず誤差の大きさが反映されます。
具体的な動作
上記の differences 配列を2乗すると以下のようになります。
squared_differences = [10**2, 10**2, 5**2]
= [100, 100, 25]
これは、それぞれの誤差の絶対的な大きさを強調する役割を持っています。二乗を取ることで、特に大きな誤差をより強く反映する仕組みになっています。
平均二乗誤差の計算
np.mean(squared_differences)
では、差の二乗の平均を計算します。この計算により、すべてのデータポイントにわたる誤差の平均的な大きさを測定します。
具体的な動作
例えば、squared_differences
が [100, 100, 25]
の場合、次のように計算されます。
mse = (100 + 100 + 25) / 3
= 225 / 3
= 75
ここで得られた値 75
が、平均二乗誤差として損失関数の結果となります。
結果の表示
print(“平均二乗誤差:”, mse) のコードは、計算された平均二乗誤差を画面に表示する役割を持っています。この print
は、Pythonで文字列や変数の値をコンソールに出力するための関数です。
具体的な動作
コード全体を実行すると以下のように表示されます。
平均二乗誤差: 75.0
ここでは “平均二乗誤差:” という固定の文字列に続けて、変数mse の値が表示されます。これにより、ユーザーは計算結果を確認できます。
これらの手順を通じて、損失関数の計算が実現されています。
まとめ
損失関数は、モデルの精度を評価するための重要な指標です。回帰問題や分類問題では適した損失関数が異なり、問題に応じた選択が必要です。また、Pythonのコードを使えば損失関数を簡単に計算でき、モデル改善の基盤となります。損失関数の正しい理解と活用が、システムトレードや機械学習の成功につながります