Темы: Очистка данных, Выбор целевой переменной, Извлечение признаков, Масштабирование, Уменьшение размерности

В этом руководстве по машинному обучению я исследую 4 этапа, которые определяют типичный проект машинного обучения: предварительная обработка, обучение, оценка и прогнозирование (развертывание). В этой первой части я завершу этап предварительной обработки. Другие уроки в этой серии: Предварительная обработка №1 (эта статья), Обучение №2, Оценка №3, Прогнозирование №4

Я буду использовать данные о ценах на акции в качестве основного набора данных. Это хороший выбор для учебника по нескольким причинам:

  • Набор данных является общедоступным по определению и может быть легко загружен из нескольких источников, чтобы любой мог воспроизвести работу.
  • Не все функции доступны сразу из источника, и их нужно извлекать с использованием знаний предметной области, как в реальной жизни.
  • Результат проекта крайне неопределенен, что опять же имитирует реальную жизнь. Ежегодно на решение проблемы прогнозирования курса акций тратятся миллиарды долларов, и подавляющее большинство проектов терпят неудачу. Таким образом, это руководство не о создании волшебной машины для печати денег; речь идет о воспроизведении опыта, который инженер по машинному обучению мог бы получить с проектом.

Весь код находится в следующем репозитории Github. Файл preprocessing.py управляет анализом. Рекомендуется Python 3.6, и в этом файле есть инструкции по настройке всех необходимых зависимостей.

Сначала нам нужно загрузить набор данных. Я несколько произвольно выберу данные об акциях Microsoft (источник: Yahoo Finance). Я буду использовать всю доступную историю, которая на момент написания включает 13.03.1986 - 30.07.2018. Цена акций за этот период изменилась следующим образом:

Ценовое движение интересно тем, что демонстрирует как минимум два режима поведения:

  • крутой рост до 2000 года, когда рухнули акции технологических компаний
  • боковое движение с 2000 года

Это создает ряд интересных сложностей машинного обучения, таких как выборка данных для обучения и тестирования.

Очистка данных

После некоторых простых манипуляций и загрузки данных csv в pandas DataFrame у нас есть следующий набор данных, где открытие, максимум, минимум и закрытие представляют цены на каждую дату, а объем - общее количество проданных акций.

Отсутствующие значения отсутствуют, что я подтвердил, выполнив следующую команду:

missing_values_count = df.isnull().sum()

Выбросы - это следующая тема, которую мне нужно затронуть. Ключевой момент, который здесь следует понять, заключается в том, что наш набор данных теперь включает цены, но цены не являются метрикой, которую я попытаюсь прогнозировать, потому что они измеряются в абсолютном выражении и поэтому их сложнее сравнивать по времени и другим активам. В приведенных выше таблицах первая доступная цена составляет ~ 0,07 доллара США, а последняя - 105,37 доллара США.

Вместо этого я попытаюсь спрогнозировать дневную доходность. Например, по итогам второго торгового дня доходность составила + 3,6% (0,073673 / 0,071132). Поэтому я создам столбец возврата и буду использовать его для анализа возможных выбросов.

В наборе данных представлены 5 наименьших ежедневных доходностей:

И 5 самых крупных ежедневных доходов:

Самая отрицательная доходность - -30% (индекс 405), самая большая - 20% (индекс 3692). Обычно здесь необходим дальнейший предметный анализ выбросов. Я пропущу его сейчас и предполагаю, что в этом руководстве процесс описывается только в иллюстративных целях. В целом, данные кажутся логичными, учитывая, что в 1987 и 2000 годах произошли рыночные обвалы, связанные с чрезвычайной волатильностью.

Такой же анализ потребуется для открытых, высоких, низких и объемных столбцов. По общему признанию, очистка данных была несколько академической, потому что Yahoo Finance - очень широко используемый и надежный источник. Это все еще полезное упражнение для понимания данных.

Выбор целевой переменной

Нам нужно определить, что наши алгоритмы машинного обучения попытаются спрогнозировать. В частности, мы прогнозируем возврат на следующий день. Здесь важны сроки возврата, поэтому мы не можем ошибочно прогнозировать сегодняшнюю или вчерашнюю прибыль. Формула для определения завтрашней прибыли в качестве целевой переменной выглядит следующим образом:

df["y"] = df["return"].shift(-1)

Извлечение функций

Теперь я перейду к некоторым простым преобразованиям цен, доходности и объема, чтобы извлечь функции, которые могут потреблять алгоритмы ML. Специалисты в области финансов разработали сотни таких функций, но я покажу лишь некоторые из них. Хедж-фонды потратили подавляющее большинство времени на этот шаг, потому что алгоритмы машинного обучения обычно настолько полезны, насколько доступны доступные данные, иначе говоря. Мусор на входе, мусор на выходе.

Одна особенность, которую мы могли бы рассмотреть, - это то, как сегодняшняя цена закрытия соотносится с ценой закрытия 5 торговых дней назад (одна календарная неделя). Я называю эту функцию «5d_momentum»:

df[“5d_momentum”] = df[“close”] / df[“close”].shift(5)

Одна типичная функция отслеживания тренда - это MACD (осциллятор схождения / расхождения скользящих средних). Здесь проявляются сильные стороны панд, потому что MACD можно создать всего за 4 строки кода. График индикатора MACD ниже. На нижнем графике типичным сигналом к ​​покупке является пересечение синей macd_line над оранжевой линией, представляющей 9-дневную экспоненциальную скользящую среднюю macd_line. Обратное будет сигналом на продажу.

Код python «generate_features.py», расположенный в репозитории Github, упомянутом выше, включает дополнительные функции, которые мы могли бы рассмотреть. Например:

В конце процесса извлечения признаков у нас есть следующие особенности:

['return', 'close_to_open', 'close_to_high', 'close_to_low', 'macd_diff', 'ma_50_200', 'sar', 'stochastic_oscillator', 'cci', 'rsi', '5d_volatility', '21d_volatility', '60d_volatility', 'bollinger', 'atr', 'on_balance_volume', 'chaikin_oscillator']

Отбор проб

Нам нужно разделить данные на сегменты обучения и тестирования. Я не могу не подчеркнуть, что набор данных тестирования никогда не должен использоваться на этапе обучения. Он будет использоваться только на этапе оценки, чтобы показатели производительности были полностью независимы от обучения и представляли объективную оценку фактической производительности.

Обычно мы можем рандомизировать выборку данных тестирования, но данные временных рядов часто не подходят для рандомизированной выборки. Причина в том, что это может повлиять на процесс обучения. Например, рандомизация может привести к ситуации, когда точка данных от 01.01.2005 используется на этапе обучения для последующего прогнозирования доходности от 01.01.2003.

Поэтому я выберу гораздо более простой способ выборки данных и буду использовать первые 7000 выборок в качестве набора данных для обучения для обучения, а оставшиеся 962 - в качестве набора данных для тестирования для оценки.

Оба набора данных будут сохранены как файлы csv, поэтому мы завершаем эту часть учебника ML, сохраняя 4 файла (MSFT_X_learn.csv, MSFT_y_learn.csv, MSFT_X_test.csv, MSFT_y_test.csv). Они будут использованы на следующих этапах этого руководства.

Масштабирование

Масштабирование функций используется для сокращения времени на обучение. Обычно это относится к стохастическому градиентному спуску и SMV.

Пакет с открытым исходным кодом sklearn будет использоваться для большинства дополнительных приложений машинного обучения, поэтому я начну использовать его здесь, чтобы масштабировать все функции, чтобы получить нулевое среднее значение и единичную дисперсию:

from sklearn import preprocessing
scaler_model = preprocessing.StandardScaler().fit(X_train)
X_train_scaled = scaler_model.transform(X_train)
X_test_scaled = scaler_model.transform(X_test)

Важно, чтобы выборка данных производилась до изменения функций, чтобы избежать какого-либо обучения тестированию утечки данных.

Уменьшение размерности

На данном этапе в нашем наборе 17 функций. Количество функций существенно влияет на скорость обучения. Мы могли бы использовать ряд методов, чтобы попытаться уменьшить количество функций, чтобы остались только самые «полезные» функции.

Многие хедж-фонды на этом этапе будут работать с сотнями функций, поэтому уменьшение размеров будет критичным. В нашем случае у нас есть только 17 иллюстративных функций, поэтому я сохраню их все в наборе данных, пока не изучу время обучения различных алгоритмов.

Однако из любопытства я проведу анализ основных компонентов (PCA), чтобы получить представление о том, сколько функций мы могли бы создать из нашего набора данных, не теряя при этом значимой объяснительной способности.

from sklearn.decomposition import PCA
sk_model = PCA(n_components=10)
sk_model.fit_transform(features_ndarray)
print(sk_model.explained_variance_ratio_.cumsum())
# [0.30661571 0.48477408 0.61031358 0.71853895 0.78043556 0.83205298
 0.8764804  0.91533986 0.94022672 0.96216244]

Первые 8 характеристик объясняют 91,5% дисперсии данных. Обратной стороной PCA является то, что новые функции расположены в пространстве с более низкой размерностью, поэтому они больше не соответствуют реальным концепциям. Например, первой оригинальной функцией может быть «macd_line», полученный мной выше. После PCA первая функция объясняет 31% отклонения, но у нас больше нет логического описания того, что эта функция представляет в реальной жизни.

На данный момент я сохраню все функции 17 оригинальных функций, но отмечу, что если время обучения алгоритмов слишком велико, будет полезен PCA.

Другие уроки в этой серии: Предварительная обработка №1 (эта статья), Обучение №2, Оценка №3, Прогнозирование №4.

Сайт автора: adamnovotny.com