Машинное обучение в трейдинге: теория, модели, практика и алготорговля - страница 136

 

А как именно вы считаете R^2, какой функцией?

Я пробовал обучить разные модели через rattle, в нём считалось "pseudo r^2" через корреляцию, а именно cor(fitpoints[,1], fitpoints[,2])^2, но я хочу посчитать r^2 тем-же методом что и вы для сравнения.

Подойдёт ли такой код [1 - sum((y-x)^2)/sum((y-mean(y))^2)] ? 

 
Dr.Trader:

А как именно вы считаете R^2, какой функцией?

Я пробовал обучить разные модели через rattle, в нём считалось "pseudo r^2" через корреляцию, а именно cor(fitpoints[,1], fitpoints[,2])^2, но я хочу посчитать r^2 тем-же методом что и вы для сравнения.

Подойдёт ли такой код [1 - sum((y-x)^2)/sum((y-mean(y))^2)] ? 


Именно так. X - модель.

 
Dr.Trader:

Чем больше нейронов в скрытом слое - тем более сложную функцию можно описать нейронкой, вам нужно больше скрытых слоёв и нейронов в них.

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

Ещё, выход нейронки ограничен активационной функцией. Для популярных - сигмоида это (0;1), relu - [0;inf). Целевые значения нужно прошкалировать в другой интервал, ваши выходы в интервале (-7;7) просто недостижимы для многих пакетов.

Я шкалирую все данные ср.0 ст.откл.1. 

можно целевку сделать -1;1. Но это реально нужно, только если на выходном нейроне нелин.активация тангенс. 

0:;1 для сигмоиды в аналогичном случае. 

А если там identity то в принципе не обязательно. но надо учесть реальных размах данных. Веса могут не насытиться до такого уровня.

А я учу с выводом кривых на трейне и тесте и вижу где остановиться надо.
 

Ещё раз взял rattle, обучил nnet, взял готовый код с лога. Rattle не совсем правильно работает с nnet, я добавил ещё немного кода для того чтоб вовремя остановить обучение.

Лучший R^2 на новых данных = 0.18. Лучшая конфигурация сети вышла довольно забавной, с одним нейроном в единственном внутреннем слое. Ещё можно два нейрона во внутреннем слое, будет примерно такой-же результат. Если продолжить увеличивать их количество - то судя по графику сеть очень быстро переобучается и всё хуже работает на новых данных.

 

На правом графике синенькая линия - это новые для модели данные, со строки 20001. Остальные это обучение и кроссвалидация.

Похоже что свёрточная сеть лидирует.

Файлы:
 
Dr.Trader:

Ещё раз взял rattle, обучил nnet, взял готовый код с лога. Rattle не совсем правильно работает с nnet, я добавил ещё немного кода для того чтоб вовремя остановить обучение.

Лучший R^2 на новых данных = 0.18. Лучшая конфигурация сети вышла довольно забавной, с одним нейроном в единственном внутреннем слое. Ещё можно два нейрона во внутреннем слое, будет примерно такой-же результат. Если продолжить увеличивать их количество - то судя по графику сеть очень быстро переобучается и всё хуже работает на новых данных.

 

На правом графике синенькая линия - это новые для модели данные, со строки 20001. Остальные это обучение и кроссвалидация.

Похоже что свёрточная сеть лидирует.

Результат хороший! Поздравляю, вы обошли мою простую НС.

Фичи готовили или подавали как есть лаги? Эту задачу на чистых лагах не решить, вроде бы. Подготовка фичей нужна.

Еще наблюдение - походу, ваш выход сети строго -1;1. Либо взяли тангенс активацию и потом не сделали обратного преобразования выхода, либо что-то еще.

И чисто для справки. Сверточная сеть (глубокое обучение) в пакете mxnet. Пока версия только с git. Но основное все работает.
 
Alexey Burnakov:

И чисто для справки. Сверточная сеть (глубокое обучение) в пакете mxnet. Пока версия только с git. Но основное все работает.

просто наблюдение, не в тему но....   когда я просил помочь разобраться с сверточной сетью  и обращал внимание на пакет  mxnet,  то все молчали, молв. тусуйся себе парень,  а теперь всем вдруг стало интересно заниматься тем о чем я говорил страниц 50 назад, почему так происходит? :)  Интересно может так через страниц 100 кто то заметит и пакет quantstrat на который я тоже обращал внимание уже давным давно....

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

 
mytarmailS:

просто наблюдение, не в тему но....   когда я просил помочь разобраться с сверточной сетью  и обращал внимание на пакет  mxnet,  то все молчали, молв. тусуйся себе парень,  а теперь всем вдруг стало интересно заниматься тем о чем я говорил страниц 50 назад, почему так происходит? :)  Интересно может так через страниц 100 кто то заметит и пакет quantstrat на который я тоже обращал внимание уже давным давно....

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

Просто замечательный комментарий, коллега! ) Ха

Позвольте ответить по пунктам согласно моему видению:

1) Здесь людьми на 90% руководит собственный интерес, фаза мышления и стадия эксперимента. Поэтому некоторые хорошие идеи откладываются в долгий ящик. Так как вы не привели никаких интересных примеров и задачек, никто не занитересовался. Просто, да?

2) Есть две стратегии получить знания: самому рыть и мучительно что-то пытаться сделать (мы все в разной степени это делаем. Я например, помню чувака из темы "Учитесь зарабатывать, Селяне!", который потратил несколько лет жизни проверяя работоспособность доступных советников. И все они слили.) Другой вариант - подождать, в надежде, что кто-то поможет и выложит готовое. Так вот, если вы в силу ваших обстоятельств, выбрали вторую стратегию, то срок ожидания готового может быть весьма растянут.

По поводу mxnet, раз уж я ей занялся, мне не жалко выложить код, который, кстати, почти в том же виде лежит в интернете:

install.packages("drat", repos="https://cran.rstudio.com")
drat:::addRepo("dmlc") 

install.packages("mxnet") 

 

 

train.x = data.matrix(dat_ready_scale[1:(nrow(dat_ready_scale) / 2), 1:100])

train.y = dat_ready_scale[1:(nrow(dat_ready_scale) / 2), 101]

test.x = data.matrix(dat_ready_scale[!rownames(dat_ready_scale) %in% rownames(train.x), 1:100])

test.y = dat_ready_scale[!rownames(dat_ready_scale) %in% rownames(train.x), 101]



########

train.x <- t(train.x)

test.x <- t(test.x)


dim(train.x) <- c(100, 1, 1, ncol(train.x))

dim(test.x) <- c(100, 1, 1, ncol(test.x))

#########



############ BUILD NET


library(mxnet)


# first conv layer


data <- mx.symbol.Variable('data')


conv1 <- mx.symbol.Convolution(data = data,

  kernel=c(14, 1),

  stride=c(1, 1),

  num.filter = 1)


tanh1 <- mx.symbol.Activation(data = conv1, 

 act.type = 'relu')


pool1 <- mx.symbol.Pooling(data = tanh1, 

     pool_type = "avg",

     kernel=c(5, 1), 

     stride=c(1, 1))



# second conv layer


conv2 <- mx.symbol.Convolution(data = conv1,

  kernel=c(12, 1),

  stride=c(1, 1),

  num.filter = 1)


tanh2 <- mx.symbol.Activation(data = conv2, 

 act.type = 'relu')


pool2 <- mx.symbol.Pooling(data = tanh2, 

     pool_type = "avg",

     kernel=c(5, 1), 

     stride=c(1, 1))



# third conv layer


conv3 <- mx.symbol.Convolution(data = conv2,

  kernel=c(10, 1),

  stride=c(1, 1),

  num.filter = 1)


tanh3 <- mx.symbol.Activation(data = conv3, 

 act.type = 'relu')


pool3 <- mx.symbol.Pooling(data = tanh3, 

     pool_type = "avg",

     kernel=c(2, 1), 

     stride=c(1, 1))



# first fully connected layer


flatten <- mx.symbol.Flatten(data = conv3)


fc1 <- mx.symbol.FullyConnected(data = flatten

   , num_hidden = 10)


tanh4 <- mx.symbol.Activation(data = fc1, act.type = 'tanh')



# second fully connected layer


fc2 <- mx.symbol.FullyConnected(data = tanh4, num_hidden = 1)


lenet <- mx.symbol.LinearRegressionOutput(data = fc2)


#### train


device <- mx.cpu()

log <- mx.metric.logger$new()


model <- mx.model.FeedForward.create(lenet, 

 X = train.x,

 y = train.y,

 ctx = device, 

 num.round = 100, 

 array.batch.size = 128,

 learning.rate = 0.01, 

 momentum = 0.9,

 eval.metric = mx.metric.rmse,

 eval.data = list(data = test.x, label = test.y),

 optimizer = 'sgd',

 initializer = mx.init.uniform(0.5),

 #array.layout = 'rowmajor',

 epoch.end.callback = mx.callback.log.train.metric(1, log))


plot(log$train, type = 'l', col = 'blue', ylim = c(min(c(log$train, log$eval)), max(c(log$train, log$eval))))

lines(log$eval, type = 'l', col = 'red')


mx.ctx.internal.default.value = list(device="cpu",device_id=0,device_typeid=1)

class(mx.ctx.internal.default.value) = "MXContext"


preds <- as.numeric(predict(model, test.x))

1 - sum((test.y - preds)^2) / sum((test.y - mean(test.y))^2)

Естественно, это просто рыба, показывающая основную логику.

 
Alexey Burnakov:
Фичи готовили или подавали как есть лаги? Эту задачу на чистых лагах не решить, вроде бы. Подготовка фичей нужна.

Еще наблюдение - походу, ваш выход сети строго -1;1. Либо взяли тангенс активацию и потом не сделали обратного преобразования выхода, либо что-то еще.

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

Насчёт "-1;1" в ответе всё забавно. Вывод на последнем нейроне там линейный, без активационной функции, то есть не ограничен ничем. Я пробовал шкалировать целевые значения тоже в -1;1, но после этого сеть стала выдавать результаты в интервале (-0.2;0.2). Почему-то результат всегда будет в более узком диапазоне чем требуется, наверное из-за быстро остановленного обучения, всего 250 итераций.
Если добавить больше нейронов, и не останавливать обучение, то в конце сеть дообучится до нужного интвервала. 100 нейронов во внутреннем слое почти хватит до 100% точности на тренировочных данных. Судя по логу, сумма остатков на всех 20000*0.7 (поправил позже) результатах была около 200. Но при этом результаты на кроссвалидации вообще перестанут коррелировать с нужными, это будут просто рандомные значения, хоть и в нужном интервале.

 
Dr.Trader:

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

Насчёт "-1;1" в ответе всё забавно. Вывод на последнем нейроне там линейный, без активационной функции, то есть не ограничен ничем. Я пробовал шкалировать целевые значения тоже в -1;1, но после этого сеть стала выдавать результаты в интервале (-0.2;0.2). Почему-то результат всегда будет в более узком диапазоне чем требуется, наверное из-за быстро остановленного обучения, всего 250 итераций.
Если добавить больше нейронов, и не останавливать обучение, то в конце сеть дообучится до нужного интвервала. 100 нейронов во внутреннем слое почти хватит до 100% точности на тренировочных данных. Судя по логу, сумма остатков на всех 20000*100 предикторах была около 200. Но при этом результаты на кроссвалидации вообще перестанут коррелировать с нужными, это будут просто рандомные значения, хоть и в нужном интервале.

Забавно. Надо подумать.

ЗЫ: скорее всего, в этом диапазоне [-1;1] сеть получает наиболее непротиворечивые сигналы на входе и этот фрагмент функции моделируется проще всего (НС учится тому, что проще всего). И, естественно, этот вариант, когда градиентный спуск находит свой минимум. С этим сложно поспорить...

 

ОК, добавлю для вас подсказку, если вы еще хотите потренироваться.

Во-первых, R^2 0.55 реально можно достичь, применив к "метафиче" некое небольшое функциональное преобразование. Другое дело, что функция получается сложноватая по своему виду.

И еще - попробуйте взять:

rowMeans(df[, 1:10]) 

rowMeans(df[, 1:20])  

rowMeans(df[, 1:30])  

...

rowMeans(df[, 1:100])

Эти 10 метафичей содержат нужную комбинацию значимых входов.  

К слову, сверточные слои позволяют это выделить уже в процессе обучения, если знать куда копать. 

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

 
Alexey Burnakov:

Просто замечательный комментарий, коллега! ) Ха

Позвольте ответить по пунктам согласно моему видению:

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

 

Нужна помощь... 

 Хочу провести тест на коинтеграцию  в скользящем но выкидывает ошибку...

 

вот просто тест на статичных данных


library(tseries) 
ri <- cumsum(rnorm(10000))  # типа цены
si <- cumsum(rnorm(10000))  # типа цены
ln <- length(ri)

data <- as.data.frame(cbind(ri,si))

#проводим линейную регрессию для определения правильного соотношения
model <- lm(  ri ~ si + 0 , data)
#вычисляем разницу цен (спред)
spread <- ri - coef(model)[1] * si
#проводим тест Дики-Фуллера на стационарность
test <- adf.test(as.vector(spread), k=0)

test$p.value

 все работает...

но когда делаю то же самое  в скользящем окне , вылетает ошибка - Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) : 

  0 (non-NA) cases  

 тест в скользящем окне

ri <- cumsum(rnorm(10000))  # типа цены
si <- cumsum(rnorm(10000))  # типа цены
ln <- length(ri)


data <- as.data.frame(cbind(ri,si))


test_vec <- rep(0,ln) # тут будем хранить показатели теста 

for(i in 151:ln){
  print(i)
          idx <- (i-150):i
                #проводим линейную регрессию для определения правильного соотношения
                model <- lm(  ri[idx] ~ si[idx] + 0 , data[idx,])
                #вычисляем разницу цен (спред)
                spread <- ri[idx] - coef(model)[1] * si[idx]
                #проводим тест Дики-Фуллера на стационарность
                test <- adf.test(as.vector(spread), k=0)
                
                test_vec[i] <- test$p.value
                
}

 на stack overflow в похожих проблемах говориться что это из за "NA" в данных, но у меня то таких нет , это точно...

в чем проблема? помогите пожалуйста  

Причина обращения: