Comment ajouter une nouvelle catégorie à un modèle d'apprentissage en profondeur?

15

Supposons que j'ai effectué un transfert d'apprentissage sur un réseau pré-formé pour reconnaître 10 objets. Comment ajouter un 11ème élément que le réseau peut classer sans perdre les 10 catégories que j'ai déjà formées ni les informations du modèle pré-formé d'origine? Un ami m'a dit que des recherches actives sont en cours dans ce domaine, mais je ne trouve aucun article pertinent ou un nom par lequel rechercher?

Je vous remercie.

nnrales
la source
Si vous vous entraînez avec beaucoup plus de classe, alors il y en a? est-ce que cela peut aider? Par exemple, disons que vous savez qu'il n'y aura pas plus de 1000 classes. Vous entraînez depuis le début votre classificateur avec 1000 classes sur la classe 10 que vous avez actuellement, et quand vous avez plus de classes, gardez simplement le train sur elles ... Est-ce que cela peut être une bonne solution? Y a-t-il du papier concernant cette approche?
Michael

Réponses:

13

S'il ne s'agit que d'un cas unique, vous pouvez simplement recycler le réseau neuronal. Si vous devez fréquemment ajouter de nouvelles classes, c'est une mauvaise idée. Ce que vous voulez faire dans de tels cas est appelé récupération d'image basée sur le contenu (CBIR), ou simplement récupération d'image ou recherche visuelle. J'expliquerai les deux cas dans ma réponse ci-dessous.

Cas unique

Si cela ne se produit qu'une seule fois - vous avez oublié la 11e classe, ou votre client a changé d'avis - mais cela ne se reproduira plus , alors vous pouvez simplement un 11e nœud de sortie vers la dernière couche. Initialisez les poids sur ce nœud de manière aléatoire, mais utilisez les poids que vous avez déjà pour les autres sorties. Ensuite, entraînez-le comme d'habitude. Il pourrait être utile de fixer certains poids, c'est-à-dire de ne pas les entraîner.

Un cas extrême serait de ne former que les nouveaux poids et de laisser tous les autres fixes. Mais je ne sais pas si cela fonctionnera aussi bien - cela pourrait valoir la peine d'être essayé.

Récupération d'image basée sur le contenu

Prenons l'exemple suivant: vous travaillez pour une boutique de CD, qui souhaite que ses clients puissent prendre une photo d'une pochette d'album, et l'application leur montre le CD qu'ils ont numérisé dans leur boutique en ligne. Dans ce cas, vous devrez réentraîner le réseau pour chaque nouveau CD qu'ils ont dans le magasin. Cela pourrait être 5 nouveaux CD chaque jour, donc la formation du réseau de cette façon ne convient pas.

La solution consiste à former un réseau, qui mappe l'image dans un espace caractéristique. Chaque image sera représentée par un descripteur, qui est par exemple un vecteur à 256 dimensions. Vous pouvez "classer" une image en calculant ce descripteur et en le comparant à votre base de données de descripteurs (c'est-à-dire les descripteurs de tous les CD que vous avez dans votre magasin). Le descripteur le plus proche de la base de données l'emporte.

Comment entraînez-vous un réseau neuronal à apprendre un tel vecteur descripteur? C'est un domaine de recherche actif. Vous pouvez trouver des travaux récents en recherchant des mots clés tels que "récupération d'image" ou "apprentissage métrique".

À l'heure actuelle, les gens prennent généralement un réseau pré-formé, par exemple VGG-16, coupent les couches FC et utilisent la convolution finale comme vecteur de descripteur. Vous pouvez continuer à former ce réseau, par exemple en utilisant un réseau siamois avec une perte de triplet.

hbaderts
la source
Je me suis penché sur l'apprentissage ponctuel. Pensez-vous que cela peut m'aider?
nnrales
Je ne connais pas vraiment l'apprentissage ponctuel. Mais les articles d'apprentissage approfondi en une seule fois que j'ai trouvés ressemblent assez à l'approche CBIR, donc cela pourrait certainement vous être utile
hbaderts
2

Votre topologie de réseau peut sembler différente, mais à la fin, votre réseau pré-formé a une couche, qui gère la reconnaissance de 10 classes originales. L'astuce la plus simple (et la plus efficace) pour introduire la 11e, 12e .. nième classe, consiste à utiliser toutes les couches avant la dernière comme accordé et à ajouter une couche supplémentaire (dans un nouveau modèle, ou parallèle) qui sera également installée au-dessus de toutes les couches, sauf les dernières, ressemblera à la couche de 10 classes (qui est très probablement une couche dense et une matrice de forme [len(dense layer), 10]avec un biais facultatif).

Votre nouveau calque serait un calque matmul avec forme [len(dense layer), len(new classes)].

Sans accès aux données de formation originales, vous auriez deux options:

  1. Geler tous les poids dans les calques d'origine en permettant au "nouveau" modèle d'optimiser uniquement les nouveaux poids. Cela vous donnera exactement le même pouvoir prédictif pour les 10 classes originales et pourrait donner des performances OK pour les nouvelles.
  2. Entraînez tout le réseau à la fois (en propageant l'erreur des nouvelles classes), ce qui pourrait fonctionner pour de nouvelles classes, mais vous vous retrouverez avec une solution originale inefficace pour 10 classes (car les poids seront modifiés pour les classes inférieures et la couche finale ne sera pas mis à jour pour correspondre à ces changements).

Bien que, étant donné que vous avez accès aux données de formation originales, vous pouvez facilement ajouter une nouvelle classe au réseau d'origine et la reformer pour prendre en charge 11 classes hors de la boîte.

chewpakabra
la source
2

Cela peut se faire facilement.

Construisez d'abord un modèle avec ces 10 classes et enregistrez le modèle en tant que base_model.

Chargez le base_model et définissez également un nouveau modèle nommé new_model as-

new_model = Sequential()

Ajoutez ensuite les couches du base_model au new_model -

# getting all the layers except the last two layers
for layer in base_model.layers[:-2]: #just exclude the last two layers from base_model
    new_model.add(layer)

Désormais, rendez les couches du nouveau modèle non entraînables car vous ne voulez pas que votre modèle soit à nouveau formé.

# prevent the already trained layers from being trained again
for layer in new_model.layers:
    layer.trainable = False

Maintenant que vous transférez l'apprentissage, lorsque vous supprimez les dernières couches, le modèle oublie les 10 classes, nous devons donc conserver les poids de base_model vers new_model -

weights_training = base_model.layers[-2].get_weights()
new_model.layers[-2].set_weights(weights_training) 

Ajoutez maintenant une couche dense à la fin et nous ne formerons cette couche dense que dans cet exemple.

new_model.add(Dense(CLASSES, name = 'new_Dense', activation = 'softmax'))

Maintenant, entraînez le modèle et j'espère qu'il donne la bonne sortie pour les 11 classes.

Bon apprentissage.

Subham Tiwari
la source