Блог им. afecn19

CNN+wavelet = blue stocks forecast

После использования вейвлетов для классификации, я конечно сразу попробовал оценить ценность вейвлет для прогнозирования, но тестирование мягко говоря затянулось. Эпох я прогонял много, 600, а одна эпоха это минута. И оставляя нейросеть на ночь я забывал, то одно, то другое. Затем я стал пробовать разные learning rate, датасеты, архитектуры и обнаружилось что тот самый позитивный первоначальный результат (в виде 55% accuracy на валидации и over +75% на тесте) исчез, сеть не могла зацепить ничего, даже на тесте. В пятницу я решил в последний раз прогнать сеть и уже с 50 эпохи сеть начала уверенно обучаться. Обьяснение тому что на том же наборе данных, одна и та же сеть, то обучается, то необучается, у меня одно — каждый раз нейросеть начинает блуждать по гиперплоскости функции ошибки с разных мест, и при одном наборе весов застревает в зоне локальных минимумов, которые чуть-чуть лучше 50%, не в силах перескочить в область более низких минимумов. 
Данные все те же — голубые, отечественные. Тестирую на недельках, прогноз на недельку вперед. 
Помимо вейвлетов и CNN занялся вопросом выбора оптимального набора весов, благо у меня выбор широк — более 600 эпох. Вот есть трейн выборка на которой нейросеть учится, и где то к 300-400 эпохам уверенно подбирается к 75% угадайки. Замечательно. Есть валидация на которой  есть пик в 57% на 200 эпохе (±20), после чего она снижается и болтается в диапазоне 52-55%. Вот интересно, тесты будут лучше коррелировать с трейном или валидацией? Теория учит нас использовать валидацию, но если подумать то и в валидации тоже есть момент подгонки, да и 1 набор валидации это все такая же игра в кости. 
Приступим. У нас 600 эпох и наша задача придумать критерий для выбора той эпохи, где набор весов оптимальный для теста (out-sample). Насколько это важно? Ну вот например так выглядят средние профиты по эпохам на тесте:

CNN+wavelet = blue stocks forecast

Скачки велики, от -0,2 на 1 эпохе до 0,5. Так что правильно выбрать эпоху важно. А то вместо профита будем подсчитывать убытки и плакать.
Что скажет купечество?! То бишь теория? Теория говорит что надо опираться на валидацию, мол валидация даст нам знак на какой эпохе самые правильные веса, чтобы не попасть в оверфит.
Ну вот я наложил средние профиты на трeйне, валидации и тесте (голубой, красный, зеленый):
CNN+wavelet = blue stocks forecast
Ну понятно, трейн улетает в небо, сбивая масштаб, но если посмотреть результаты на тесте и валидации отдельно

CNN+wavelet = blue stocks forecast


то разве кто то скажет что тут все четко, и по валидации можно вытащить хороший набор весов для теста?
Я посчитал корреляцию по среднему профиту, и между тестом и валидацией он равен +0,28, а тестом и трейном +0,14. Если взять по точности, то корреляция трейна с валидацией выше: +0,49, но с тестом она еще выше +0,57. О как.  То есть ориентироваться на валидацию дело довольно сомнительное. 
Далее я пробовал разные способы, подбора по результатам на трейне и валидации найти оптимальный набор для теста, даже думал еще одну нейросеть прикрутить, но в общем ничего интересного не получил, поэтому описывать не буду.
Ну и наконец ради чего все это затевалось — можно ли на основе вейвлет преобразования на неделе, сделать какой то вразумительный прогноз на следующую неделю?! Взял эпоху по лучшей валидации. И у меня получилось что да, можно, мягко говоря не озолотитесь, но после того как мои прошлые нейросети не могли зацепить ничего от слова совсем, уступая в одну калитку градиентному бустингу /случайному лесу, то для меня это уже результ.
Результаты прогнозирования, count понятно что, mean — средняя профитность сделки:

CNN+wavelet = blue stocks forecast
Спрогнозировали 93 недели (каждый год должен быть по 40-42 недели, но часть 2018 года ушла под валидацию, а 2020 все никак не закончится). Данные представил с разной разбивкой-по акциям (стабильно по всем акциям, только Роснефть что то химичит), по лонг/шорт (видим что в половине случаев сеть спрогнозировала шорт, в половине лонг, что приятно. и там и там профиты). Для тех кто не понял почему суммы по count не совпадают: 
Недель 93, но каждая неделя это 6 фишек: 6*93 сделок.  93 лонгов означает что каждую недели были какие то лонговые сделки, средняя их равна +0,5%. Шортовых 92 — это значит что из 93 недель, в одну неделю ни одна акция не показала в шорт. 
Кстати если бы мы каждую неделю просто покупали бы все эти фишки, а в конце продавали, то средняя профитность составила бы +0,27% за неделю. Использование системы позволяет увеличить доходность по сделкам «только в лонг» до +0,5%. 

11 комментариев

Я когда пробовал нейросети первый раз — ещё мало что понимал, у меня получилось что что чуть ли не с третьей эпохи результат начинает ухудшаться на отложенной выборке. Щас я конечно по-другому бы все делал — может и результаты были бы другие. Здесь на графиках вижу, что после 50-й эпохи обучаться дальше нет смысле и выбирать «правильную» точку на участке 50+ — даже не переподгонка в стандартном смысле слова — просто самообман. На первых (единицы эпох) эпохах нейросеть вычленяет основную суть, дальше еще несколько десятков эпох что-то довысасывает из данных, дальше белый шум. Но из-за зашумленности данных (и выбранной архитектуры тоже, видимо) модель не переобучается в привычном смысле слова, результаты на отложенной выборке не падают.

 

Я буду копать в сторону более интересных данных на входе. Ещё хочу попробовать по-максимуму отнормировать данные и слить данные по разным тикерам в один датасет чтобы нейросеть получила больше данных на вход и выявила наиболее общие закономерности. Кстати, как вариант, можно обучить нейросеть на слитых данных, потом, как вариант, заморозить часть слоев (или нет) и дообучить на конкретном инструменте. 

avatar
Replikant_mih, имхо лучше просто в виде эмбединга добавлять значение тикера и прочие его качественные характеристики (тип инструмента, отрасль и т.д.) и учить в один проход сразу для всех инструментов. 
avatar
Михаил, Ну или так. Я пока только обучался на данных по одному инструменту. В смысле на разных инструментах, но всегда по одному. В общем надо экспериментировать, как всегда).
avatar
А чего за сеть вы используете?
avatar
Михаил, CNN:

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), strides=(1, 1), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Dropout(0.3))

model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(num_classes, activation='softmax'))


opt = keras.optimizers.Adam(learning_rate=0.001)

model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adam(),
metrics=['accuracy'])

С архитектурой особо не заморачивался, когда хотел усложнить — ресурсы у компа кончились
avatar
Марат, а сколько в ней обучаемых параметров и сколько у вас обучающих примеров?
avatar
Михаил, 1800 тест и по 500-600 на валидации и тесте

avatar
Марат, ёперный театр, так недели — это таймфрейм? были у меня сомнения, у меня даже бустинг на таком размере выборки не обучится), разве что если кол-во признаков измеряется единицами).
avatar
Replikant_mih, ну что делать, за день 15 минуток наберете штук 30-40, а это маловато для вейвлет преобразований. 
avatar
Марат, Сверточным слоям важно чтоб соседние ячейки в двумерном входном тензоре были обоснованно, скажем, так близки друг к другу. По одной из осей в рыночных данных (временная ось) это естественным образом обеспечивается, а вот по второй оси — это надо какие-то особым образом сформированные данные на вход подавать, иначе не уверен. Вроде есть свертка по одной оси, но пока не пробовал такую. 
avatar

теги блога Марат

....все тэги



UPDONW
Новый дизайн