Регрессия с переменной Date с использованием Scikit-learn
У меня есть Pandas DataFrame с столбцом date
(например: 2013-04-01
) dtype datetime.date
. Когда я включаю этот столбец в X_train
и пытаюсь подобрать модель регрессии, я получаю float() argument must be a string or a number
error float() argument must be a string or a number
. Удаление столбца date
предотвратило эту ошибку.
Каков правильный способ учета 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
Ответы
Ответ 1
Лучший способ - взорвать дату в набор категориальных функций, закодированных в логической форме, с использованием кодирования 1-к-K (например, как это сделано DictVectorizer). Вот некоторые функции, которые можно извлечь из даты:
- час дня (24 логических объекта)
- день недели (7 булевых функций)
- день месяца (до 31 логических функций)
- месяц года (12 логических функций)
- год (как много логических функций, поскольку они разные годы в вашем наборе данных)...
Это должно позволить идентифицировать линейные зависимости от периодических событий на типичных жизненных циклах человека.
Кроме того, вы также можете вывести дату одним поплавком: конвертировать каждую дату в число дней с момента минимальной даты вашего тренировочного набора и разделить на разницу между количеством дней между максимальной датой и количеством дней с датой min, Эта численная функция должна позволять идентифицировать долгосрочные тенденции между выходом даты события: например, линейный наклон в задаче регрессии, чтобы лучше прогнозировать эволюцию в ближайшие годы, которая не может быть закодирована с помощью логической категориальной переменной для функции года,
Ответ 2
У вас есть два варианта. Вы можете преобразовать дату в порядковый номер, т. toordinal
Целое число, представляющее количество дней с 1-го дня 1-го дня. Вы можете сделать это с помощью функции datetime.date
toordinal
.
Кроме того, вы можете включить даты в категориальные переменные, используя sklearn OneHotEncoder. Он создает новую переменную для каждой отдельной даты. Так что вместо того, чтобы что - то вроде столбца date
со значениями ['2013-04-01', '2013-05-01']
, вы будете иметь две колонки, date_2013_04_01
со значениями [1, 0]
и date_2013_05_01
со значениями [0, 1]
,
Я бы рекомендовал использовать подход toordinal
если у вас много разных дат, и один горячий кодировщик, если количество отдельных дат невелико (допустим, до 10 - 100, в зависимости от размера ваших данных и какого рода отношение к дате имеет с выходной переменной).
Ответ 3
Прежде чем делать булево кодирование с использованием кодировки 1-в-K, предложенной @ogrisel, вы можете попробовать обогатить свои данные и сыграть с количеством функций, которые вы можете извлечь из типа datetime, то есть день недели, день месяца, день года, недели года, квартала и т.д. См. например https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DatetimeIndex.weekofyear.html и ссылки на другие функции.