A propos d'EDM posté dans Article précédent, c'est une histoire d'implémentation de Simplex Projection en Python afin de contester la réflexion des contenus d'apprentissage et de l'extrapolation temporelle. ..
Concernant pyEDM implémenté dans le laboratoire du proposant Sugihara et al., Nous allons l'implémenter car il ne prend pas en charge la prédiction en dehors du DataFrame d'entrée. (Référence).
Pour cette implémentation, nous nous référons au Blog du professeur Ushio de l'Université de Kyoto.
Simplex Projection
À partir de l'exemple de jeu de données pyEDM [Tent Mapping](https://ja.wikipedia.org/wiki/%E3%83%86%E3%83%B3%E3%83%88%E5%86%99%E5% 83% 8F) sont utilisées.
!pip install pyEDM
import pyEDM
tentmap = pyEDM.sampleData['TentMap']
print(tentmap.head())
Time TentMap
0 1 -0.09920
1 2 -0.60130
2 3 0.79980
3 4 -0.79441
4 5 0.79800
Son propre décalage pour la variable $ y_t
Dans le cas de pyEDM, ʻEmbed () est préparé ([doc]([ʻEmbed ()
](https://sugiharalab.github.io/EDM_Documentation/edm_functions/#embed))).
Mis en œuvre
def time_delay_embedding(objective_df, target_var, E=2, tau=1):
return_df = pd.DataFrame(objective_df[target_var].values,
columns=[target_var+"(t-0)"],
index=objective_df.index)
for i in range(tau, E*tau-1, tau):
colname = target_var + "(t-" + str(i) + ")"
return_df[colname] = objective_df[[target_var]].shift(i)
return return_df.dropna()
emb_df = time_delay_embedding(tentmap, "TentMap", E=2, tau=1)
print(emb_df.head())
TentMap(t-0) TentMap(t-1)
1 -0.60130 -0.09920
2 0.79980 -0.60130
3 -0.79441 0.79980
4 0.79800 -0.79441
5 -0.81954 0.79800
Dans cette implémentation, la dernière valeur des données disponibles est ciblée et prédite après 1 $ de temps.
target_pt = emb_df.iloc[-1,:].values #La dernière valeur qui sert de base à la prédiction
diff = emb_df.values - target_pt #Différence entre tous les points de données disponibles à partir du point de référence
l2_distance = np.linalg.norm(diff, ord=2, axis=1) #Calcul de la norme L2 à partir de la différence
l2_distance = pd.Series(l2_distance, index=emb_df.index, name="l2") #Je veux trier les pandas.Convertir en série
nearest_sort = l2_distance.iloc[:-1].sort_values(ascending=True) #fin(=La dernière valeur qui est la norme)Trier par ordre croissant sauf
print(nearest_sort.head(3))
index distance
124 0.003371
177 0.018171
163 0.018347
Name: l2
Soit $ y_ {t} $ le point de référence pour la prédiction, et \ {$ y_ {t_1}, y_ {t_2}, y_ {t_3} $ } les points de voisinage extraits. Utilisez \ {$ y_ {t_1 + 1}, y_ {t_2 + 1}, y_ {t_3 + 1} $ } pour calculer le point $ y_ {t + 1} $ que vous souhaitez prédire. Puisque l'indice des points de voisinage obtenu dans la section précédente est \ {124, 177, 163 }, Vous utiliserez les points qui correspondent à \ {125, 178, 164 }.
Il n'y a pas de limite au nombre de points voisins qui peuvent être référencés, mais $ E + 1 $ est utilisé pour la dimension incorporée $ E $.
knn = int(emb_df.shape[1] + 1)
nn_index = np.array(nearest_sort.iloc[:knn,:].index.tolist())
nn_future_index = nn_index + pt
print(nn_index, "-->", nn_future_index)
nn_future_points = lib_df.loc[nn_future_index].values
print(nn_future_points)
[124 177 163] --> [125 178 164]
[[0.16743 0.91591]
[0.15932 0.91998]
[0.1335 0.93295]]
\ {$ Y_ {t_1 + 1}, y_ {t_2 +, selon la distance aux points de référence $ y_ {t} $ et \ {$ y_ {t_1}, y_ {t_2}, y_ {t_3} $ } Calculez les poids \ {$ w_ {t_1 + 1}, w_ {t_2 + 1}, w_ {t_3 + 1} $ } pour 1}, y_ {t_3 + 1} $ }.
nn_distances = nearest_sort.loc[nn_index].values #À partir du point de référence yt1, yt2,Distance à yt3
nn_weights = np.exp(-nn_distances/nn_distances[0]) #Calculer le poids
total_weight = np.sum(nn_weights)
print("nn_distances")
print("nn_weights")
print("total_weight")
[0.00337083 0.01817143 0.01834696]
[0.36787944 0.00455838 0.00432709]
0.376764916711149
Calculez le point de prédiction $ y_ {t + 1} $ en utilisant les poids. La formule est une moyenne pondérée simple, $ y_{t+1} = \frac{w_{t_1+1} \times y_{t_1+1} + w_{t_2+1} \times y_{t_2+1} + w_{t_3+1} \times y_{t_3+1}}{w_{total}}$
forecast_point = list()
for yt in nn_future_points.T:
forecast_point.append(np.sum((yt * nn_weights) / total_weight))
print(forecast_point)
[0.16694219792961462, 0.9161549438807427]
À propos, la bonne réponse dans ce cas est
ground_truth: [0.16928 0.91498]
Par conséquent, une valeur assez proche est requise.
Enfin, j'ai tracé l'état du calcul.
Vue d'ensemble
Expansion des points de référence $ y_ {t} $ et \ {$ y_ {t_1}, y_ {t_2}, y_ {t_3} $ }
Expansion de la valeur prédite et de la valeur réelle
La fonction entière qui combine 1. à 4. 2.
def forecast_simplex_projection(input_df=None,
forecast_tp=1, knn=None
):
if input_df is None:
raise Exception("Invalid argument: is None: lib_df<pandas.DataFrame> is None")
if knn is None:
knn = int(input_df.shape[1] + 1) #Dimension intégrée+1
#Obtenir le nom de la variable à partir du DataFrame d'entrée
input_cols = input_df.columns.tolist()
#Données DeepCopy pour un traitement récursif ultérieur
lib_df = input_df.copy()
# forecast_Exécuter de manière récursive la prédiction en 1 étape jusqu'à l'étape spécifiée par tp
forecast_points = list()
for pt in range(1, forecast_tp+1):
#Calcul de la distance du point de référence à chaque point de la bibliothèque
target_pt = lib_df.iloc[-1,:].values
lib_pt = lib_df.values
diff = lib_pt - target_pt
l2_distance = np.linalg.norm(diff, ord=2, axis=1)
l2_distance = pd.Series(l2_distance, index=lib_df.index, name="l2")
#Trier les distances par ordre croissant
nearest_sort = l2_distance.iloc[:-1].sort_values(ascending=True)
#Indice des points voisins par rapport au point de référence et t+Index de 1
nn_index = np.array(nearest_sort.iloc[:knn].index.tolist())
nn_future_index = nn_index + 1
#Calculer le poids en fonction de la distance des points voisins
nn_distances = nearest_sort.loc[nn_index].values
nn_distances = nn_distances + 1.0e-6
nn_weights = np.exp(-nn_distances/nn_distances[0])
total_weight = np.sum(nn_weights)
#Calculer la valeur prévue pour chaque dimension incorporée
forecast_value = list()
for yt in nn_future_points.values.T:
forecast_value.append(np.sum((yt * nn_weights) / total_weight))
#Ajouter les résultats de prédiction à la bibliothèque
forecast_points.append(forecast_value)
series_forecast = pd.Series(forecast_value, index=input_df.columns)
lib_df = lib_df.append(series_forecast, ignore_index=True)
forecast_points = np.array(forecast_points)
return forecast_points
Cette fois, j'ai implémenté Simplex Projection, qui est le plus simple d'EDM, en Python. Les autres méthodes incluent S-Map et Multiview Embedding. Il est également possible d'utiliser différents décalages avec plusieurs variables pour la reconstruction dynamique, ce qui affecte la précision de la prédiction. Dès la prochaine fois, nous contesterons ces contenus.
Recommended Posts