web-dev-qa-db-ja.com

Scikit-learnを使用した日付変数による回帰

Pandas dtype 2013-04-01date列(例:datetime.date)を含むDataFrameがあります。その列をX_trainに含め、回帰モデルに適合させようとすると、エラーfloat() argument must be a string or a numberdate列を削除すると、このエラーは回避されました。

回帰モデルでdateを考慮する適切な方法は何ですか?

コード

data = sql.read_frame(...)
X_train = data.drop('y', axis=1)
y_train = data.y

rf = RandomForestRegressor().fit(X_train, y_train)

エラー

TypeError                                 Traceback (most recent call last)
<ipython-input-35-8bf6fc450402> in <module>()
----> 2 rf = RandomForestRegressor().fit(X_train, y_train)

C:\Python27\lib\site-packages\sklearn\ensemble\forest.pyc in fit(self, X, y, sample_weight)
    292                 X.ndim != 2 or
    293                 not X.flags.fortran):
--> 294             X = array2d(X, dtype=DTYPE, order="F")
    295 
    296         n_samples, self.n_features_ = X.shape

C:\Python27\lib\site-packages\sklearn\utils\validation.pyc in array2d(X, dtype, order, copy)
     78         raise TypeError('A sparse matrix was passed, but dense data '
     79                         'is required. Use X.toarray() to convert to dense.')
---> 80     X_2d = np.asarray(np.atleast_2d(X), dtype=dtype, order=order)
     81     _assert_all_finite(X_2d)
     82     if X is X_2d and copy:

C:\Python27\lib\site-packages\numpy\core\numeric.pyc in asarray(a, dtype, order)
    318 
    319     """
--> 320     return array(a, dtype, copy=False, order=order)
    321 
    322 def asanyarray(a, dtype=None, order=None):

TypeError: float() argument must be a string or a number
24
Nyxynyx

最善の方法は、1-of-Kエンコーディングを使用してブール形式でエンコードされた一連のカテゴリカル特徴に日付を分解することです(例: DictVectorizer で行われるように)。日付から抽出できるいくつかの機能は次のとおりです。

  • 時間帯(24のブール型機能)
  • 曜日(7つのブール機能)
  • 月の日(最大31のブールフィーチャ)
  • 今年の月(12のブール機能)
  • 年(データセット内の異なる年と同じ数のブールフィーチャ)...

これにより、典型的な人間のライフサイクルにおける定期的なイベントの線形依存関係を特定できるようになります。

さらに、日付を単一の浮動小数点数で抽出することもできます。各日付をトレーニングセットの最小日付以降の日数として変換し、最大日付と最小日付の日数の差で除算します。この数値機能により、イベント日付の出力間の長期的な傾向を特定できるようになります。年の特徴のブールカテゴリ変数でエンコードできない、来たる年の進化をよりよく予測するための回帰問題の線形勾配。

31
ogrisel

2つのオプションがあります。日付を序数、つまり1年1日からの日数を表す整数に変換できます。これは、datetime.datetoordinal関数。

または、sklearnの OneHotEncoder を使用して日付をカテゴリ変数に変換することもできます。それが行うことは、それぞれの異なる日付に対して新しい変数を作成することです。したがって、列dateのような値ではなく、値['2013-04-01', '2013-05-01']、2つの列、date_2013_04_01値付き[1, 0]およびdate_2013_05_01値付き[0, 1]

異なる日付が多数ある場合はtoordinalアプローチを使用し、個別の日付の数が少ない場合は1つのホットエンコーダーを使用することをお勧めします(データのサイズと内容によっては最大10〜100としましょう)日付と出力変数の関係の種類)。

12
Ando Saabas

@ogriselによって提案された1-of-Kエンコーディングを使用してブールエンコーディングを実行する前に、データを充実させて、datetime-typeから抽出できる多数の機能(つまり、曜日、曜日、日)を試してみることができます。年、週、四半期など。例 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DatetimeIndex.weekofyear.html と他へのリンクを参照機能。

2

多くの場合、機能の量を少なくしておくことをお勧めします。タイムスタンプから必要な情報は多くありません。私の場合、日付を最初のタイムスタンプとの日差として保持することで十分でした。これにより順序が保持され、1つの(通常の)機能のみが残ります。

df['DAY_DELTA'] = (df.TIMESTAMP - df.TIMESTAMP.min()).dt.days

原因として、これは1日以内の動作を識別しません(時間に依存)。そのため、データの変化する動作を最もよく識別するスケールまで下がる必要があるかもしれません。

何時間も:

df['HOURS_DELTA'] = (df.TIMESTAMP - df.TIMESTAMP.min()).dt.components['hours']

上記のコードは、古いTIMESTAMPを削除するために、デルタ値を持つ新しい列を後で追加します。

df = df.drop('TIMESTAMP', axis=1)
0
Sebastian N