Je construis un réseau RNN LSTM pour classer les textes en fonction de l'âge des écrivains (classification binaire - jeune/adulte).
On dirait que le réseau n'apprend pas et commence soudainement à sur-adapter:
Une possibilité pourrait être que la représentation des données ne soit pas assez bonne. Je viens de trier les mots uniques par leur fréquence et de leur donner des indices. Par exemple.:
unknown -> 0
the -> 1
a -> 2
. -> 3
to -> 4
J'essaie donc de remplacer cela par l'intégration de Word. J'ai vu quelques exemples mais je ne parviens pas à l'implémenter dans mon code. La plupart des exemples ressemblent à ceci:
embedding = tf.Variable(tf.random_uniform([vocab_size, hidden_size], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, input_data)
Est-ce que cela signifie que nous construisons une couche qui apprend l'intégration? Je pensais qu'il fallait télécharger Word2Vec ou Glove et l'utiliser.
Quoi qu'il en soit, disons que je veux construire cette couche d'intégration ...
Si j'utilise ces 2 lignes dans mon code, j'obtiens une erreur:
TypeError: la valeur transmise au paramètre 'indices' a DataType float32 ne figurant pas dans la liste des valeurs autorisées: int32, int64
Donc, je suppose que je dois changer le type input_data
en int32
. Donc, je fais ça (après tout, ce sont tous les indices), et je comprends ceci:
TypeError: les entrées doivent être une séquence
J'ai essayé d'encapsuler inputs
(argument à tf.contrib.rnn.static_rnn
) avec une liste: [inputs]
comme suggéré dans cette réponse , mais cela a généré une autre erreur:
ValueError: la taille de l'entrée (dimension 0 des entrées) doit être accessible via l'inférence de forme, mais la valeur de la vue est None.
Mise à jour:
Je désempilais le tenseur x
avant de le passer à embedding_lookup
. J'ai déplacé le dépilage après l'intégration.
Code mis à jour:
MIN_TOKENS = 10
MAX_TOKENS = 30
x = tf.placeholder("int32", [None, MAX_TOKENS, 1])
y = tf.placeholder("float", [None, N_CLASSES]) # 0.0 / 1.0
...
seqlen = tf.placeholder(tf.int32, [None]) #list of each sequence length*
embedding = tf.Variable(tf.random_uniform([VOCAB_SIZE, HIDDEN_SIZE], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, x) #x is the text after converting to indices
inputs = tf.unstack(inputs, MAX_POST_LENGTH, 1)
outputs, states = tf.contrib.rnn.static_rnn(lstm_cell, inputs, dtype=tf.float32, sequence_length=seqlen) #---> Produces error
* seqlen: j'ai mis à zéro les séquences afin qu'elles aient toutes la même taille de liste, mais comme la taille réelle diffère, j'ai préparé une liste décrivant la longueur sans remplissage.
Nouvelle erreur:
ValueError: l'entrée 0 de la couche basic_lstm_cell_1 est incompatible avec la couche: ndim attendu = 2, trouvé ndim = 3. Forme complète reçue: [Aucun, 1, 64]
_ {64 est la taille de chaque calque masqué.
Il est évident que j'ai un problème avec les dimensions ... Comment puis-je adapter les entrées au réseau après l'intégration?
À partir de tf.nn.static_rnn , nous pouvons voir que les arguments inputs
sont:
Une longueur T liste d’entrées, chacune un tenseur de forme [batch_size, input_size]
Donc, votre code devrait être quelque chose comme:
x = tf.placeholder("int32", [None, MAX_TOKENS])
...
inputs = tf.unstack(inputs, axis=1)
tf.squeeze est une méthode permettant de supprimer les dimensions de taille 1 du tenseur. Si l'objectif final est d'avoir la forme en entrée sous la forme [Aucun, 64], placez une ligne semblable à inputs = tf.squeeze(inputs)
et cela résoudrait votre problème.