[PYTHON] Étude des réseaux de neurones récursifs: pouvez-vous reproduire des fonctions périodiques?

En apprentissage profond, j'ai essayé de voir à quel point la fonction périodique peut être reproduite afin d'étudier le réseau neuronal récurrent utilisé pour l'analyse des données de séries chronologiques.

Définition de trois types de fonctions périodiques

Ici, nous avons défini les trois types de fonctions périodiques suivants: f`` g`` h.

import numpy as np

def f(t, freq=25):
    return np.sin(2. * np.pi * t / freq)

def g(t, freq=25, amp=10, threshold = 10):
    return 1/(1 + np.exp(10 * np.sin(2 * np.pi * t / freq) + 10))

def h(t, freqs=[11, 23, 31, 41, 53, 61, 71, 83, 97]):
    value = np.zeros_like(t)
    for freq in freqs:
        value += f(t, freq)
    return value

Fonction f

La fonction f est une fonction triangulaire $ sin $. Ici, la période est fixée à 25 $.

%matplotlib inline
import matplotlib.pyplot as plt

total_time_length = 1000
times = np.linspace(0, total_time_length, total_time_length + 1)

plt.figure(figsize=(15, 6))
plt.plot(f(times))
plt.xticks(np.linspace(0, 1000, 11))
plt.grid()

output_2_0.png

Fonction g

La fonction g transforme la fonction triangulaire $ sin $ avec une fonction sigmoïde en une forme étrange. Encore une fois, j'ai mis le cycle à 25 $.

%matplotlib inline
import matplotlib.pyplot as plt

total_time_length = 1000
times = np.linspace(0, total_time_length, total_time_length + 1)

plt.figure(figsize=(15, 6))
plt.plot(g(times))
plt.xticks(np.linspace(0, 1000, 11))
plt.grid()

output_3_0.png

Fonction h

La fonction «h» est la somme des fonctions triangulaires $ sin $ dont la période est de plusieurs nombres premiers.

%matplotlib inline
import matplotlib.pyplot as plt

total_time_length = 1000
times = np.linspace(0, total_time_length, total_time_length + 1)

plt.figure(figsize=(15, 6))
plt.plot(h(times))
plt.xticks(np.linspace(0, 1000, 11))
plt.grid()

output_4_0.png

Ces fonctions peuvent-elles être reproduites dans un réseau de neurones récursif?

Transformée de Fourier

Avant d'utiliser le réseau de neurones récursif, convertissons les trois fonctions ci-dessus en fréquences par transformée de Fourier et prenons le nombre inverse pour vérifier la "période".

plt.figure(figsize=(6,6))

sp = np.fft.fft(f(times))
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(311)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="f")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

sp = np.fft.fft(g(times))
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(312)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="g")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

sp = np.fft.fft(h(times))
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(313)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="h")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

output_6_1.png

La fonction f consiste uniquement en des ondes sin avec une période de 25 $. Vous pouvez voir que la fonction «h» consiste en une combinaison de périodes des nombres premiers spécifiés. D'autre part, vous pouvez voir que la fonction g contient divers composants autres que la période spécifiée de 25 $.

Création d'un jeu de données de séries chronologiques

Créons maintenant un ensemble de données chronologiques pour entraîner un réseau de neurones récursif. Dans un réseau de neurones récursif, si vous entrez la sortie $ X_ {t, t + w} $ du temps $ t $ à $ t + w $, la sortie $ X_ {t + w + 1} $ à la prochaine fois est prédite. Visez à créer un modèle à faire.

import numpy as np
from sklearn.model_selection import train_test_split

func = f #Vous pouvez changer la fonction en réécrivant ici
#func = g
#func = h

total_time_length = 10000 #Toutes les largeurs de temps à gérer
pred_length = 1000 #Largeur de temps prévue
learning_time_length = 100 #Largeur de temps utilisée pour l'apprentissage

time_series_T = np.linspace(0, total_time_length, total_time_length + 1) #Graver le temps prévu T (correspondant à l'axe horizontal du graphique)
time_series_X = func(time_series_T) #Sortie de fonction X (correspond à l'axe vertical du graphique)

X_learn = [] #Heure t ~ t+learning_time_Stocke X jusqu'à la longueur
Y_learn = [] #Heure t+learning_time_length+Stocker 1 X
for i in range(total_time_length - learning_time_length):
    X_learn.append(time_series_X[i:i+learning_time_length].reshape(1, learning_time_length).T)
    Y_learn.append([time_series_X[i+learning_time_length]])

#Divisé en données d'entraînement et données de vérification
#Aléatoire pour les données de séries chronologiques=Doit être faux
X_train, X_val, Y_train, Y_val = \
train_test_split(X_learn, Y_learn, test_size=0.2, shuffle=False)

# scikit-Convertir en type de données pour apprendre
X_train2sklearn = [list(x.reshape(1, len(x))[0]) for x in X_train]
Y_train2sklearn = [y[0] for y in Y_train]

Méthode d'apprentissage en profondeur

MLP (Multi-Layer Perceptron)

À titre de comparaison, nous utilisons Multi-Layer Perceptron (MLP), qui est le modèle le plus simple d'apprentissage en profondeur. J'ai utilisé le Perceptron multicouche car scikit-learn est facile et rapide.

%%time
from sklearn.neural_network import MLPRegressor
regressor = MLPRegressor(hidden_layer_sizes=(100, 100, 100), 
                         early_stopping=True, max_iter=10000) 
regressor.fit(X_train2sklearn, Y_train2sklearn) 
CPU times: user 2.84 s, sys: 1.41 s, total: 4.25 s
Wall time: 2.22 s

La courbe d'apprentissage a été dessinée comme suit.

plt.plot(regressor.loss_curve_)
%matplotlib inline
import matplotlib.pyplot as plt
plt.subplot(211)
plt.plot(regressor.loss_curve_, label='train_loss')
plt.legend()
plt.grid()
plt.subplot(212)
plt.plot(regressor.loss_curve_, label='train_loss')
plt.yscale('log')
plt.legend()
plt.grid()

output_11_0.png

Donnez au modèle entraîné les premières heures (uniquement la longueur de pred_length) comme entrée pour prédire la sortie à la prochaine fois. Ajoutez la valeur prévue de sortie à l'entrée pour prédire la sortie à la prochaine fois. Répétez-le à l'infini.

%%time
pred_length = 1000
X_pred_length = np.linspace(0, pred_length , pred_length + 1)
Y_observed = func(X_pred_length)
Y_pred = Y_observed[:learning_time_length+1]

for i in range(pred_length):
    X_ = [Y_pred[i:i+learning_time_length]]
    Y_ = regressor.predict(X_)
    Y_pred = np.append(Y_pred, Y_)
CPU times: user 383 ms, sys: 279 ms, total: 662 ms
Wall time: 351 ms

La courbe de la valeur prédite obtenue de cette manière et la courbe réelle sont illustrées et comparées.

plt.figure(figsize=(36, 6))
times = np.linspace(0, Y_pred.shape[0] - 1, Y_pred.shape[0])
plt.plot(func(times), label="time series")
plt.plot(Y_pred, alpha=0.5, label="predicted")
plt.xticks(np.linspace(0, 1000, 11))
plt.xlim([0, 1000])
plt.grid()
plt.legend()

output_13_1.png

Si la figure est petite et difficile à voir, vous pouvez l'agrandir en cliquant dessus. Jusqu'à 100 $, les données d'entraînement sont utilisées telles quelles, donc elles correspondent, mais après 100 $, vous pouvez voir que la valeur réelle (valeur de la fonction f) et la valeur prédite changent progressivement. ..

Comparons les résultats de la transformée de Fourier.

plt.figure(figsize=(6,4))

sp = np.fft.fft(func(times))
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(211)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="observed")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

sp = np.fft.fft(Y_pred)
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(212)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="predicted")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

output_14_1.png

Le cycle prévu est proche du cycle réel, mais semble être légèrement décalé.

Réseau neuronal récursif

Construisons maintenant un réseau de neurones récursif. Ici, PyTorch, une bibliothèque pour l'apprentissage en profondeur, est utilisée.

Commencez par configurer l'appareil. Si vous pouvez utiliser le GPU, utilisez le GPU, et sinon, utilisez le CPU comme suit.

import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

Préparez une fonction pour EarlyStopping. L'arrêt prématuré est le processus d'interruption de l'apprentissage lorsqu'il est déterminé que l'apprentissage ne se poursuivra plus.

Dans l'apprentissage profond, l'erreur de prédiction est appelée perte. Afin d'éviter le surajustement (également appelé surajustement), ici, au lieu de la «perte» des données d'apprentissage, l'apprentissage est arrêté lorsqu'il est jugé que la «perte» des données de vérification non utilisées pour l'entraînement ne diminuera plus. .. En tant que jugement, nous introduisons le concept de «patience». Si patience = 20, comparez la valeur minimale de perte de 20 $ récemment avec la valeur minimale de perte avant cela, et si la première est plus grande, jugez que" ce ne sera pas mieux "et apprenez. Je vais interrompre.

def EarlyStopping(log, patience=20):
    if len(log) <= patience:
        return False
    min1 = log[:len(log)-patience].min()
    min2 = log[len(log)-patience:].min()
    if min1 <= min2:
        return True
    else:
        return False

RNN(Recurrent Neural Network)

C'est un peu déroutant, mais RNN (Recurrent Neural Network) a "RNN au sens large" et "RNN au sens étroit". RNN au sens strict peut être implémenté dans PyTorch comme suit.

import torch
class RNN(torch.nn.Module):
    def __init__(self, hidden_dim):
        super().__init__()
        self.l1 = torch.nn.RNN(1, hidden_dim,
                         nonlinearity='tanh',
                         batch_first=True)
        self.l2 = torch.nn.Linear(hidden_dim, 1)
        torch.nn.init.xavier_normal_(self.l1.weight_ih_l0)
        torch.nn.init.orthogonal_(self.l1.weight_hh_l0)

    def forward(self, x):
        h, _ = self.l1(x)
        y = self.l2(h[:, -1])
        return y

LSTM (Long Short-Term Memory)

LSTM (Long Short-Term Memory) est long ou court! !! C'est un nom qui donne envie de creuser, mais c'est une sorte de "RNN au sens large". On dit que la mémoire à long terme est supérieure à "RNN au sens étroit". Il peut être implémenté dans PyTorch comme suit:

import torch
class LSTM(torch.nn.Module):
    def __init__(self, hidden_dim):
        super().__init__()
        self.l1 = torch.nn.LSTM(1, hidden_dim, batch_first=True)
        self.l2 = torch.nn.Linear(hidden_dim, 1)
        torch.nn.init.xavier_normal_(self.l1.weight_ih_l0)
        torch.nn.init.orthogonal_(self.l1.weight_hh_l0)

    def forward(self, x):
        h, _ = self.l1(x)
        y = self.l2(h[:, -1])
        return y

GRU (Gated Recurrent Unit)

Le GRU n'est pas un Glavnoye Razvedyvatelnoye Upravleniye, mais une unité récurrente fermée. On dit que le temps de calcul est court tout en ayant des performances identiques ou supérieures au LSTM.

import torch
class GRU(torch.nn.Module):
    def __init__(self, hidden_dim):
        super().__init__()
        self.l1 = torch.nn.GRU(1, hidden_dim, batch_first=True)
        self.l2 = torch.nn.Linear(hidden_dim, 1)
        torch.nn.init.xavier_normal_(self.l1.weight_ih_l0)
        torch.nn.init.orthogonal_(self.l1.weight_hh_l0)

    def forward(self, x):
        h, _ = self.l1(x)
        y = self.l2(h[:, -1])
        return y

Exécution de l'apprentissage par RNN

J'ai appris comme suit. Le code suivant est pour RNN, mais vous pouvez le changer en LSTM ou GRU en le réécrivant au même endroit.

%%time
from sklearn.utils import shuffle
model = RNN(50).to(device) #Vous pouvez changer de réseau en réécrivant ici
#model = LSTM(50).to(device)
#model = GRU(50).to(device)
criterion = torch.nn.MSELoss(reduction='mean')
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, 
                            betas=(0.9, 0.999), amsgrad=True)

epochs = 1000
batch_size = 100
n_batches_train = len(X_train) // batch_size - 1
n_batches_test = len(X_val) // batch_size - 1
hist = {'train_loss':[], 'val_loss':[]}

for epoch in range(epochs):
    train_loss = 0.
    val_loss = 0.
    X_, Y_ = shuffle(X_train, Y_train)

    for batch in range(n_batches_train):
        start = batch * batch_size
        end = start + batch_size
        X = torch.Tensor(X_[start:end])
        Y = torch.Tensor(Y_[start:end])
        model.train()
        Y_pred = model(X)
        loss = criterion(Y, Y_pred)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        train_loss += loss.item()

    for batch in range(n_batches_test):
        start = batch * batch_size
        end = start + batch_size
        X = torch.Tensor(X_val[start:end])
        Y = torch.Tensor(Y_val[start:end])
        model.eval()
        Y_pred = model(X)
        loss = criterion(Y, Y_pred)
        val_loss += loss.item()
    
    train_loss /= n_batches_train
    val_loss /= n_batches_test
    hist['train_loss'].append(train_loss)
    hist['val_loss'].append(val_loss)
    print("Epoch:", epoch + 1, "Train loss:", train_loss, "Val loss:", val_loss)

    if EarlyStopping(np.array(hist['val_loss'])):
        print("Early stopping at epoch", epoch + 1)
        break
Epoch: 1 Train loss: 0.024917872337913975 Val loss: 6.828008190495893e-05
Epoch: 2 Train loss: 3.570798083110742e-05 Val loss: 3.464157634880394e-05
Epoch: 3 Train loss: 2.720728588638639e-05 Val loss: 1.954806430148892e-05
...
Epoch: 580 Train loss: 5.4337909078255436e-08 Val loss: 4.0113718569045886e-08
Epoch: 581 Train loss: 6.47745306281422e-08 Val loss: 5.6099906942108646e-08
Epoch: 582 Train loss: 5.797503896896836e-08 Val loss: 1.620698952820021e-07
Early stopping at epoch 582
CPU times: user 26min 9s, sys: 21.6 s, total: 26min 31s
Wall time: 26min 39s

L'apprentissage est terminé. Sort la courbe d'apprentissage.

%matplotlib inline
import matplotlib.pyplot as plt
plt.subplot(211)
plt.plot(hist['train_loss'], label='train_loss')
plt.plot(hist['val_loss'], label='val_loss')
plt.legend()
plt.grid()
plt.subplot(212)
plt.plot(hist['train_loss'], label='train_loss')
plt.plot(hist['val_loss'], label='val_loss')
plt.yscale('log')
plt.legend()
plt.grid()

output_27_0.png

Donnez au modèle entraîné les premières heures (uniquement la longueur de pred_length) comme entrée pour prédire la sortie à la prochaine fois. Ajoutez la valeur prévue de sortie à l'entrée pour prédire la sortie à la prochaine fois. Répétez-le à l'infini.

%%time
total_time_length = 10000
pred_length = 1000
learning_time_length = 100

X_pred_length = np.linspace(0, pred_length , pred_length + 1)
Y_observed = func(X_pred_length)
Y_pred = Y_observed[:learning_time_length+1]

for i in range(pred_length):
    X_ = Y_pred[i:i+learning_time_length+1].reshape(1, learning_time_length + 1, 1)
    Y_ = model(torch.Tensor(X_)).detach().numpy()
    Y_pred = np.append(Y_pred, Y_)
CPU times: user 2.54 s, sys: 5.97 ms, total: 2.55 s
Wall time: 2.55 s

La courbe de la valeur prédite obtenue de cette manière et la courbe réelle sont illustrées et comparées.

plt.figure(figsize=(36, 6))
times = np.linspace(0, Y_pred.shape[0] - 1, Y_pred.shape[0])
plt.plot(func(times), label="time series")
plt.plot(Y_pred, alpha=0.5, label="predicted")
plt.xticks(np.linspace(0, 1000, 11))
plt.xlim([0, 1000])
plt.grid()
plt.legend()

output_29_1.png

Si la figure est petite et difficile à voir, vous pouvez l'agrandir en cliquant dessus. Jusqu'à 100 $, les données d'entraînement sont utilisées telles quelles, il est donc naturel qu'elles correspondent, mais après 100 $, vous pouvez voir qu'elles correspondent parfaitement.

Comparons les résultats de la transformée de Fourier.

plt.figure(figsize=(6,4))

sp = np.fft.fft(func(times))
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(211)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="observed")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

sp = np.fft.fft(Y_pred)
freq = np.fft.fftfreq(times.shape[-1])

plt.subplot(212)
plt.plot(1/freq, abs(sp.real) + abs(sp.imag), label="predicted")
plt.plot(1/freq, abs(sp.real))
plt.plot(1/freq, abs(sp.imag), alpha=0.5)
plt.legend()
plt.xlim([0, 150])
plt.xticks(np.linspace(0, 150, 16))
plt.grid()

output_30_1.png

Il semble que les cycles soient exactement les mêmes.

Exécution d'apprentissage par LSTM

Comme mentionné ci-dessus, l'apprentissage du LSTM réécrit simplement «model = RNN (50) .to (device)» dans le code ci-dessus en «model = LSTM (50) .to (device)».

Epoch: 1 Train loss: 0.24947839844315192 Val loss: 0.0037629783619195223
Epoch: 2 Train loss: 0.0010665786028720248 Val loss: 0.0004544752591755241
Epoch: 3 Train loss: 0.000281030429528656 Val loss: 0.00014765093510504812
...
Epoch: 397 Train loss: 1.9865108783006072e-08 Val loss: 1.99065262052045e-08
Epoch: 398 Train loss: 1.840841412067617e-08 Val loss: 1.814414751777349e-08
Epoch: 399 Train loss: 1.7767042196444784e-08 Val loss: 1.9604467382805524e-08
Early stopping at epoch 399
CPU times: user 48min 40s, sys: 51.2 s, total: 49min 31s
Wall time: 49min 41s

output_33_0.png

CPU times: user 7.67 s, sys: 14 ms, total: 7.68 s
Wall time: 7.69 s

output_35_1.png

output_36_1.png

Il semble que c'était aussi une prédiction parfaite.

Exécution de l'apprentissage par GRU

Comme mentionné ci-dessus, l'apprentissage de GRU remplace simplement «model = RNN (50) .to (device)» dans le code ci-dessus par «model = GRU (50) .to (device)».

Epoch: 1 Train loss: 0.2067998453276232 Val loss: 0.0007729934877716005
Epoch: 2 Train loss: 0.0005770771786979495 Val loss: 0.00023205751494970173
Epoch: 3 Train loss: 0.00018625847849015816 Val loss: 0.00014329736586660147
...
Epoch: 315 Train loss: 5.816128262764026e-09 Val loss: 5.750611098420677e-09
Epoch: 316 Train loss: 5.757192062114896e-09 Val loss: 5.7092033323158375e-09
Epoch: 317 Train loss: 5.780735246610847e-09 Val loss: 5.6715170337895415e-09
Early stopping at epoch 317
CPU times: user 34min 51s, sys: 42.1 s, total: 35min 33s
Wall time: 35min 40s

output_39_0.png

CPU times: user 8.81 s, sys: 7.04 ms, total: 8.81 s
Wall time: 8.82 s

output_41_1.png

output_42_1.png

Il semble que c'était aussi une prédiction parfaite.

Expérience pour changer la forme et la période d'une fonction

Maintenant que je sais comment le déplacer, essayons enfin de changer la forme et la période de la fonction. Le résultat est le suivant.

Augmenter la période de fonction f

MLP, fonction f

MLP, fonction f, période = 25

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

MLP, fonction f, période = 50

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

MLP, fonction f, période = 100

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

MLP, fonction f Résumé

Même si le cycle devient grand, il n'y a pas de grand changement dans le nombre d'époques passées jusqu'à la fin précoce. La forme de la courbe ne s'est pas effondrée de manière significative, mais il y a eu un changement dans le cycle. La hauteur de sortie (amplitude) a été préservée lorsque la période était courte, mais on a constaté qu'elle avait tendance à diminuer à mesure que la période devenait plus longue.

RNN, fonction f

RNN, fonction f, période = 25

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

RNN, fonction f, période = 50

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

RNN, fonction f, période = 100

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

RNN, résumé de la fonction f

Le nombre d'époques passées pour finir tôt avait tendance à diminuer à mesure que le cycle augmentait. La courbe de prédiction a fait de bonnes prédictions dans le cycle court (25) ou cycle moyen (50), mais a perdu sa forme de manière significative dans le cycle long (100). Dans la prévision à longue période, un pic net a été observé à un endroit étrange.

LSTM, fonction f

LSTM, fonction f, période = 25

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

LSTM, fonction f, période = 50

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

LSTM, fonction f, période = 100

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

LSTM, fonction f Résumé

Le nombre d'époques passées avant l'arrêt anticipé peut (bien que peu clair) diminuer avec des cycles plus longs. De bonnes prédictions ont été faites pour l'ensemble du cycle court (25), du cycle moyen (50) et du cycle long (100).

GRU, fonction f

GRU, fonction f, période = 25

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

GRU, fonction f, période = 50

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

GRU, fonction f, période = 100

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

GRU, fonction f

J'ai entendu dire que GRU est plus rapide que LSTM, mais le nombre d'époques passées avant la résiliation anticipée était plutôt long (atteignant 1000 époques). De bonnes prédictions ont été faites pour l'ensemble du cycle court (25), du cycle moyen (50) et du cycle long (100).

Augmenter la période de fonction g

MLP, fonction g

MLP, fonction g, période = 25

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

MLP, fonction g, période = 50

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

MLP, fonction g, période = 100

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

MLP, fonction g Résumé

Le nombre d'époques passées jusqu'à la fin précoce est pratiquement inchangé même si le cycle change. La forme approximative est préservée, mais le cycle a tendance à se déplacer lorsque les pieds sont robustes et que la hauteur du pic est faible. En regardant la figure de la transformée de Fourier, il semble que de nombreux pics (périodes) sont captés (bien qu'ils ne soient pas alignés).

RNN, fonction g

RNN, fonction g, période = 25

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

RNN, fonction g, période = 50

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

RNN, fonction g, période = 100

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

RNN, résumé de la fonction g

Celui avec un cycle court (25) est une bonne prédiction. Celui avec le cycle médian (50) capte les pics principaux, mais ils ne sont pas alignés. Dans le cycle long (100), RNN semble avoir abandonné prématurément la prédiction. Parmi les nombreux cycles, il semble que seuls des cycles relativement courts soient repris.

LSTM, fonction g

LSTM, fonction g, période = 25

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

LSTM, fonction g, période = 50

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

LSTM, fonction g, période = 100

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

LSTM, fonction g Résumé

Étonnamment, cela ne fonctionnait pas dans tous les cycles. Le cycle court a bien fonctionné avec RNN, mais pas avec LSTM, enregistrant un pic improbable. Le résultat du cycle intermédiaire est le meilleur, mais le cycle était toujours désactivé. J'entends la voix dire que j'ai abandonné la prédiction pour le long cycle.

GRU, fonction g

GRU, fonction g, période = 25

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

GRU, fonction g, période = 50

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

GRU, fonction g, période = 100

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

GRU, résumé de la fonction g

C'est également surprenant. LSTM était pire que RNN, mais GRU était pire. Le cycle court est un peu meilleur, mais le cycle intermédiaire donne l'impression que j'ai abandonné.

Fonction avec différentes périodes h

Au début, je pensais mélanger des cycles plus diversifiés, mais après avoir vu les résultats ci-dessus, j'ai pensé qu'il serait préférable de mélanger un peu moins.

MLP, fonction h

Courbe d'apprentissage

output_11_0.png

Courbe de prédiction

output_13_1.png

Transformée de Fourier

output_14_1.png

La reprise du cycle semble être relativement réussie. Cependant, comme l'amplitude n'est pas bien captée, le résultat est une prédiction avec une erreur importante.

RNN, fonction h

Courbe d'apprentissage

output_27_0.png

Courbe de prédiction

output_29_1.png

Transformée de Fourier

output_30_1.png

Je prends généralement le cycle, mais quelque chose n'est pas synchronisé. L'amplitude a augmenté pour une raison quelconque.

LSTM, fonction h

Courbe d'apprentissage

output_33_0.png

Courbe de prédiction

output_35_1.png

Transformée de Fourier

output_36_1.png

J'ai ramassé quelques cycles, mais j'ai ramassé plusieurs cycles qui ne sont pas là. En ce sens, RNN est-il un peu mieux?

GRU, fonction h

Courbe d'apprentissage

output_39_0.png

Courbe de prédiction

output_41_1.png

Transformée de Fourier

output_42_1.png

C'est encore pire que LSTM.

Résumé

Ceci est le résumé. Pour autant que j'ai traité de certaines fonctions périodiques

Je n'ai pas encore assez étudié, donc il peut y avoir des parties étranges, mais j'apprécierais que vous puissiez souligner les points que vous avez remarqués ... (ヽ ´ω`)

Recommended Posts

Étude des réseaux de neurones récursifs: pouvez-vous reproduire des fonctions périodiques?
Réseau neuronal récursif: une introduction à RNN
Fonctions pouvant être utilisées dans l'instruction for