--Classification de texte à l'aide de réseaux de neurones convolutionnels (CNN).
Poursuite de la classification des documents [Chainer] précédemment publiée par les réseaux de neurones convolutifs, [Réseaux de neurones convolutifs pour la classification des phrases](http: / /emnlp2014.org/papers/pdf/EMNLP2014181.pdf) a été implémenté dans Chainer.
GitHub de l'auteur publie également une implémentation utilisant Theano.
Le code source développé cette fois-ci est disponible ici: chainer-cnnsc
-Les données peuvent être trouvées à ici. J'ai utilisé "jeu de données de polarité de phrase v1.0".
--Installation de Chainer, scikit-learn, gensim
Utilisez des données textuelles en anglais. Veuillez obtenir les données textuelles de la destination de téléchargement ci-dessus. Chaque ligne correspond à un document. La première colonne est le libellé et la deuxième colonne et les suivantes sont le texte. Les étiquettes 0 sont des documents négatifs et 1 sont des documents positifs.
[étiquette] [texte(Délimiteur d'espace demi-largeur)]
0 it just didn't mean much to me and played too skewed to ever get a hold on ( or be entertained by ) .
1 culkin , who's in virtually every scene , shines as a young man who uses sarcastic lies like a shield .
...
Cette fois, j'ai utilisé le modèle proposé dans cet article (Convolutional Neural Networks for Sentence Classification). Vous pouvez trouver une description du modèle dans cet article.
Dans le programme, plusieurs tailles de filtre pour la convolution sont définies et la convolution est effectuée pour chaque filtre.
La taille de filtre définie est stockée dans filter_height
au format liste.
Pour la propagation directe, la boucle est tournée pour chaque taille de filtre pour effectuer la convolution comme indiqué ci-dessous.
#Tournez la boucle pour chaque type de filtre
for i, filter_size in enumerate(self.filter_height):
#À travers la couche de convolution
h_conv[i] = F.relu(self[i](x))
#À travers la couche Pooling
h_pool[i] = F.max_pooling_2d(h_conv[i], (self.max_sentence_len+1-filter_size))
Le code source de la partie réseau est indiqué ci-dessous.
#Je veux rendre le nombre de liens variable, donc j'utilise ChainList
class CNNSC(ChainList):
def __init__(self,
input_channel,
output_channel,
filter_height,
filter_width,
n_label,
max_sentence_len):
#Le nombre de filtres, la hauteur des filtres utilisés et la longueur maximale de la phrase seront utilisés ultérieurement.
self.cnv_num = len(filter_height)
self.filter_height = filter_height
self.max_sentence_len = max_sentence_len
#Ajout d'un lien pour la couche de convolution pour chaque filtre
# Convolution2D(Nombre de canaux d'entrée,Nombre de canaux de sortie (nombre de filtres pour chaque forme),Forme du filtre (au format tapple),Taille du rembourrage)
link_list = [L.Convolution2D(input_channel, output_channel, (i, filter_width), pad=0) for i in filter_height]
#Lien ajouté pour le dépôt
link_list += [L.Linear(output_channel * self.cnv_num, output_channel * self.cnv_num)]
#Lien ajouté à la couche de sortie
link_list += [L.Linear(output_channel * self.cnv_num, n_label)]
#Initialisez la classe en utilisant la liste des liens définis jusqu'à présent
super(CNNSC, self).__init__(*link_list)
#Au fait
# self.add_link(link)
#Il est normal d'énumérer les liens et de les ajouter un par un comme
def __call__(self, x, train=True):
#Préparez la couche intermédiaire filtrée
h_conv = [None for _ in self.filter_height]
h_pool = [None for _ in self.filter_height]
#Tournez la boucle pour chaque type de filtre
for i, filter_size in enumerate(self.filter_height):
#À travers la couche de convolution
h_conv[i] = F.relu(self[i](x))
#À travers la couche Pooling
h_pool[i] = F.max_pooling_2d(h_conv[i], (self.max_sentence_len+1-filter_size))
# Convolution+Combinez les résultats de la mise en commun
concat = F.concat(h_pool, axis=2)
#Supprimer le résultat combiné
h_l1 = F.dropout(F.tanh(self[self.cnv_num+0](concat)),ratio=0.5,train=train)
#Compresser le résultat de la suppression dans la couche de sortie
y = self[self.cnv_num+1](h_l1)
return y
Dans l'expérience, l'ensemble de données a été divisé en données de formation et données de test, et 50 époques ont été tournées pour la formation. Le taux de réponse correct pour les données de test était la 50e époque et «précision = 0,799437701702».
Cet article lors de la classification de documents avec un modèle utilisant un CNN plus simple, c'était ʻexactitude = 0.775624996424`, donc le taux de réponse correct est légèrement A été trouvé pour s'améliorer.
input file name: dataset/mr_input.dat
loading word2vec model...
height (max length of sentences): 59
width (size of wordembedding vecteor ): 300
epoch 1 / 50
train mean loss=0.568159639835, accuracy=0.707838237286
test mean loss=0.449375987053, accuracy=0.788191199303
epoch 2 / 50
train mean loss=0.422049582005, accuracy=0.806962668896
test mean loss=0.4778624475, accuracy=0.777881920338
epoch 3 / 50
train mean loss=0.329617649317, accuracy=0.859808206558
test mean loss=0.458206892014, accuracy=0.792877197266
epoch 4 / 50
train mean loss=0.240891501307, accuracy=0.90389829874
test mean loss=0.642955899239, accuracy=0.769447028637
...
epoch 47 / 50
train mean loss=0.000715514877811, accuracy=0.999791562557
test mean loss=0.910120248795, accuracy=0.799437701702
epoch 48 / 50
train mean loss=0.000716249051038, accuracy=0.999791562557
test mean loss=0.904825389385, accuracy=0.801312088966
epoch 49 / 50
train mean loss=0.000753249507397, accuracy=0.999791562557
test mean loss=0.900236129761, accuracy=0.799437701702
epoch 50 / 50
train mean loss=0.000729961204343, accuracy=0.999791562557
test mean loss=0.892229259014, accuracy=0.799437701702
Cet article présente également la mise en œuvre de la classification de texte à l'aide de CNN.