[PYTHON] J'ai essayé la méthode la plus simple de classification de documents multi-étiquettes

Qu'est-ce que la classification des documents?

L'une des tâches de la PNL est la classification des documents. Il évalue l'étiquette d'un document étiqueté.

La classification des documents peut être largement divisée en deux types suivant la nature de l'étiquette attachée au document.

--Classification thématique --Documents étiquetés sur le sujet

--Analyse des sentiments

Modèle de classification des documents

Il existe de nombreuses façons de résoudre ces problèmes de classification de documents. Il existe les deux méthodes typiques suivantes. (Je pense qu'il y en a d'autres)

--Créez un vecteur de document et classez-le par méthode d'apprentissage automatique --Comment créer un vecteur de document - Tf-idf --bag d'incorporation (prend la moyenne ou le maximum pour la représentation distribuée de chaque mot dans le document) --Comment classer - Logistic Regression - Naive Baise model - Support Vector Machine - Random Forest, Xgboost --Etc

--Placer le texte de la ligne dans un réseau neuronal - LSTM - BERT fine tuning --Etc

J'ai essayé le moyen le plus simple

Même si j'ai fait le plus simple, je ne sais pas vraiment lequel est le plus facile (hé). Cette fois, je voudrais travailler sur la méthode de SVM (avec karnel linéaire) le vecteur Tf-idf. Tf-idf est un vecteur dont la fréquence d'occurrence de chaque mot dans un document est multipliée par l'importance de ce mot en tant qu'élément. Par conséquent, la dimension du vecteur de document est égale au nombre de vocabulaire.

SVM avec karnel linéaire semble être un peu difficile à expliquer, donc je vais l'omettre.

Cette fois, j'utiliserai celui inclus dans sklearn.

Le modèle étant simple (?), Je vais essayer d'utiliser un corpus un peu compliqué (multi-étiquettes + quelques rubriques sont données à chaque document). Le corpus utilisé est un article de presse de Reuters avec environ 10 000 documents et 90 étiquettes.

Téléchargez d'abord le corpus

Téléchargez le corpus. Le corpus reuters est inclus dans le module python nltk, alors utilisez-le.

Premièrement, si nltk n'est pas inclus

pip install nltk

Tapez ensuite ce qui suit dans le shell interactif de python:

python
>>> import nltk
>>> nltk.download("reuters")

Ensuite, un répertoire appelé nltk_data est créé sous le répertoire utilisateur et les données se trouvent dans ce répertoire. ____ Est à l'intérieur.

Code d'implémentation


import glob
import nltk
import re
import codecs
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk import word_tokenize
from nltk.stem.porter import PorterStemmer
from nltk.corpus import stopwords, reuters
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
from sklearn import metrics

path = "../nltk_data/corpora/reuters/"
with open(path+"stopwords") as sw:
    stopwords = [x for x in sw]

#Définir le tokenizer
def tokenize(text):
  min_length = 3
  words = map(lambda word: word.lower(), word_tokenize(text))
  words = [word for word in words if word not in stopwords]
  tokens = (list(map(lambda token: PorterStemmer().stem(token), words)))
  p = re.compile('[a-zA-Z]+');
  filtered_tokens = list(filter (lambda token: p.match(token) and len(token) >= min_length, tokens))
  return filtered_tokens
    
#Obtenir l'identifiant du document et sa catégorie à partir des données
with codecs.open("../nltk_data/corpora/reuters/cats.txt", "r", "utf-8", "ignore") as categories:
    train_docs_id = [line.split(" ")[0][9:] for line in categories if line.split(" ")[0][:9] == 'training/']
    categories.seek(0)
    test_docs_id = [line.split(" ")[0][5:] for line in categories if line.split(" ")[0][:5] == 'test/']
    categories.seek(0)
    train_docs_cat = [line.strip("\n").split(" ")[1:] for line in categories if line.split(" ")[0][:9] == 'training/']
    categories.seek(0)
    test_docs_cat = [line.strip("\n").split(" ")[1:] for line in categories if line.split(" ")[0][:5] == 'test/']

#Lister les documents
train_docs = []
test_docs = []
for num in train_docs_id:
    with codecs.open(path+"training/"+num, "r", "utf-8", "ignore") as doc:
        train_docs.append(" ".join([line.strip(" ") for line in doc.read().split("\n")]))
for num in test_docs_id:
    with codecs.open(path+"test/"+num, "r", "utf-8", "ignore") as doc:
        test_docs.append(" ".join([line.strip(" ") for line in doc.read().split("\n")]))

#Sklearn à partir de la liste des documents.Générer un vecteur de document avec TfidfVectorizer
vectorizer = TfidfVectorizer(tokenizer=tokenize)
vectorised_train_documents = vectorizer.fit_transform(train_docs)
vectorised_test_documents = vectorizer.transform(test_docs)

#Étiquette binaire(0 or 1)Convertir en un vecteur de
# Transform multilabel labels
mlb = MultiLabelBinarizer()
train_labels = mlb.fit_transform(train_docs_cat)
test_labels = mlb.transform(test_docs_cat)

# Classifier
#Essayez différents paramètres
param_list = [0.001, 0.01, 0.1, 0.5, 1, 10, 100]
for C in param_list:
    classifier = OneVsRestClassifier(LinearSVC(C=C, random_state=42))
    classifier.fit(vectorised_train_documents, train_labels)
    predictions = classifier.predict(vectorised_test_documents)
    train_predictions = classifier.predict(vectorised_train_documents)
    ftest = metrics.f1_score(test_labels, predictions, average="macro")
    ftrain = metrics.f1_score(train_labels, train_predictions, average="macro")
    print("parameter       test_f1                 train_f1")
    print("c={}:\t{}\t{}".format(C, ftest, ftrain))  

L'exécution du code ci-dessus donne le résultat suivant:

parameter       test_f1                 train_f1
c=0.001:	0.009727246626471432	0.007884179312750742
c=0.01:	0.02568945815128711	0.02531440097069285
c=0.1:	0.20504347026711428	0.26430270726815386
c=0.5:	0.3908058642922242	0.6699048987962078
c=1:	0.45945765878179573	0.9605946547451458
c=10:	0.5253686991407462	0.9946632502765812
c=100:	0.5312185383446876	0.9949908225328556

Vous apprenez à votre guise. La même méthode selon l'article ci-dessous devrait donner une précision de la seconde moitié de 80% ... https://www.aclweb.org/anthology/N19-1408/

Si quelqu'un sait pourquoi ce n'est pas bon, faites-le moi savoir.

Recommended Posts

J'ai essayé la méthode la plus simple de classification de documents multi-étiquettes
J'ai essayé le serveur asynchrone de Django 3.0
J'ai essayé de résumer la méthode de mise en œuvre fréquemment utilisée de pytest-mock
J'ai essayé la méthode la plus simple de classification de documents multi-étiquettes
Lancez un serveur WEB simple qui peut vérifier l'en-tête
[Linux] J'ai essayé de vérifier la méthode de confirmation sécurisée du FQDN (CentOS7)
J'ai essayé la fonction de tableau croisé dynamique des pandas
J'ai essayé la méthode des moindres carrés en Python
J'ai essayé de corriger la forme trapézoïdale de l'image
J'ai essayé d'utiliser le filtre d'image d'OpenCV
J'ai essayé de vectoriser les paroles de Hinatazaka 46!
J'ai couru le tutoriel TensorFlow avec des commentaires (classification du texte des critiques de films)
J'ai essayé de résumer la forme de base de GPLVM
J'ai essayé le tutoriel MNIST de tensorflow pour les débutants.
J'ai essayé de regrouper les données ECG en utilisant la méthode K-Shape
J'ai essayé d'utiliser l'API de Sakenowa Data Project
J'ai essayé de visualiser les informations spacha de VTuber
J'ai essayé d'effacer la partie négative de Meros
J'ai essayé de simuler la méthode de calcul de la moyenne des coûts en dollars
J'ai essayé de classer les voix des acteurs de la voix
J'ai essayé d'exécuter l'exemple de code du module Ansible
J'ai essayé de résumer les opérations de chaîne de Python
J'ai essayé la classification d'image d'AutoGluon
J'ai essayé la bibliothèque changefinder!
J'ai essayé de trouver l'entropie de l'image avec python
[Courses de chevaux] J'ai essayé de quantifier la force du cheval de course
J'ai essayé d'obtenir les informations de localisation du bus Odakyu
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
J'ai essayé de refactoriser le modèle CNN de TensorFlow en utilisant TF-Slim
J'ai essayé la reconnaissance faciale du problème du rire en utilisant Keras.
J'ai essayé l'analyse morphologique du commentaire général du putain de jeu de l'année
[Python] J'ai essayé de visualiser la relation de suivi de Twitter
J'ai essayé un peu le comportement de la fonction zip
[Apprentissage automatique] J'ai essayé de résumer la théorie d'Adaboost
[Python] J'ai essayé de collecter des données en utilisant l'API de wikipedia
J'ai essayé de combattre le minimum local de la fonction Goldstein-Price
J'ai essayé de vérifier la classification yin et yang des membres hololive par apprentissage automatique
Je veux obtenir le nom de la fonction / méthode en cours d'exécution
J'ai essayé de gratter le classement du calendrier de l'avent Qiita avec Python
[Linux] J'ai essayé de résumer les commandes de confirmation des ressources
J'ai essayé le tutoriel TensorFlow 1er
J'ai essayé le roman Naro API 2
J'ai essayé d'automatiser l'arrosage du pot avec Raspberry Pi
J'ai essayé de créer l'image de démarrage SD de LicheePi Nano
J'ai essayé d'utiliser GrabCut d'OpenCV
J'ai essayé le tutoriel TensorFlow 2ème
J'ai regardé les méta-informations de BigQuery et essayé de les utiliser
J'ai essayé d'agrandir la taille du volume logique avec LVM
J'ai essayé l'API du roman Naruro
J'ai essayé d'exécuter la partie DNN d'OpenPose avec le processeur Chainer
J'ai essayé de visualiser la condition commune des téléspectateurs de la chaîne VTuber
J'ai essayé de déplacer le ballon
[Classification des phrases] J'ai essayé différentes méthodes de mise en commun des réseaux de neurones convolutifs
J'ai essayé d'utiliser l'API checkio
J'ai essayé d'estimer la section.
J'ai essayé de transformer l'image du visage en utilisant sparse_image_warp de TensorFlow Addons
J'ai essayé d'obtenir les résultats de Hachinai en utilisant le traitement d'image
J'ai essayé de visualiser la tranche d'âge et la distribution des taux d'Atcoder