L'apprentissage automatique dans la négociation : théorie, modèles, pratique et algo-trading - page 136

 

Et comment calculez-vous exactement R^2, quelle fonction ?

J'ai essayé d'entraîner différents modèles par le biais de rattle, il a compté le "pseudo r^2" par corrélation, à savoir cor(fitpoints[,1], fitpoints[,2])^2, mais je veux calculer le r^2 en utilisant la même méthode que vous pour la comparaison.

Ce code [1 - sum((y-x)^2)/sum((y-mean(y))^2)] fonctionnera-t-il ?

 
Dr. Trader:

Et comment calculez-vous exactement R^2, quelle fonction ?

J'ai essayé d'entraîner différents modèles par le biais de rattle, il a compté le "pseudo r^2" par corrélation, à savoir cor(fitpoints[,1], fitpoints[,2])^2, mais je veux calculer le r^2 en utilisant la même méthode que vous pour la comparaison.

Ce code [1 - sum((y-x)^2)/sum((y-mean(y))^2)] fonctionnera-t-il ?


Exactement. X est un modèle.

 
Dr. Trader:

Plus il y a de neurones dans la couche cachée, plus la fonction décrite par le neurone est complexe. Il faut donc plus de couches cachées et de neurones dans celles-ci.

Mais alors le problème sera que le neurone utilise des additions et des multiplications consécutives (et par exemple des sigmoïdes pour la fonction d'activation) pour décrire la cible, c'est-à-dire que vous n'obtiendrez évidemment pas votre fonction originale, mais une sorte d'approximation. Et il peut s'avérer que cette approximation se souviendra de certaines caractéristiques des données d'apprentissage, de sorte qu'elle ne fonctionnera pas correctement avec les nouvelles données. Il faut donc parfois arrêter la formation, voir si l'erreur sur l'échantillon de test a diminué, et poursuivre la formation si tout va bien. À un moment donné, l'erreur sur les données de test commencera à augmenter, et il faudra alors arrêter complètement la formation.

De même, la sortie d'un neurone est limitée par la fonction d'activation. Pour le populaire - sigmoïde est (0;1), relu est [0;inf). Les valeurs cibles doivent être mises à l'échelle dans un intervalle différent, vos sorties dans l'intervalle (-7;7) sont tout simplement irréalisables pour de nombreux paquets.

Je mets à l'échelle toutes les données avec cf 0 st.off 1.

il est possible de cibler -1;1. Mais cela n'est vraiment nécessaire que si le neurone de sortie a une activation tangente.

0:;1 pour le sigmoïde dans un cas similaire.

Et s'il y a une identité, vous n'êtes pas obligé de le faire. Mais vous devez tenir compte de la propagation réelle des données. Les poids peuvent ne pas saturer à ce niveau.

Et j'apprends avec les courbes de sortie sur trayne et je teste pour voir où m'arrêter.
 

Encore une fois, j'ai pris Rattle, j'ai formé Nnet, j'ai pris le code fini dans le journal. Rattle ne fonctionne pas tout à fait correctement avec nnet, j'ai ajouté un peu plus de code pour arrêter l'entraînement à temps.

Meilleur R^2 sur les nouvelles données = 0.18. La meilleure configuration du réseau est assez bizarre, avec un neurone dans la seule couche interne. Je pourrais avoir deux neurones de plus dans la couche interne, le résultat serait à peu près le même. Si nous continuons à augmenter le nombre de neurones, le graphique suggère que le réseau se réapprend très rapidement et est de moins en moins performant sur les nouvelles données.

Sur le graphique de droite, la ligne bleue représente les nouvelles données du modèle, à partir de la ligne 20001. Le reste est de la formation et de la validation croisée.

Le réseau convolutif semble être en tête.

Dossiers :
 
Dr.Trader:

Une fois de plus, j'ai pris Rattle, j'ai formé Nnet, j'ai pris le code fini dans le journal. Rattle ne fonctionne pas tout à fait correctement avec nnet, j'ai ajouté un peu plus de code pour arrêter l'entraînement à temps.

Meilleur R^2 sur les nouvelles données = 0.18. La meilleure configuration du réseau est assez bizarre, avec un neurone dans la seule couche interne. Je pourrais avoir deux neurones de plus dans la couche interne, le résultat serait à peu près le même. Si nous continuons à augmenter le nombre de neurones, le graphique montre que le réseau se réapprend très rapidement et que ses performances sont de plus en plus mauvaises sur les nouvelles données.

Sur le graphique de droite, la ligne bleue représente les nouvelles données du modèle, à partir de la ligne 20001. Le reste est de la formation et de la validation croisée.

Le réseau convolutif semble être en tête.

Le résultat est bon ! Félicitations, vous avez battu mon simple NS.

Avez-vous préparé les frites ou les avez-vous nourries telles quelles ? Ce problème ne peut pas être résolu sur des lags purs, il semble. La préparation des copeaux est nécessaire.

Une autre observation - il semble que la sortie de votre réseau est strictement -1;1. Soit vous avez pris l'activation tangentielle et puis n'avez pas reconverti la sortie, ou quelque chose d'autre.

Et juste pour référence. Réseau convergent (apprentissage profond) dans le paquet mxnet. Jusqu'à présent la version avec git seulement. Mais les trucs de base fonctionnent.
 
Alexey Burnakov:

Et juste pour référence. Réseau convergent (apprentissage profond) dans le paquet mxnet. Jusqu'à présent la version avec git seulement. Mais en principe, tout fonctionne.

juste une observation, hors sujet mais.... quand j'ai demandé de l'aide pour mxnet et indiqué le paquet mxnet, tout le monde s'est tu et n'a rien dit. maintenant tout le monde est soudainement intéressé par ce que j'ai dit à ce sujet il y a 50 pages, pourquoi cela se produit-il ? :) Je me demande si, après 100 pages, quelqu'un remarquera le paquet quantstrat auquel j'ai également prêté attention il y a longtemps.....

Vous me direz - ha, bien, allez le faire vous-même si vous êtes si intelligent, le fait est que je ne le suis pas et que je ne suis pas intelligent et que je ne comprends pas grand-chose et que mon anglais est aussi très mauvais et que vos quatre lignes de code avec des explications pour moi pourraient prendre des semaines pour y arriver, et même là, je ne réussis pas toujours...

 
mytarmailS:

juste une observation, hors sujet mais.... lorsque j'ai demandé de l'aide pour le réseau de convolution et que j'ai indiqué le paquet mxnet, tout le monde est resté silencieux et n'a rien dit, mais maintenant tout le monde est soudainement intéressé par ce dont je parlais il y a 50 pages, pourquoi cela se produit-il ? :) Je me demande si, après 100 pages, quelqu'un remarquera le paquet quantstrat auquel j'ai également prêté attention il y a longtemps.....

Vous me direz - ha, bien, allez le faire vous-même si vous êtes si intelligent, le fait est que je ne le suis pas et que je ne suis pas intelligent et que je ne comprends pas grand-chose et que mon anglais est aussi très mauvais et que vos quatre lignes de code avec des explications pour moi pourraient prendre des semaines pour y arriver, et même là, je ne réussis pas toujours...

Un excellent commentaire, collègue ! ) Ha

Je vais répondre point par point en fonction de ma vision :

1) 90% des gens ici sont motivés par l'intérêt personnel, la phase de réflexion et la phase d'expérimentation. Par conséquent, certaines bonnes idées sont mises de côté pendant longtemps. Comme vous n'avez pas fourni d'exemples et de défis intéressants, cela n'intéresse personne. C'est simple, n'est-ce pas ?

2) Il existe deux stratégies pour obtenir des connaissances : creuser et essayer péniblement de faire quelque chose (nous le faisons tous à des degrés divers). Par exemple, je me souviens du gars dans le fil de discussion "Apprenez à gagner, villageois !", qui a passé plusieurs années de sa vie à tester l'efficacité des conseillers experts disponibles. Et ils ont tous échoué). Une autre option - attendre dans l'espoir que quelqu'un nous aide et poste un modèle prêt à l'emploi. Ainsi, si vous avez choisi la deuxième stratégie en raison de votre situation, la période d'attente pour un EA prêt à l'emploi peut être très longue.

En ce qui concerne mxnet, puisque j'en fais partie, cela ne me dérange pas de poster le code, qui, d'ailleurs, est presque le même sur Internet :

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)

Naturellement, ce n'est qu'un poisson qui montre la logique de base.

 
Alexey Burnakov:
Les frites ont-elles été préparées ou ont-elles été nourries comme les autres ? Cette tâche ne peut pas être résolue par un simple décalage, semble-t-il. La préparation des copeaux est nécessaire.

Une autre observation - il semble que votre sortie nette soit strictement -1;1. Soit vous avez pris l'activation de la tangente et n'avez pas fait la conversion inverse de la sortie, soit il y a autre chose.

J'ai alimenté tout comme c'est dans l'original, pas de changement. Je suis sûr que j'aurais pu obtenir un meilleur résultat si j'avais calculé les valeurs des indicateurs corrects et si je les avais également utilisés pour la prédiction. Mais quels sont les bons indicateurs ? (question rhétorique, sans réponse).

Tout est drôle à propos de "-1;1" dans la réponse. La sortie du dernier neurone y est linéaire, sans fonction d'activation, c'est-à-dire qu'elle n'est limitée par rien. J'ai également essayé de mettre à l'échelle les valeurs cibles en -1;1, mais après cela, le réseau commence à donner des résultats dans la plage (-0.2;0.2). Pour une raison quelconque, les résultats se situent toujours dans une fourchette plus étroite que celle requise, probablement en raison d'un apprentissage rapidement interrompu, avec seulement 250 itérations.
Si nous ajoutons plus de neurones et que nous n'arrêtons pas d'apprendre, le réseau finira par apprendre le bon invariant. 100 neurones dans la couche interne sont presque suffisants pour obtenir une précision de 100 % sur les données de formation. A en juger par le log, la somme des résidus sur l'ensemble des 20000*0,7 (corrigés plus tard) résultats était d'environ 200. Mais dans ce cas, les résultats de la validation croisée cesseront d'être en corrélation avec les résultats nécessaires, ils ne seront que des valeurs aléatoires, bien que dans l'intervalle nécessaire.

 
Dr. Trader:

J'ai soumis tout comme c'est dans l'original, sans aucune modification. Je suis sûr qu'en calculant les valeurs des indicateurs corrects et en les utilisant également pour la prédiction, je pourrais obtenir un meilleur résultat. Mais quels sont les bons indicateurs ? (question rhétorique, pas encore de réponse).

À propos du "-1;1" dans la réponse, c'est tout à fait drôle. La sortie du dernier neurone est linéaire, sans fonction d'activation, c'est-à-dire qu'elle n'est limitée par rien. J'ai essayé de mettre à l'échelle les valeurs cibles également en -1;1, mais après cela, le réseau commence à produire des résultats dans la plage (-0,2;0,2). Pour une raison quelconque, les résultats se situent toujours dans une fourchette plus étroite que celle requise, probablement en raison d'un apprentissage rapidement interrompu, avec seulement 250 itérations.
Si nous ajoutons plus de neurones et que nous n'arrêtons pas d'apprendre, le réseau finira par apprendre le bon invariant. 100 neurones dans la couche interne sont presque suffisants pour obtenir une précision de 100 % sur les données de formation. Selon le log, la somme des résidus sur l'ensemble des 20000*100 prédicteurs était d'environ 200. Mais les résultats de la validation croisée ne seront pas du tout corrélés, ils seront juste des valeurs aléatoires, bien que dans un intervalle requis.

C'est drôle. Je vais devoir y réfléchir.

HH : très probablement, dans cette plage [-1;1] , le réseau reçoit les signaux les plus cohérents à l'entrée et ce fragment de la fonction est le plus facile à modéliser (le réseau apprend ce qui est le plus facile). Et, bien sûr, cette variante lorsque la descente du gradient trouve son minimum. C'est difficile d'argumenter avec ça...

OK, je vais ajouter un indice pour vous si vous voulez toujours vous entraîner.

Tout d'abord, R^2 0,55 peut réellement être obtenu en appliquant une petite transformation fonctionnelle à la "métafonction". Par ailleurs, la fonction s'avère un peu compliquée en apparence.

Aussi, essayez de prendre :

rowMeans(df[, 1:10])

rowMeans(df[, 1:20])

rowMeans(df[, 1:30])

...

rowMeans(df[, 1:100])

Ces 10 métafiches contiennent la combinaison souhaitée d'entrées significatives.

D'ailleurs, les couches convolutionnelles permettent de le repérer dès le processus d'apprentissage, si vous savez où creuser.

La raison pour laquelle je vous incite, en fait - même si vous savez à quoi correspondre, vous devriez essayer de reproduire l'approximation de la sortie. Et en tant qu'initié, je n'aime pas l'impression d'essayer de vendre aux gens un problème insoluble.

 
Alexey Burnakov:

Un excellent commentaire, collègue ! ) Ha

Permettez-moi de répondre point par point en fonction de ma vision :

Je te comprends, je m'attendais à une réponse plus brutale, merci de ne pas t'être battu))) et merci aussi pour le code, j'essaierai de le mettre au point ce week-end car je suis occupé par une autre idée en ce moment.....

Besoin d'aide...

Je veux faire un test de cointégration dans sliding mais il jette une erreur...

Voici un test simple sur des données statiques...


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

ça marche...

Mais lorsque je fais la même chose dans une fenêtre glissante, j'obtiens une erreur -Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) :

0 (cas non-NA)

test de la fenêtre glissante

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
                
}

sur stack overflow dans des problèmes similaires il est dit que c'est dû à "NA" dans les données mais je ne l'ai pas, c'est sûr....

quel est leproblème ? aidez-moi s'il vous plaît

Raison: