[PYTHON] Implémentez un réseau de neurones feedforward dans Chainer pour classer les documents

introduction

Récemment, j'ai essayé d'implémenter un classificateur binaire qui juge le positif et le négatif d'un document en utilisant Chainer, qui est un sujet brûlant. Depuis que j'ai utilisé Chainer pour la première fois, c'est un modèle simple car c'est pour la pratique. Pour ceux qui veulent implémenter un réseau neuronal profond avec Chainer et faire quelque chose comme l'auteur.

Il serait utile que vous puissiez signaler les erreurs dans la section des commentaires.

Veuillez consulter ici pour le code complet.

Préparation préalable

--Installation de chainer, gensim, scikit-learn

environnement

--Série Python 2.7

Exemple de données à utiliser

Les données utilisées sont un document sur un examen de quelque chose en anglais. Chaque ligne correspond à un document et chaque mot du document est séparé par un espace demi-largeur. Le numéro au début de chaque ligne (par exemple 1, 0) est l'étiquette.

0 each scene drags , underscoring the obvious , and sentiment is slathered on top . 0 afraid to pitch into farce , yet only half-hearted in its spy mechanics , all the queen's men is finally just one long drag . 1 clooney directs this film always keeping the balance between the fantastic and the believable . . . 1 just about the best straight-up , old-school horror film of the last 15 years .

Vectorisation de documents

Vectorisez avec un sac de mots pour traiter chaque document comme une entrée dans le réseau neuronal. Pour la vectorisation, j'ai utilisé la fonction de gensim. Veuillez consulter cet article pour plus de détails. → Classer les articles de presse par scikit-learn et gensim

La fonction load_data lit les données d'entrée et divise l'étiquette et la chaîne de mots de chaque document par l.strip (). Split (" ", 1). L'étiquette du document est stockée dans «cible» et le vecteur de document est stocké dans «source».

corpora.Dictionary (document_list) crée un dictionnaire de mots en passant une liste de listes de documents (document_list) avec chaque mot comme élément. À l'origine, je devais créer un dictionnaire de mots en utilisant uniquement des données de formation, mais je voulais omettre le traitement de texte inconnu, j'ai donc créé un dictionnaire de mots en utilisant tous les documents.

Où «vocab_size» est le nombre de vocabulaire dans tout le document et correspond au nombre de dimensions du vecteur de document. Par conséquent, le nombre d'unités dans la couche d'entrée du réseau neuronal mis en œuvre cette fois est égal à «vocab_size».

def load_data(fname):
    source = []
    target = []
    f = open(fname, "r")

    document_list = [] #Un document sur chaque ligne.Les éléments du document sont des mots
    for l in f.readlines():
        sample = l.strip().split(" ", 1)        #Libellés et chaînes de mots séparés
        label = int(sample[0])                  #étiquette
        target.append(label)
        document_list.append(sample[1].split()) #Diviser les mots et les ajouter à la liste des documents

    #Créer un dictionnaire de mots
    dictionary = corpora.Dictionary(document_list)
    dictionary.filter_extremes(no_below=5, no_above=0.8)
    # no_below:Le document utilisé est non_Ignorer les mots ci-dessous
    # no_above:Le pourcentage de phrases utilisées est non_Ignorer ci-dessus ci-dessus

    #Vectorisation de documents
    for document in document_list:
        tmp = dictionary.doc2bow(document) #Représentation BoW du document
        vec = list(matutils.corpus2dense([tmp], num_terms=len(dictionary)).T[0])
        source.append(vec)

    dataset = {}
    dataset['target'] = np.array(target)
    dataset['source'] = np.array(source)
    print "vocab size:", len(dictionary.items()) #Nombre de vocabulaire=Nombre d'unités dans la couche d'entrée

    return dataset, dictionary

Définition du modèle

Cette fois c'était pour la pratique, j'ai donc implémenté un modèle simple. (Le dataset reçu de la fonction précédenteload_data est divisé en données d'entraînement et données de test à l'aide de la fonction train_test_split contenue dans scikit-learn.)

Le nombre d'unités dans la couche d'entrée ʻin_units contient le nombre de dimensions du vecteur de document (x_train.shape [1]`). La couche cachée (couche intermédiaire) peut être définie de manière appropriée. Cette fois, j'essaye de passer 500 par défaut. Étant donné que la couche de sortie utilise la fonction softmax, le nombre d'unités est de 2, ce qui correspond au nombre de types d'étiquettes.

x_train, x_test, y_train, y_test = train_test_split(dataset['source'], dataset['target'], test_size=0.15)
N_test = y_test.size         # test data size
N = len(x_train)             # train data size
in_units = x_train.shape[1]  #Nombre d'unités dans la couche d'entrée(Nombre de vocabulaire)

n_units = args.units #Nombre d'unités de calque masquées
n_label = 2          #Nombre d'unités dans la couche de sortie

#Définition du modèle
model = chainer.Chain(l1=L.Linear(in_units, n_units),
                      l2=L.Linear(n_units, n_units),
                      l3=L.Linear(n_units,  n_label))

Propagation vers l'avant

La fonction «forward» effectue une propagation vers l'avant. Couche d'entrée-> couche cachée, couche cachée-> fonction d'activation de couche cachée utilisée fonction sigmoïde.

def forward(x, t, train=True):
    h1 = F.sigmoid(model.l1(x))
    h2 = F.sigmoid(model.l2(h1))
    y = model.l3(h2)
    return F.softmax_cross_entropy(y, t), F.accuracy(y, t)

Apprentissage

Dans l'ensemble,

  1. Créez un lot à partir des données d'entraînement
  2. Propagation vers l'avant
  3. Rétropropagation de l'erreur
  4. Mise à jour des paramètres C'est comme ça. (Je ne suis pas si confiant ...)

Chaque époque calcule l'erreur pour les données d'apprentissage et l'erreur pour les données de test. De plus, puisqu'il s'agit d'un problème de classification, le taux d'exactitude de classification «précision» est également calculé.

# Setup optimizer
optimizer = optimizers.Adam()
optimizer.setup(model)

# Learning loop
for epoch in six.moves.range(1, n_epoch + 1):

    print 'epoch', epoch

    # training
    perm = np.random.permutation(N) #Obtenez une liste aléatoire de colonnes entières
    sum_train_loss     = 0.0
    sum_train_accuracy = 0.0
    for i in six.moves.range(0, N, batchsize):

        #x en utilisant perm_train, y_Sélectionnez un jeu de données du train(Les données cibles sont différentes à chaque fois)
        x = chainer.Variable(xp.asarray(x_train[perm[i:i + batchsize]])) #source
        t = chainer.Variable(xp.asarray(y_train[perm[i:i + batchsize]])) #target

        model.zerograds()            #Zéro initialisation du gradient
        loss, acc = forward(x, t)    #Propagation vers l'avant
        sum_train_loss      += float(cuda.to_cpu(loss.data)) * len(t)   #Pour le calcul de l'erreur moyenne
        sum_train_accuracy  += float(cuda.to_cpu(acc.data )) * len(t)   #Pour calculer le taux de précision moyen
        loss.backward()              #Erreur de propagation de retour
        optimizer.update()           #optimisation

    print('train mean loss={}, accuracy={}'.format(
        sum_train_loss / N, sum_train_accuracy / N)) #Erreur moyenne


    # evaluation
    sum_test_loss     = 0.0
    sum_test_accuracy = 0.0
    for i in six.moves.range(0, N_test, batchsize):

        # all test data
        x = chainer.Variable(xp.asarray(x_test[i:i + batchsize]))
        t = chainer.Variable(xp.asarray(y_test[i:i + batchsize]))

        loss, acc = forward(x, t, train=False)

        sum_test_loss     += float(cuda.to_cpu(loss.data)) * len(t)
        sum_test_accuracy += float(cuda.to_cpu(acc.data))  * len(t)

    print(' test mean loss={}, accuracy={}'.format(
        sum_test_loss / N_test, sum_test_accuracy / N_test)) #Erreur moyenne

#Enregistrer le modèle et l'optimiseur
print 'save the model'
serializers.save_npz('pn_classifier_ffnn.model', model)
print 'save the optimizer'
serializers.save_npz('pn_classifier_ffnn.state', optimizer)

Résultat d'exécution

Le taux d'exactitude de classification pour les données d'essai finales était «précision = 0,716875001788». Cependant, à mesure que l'apprentissage progresse, l'erreur de test augmente et un surapprentissage se produit ...

Probablement à cause du fait que le modèle a finalement été construit.

>python train.py --gpu 1 --data input.dat --units 1000
vocab size: 4442
epoch 1
train mean loss=0.746377664579, accuracy=0.554684912523
 test mean loss=0.622971419245, accuracy=0.706875003874
epoch 2
train mean loss=0.50845754933, accuracy=0.759408453399
 test mean loss=0.503996372223, accuracy=0.761249992996
epoch 3
train mean loss=0.386604680468, accuracy=0.826067760105
 test mean loss=0.506066314876, accuracy=0.769374992698
epoch 4
train mean loss=0.301527346359, accuracy=0.870433726909
 test mean loss=0.553729468957, accuracy=0.774999994785
epoch 5
train mean loss=0.264981631757, accuracy=0.889085094432
 test mean loss=0.599407823756, accuracy=0.766874998808
epoch 6
train mean loss=0.231274759588, accuracy=0.901114668847
 test mean loss=0.68350501731, accuracy=0.755625002086

...

epoch 95
train mean loss=0.0158744356008, accuracy=0.993598945303
 test mean loss=5.08019682765, accuracy=0.717499997467
epoch 96
train mean loss=0.0149783944279, accuracy=0.994261124581
 test mean loss=5.30629962683, accuracy=0.723749995232
epoch 97
train mean loss=0.00772037562047, accuracy=0.997351288256
 test mean loss=5.49559159577, accuracy=0.720624998212
epoch 98
train mean loss=0.00569957431572, accuracy=0.99834455516
 test mean loss=5.67661693692, accuracy=0.716875001788
epoch 99
train mean loss=0.00772406136085, accuracy=0.997240925267
 test mean loss=5.63734056056, accuracy=0.720000002533
epoch 100
train mean loss=0.0125463016702, accuracy=0.995916569395
 test mean loss=5.23713605106, accuracy=0.716875001788
save the model
save the optimizer

en conclusion

J'ai utilisé Chainer pour implémenter un réseau neuronal feedforward pour la classification de documents. Je voudrais améliorer le modèle pour qu'il n'y ait pas de surentraînement.

Si vous souhaitez voir le code pour étudier Chainer, veuillez vous référer à ici.

Page de référence

Recommended Posts

Implémentez un réseau de neurones feedforward dans Chainer pour classer les documents
Réseau de neurones pour comprendre et mettre en œuvre en mathématiques au secondaire
Implémenter un réseau neuronal convolutif
Implémenter le réseau neuronal à partir de zéro
Implémenter un réseau neuronal à 3 couches
Réseau de neurones commençant par Chainer
Implémentation de réseau neuronal en python
J'ai essayé de mettre en œuvre le modèle de base du réseau neuronal récurrent
J'ai essayé de classer la musique en majeur / mineur sur Neural Network
Implémentation simple d'un réseau neuronal à l'aide de Chainer
[Deep Learning from scratch] À propos des couches requises pour implémenter le traitement de rétropropagation dans un réseau neuronal
J'ai essayé d'implémenter PLSA en Python
J'ai essayé d'implémenter PLSA dans Python 2
Comment implémenter un sérialiseur imbriqué avec drf-flex-fields
J'ai essayé d'implémenter ADALINE en Python
J'ai essayé d'implémenter PPO en Python
Implémentation de réseaux neuronaux "flous" avec Chainer
[Chainer] Classification des documents par réseau de neurones convolutifs
Essayez d'implémenter Oni Mai Tsuji Miserable avec python
Comment implémenter la fonctionnalité de type helper Rails dans Django
Comment implémenter la mémoire partagée en Python (mmap.mmap)
Comment implémenter un sélecteur de dégradé dans Houdini
J'ai essayé d'implémenter TOPIC MODEL en Python
Comment créer des données à mettre dans CNN (Chainer)
J'ai essayé d'implémenter le tri sélectif en python