Mon ensemble de formation contient environ 50k entrées avec lesquelles je fais un apprentissage initial. Sur une base hebdomadaire, environ 5 000 entrées sont ajoutées; mais la même quantité "disparaît" (car ce sont les données utilisateur qui doivent être supprimées après un certain temps).
Par conséquent, j'utilise l'apprentissage en ligne car je n'ai pas accès à l'ensemble de données complet ultérieurement. Actuellement j'utilise un SGDClassifier
qui fonctionne, mais mon gros problème: de nouvelles catégories apparaissent et maintenant je ne peux plus utiliser mon modèle comme il ne l'était pas au départ fit
.
Existe-t-il un moyen avec SGDClassifier
ou un autre modèle? L'apprentissage en profondeur?
Peu importe si je dois recommencer à zéro MAINTENANT (c'est-à-dire utiliser autre chose que SGDClassifier
), mais j'ai besoin de quelque chose qui permette l'apprentissage en ligne avec de nouvelles étiquettes.
Réponses:
Il semble que vous ne souhaitiez pas commencer à recycler le modèle chaque fois qu'une nouvelle catégorie d'étiquette apparaît. Le moyen le plus simple de conserver des informations maximales sur les données passées serait de former un classificateur par catégorie.
De cette façon, vous pouvez continuer à former chaque classificateur de manière incrémentielle ("en ligne") avec quelque chose comme
SGDClassifier
sans avoir à les recycler. Chaque fois qu'une nouvelle catégorie apparaît, vous ajoutez un nouveau classificateur binaire pour cette catégorie uniquement. Vous sélectionnez ensuite la classe avec la probabilité / le score le plus élevé parmi l'ensemble des classificateurs.Cela n'est pas non plus très différent de ce que vous faites aujourd'hui, car il
scikit's SDGClassifier
gère déjà le scénario multiclasse en installant plusieurs classificateurs "One vs All" sous le capot.Si de nombreuses nouvelles catégories continuent d'apparaître, bien sûr, cette approche pourrait devenir un peu délicate à gérer.
la source
warm_start
option.Si de nouvelles catégories arrivent très rarement, je préfère moi-même la solution "one vs all" proposée par @oW_ . Pour chaque nouvelle catégorie, vous entraînez un nouveau modèle sur X nombre d'échantillons de la nouvelle catégorie (classe 1) et X nombre d'échantillons du reste des catégories (classe 0).
Cependant, si de nouvelles catégories arrivent fréquemment et que vous souhaitez utiliser un seul modèle partagé , il existe un moyen d'y parvenir en utilisant des réseaux de neurones.
En résumé, à l'arrivée d'une nouvelle catégorie, nous ajoutons un nouveau nœud correspondant à la couche softmax avec des poids zéro (ou aléatoires), et gardons les anciens poids intacts, puis nous entraînons le modèle étendu avec les nouvelles données. Voici un croquis visuel de l'idée (dessiné par moi-même):
Voici une implémentation pour le scénario complet:
Le modèle est formé sur deux catégories,
Une nouvelle catégorie arrive,
Le modèle et les formats cibles sont mis à jour en conséquence,
Le modèle est formé sur les nouvelles données.
Code:
qui génère:
Je devrais expliquer deux points concernant cette sortie:
Les performances du modèle sont réduites de
0.9275
à0.8925
simplement en ajoutant un nouveau nœud. En effet, la sortie du nouveau nœud est également incluse pour la sélection de catégorie. En pratique, la sortie du nouveau nœud doit être incluse uniquement après que le modèle a été formé sur un échantillon de taille importante. Par exemple,[0.15, 0.30, 0.55]
à ce stade , nous devrions atteindre le sommet de la première des deux premières entrées , c'est- à -dire la 2e classe.Les performances du modèle étendu sur deux (anciennes) catégories
0.88
sont inférieures à celles de l'ancien modèle0.9275
. C'est normal, car maintenant le modèle étendu veut affecter une entrée à l'une des trois catégories au lieu de deux. Cette diminution est également attendue lorsque nous sélectionnons parmi trois classificateurs binaires par rapport à deux classificateurs binaires dans l'approche "un contre tous".la source
Je dois dire que je n'ai trouvé aucune littérature concernant ce sujet. Pour autant que je sache, ce que vous demandez est impossible. Vous devez en être conscient et le propriétaire du produit doit l'être également. La raison en est que toute fonction de perte repose sur des étiquettes connues, il n'y a donc aucun moyen de prédire une étiquette qui ne figure pas dans les données d'apprentissage. En outre, est-ce de la science-fiction qu'un algorithme d'apprentissage automatique peut prédire quelque chose pour lequel il n'a pas été formé
Cela dit, je pense qu'il peut y avoir une solution de contournement (permettez-moi de souligner qu'il s'agit d'une opinion non basée sur la littérature formelle). Si le classificateur est probabiliste, la sortie est la probabilité que chaque classe soit vraie et la décision est la probabilité la plus élevée. Vous pouvez peut-être définir un seuil pour cette probabilité, de sorte que le modèle prédit "inconnu" si toutes les probabilités sont inférieures à ce seuil. Laisse moi te donner un exemple.
LaisserM( x ) être un modèle tel que: étant donné X , décide si X appartient à une catégorie sur trois c1, c2, c3 . La sortie deM est un vecteur de probabilités p . La décision est prise en prenant le plus haut probp . Donc, une sortie deM( x ) = p ( x ) = ( 0,2 , 0,76 , 0,5 ) correspondrait à la décision X appartient à c2 . Vous pouvez modifier cette décision en définissant unτ tel si aucun des pje≥ τ alors la décision est X appartient à une classe inconnue
Que faites-vous de ces inconnus dépend de la logique des bussines. S'ils sont importants, vous pouvez en créer un pool et recycler le modèle à l'aide des données disponibles. Je pense que vous pouvez faire une sorte de «transfert d'apprentissage» à partir du modèle formé en changeant la dimension de la sortie. Mais c'est quelque chose que je n'ai pas rencontré, donc je dis juste
Prenez le compte qui
SGDClassifier
utilise enSVM
dessous, qui n'est pas un algorithme probabiliste. LaSGDClassifier
documentation suivante vous permet de modifier l'loss
argument enmodified_huber
oulog
afin d'obtenir des sorties probabilistes.la source
Il y a deux options:
Prédisez la probabilité qu'un point de données appartienne à une
unk
catégorie ou à un inconnu . Toutes les nouvelles catégories qui apparaissent dans le flux doivent être prédites commeunk
. Ceci est courant dans le traitement du langage naturel (NLP) car il y a toujours de nouveaux jetons de mots qui apparaissent dans les flux de mots.Réentraînez le modèle chaque fois qu'une nouvelle catégorie apparaît.
Depuis que vous mentionnez
SGDClassifier
, je suppose que vous utilisez scikit-learn. Scikit-learn ne prend pas très bien en charge l'apprentissage en ligne. Il serait préférable de changer de cadre qui prend mieux en charge le streaming et l'apprentissage en ligne, comme Spark .la source