[PYTHON] Complexité et robustesse du modèle

Vérifier la complexité du modèle et la détérioration de la précision du modèle lorsque du bruit léger est ajouté aux données

Comme j'ai tendance à penser que les données utilisées pour construire le modèle étaient un échantillon d'événements qui auraient pu se produire dans le passé, il était également possible que le seul échantillon apparu dans le passé soit un événement légèrement flou. Les choses dont vous voulez vous soucier. Si vous dites "pensez que l'échantillon est un peu flou" = "ajoutez du bruit à l'échantillon visible", vous pouvez l'utiliser comme un moyen de vérifier la robustesse (dépendance aux données) de votre modèle. J'ai pensé que ça pourrait l'être et je l'ai créé

Grosso modo Ceci n'est pas divisé en données de test et données d'entraînement! !! J'ai fait un modèle appelé, et en réalité, les données peuvent être légèrement différentes. Dans quelle mesure la précision du modèle se détériore à ce moment-là Le motif était que je voulais confirmer le phénomène

Si le modèle est simple et que le bruit est simple, je pense que la détérioration de la précision de la prédiction peut être calculée à l'aide de formules mathématiques, mais en la faisant à partir de la simulation, il peut être possible de traiter différents modèles, du bruit qui n'est ni iid ni une distribution normale. Je ne sais pas

Importer etc.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# import statsmodels.api as sm
# from statsmodels.tsa.arima_model import ARIMA
import pandas_datareader.data as web
import yfinance as yf
from numpy.random import *

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

import seaborn as sns
import warnings
import sys

warnings.filterwarnings('ignore')

plt.style.use('seaborn-darkgrid')
plt.rcParams['axes.xmargin'] = 0.01
plt.rcParams['axes.ymargin'] = 0.01

Obtenez'USDJPY'de yfinance et créez des retours hebdomadaires

ReadDF = yf.download('JPY=X', start="1995-01-01", end="2019-10-30")
ReadDF.index = pd.to_datetime(ReadDF.index)
IndexValueReadDF_rsmpl = ReadDF.resample('W').last()['Adj Close']
ReadDF = IndexValueReadDF_rsmpl / IndexValueReadDF_rsmpl.shift(1) - 1

Variable explicative (X), variable expliquée (y) Création de données

ret_df = pd.DataFrame()
ret_df[mkt] = ReadDF

test = pd.DataFrame(ret_df[mkt])
for i in range(1, 5):
    test['i_' + str(i)] = test['USDJPY'].shift(1 * i)

test = test.dropna(axis=0)
X = test.ix[:, 1:]
y = test[mkt]

Création du modèle (échantillon réel et bruit ajoutés)

m_ = 3  # 0.Un crochet pour avoir 3 fois la volatilité
output_degree = {}

for k in range(1, 7):
    polynomial_features = PolynomialFeatures(degree=k, include_bias=False)
    linear_regression = LinearRegression()
    pipeline = Pipeline([("polynomial_features", polynomial_features),
                         ("linear_regression", linear_regression)])

    pipeline.fit(X, y)

    k_sample = pd.DataFrame()

    for l in range(0, 300):

        #Génération normale de nombres aléatoires
        eps_0 = pd.DataFrame(randn(X.shape[0], X.shape[1]))
        eps_1 = eps_0.apply(lambda x: x * list(X.std()), axis=1)

        eps_1.columns = X.columns
        eps_1.index = X.index

        #Ajouter aux données d'origine
        X_r = X + m_/10 * eps_1

        signal = pd.DataFrame()
        signal[mkt] = np.sign(pd.DataFrame(pipeline.predict(X_r)))[0]

        signal.index = y.index

        k_sample['s_' + str(l)] = (pd.DataFrame(signal[mkt]) * pd.DataFrame(y)).ix[:, 0]

    signal_IS = pd.DataFrame()
    # signal_IS[mkt] = np.sign(pd.DataFrame(pipeline.predict(X.ix[:, 0][:, np.newaxis])))[0]

    signal_IS[mkt] = np.sign(pd.DataFrame(pipeline.predict(X)))[0]

    signal_IS.index = y.index

    k_sample['IS'] = (pd.DataFrame(signal_IS[mkt])*pd.DataFrame(y)).ix[:, 0]
    k_sample[mkt] = pd.DataFrame(y).ix[:, 0]

    output_degree['degree_' + str(k)] = k_sample

Histogramme de sortie (chaque degré N)


Performance_sim = pd.DataFrame()

fig = plt.figure(figsize=(15, 7), dpi=80)
for k in range(1, 7):
    ax = fig.add_subplot(2, 3, k)

    for_stats = output_degree['degree_' + str(k)]
    Performance = pd.DataFrame(for_stats.mean()*50 / (for_stats.std()*np.sqrt(50))).T

    Performance_tmp = Performance.ix[:, 1:].T

    ax.hist(Performance.drop(['IS', mkt], axis=1), bins=30, color="dodgerblue", alpha=0.8)
    ax.axvline(x=float(Performance.drop(['IS', mkt], axis=1).mean(axis=1)), color="b")
    ax.axvline(x=float(Performance['IS']), color="tomato")
    ax.axvline(x=float(Performance[mkt]), color="gray")
    ax.set_ylim([0, 40])
    ax.set_xlim([-0.3, 2.5])
    ax.set_title('degree-N polynomial: ' + str(m_))
fig.show()

résultat

Model_Complexity.png

C'est un résultat naturel s'il s'agit de données simples, mais cela semble utile pour la vérification lorsque j'ai fait un modèle

Addendum 1

Dans ce qui précède, la complexité du modèle est définie sur degré = k de PolynomialFeatures, mais le degré = 3, le modèle est RandomForestRegressor et la complexité du modèle est max_depth = k.

    pipeline = Pipeline([("polynomial_features", polynomial_features),
                         ("rf_regression", RandomForestRegressor(max_depth=k))])

résultat

Model_Complexity_RF.png

Addendum 2

Encore une fois, dans l'exemple où la complexité du modèle est fixée au degré = k de PolynomialFeatures, une variable explicative est ajoutée, et la variable explicative est utilisée dans la partie régression en ce sens qu'elle contrôle systématiquement le désir de créer un modèle. Faire une sélection

    pipeline = Pipeline([("polynomial_features", polynomial_features),
                         ("linear_regression", LassoCV(cv=5))])

Model_Complexity_LassoCV.png

Recommended Posts

Complexité et robustesse du modèle
Création, apprentissage et raisonnement de modèles d'apprentissage
Mémorandum de sauvegarde et modèle de chargement
Modèle de régression utilisant scikit-learn et sa visualisation
Chargement et test du modèle imagenet entraîné de Chainer
Implémenter un modèle avec état et comportement