🈷️

月や曜日データを機械学習に使うときの「落とし穴」と「sin/cos変換」のすごい力

に公開

~時系列データ前処理の最適解を数学的にやさしく解説~

はじめに

株価や売上など、時系列データの分析・予測では「月(1月, 12月)」や「曜日(日~土)」など周期的なカレンダー情報を特徴量として使うことが多いです。
でも、「1月=1」「12月=12」とそのまま数値で入れるのはNGって知っていましたか?

本記事では、その理由とsin/cos関数を用いた変換(円環特徴量エンコーディング)の本質的なメリットを、初心者にも分かるように数式・図解・コード付きで解説します。


1. 月や曜日を「そのまま数値」で使う落とし穴

1-1. 危険性その1「数値の距離が意味を持たない」

例えば、「月」データ。

  • 1月 → 1
  • 12月 → 12

と入れてしまうと、1月と12月の距離が「11」もあることになる
でも本当は、カレンダー上は「1月⇔12月」は1ヶ月しか離れていません(12月→1月はすぐ隣)。

つまり「数字の差=現実の距離」にならず、機械学習モデルが誤解してしまう。

1-2. 危険性その2「順序の誤認識」

また、「12月」→「1月」とカレンダーが循環的に繰り返されることも、そのままでは伝わりません。
曜日も同様で、「日曜=0」「月曜=1」…「土曜=6」としても、「土曜」と「日曜」が「6」も離れてしまう。


2. 周期データを正しく表現する「sin/cos変換」

2-1. 数学的なアイデア:「円(単位円)」に乗せる

周期性(循環性)があるデータは、「直線」上ではなく「円(単位円)」上にマッピングするのが直感的。
1年=12ヶ月、1週間=7日と考えて、それぞれ0~2πの角度に対応させます。

  • 月データの場合

    \text{θ(月)} = 2π \times \frac{\text{月番号}}{12}
  • 曜日データの場合(週始めを0とした場合)

    \text{θ(曜日)} = 2π \times \frac{\text{曜日番号}}{7}

2-2. sin/cos変換の式と図解

  • sin変換:

    \text{sin}(θ) = \text{sin}\left(2π \times \frac{\text{値}}{周期}\right)
  • cos変換:

    \text{cos}(θ) = \text{cos}\left(2π \times \frac{\text{値}}{周期}\right)


(※単位円上のsin/cosのイメージ)

2-3. Pythonでの実装例

import numpy as np

# 月をsin/cosに変換
df["Month_sin"] = np.sin(2 * np.pi * df["Date"].dt.month / 12)
df["Month_cos"] = np.cos(2 * np.pi * df["Date"].dt.month / 12)

# 曜日(例:月〜金のみ稼働の株価の場合は周期5)をsin/cosに変換
df["DOW_sin"] = np.sin(2 * np.pi * df["Date"].dt.dayofweek / 5)
df["DOW_cos"] = np.cos(2 * np.pi * df["Date"].dt.dayofweek / 5)

※曜日は一般的には/7ですが、株式市場など「週5日」稼働の場合は/5に調整します。


3. sin/cos変換の直感的な効果機械学習へのメリット

3-1. 「循環性」を適切に表現

  • 1月と12月、日曜と土曜など、円の上で近い値として表現される
  • 距離感が現実と一致する

3-2. 「同じ周期上でパターン」を学習しやすい

  • XGBoostなどのツリー系モデルでも、連続的な値の組み合わせパターンを拾える
  • 「季節性」や「曜日パターン」の検出が容易に

3-3. 実際のモデル精度の向上も期待

  • 実務でも、周期データのsin/cos変換で予測精度・解釈性が改善する事例多数

4. おまけ:sin/cos変換のペアは必ずセットで!

  • sinだけ、cosだけでは「どの位置にいるか」を完全には表現できません。
  • **「sinとcosをセットで」**使うことで、円周上の任意の1点(角度)を一意に表現できます。

まとめ

  • 月や曜日などの周期データを「そのまま数値」で入れるのはNG
  • sin/cos変換を使えば、周期性・循環性を正しくモデルに伝えられる
  • 数学的な裏付けと実装も簡単
  • 時系列予測や分類の精度・安定性向上に必須のテクニック

参考文献・リンク

Discussion