Eine der Aufgaben von NLP ist die Klassifizierung von Dokumenten. Es schätzt die Beschriftung für ein beschriftetes Dokument.
Die Klassifizierung von Dokumenten kann je nach Art des dem Dokument beigefügten Etiketts grob in die folgenden zwei Typen unterteilt werden.
Thema Klassifizierung --Dokumente zum Thema
Schauen Sie sich häufig Nachrichtenartikel an, die als Politik, Sport, Unterhaltung usw. gekennzeichnet sind. ――Einige werden in zwei Kategorien eingeteilt, und einige sind mehrfach gekennzeichnet (es gibt mehr mehrfach gekennzeichnete).
Auf Empfehlungen für Nachrichtenartikel usw. angewendet.
Stimmungsanalyse
Beschriftet, ob das Dokument positiv oder negativ ist ――Es gibt eine binäre Klassifizierung und sie wird auch in mehrere Zahlen klassifiziert (3 Bezeichnungen für positiv, neutral, negativ usw.). ――Es wird auch für die Marktforschung verwendet
Es gibt viele Möglichkeiten, diese Probleme bei der Dokumentklassifizierung zu lösen. Es gibt die folgenden zwei typischen Methoden. (Ich denke, es gibt andere)
--Erstellen Sie einen Dokumentvektor und klassifizieren Sie ihn nach der Methode des maschinellen Lernens
So erstellen Sie einen Dokumentvektor - Tf-idf --Bag der Einbettung (nimmt den Durchschnitt oder das Maximum für die verteilte Darstellung jedes Wortes im Dokument)
Wie klassifiziere ich? - Logistic Regression - Naive Baise model - Support Vector Machine - Random Forest, Xgboost --Und so weiter
Fügen Sie Zeilentext in ein neuronales Netzwerk ein
Obwohl ich das einfachste gemacht habe, bin ich mir nicht sicher, welches das einfachste ist (hey). Dieses Mal möchte ich an der Methode der SVM (mit linearem Karnel) des Tf-idf-Vektors arbeiten. Tf-idf ist ein Vektor, bei dem die Häufigkeit des Auftretens jedes Wortes in einem Dokument mit der Wichtigkeit dieses Wortes als Element multipliziert wird. Daher ist die Dimension des Dokumentvektors gleich der Anzahl der Vokabeln.
SVM mit linearem Karnel scheint etwas schwierig zu erklären zu sein, deshalb werde ich es weglassen.
Dieses Mal werde ich die in sklearn enthaltene verwenden.
Da das Modell einfach ist (?), Werde ich versuchen, einen etwas komplizierten Korpus zu verwenden (Multi-Label + einige Themen werden jedem Dokument zugewiesen). Der verwendete Korpus ist ein Reuters-Nachrichtenartikel mit etwa 10.000 Dokumenten und 90 Etiketten.
Laden Sie den Korpus herunter. Das reuters-Korpus ist im Python-Modul nltk enthalten, verwenden Sie es also.
Erstens, wenn nltk nicht enthalten ist
pip install nltk
Geben Sie dann Folgendes in die interaktive Shell von Python ein:
python
>>> import nltk
>>> nltk.download("reuters")
Anschließend wird unter dem Benutzerverzeichnis ein Verzeichnis mit dem Namen nltk_data erstellt, und die Daten befinden sich in diesem Verzeichnis. ____ ist drinnen.
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]
#Tokenizer definieren
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
#Abrufen der Dokument-ID und ihrer Kategorie aus Daten
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/']
#Dokumente auflisten
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 aus der Dokumentenliste.Generieren Sie einen Dokumentvektor mit TfidfVectorizer
vectorizer = TfidfVectorizer(tokenizer=tokenize)
vectorised_train_documents = vectorizer.fit_transform(train_docs)
vectorised_test_documents = vectorizer.transform(test_docs)
#Binäres Etikett(0 or 1)In einen Vektor von konvertieren
# Transform multilabel labels
mlb = MultiLabelBinarizer()
train_labels = mlb.fit_transform(train_docs_cat)
test_labels = mlb.transform(test_docs_cat)
# Classifier
#Probieren Sie verschiedene Parameter aus
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))
Das Ausführen des obigen Codes führt zu folgendem Ergebnis:
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
Sie lernen nach Herzenslust über. Die gleiche Methode gemäß dem folgenden Papier sollte eine Genauigkeit der zweiten Hälfte von 80% ergeben ... https://www.aclweb.org/anthology/N19-1408/
Wenn jemand weiß, warum es nicht gut ist, lass es mich wissen.
Recommended Posts