Je veux apprendre RNN flou (Chainer meetup 01) était très intéressant, je l'ai donc implémenté avec Chainer également. De plus, j'ai créé une application qui vous permet de vérifier le modèle entraîné directement depuis le navigateur.
Tout d'abord, ce que j'ai fait était essentiellement le deuxième breuvage de la diapositive originale, et en parlant de la différence, j'ai essayé d'augmenter les données d'apprentissage (ce n'était pas bien appris) et j'ai créé une application Web. C'est à peu près ça.
L'application Web que j'ai créée ressemble à ceci.
Celui que j'ai créé cette fois-ci est disponible sur GitHub. La documentation pourrait être rédigée prochainement.
Il y a des recherches qu'il est possible de générer une description (légende) d'une image en entrant les caractéristiques de l'image extraite à l'aide du réseau neuronal convolutif (CNN) au réseau neuronal récurrent (RNN). Les lieux célèbres incluent [Karpathy + 2015] et [Vinyals + 2014]. Peut être mentionné.
(À partir de [Vinyals + 2014])Sur cette figure, une image est entrée, et après avoir traversé un CNN multicouche, elle est entrée dans LSTM (un type de RNN), et une explication est générée mot par mot. C'est un modèle simple, mais il est connu pour fonctionner étonnamment bien, vous pouvez voir un exemple de génération réel ici (c'est Karpathy)
En passant, si ** l'image d'entrée peut être traduite en "description", il peut être possible de ** traduire l'image d'entrée en "floue". En d'autres termes, est-il possible de «brouiller» ** avec un réseau neuronal? Sur la base de cette intuition, en implémentant ces modèles avec Chainer, nous avons créé un "réseau neuronal flou entièrement automatique".
Pour 1, il était facile d'utiliser le modèle entraîné fourni pour Caffe. Cette fois, j'ai utilisé CaffeNet, mais je pense que d'autres réseaux peuvent être utilisés. Cependant, comme la sortie de la couche fc7 (couche entièrement connectée) est nécessaire pour extraire les caractéristiques de l'image, cela ressemble à GoogleNet. Les modèles plus légers sont (probablement) inutilisables.
En ce qui concerne 2, il existe un merveilleux service Web appelé bokete-un service Web qui brouille un mot avec des images, donc je vais ramper à partir d'ici et le collecter avec enthousiasme. Comme mentionné par l'ancien auteur de diapositives, il n'est pas si difficile de collecter des données car chaque page floue a une structure simple de "1 image + 1 texte".
Chainer est très pratique car il peut lire le modèle entraîné de Caffe. J'ai défini la méthode suivante dans Model Class et utilisé la sortie.
Model.py
def encode_image(self, img_array):
batchsize = img_array.shape[0]
if self.config["use_caffenet"]:
img_x = chainer.Variable(img_array, volatile='on')
y = self.enc_img(
inputs={"data": img_x},
outputs={"fc7"})[0]
else:
x = self.xp.random.rand(batchsize, 4096).astype(np.float32)
y = chainer.Variable(x)
y.volatile = 'off'
return self.img2x(y)
Le fichier image vectorisé par PIL etc. est stocké dans img_array. Pour cela, je me suis référé à Reading caffemodel with Chainer and classifying images --Qiita.
Entrez les caractéristiques de l'image extraite dans LSTM. Ceci est également défini dans Model Class.
Model.py
def __call__(self, x, img_vec=None):
if img_vec is not None:
h0 = self.embed_mat(x) + img_vec
else:
h0 = self.embed_mat(x)
h1 = self.dec_lstm(h0)
y = self.l1(h1)
return y
En fait, nous voulons entrer la fonction uniquement lorsque le temps t = 0, donc Le vecteur d'image n'est donné que lorsque n = 0
dans le processus de calcul.
Trainer.py
def _calc_loss(self, batch):
boke, img = batch
boke = self.xp.asarray(boke, dtype=np.int32)
img = self.xp.asarray(img, dtype=np.float32)
# 1.Mettez l'image vectorisée dans CNN et faites-en un vecteur de caractéristiques
img_vec = self.model.predictor.encode_image(img)
# 2.Apprenez à décoder la boke
accum_loss = 0
n = 0
for curr_words, next_words in zip(boke.T, boke[:, 1:].T):
if n == 0:
accum_loss += self.model(curr_words, img_vec, next_words)
else:
accum_loss += self.model(curr_words, next_words)
n += 1
return accum_loss
Vous vous demandez peut-être: "N'entrez-vous pas les caractéristiques de l'image toutes les heures?", Mais [Karpathy + 2015]
Note that we provide the image context vector b v to the RNN only at the first iteration, which we found to work better than at each time step.
Il semble que vous ne pouvez obtenir une meilleure sortie que lorsque t = 0
(je ne l'ai pas vraiment essayé).
Le pionnier je veux apprendre le RNN flou (Chainer meetup 01) a appris avec 500 échantillons, puis 20 000 échantillons. Il était écrit que je voulais l'essayer, donc je voulais aussi le faire à cette échelle, alors j'ai essayé d'apprendre avec environ 30 000 échantillons. (Word Embedding, la couche cachée de LSTM est de 100 dimensions, la taille du lot 16 Dropout, etc.)
Cependant, la perte n'a pas bien diminué.
average_loss.log
"average_loss":[
10.557335326276828,
9.724091438064605,
9.051927699901125,
8.728849313754363,
8.36422316245738,
8.1049892753394,
7.999240087562069,
7.78314874008182,
7.821357278519156,
7.629313596859783
]
(Au fait, c'est la perte de données d'entraînement)
Au stade de tourner environ 30 époques, la perte n'a pas diminué. Au fait, j'ai essayé de brouiller l'image à portée de main, mais je ne pouvais pas obtenir une sortie décente ...
C'est probablement parce qu'il n'y avait qu'environ 2000 images du flou d'origine pour 30 000 flous. (Plusieurs flous sont ajoutés à une image pour faciliter l'acquisition de données à partir de "flou") Puisqu'il y a probablement plus de 10 réponses correctes (destinations de traduction) pour une image, les paramètres du modèle peuvent ne pas être ajustés dans une direction unique. Je pense.
Puisque "je veux vérifier simplement en réduisant la perte", j'ai veillé à ce qu'un flou corresponde à une image, et ai mené une expérience avec des données à petite échelle (environ 300 flous):
average_loss.log
"average_loss": [
6.765932078588577,
1.7259380289486477,
0.7160143222127642,
0.3597904167004994,
0.1992428061507997
]
Certes, la perte a diminué. (Tourné jusqu'à un total de 100 époques)
À partir de là, même dans le cas de données à grande échelle, on peut s'attendre à ce que "la perte diminuera (= peut être apprise) s'il y a une correspondance biunivoque entre l'image et le flou".
Lorsque je l'ai essayé avec l'image à portée de main, j'ai obtenu la sortie suivante. ** (Est-ce flou ...?) **
J'ai beaucoup appris, et c'est ennuyeux si je ne peux pas le vérifier depuis le navigateur, j'ai donc créé une application Web. (Le code est ouvert au public)
C'est un état. Vous pouvez voir les statistiques des données utilisées pour la formation. En appuyant sur le bouton Générer, vous pouvez voir le flou des données de formation / développement.Le modèle entraîné de Chainer est chargé derrière l'application Web et la méthode de génération de flou se déclenche lorsqu'un bouton est enfoncé du côté du navigateur.
Cette fois, j'ai utilisé le modèle de génération d'explications d'images comme [Karpathy + 2015] et [Vinyals + 2014] pour apprendre et générer du flou, mais je ne pense pas que ce modèle soit le meilleur pour gérer le flou. Puisque ce modèle est conçu et évalué sur l'hypothèse qu'il n'y a qu'une seule réponse correcte dans la description de l'image **, il s'agit d'une "réponse correcte arbitraire (= intéressante)" telle que "flou sur l'image". C'est parce que je ne pense pas qu'il convient aux données «floues». En fait, après avoir essayé d'apprendre en donnant plusieurs données de réponse correcte (flou) à une image, j'ai souffert du phénomène selon lequel la perte ne diminue pas.
De plus, même si la perte sur les données d'apprentissage est réduite, la perte sur les données de développement ne sera probablement pas réduite. (Il devrait certainement être nécessaire de réduire davantage le domaine d'entrée / sortie, par exemple, réduire l'image d'entrée à l'ossan, ne pas remplir les espaces, etc.)
En premier lieu, est-ce que l'approche consistant à «générer du flou sur l'image d'entrée» est appropriée? Existe-t-il une approche plus simple? Par exemple, si vous ajoutez intentionnellement une description d'image complètement différente à l'image d'entrée **, ce serait un flou intéressant.
Par exemple comme ça (C'est une image)
Un réseau neuronal est-il vraiment nécessaire pour un flou intéressant ... C'est un endroit très ennuyeux.
Recommended Posts