Essayez de prédire FX avec LSTM en utilisant Keras + Tensorflow Partie 2 (calculer avec GPU) Ecrivez que le début est finalement désactivé J'ai fait. La raison en est qu'il existe de nombreux paramètres utilisés dans le deep learning et le FX, mais je pensais qu'il faudrait beaucoup de temps pour trouver des valeurs importantes ou correctes parmi eux.
C'est vrai, vous ne pouvez pas le trouver sans utiliser GPU.
Donc, cette fois, je peux utiliser le GPU, donc je vais essayer de trouver une bonne valeur en arrondissant divers paramètres que j'ai désirés.
La source est à https://github.com/rakichiki/keras_fx. Ou faites un clone git.
git clone https://github.com/rakichiki/keras_fx.git
La source cette fois est keras_fx_gpu_multi.ipynb. Obtenez ceci et téléchargez-le sur jupyter.
Laissez-moi vous expliquer un peu.
Tout d'abord, j'ai décidé des paramètres que je voulais changer. C'est comme suit. (Si vous regardez de près, ce n'est pas tout ...)
Tournoi à la ronde
l_of_s_list = [20,25]
n_next_list = [5,7]
check_treshhold_list = [0.50,0.60]
#activation_list = ['sigmoid','tanh','linear']
activation_list = ['tanh']
#loss_func_list = ['mean_squared_error','mean_absolute_error','mean_squared_logarithmic_error']
loss_func_list = ['mean_squared_error','mean_absolute_error']
#optimizer_func_list = ['sgd','adadelta','adam','adamax']
optimizer_func_list = ['adadelta','adam','adamax']
#validation_split_number_list = [0.1,0.05]
validation_split_number_list = [0.05]
currency_pair_list = ['usdjpy']
#Stockage du fichier de résultats
if os.path.exists('result') == False:
os.mkdir('result')
if os.path.exists('png') == False:
os.mkdir('png')
save_file_name = 'result/result_' + dt.today().strftime("%Y%m%d%H%M%S") + '.txt'
save_file_name = dt.today().strftime("%Y%m%d%H%M%S")
#acquisition de données fx
start_day = "20010101"
end_day = dt.today().strftime("%Y%m%d")
for currency_pair in currency_pair_list:
(train_start_count, train_end_count,test_start_count, test_end_count,data) = \
get_date(start_day, end_day, currency_pair)
file_name = currency_pair + '_d.csv'
for l_of_s in l_of_s_list:
for n_next in n_next_list:
for check_treshhold in check_treshhold_list:
#
(chane_data,average_value,diff_value, up_down,check_percent) = \
get_data(l_of_s, n_next,check_treshhold, file_name,train_start_count,\
train_end_count,test_start_count, test_end_count,data)
#
for activation in activation_list:
for loss_func in loss_func_list:
for optimizer_func in optimizer_func_list:
for validation_split_number in validation_split_number_list:
print('--------------------------')
fit_starttime = time.time()
fit(l_of_s, n_next,check_treshhold,file_name,save_file_name,activation,loss_func,optimizer_func,\
validation_split_number,train_start_count, train_end_count,test_start_count, test_end_count,\
chane_data,average_value,diff_value,up_down,check_percent)
print(str(math.floor(time.time() - fit_starttime)) + "s")
print('')
Je voudrais dire que je voudrais arrondir l'éventail des attentes, mais comme le temps augmentera de manière exponentielle, il vaut mieux réduire dans une certaine mesure et enquêter petit à petit. Eh bien, même si vous pouvez utiliser le GPU, si la vitesse est 10 fois plus rapide et la quantité de calcul est de 1000 fois, c'est le Kiami d'origine. (Mais il n'est plus dans la plage qui peut être calculée par le CPU)
Aussi, allons-y petit à petit au lieu de faire demi-tour depuis le début à cause du problème décrit plus loin (c'est moi qui ai échoué en faisant beaucoup demi-tour au début).
La quantité de calcul a explosé en raison de l'arrondissement des paramètres, mais l'amélioration de la simple introduction du GPU ne suffit pas. Par conséquent, nous allons introduire l'arrêt anticipé pour éviter les boucles inutiles par périodes.
EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=10, verbose=1)
~~
high_history = high_model.fit(X_high_train, y_high_train, batch_size=100, epochs=300, \
validation_split=validation_split_number, callbacks=[early_stopping])
Je pense que Keras est facile ici. Cependant, on ne sait pas si c'est la condition d'un arrêt précoce.
Bien sûr, vous ne pouvez pas dire si les paramètres sont corrects sans regarder la courbe d'apprentissage. L'introduire n'est pas trop difficile.
Gardez simplement la valeur de retour de fit et représentez-la.
Courbe d'apprentissage
#Apprentissage
high_history = high_model.fit(X_high_train, y_high_train, batch_size=100, epochs=300, \
validation_split=validation_split_number, callbacks=[early_stopping])
~~~~
# high
val_loss = high_history.history['val_loss']
plt.rc('font',family='serif')
fig = plt.figure()
plt.plot(range(len(high_history.history['val_loss'])), val_loss, label='val_loss', color='black')
plt.xlabel('epochs')
plt.savefig('png/' + save_file_name + '_high_' + \
str(l_of_s) + '_' + str(n_next) + \
'_' + str(check_treshhold) + '_' + file_name + \
'_' + activation + '_' + loss_func + \
'_' + optimizer_func + '_' + str(validation_split_number) + \
'.png')
plt.show()
En guise de mise en garde, si vous voulez laisser un graphique, faites plt.show () après plt.savefig. La raison est inconnue, mais si c'est l'inverse, elle ne restera pas (j'ai renvoyé quelque part à la réponse dans le coin des questions).
Quand c'est bon, le graphe avec la transition de val_loss est affiché comme ci-dessous.
Eh bien, c'est une autre question de savoir si le taux de réussite est bon simplement parce que c'est beau. Cependant, vous pouvez voir si l'apprentissage est possible ou non dans ce graphique.
On s'attend à ce que cela prenne très longtemps, mais le PC peut s'arrêter en cours de route. je , Je ne suis pas du genre à vouloir laisser un PC sans mémoire ECC fonctionner pendant plus de 10 heures et continuer à prier pour qu'il ne tombe pas en chemin.
Donc, enregistrez le résultat de l'analyse dans un fichier et prenez des mesures même si le PC tombe en panne au milieu (bien que j'abandonne en cas de panne de stockage).
Sortie de fichier
f = open(save_file_name, 'a')
f.write('l_of_s: ' + str(l_of_s) + ' n_next: ' + str(n_next) + \
' check_treshhold:' + str(check_treshhold) + ' file_name:' + file_name + \
' activation:' + activation + ' loss_func:' + loss_func + \
' optimizer_func:' + optimizer_func + ' validation_split_number:' + str(validation_split_number) + \
'\n')
f.write('UP: ' + str(up_ok_count) + ' - ' + str(up_ng_count) + ' - ' + str(up_ev_count) + '\n')
f.write('DN: ' + str(down_ok_count) + ' - ' + str(down_ng_count) + ' - ' + str(down_ev_count) + '\n')
f.close()
Le format csv était-il meilleur? Non, était-il préférable d'utiliser le format JSON (j'aime le format JSON)? Cependant, je publierai les progrès pour le moment. Ah, le format JSON est inutile vu qu'il échouera en cours de route.
Comme mentionné ci-dessus, vous pouvez également enregistrer le graphique.
Je l'ai beaucoup tourné pour le moment. Cependant, pour la raison décrite plus loin, c'est un peu doux (ne dites pas qu'il n'y a qu'un seul modèle tel que la fonction d'activation).
La seule paire de devises est usdjpy. Le résultat est le suivant (sur le nombre de jours d'achat et de vente, le jugement n'est pas inclus dans le taux de réussite).
Jours de jugement d'achat et de vente | Jours après l'achat et la vente | Changer le taux pour le jugement commercial | Fonction d'activation | Fonction objective | Algorithme d'optimisation | Pourcentage de données d'entraînement(%) | Nombre de coups en montant | Nombre de ratés lors de la montée | Nombre de coups quand il tombe | Nombre d'écarts lors de l'abaissement | Taux de réussite total(%) |
---|---|---|---|---|---|---|---|---|---|---|---|
20 | 5 | 0.5 | tanh | mse | adadelta | 0.05 | 55 | 34 | 114 | 81 | 59.5 |
20 | 5 | 0.5 | tanh | mse | adam | 0.05 | 24 | 22 | 66 | 46 | 57.0 |
20 | 5 | 0.5 | tanh | mse | adamax | 0.05 | 14 | 14 | 46 | 33 | 56.1 |
20 | 5 | 0.5 | tanh | mae | adadelta | 0.05 | 69 | 58 | 95 | 88 | 52.9 |
20 | 5 | 0.5 | tanh | mae | adam | 0.05 | 31 | 28 | 69 | 58 | 53.8 |
20 | 5 | 0.5 | tanh | mae | adamax | 0.05 | 29 | 26 | 84 | 69 | 54.3 |
20 | 5 | 0.6 | tanh | mse | adadelta | 0.05 | 72 | 53 | 129 | 98 | 57.1 |
20 | 5 | 0.6 | tanh | mse | adam | 0.05 | 64 | 52 | 111 | 97 | 54.0 |
20 | 5 | 0.6 | tanh | mse | adamax | 0.05 | 43 | 33 | 59 | 52 | 54.5 |
20 | 5 | 0.6 | tanh | mae | adadelta | 0.05 | 51 | 40 | 140 | 120 | 54.4 |
20 | 5 | 0.6 | tanh | mae | adam | 0.05 | 75 | 57 | 102 | 75 | 57.3 |
20 | 5 | 0.6 | tanh | mae | adamax | 0.05 | 45 | 39 | 107 | 93 | 53.5 |
20 | 7 | 0.5 | tanh | mse | adadelta | 0.05 | 11 | 12 | 84 | 81 | 50.5 |
20 | 7 | 0.5 | tanh | mse | adam | 0.05 | 7 | 5 | 45 | 35 | 56.5 |
20 | 7 | 0.5 | tanh | mse | adamax | 0.05 | 22 | 18 | 61 | 40 | 58.9 |
20 | 7 | 0.5 | tanh | mae | adadelta | 0.05 | 46 | 37 | 92 | 81 | 53.9 |
20 | 7 | 0.5 | tanh | mae | adam | 0.05 | 25 | 28 | 47 | 31 | 55.0 |
20 | 7 | 0.5 | tanh | mae | adamax | 0.05 | 20 | 28 | 75 | 62 | 51.4 |
20 | 7 | 0.6 | tanh | mse | adadelta | 0.05 | 23 | 16 | 39 | 39 | 53.0 |
20 | 7 | 0.6 | tanh | mse | adam | 0.05 | 24 | 21 | 77 | 67 | 53.4 |
20 | 7 | 0.6 | tanh | mse | adamax | 0.05 | 27 | 26 | 61 | 45 | 55.3 |
20 | 7 | 0.6 | tanh | mae | adadelta | 0.05 | 56 | 43 | 120 | 107 | 54.0 |
20 | 7 | 0.6 | tanh | mae | adam | 0.05 | 40 | 36 | 65 | 58 | 52.8 |
20 | 7 | 0.6 | tanh | mae | adamax | 0.05 | 49 | 41 | 60 | 54 | 53.4 |
25 | 5 | 0.5 | tanh | mse | adadelta | 0.05 | 54 | 32 | 86 | 60 | 60.3 |
25 | 5 | 0.5 | tanh | mse | adam | 0.05 | 25 | 21 | 59 | 41 | 57.5 |
25 | 5 | 0.5 | tanh | mse | adamax | 0.05 | 15 | 14 | 53 | 39 | 56.2 |
25 | 5 | 0.5 | tanh | mae | adadelta | 0.05 | 46 | 37 | 126 | 95 | 56.6 |
25 | 5 | 0.5 | tanh | mae | adam | 0.05 | 34 | 30 | 56 | 41 | 55.9 |
25 | 5 | 0.5 | tanh | mae | adamax | 0.05 | 25 | 24 | 69 | 47 | 57.0 |
25 | 5 | 0.6 | tanh | mse | adadelta | 0.05 | 23 | 21 | 108 | 94 | 53.3 |
25 | 5 | 0.6 | tanh | mse | adam | 0.05 | 19 | 20 | 58 | 51 | 52.0 |
25 | 5 | 0.6 | tanh | mse | adamax | 0.05 | 18 | 19 | 86 | 69 | 54.2 |
25 | 5 | 0.6 | tanh | mae | adadelta | 0.05 | 92 | 80 | 92 | 85 | 52.7 |
25 | 5 | 0.6 | tanh | mae | adam | 0.05 | 26 | 28 | 117 | 100 | 52.8 |
25 | 5 | 0.6 | tanh | mae | adamax | 0.05 | 32 | 31 | 126 | 102 | 54.3 |
25 | 7 | 0.5 | tanh | mse | adadelta | 0.05 | 32 | 18 | 110 | 95 | 55.7 |
25 | 7 | 0.5 | tanh | mse | adam | 0.05 | 16 | 16 | 37 | 19 | 60.2 |
25 | 7 | 0.5 | tanh | mse | adamax | 0.05 | 9 | 10 | 42 | 28 | 57.3 |
25 | 7 | 0.5 | tanh | mae | adadelta | 0.05 | 33 | 23 | 40 | 30 | 57.9 |
25 | 7 | 0.5 | tanh | mae | adam | 0.05 | 25 | 21 | 71 | 55 | 55.8 |
25 | 7 | 0.5 | tanh | mae | adamax | 0.05 | 36 | 29 | 55 | 38 | 57.6 |
25 | 7 | 0.6 | tanh | mse | adadelta | 0.05 | 43 | 35 | 104 | 92 | 53.6 |
25 | 7 | 0.6 | tanh | mse | adam | 0.05 | 23 | 23 | 63 | 58 | 51.5 |
25 | 7 | 0.6 | tanh | mse | adamax | 0.05 | 25 | 22 | 90 | 70 | 55.6 |
25 | 7 | 0.6 | tanh | mae | adadelta | 0.05 | 37 | 25 | 118 | 108 | 53.8 |
25 | 7 | 0.6 | tanh | mae | adam | 0.05 | 33 | 25 | 76 | 63 | 55.3 |
25 | 7 | 0.6 | tanh | mae | adamax | 0.05 | 40 | 25 | 74 | 59 | 57.6 |
Au mieux 60% et au pire 50%, la moyenne était de 55%, ce qui était un peu mieux que les jours précédents. À propos, il a fallu environ 2 heures pour calculer 48 modèles (avec Geforce GTX 1070). En outre, l'augmentation des paramètres devrait prendre du temps de manière exponentielle. Pour cette raison, il faudra prendre des mesures pour accélérer quelque part, et comme le taux de réussite est faible, il faut prendre des mesures, mais avant cela, un gros problème a été trouvé.
J'ai pu trouver les paramètres souhaités dans une certaine mesure, mais j'ai trouvé un problème décevant.
C'est un problème gourmand en mémoire. Au départ, je cherchais environ 1000 modèles, mais un événement qui est devenu très lent s'est produit au milieu. Après avoir pris les contre-mesures, l'état du PC suite à moins de 48 modèles est le suivant.
La mémoire du PC lui-même consomme 12 Go et le GPU 2 Go. Bien qu'il ne soit pas publié lorsqu'un modèle est exécuté, le GPU a consommé moins de 1 Go et le corps principal a consommé moins de 4 Go.
Eh bien, pour le dire simplement, il y a une fuite de mémoire. Au départ, ce PC n'avait que 8 Go de mémoire, mais je suis pressé de remplacer la mémoire (le châssis est Mini-ITX et il n'y a que deux emplacements de mémoire) et je l'ai augmentée à 32 Go (je pense que 16 Go était bien ici). Il y a un avis, mais l'investissement à mi-chemin ne donne pas de bons résultats, alors je l'ai fait 32 Go à la fois).
Je ne sais pas pourquoi cela ne consomme pas (ou ne libère pas) autant de mémoire, mais si vous voulez en faire plus avec ce script, vous devez prendre en compte la quantité de mémoire, le modèle et le temps d'exécution. .. Je n'ai pas encore trouvé de solution de contournement.
Cette série était en fait prévue jusqu'à présent. À l'avenir, je ferai de mon mieux pour améliorer les résultats dans la plage de l'erreur, mais rien ne garantit que les résultats seront obtenus jusqu'à présent.
Pour cette raison, je ne sais pas jusqu'où je peux aller, mais je pense que je peux faire beaucoup de choses. Voici ce que je suppose à ce stade:
Je pense que je peux faire beaucoup de choses comme celle-ci, mais pour être clair, c'est un niveau qu'un GPU est peu susceptible de faire. Dans ce cas, il peut être nécessaire d'installer plusieurs GPU ou de louer AWS. Je compte réfléchir aux prochaines mesures tout en réfléchissant un peu à ce domaine.
Recommended Posts