Formation d'un échantillon de données d'entraînement avec décalage de distribution

Avertissement: Cet article est un produit traduit de Max Halforda . La traduction n'est pas propre, mais adaptative. Telle qu'il y a compréhension à n'importe quelle ligne de connaissance







«Mes amis et moi nous sommes récemment qualifiés pour la finale du Data Science Game 2017. La première partie de la compétition était Kaggle avec un jeu de données de Deezer (1). Le problème consistait à résoudre le problème de classification binaire: il fallait prédire si l'utilisateur allait passer à l'écoute de la composition qui lui était proposée.



Comme d'autres équipes, nous avons extrait les fonctionnalités pertinentes et formé le classificateur XGBoost (2). Cependant, nous avons fait quelque chose de spécial, un sous-échantillon de l'ensemble de données d'entraînement, afin qu'il (l'ensemble de données d'entraînement) devienne plus représentatif de l'ensemble de test. "




L'une des exigences de base du processus d'apprentissage pour le bon fonctionnement d'un modèle de machine est la même nature des distributions dans les ensembles de données d'entraînement et de test. À titre d'exemple approximatif: le modèle est formé sur des utilisateurs de 20 ans, et dans l'échantillon de test, les utilisateurs ont plus de 60 ans.



Ici, il est intuitivement naturel qu'avec l'âge auquel le modèle n'a pas été formé, il ne s'en sortira pas. Bien sûr, un tel exemple est purement synthétique, mais en réalité, pour des différences significatives, il suffit de former le modèle pour 20+ et d'essayer de le faire fonctionner pendant 30+. Le résultat sera similaire.



En effet, les modèles apprennent les distributions (3) des données. Si les distributions d'une fonctionnalité dans les ensembles de formation et de test sont les mêmes, le modèle vous en remerciera.



Insertion du traducteur: Quand je me suis assis pour traduire, j'avais une question: pourquoi la formation devrait-elle être ajustée au test, car, en fait , le test reflète des données invisibles qui entreront dans le modèle à l'entrée de la production. Puis j'ai dormi trop longtemps, relu et tout s'est passé. L'astuce est que, sous l'influence de facteurs, la rétrospective peut devenir hors de propos pour le présent. Plus d'informations à ce sujet plus tard (exemple légèrement réadapté).



Un biais dans les distributions pour une fonction peut se produire pour diverses raisons. L'exemple le plus intuitif peut être emprunté à Facebook.



Disons qu'une entreprise a été formée sur un modèle basé sur une fonctionnalité (une fonctionnalité est la même chose qu'une fonctionnalité) comme passe-temps en quelques minutes. Laissez-le prédire synthétiquement le niveau de fidélité des utilisateurs sur une échelle de dix points.



Lorsque la scission de l'application Facebook commune entre le réseau social principal (flux, etc.) et le système de messagerie s'est produite, le temps passé dans l'application principale a diminué, c'est-à-dire que les ensembles de données entrants ont changé et ne correspondaient plus à la rétrospective passée.

Mathématiquement, en tenant compte de la caractéristique temporelle, le modèle prédira un niveau de fidélité inférieur, bien qu'en réalité ce ne soit pas le cas - le transfert de temps est simplement divisé en deux applications. Cela sort tristement.



Ainsi, un décalage de distribution se produit lorsque la distribution des données historiques n'est plus pertinente pour prédire de nouvelles données.



Dans l'ensemble de données Deezer, l'incohérence des distributions résidait dans la fonction mesurant le nombre de chansons écoutées avant de résoudre le problème de prédiction. Cette fonctionnalité avait une distribution exponentielle (4) dans les ensembles de données publics et de test. Cependant, dans l'ensemble de données de test, il était plus prononcé, de sorte que la moyenne de l'ensemble d'apprentissage était inférieure à celle de l'ensemble de test. Après avoir rééchantillonné la distribution de la formation, nous avons réussi à augmenter la métrique ROC-AUC (5) et à augmenter la note d'environ 20 points.



Voici un exemple de la différence de distribution:



import numpy as np
import plotly.figure_factory as ff

train = np.random.exponential(2, size=100000)
test = np.random.exponential(1, size=10000)

distplot = ff.create_distplot([train, test], ['Train', 'Test'], bin_size=0.5)
distplot.update_layout(title_text=' Test, Train')


" "



L'idée de niveler le décalage de distribution est de remodeler l'échantillon d'apprentissage pour refléter la distribution de test.



Imaginons que nous souhaitons créer un sous-échantillon de 50 000 observations à partir de notre ensemble d'entraînement pour s'adapter à la distribution de l'ensemble de test. Que voulez-vous faire intuitivement?



Faites en sorte que les objets les plus courants dans le jeu de données de test soient également communs dans la formation! Mais comment déterminer quels objets sont les plus nécessaires et lesquels moins souvent?



Balance!



Les étapes seront quelque chose comme ceci:



  • divisez la droite numérique de distribution en intervalles égaux (ou paniers
  • compter le nombre d'objets dans chaque panier (taille du bac)
  • pour chaque observation dans le panier, calculer son poids égal à 1 / (taille du bac)
  • créer un sous-échantillon de k avec une distribution pondérée (les objets avec un poids plus élevé apparaîtront plus souvent dans le sous-échantillon)


En transférant vers le code, nous effectuons les actions suivantes:



SAMPLE_SIZE = 50000
N_BINS = 300

#   ,       .
#        
step = 100 / N_BINS

test_percentiles = [
    np.percentile(test, q, axis=0)
    for q in np.arange(start=step, stop=100, step=step)
]

#     . 
#    ,    
train_bins = np.digitize(train, test_percentiles)

#          i   ,
#  0      , 1    1    i 
train_bin_counts = np.bincount(train_bins)

#    ,        
weights = 1 / np.array([train_bin_counts[x] for x in train_bins])

#   ,     
weights_norm = weights / np.sum(weights)

np.random.seed(0)

sample = np.random.choice(train, size=SAMPLE_SIZE, p=weights_norm, replace=False)

distplot_with_sample = ff.create_distplot([train, test, sample], ['Train', 'Test', 'New train'], bin_size=0.5)
distplot_with_sample.update_layout(title_text=' Test, Train, New train')


" " La



nouvelle distribution (verte) correspond mieux à la distribution de l'échantillon de test (orange). Nous avons utilisé des actions similaires dans le concours - l'ensemble de données d'origine contenait 3 millions de lignes, nous avons généré la taille du nouvel échantillon à partir de 1,3 million d'objets. Les données sont devenues plus petites, mais la représentativité de la distribution a amélioré la qualité de la formation.



Quelques notes de l'expérience personnelle de l'auteur:



  • Le nombre de paniers ne joue pas un grand rôle, mais moins il y a de paniers, plus l'algorithme apprend vite (essayez de changer le nombre de paniers (N_BINS) à 3, 30 dans l'exemple et vous verrez que la différence est vraiment petite)
  • , , , “” , , .

    ( , “” , “” . . , )



L'algorithme de remodelage se trouve sur le github de l'auteur (dossier xam ). À l'avenir, l'auteur prévoit d'analyser de nouveaux sujets et de les partager dans le blog.



J'espère que la traduction et les notes ont été utiles et claires. J'attends avec impatience vos commentaires dans un format constructif. Merci pour votre temps.



Notes de bas de page:



1. Deezer est un service de streaming musical en ligne français. Tapez Spotify, Ya.Muzyki et bien, vous obtenez



2. XGBoost- algorithme de renforcement de gradient extrême. J'ai vraiment adoré l'appeler «gradient boosting on steroids». L'idée du boosting est de former plusieurs élèves faibles homogènes, dont chacun forme des notes basées sur l'expérience d'apprentissage rétrospectif du précédent, en prêtant attention aux classes où l'algorithme précédent a le plus trébuché. L'idée derrière un gradient est, en termes simples, de minimiser les erreurs d'apprentissage. XGBoost, en tant qu'algorithme, est une configuration plus avantageuse en termes de calcul de Gradient Boosting



3. La distribution signifie ici exactement ce qui décrit la loi par laquelle les nombres sont dispersés dans une variable.



4. À mon avis, le stimulant le plus compréhensible pour visualiser l' exponentiellela distribution dans la tête est sa définition comme distribution, avec une intensité constante.



5. ROC-AUC (courbe caractéristique de fonctionnement de la zone sous le récepteur) - la zone sous la courbe «caractéristiques de traitement du récepteur» - un nom littéral, puisque la métrique provient de la théorie du traitement du signal. La courbe ROC est très abrupte - elle montre le rapport entre les réponses Vrai positif et Faux positif des réponses du modèle lorsque le seuil de probabilité pour l'affectation à une classe change, formant un «arc». Du fait que le rapport de TP et FP peut être vu, le seuil optimal de probabilités peut être sélectionné en fonction des erreurs du 1er et du 2ème type.



Dans le cas de la prise en compte de la précision du modèle, sans prêter attention au seuil probabiliste des réponses, la métrique ROC-AUC est utilisée, qui prend des valeurs dans l'intervalle [0,1]. Pour un modèle constant avec un équilibre de classes, le ROC-AUC sera approximativement égal à 0,5, par conséquent, les modèles ci-dessous ne passent pas le contrôle de cohérence (contrôle de cohérence). Plus l'aire sous la courbe ROC est proche de un, mieux c'est, mais pour indexer l'utilité des résultats en général, il est pertinent de comparer l'AUC-ROC du modèle entraîné avec l'AUC-ROC du modèle constant.



All Articles