[PYTHON] 100 Sprachverarbeitung Knock-73 (mit Scikit-Learn): Lernen

Dies ist die Aufzeichnung des 73. "Lernens" von Language Processing 100 Knock 2015. Es hat viel Zeit gekostet, Nachforschungen anzustellen und Versuch und Irrtum zu machen.

Bis jetzt habe ich es nicht in den Block gepostet, da es im Grunde dasselbe war wie "Amateur-Sprachverarbeitung 100 Klopfen". , "Kapitel 8: Maschinelles Lernen" wurde ernst genommen und teilweise geändert. Ich werde posten. Ich benutze hauptsächlich scikit-learn.

Referenzlink

Verknüpfung Bemerkungen
073_1.Lernen(Vorverarbeitung).ipynb Antwortprogramm(Vorverarbeitung編)GitHub-Link
073_2.Lernen(Ausbildung).ipynb Antwortprogramm(Ausbildung編)GitHub-Link
100 Klicks Amateur-Sprachverarbeitung:73 Ich bin Ihnen immer mit 100 Sprachverarbeitungsklopfen zu Dank verpflichtet
Einführung in Python mit 100 Klopfen Sprachverarbeitung#73 -Maschinelles Lernen, Scikit-Logistische Rückkehr mit Lernen scikit-Klopfen Sie das Ergebnis mit lernen

Umgebung

Art Ausführung Inhalt
OS Ubuntu18.04.01 LTS Es läuft virtuell
pyenv 1.2.15 Ich benutze pyenv, weil ich manchmal mehrere Python-Umgebungen benutze
Python 3.6.9 python3 auf pyenv.6.Ich benutze 9
3.7 oder 3.Es gibt keinen tiefen Grund, keine 8er-Serie zu verwenden
Pakete werden mit venv verwaltet

In der obigen Umgebung verwende ich die folgenden zusätzlichen Python-Pakete. Einfach mit normalem Pip installieren.

Art Ausführung
nltk 3.4.5
stanfordnlp 0.2.0
pandas 0.25.3
scikit-learn 0.21.3

Aufgabe

Kapitel 8: Maschinelles Lernen

In diesem Kapitel [Satzpolaritätsdatensatz] von Movie Review Data, veröffentlicht von Bo Pang und Lillian Lee. v1.0](http://www.cs.cornell.edu/people/pabo/movie-review-data/rt-polaritydata.README.1.0.txt) wird verwendet, um den Satz positiv oder negativ zu machen. Arbeiten Sie an der Aufgabe (Polaritätsanalyse), um sie als (negativ) zu klassifizieren.

73. Lernen

Lernen Sie das logistische Regressionsmodell anhand der in> 72 extrahierten Eigenschaften.

Antworten

Antwort Prämisse

Annahme 1: Teilen Sie sich in Vorverarbeitung und Lernen auf

Ich habe Stanford NLP zum Entfernen von Stoppwörtern und zur Verarbeitung von Lemma-Stemming verwendet. Es hat lange gedauert, daher habe ich es in Vorverarbeitung und Lernen unterteilt.

Annahme 2: Wortvektorisierung

Ich verwende tf-idf, um Wörter zu vektorisieren. tf-idf berechnet die Wichtigkeit basierend auf zwei Indikatoren, tf (Termfrequenz) und idf (Inverse Dokumentfrequenz). Verringern Sie die Wichtigkeit von Wörtern (allgemeinen Wörtern), die in vielen Dokumenten vorkommen, und erhöhen Sie die Wichtigkeit von Wörtern, die nur in bestimmten Dokumenten vorkommen.

Annahme 3: Suche nach Hyperparametern

Um ehrlich zu sein, konnte ich nicht beurteilen, ob tf-idf auch bei der Stoppwortverarbeitung gültig war, also [CountVectorizer](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer. Wir vektorisieren und vergleichen die Genauigkeit mit der einfachen Worthäufigkeit unter Verwendung von HTML. Wir vergleichen auch die Hyperparameter der logistischen Regression mit einer Rastersuche.

Antwortprogramm (Extraktion) [073_1. Lernen (Vorverarbeitung) .ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/08.%E6%A9%9F%E6%A2%B0%E5 % AD% A6% E7% BF% 92 / 073_1.% E5% AD% A6% E7% BF% 92 (% E5% 89% 8D% E5% 87% A6% E7% 90% 86) .ipynb)

Erstens ist die Vorverarbeitung. Was wir jedoch tun, ist [Vorheriges "Antwortprogramm (Analyse) 072_2. Identitätsextraktion (Analyse) .ipynb"](https://qiita.com/FukuharaYohei/items/f1a12d8e63fc576a456f#%E5%9B % 9E% E7% AD% 94% E3% 83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% A0% E5% 88% 86% E6% 9E% 90 % E7% B7% A8-072_2% E7% B4% A0% E6% 80% A7% E6% 8A% BD% E5% 87% BA% E5% 88% 86% E6% 9E% 90ipynb Es gibt nichts Besonderes zu erwähnen. Der Nachteil ist, dass die Verarbeitung etwa eine Stunde dauert.

import warnings
import re
import csv

from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer as PS
import stanfordnlp

#Definiert als Taple für Geschwindigkeit
STOP_WORDS = set(stopwords.words('english'))

# Stemmer
ps = PS()

#Scheint mit Universal POS-Tags kompatibel zu sein
# https://universaldependencies.org/u/pos/
EXC_POS = {'PUNCT',   #Interpunktion
           'X',       #Andere
           'SYM',     #Symbol
           'PART',    #Partikel('s etc.)
           'CCONJ',   #Verbindung(und soweiter und sofort.)
           'AUX',     #Hilfsverb(würde etc.)
           'PRON',    #Gleichbedeutend
           'SCONJ',   #Untergeordneter Konnektiv(ob etc.)
           'ADP',     #Konjunkt(in etc.)
           'NUM'}     #Nummer
		   
#Es war langsam, alle Standardprozessoren anzugeben, also beschränken Sie sich auf das Minimum
# https://stanfordnlp.github.io/stanfordnlp/processors.html
nlp = stanfordnlp.Pipeline(processors='tokenize,pos,lemma')

reg_sym = re.compile(r'^[!-/:-@[-`{-~]|[!-/:-@[-`{-~]$')
reg_dit = re.compile('[0-9]')


#Entfernen von führenden und nachfolgenden Symbolen
def remove_symbols(lemma):
    return reg_sym.sub('', lemma)
	

#Beenden Sie die Beurteilung der Wortauthentizität
def is_stopword(word):
    lemma = remove_symbols(word.lemma)
    return True if lemma in STOP_WORDS \
                  or lemma == '' \
                  or word.upos in EXC_POS \
                  or len(lemma) == 1 \
                  or reg_dit.search(lemma)\
                else False

#Warnung ausblenden
warnings.simplefilter('ignore', UserWarning)

with open('./sentiment.txt') as file_in:
    with open('./sentiment_stem.txt', 'w') as file_out:
        writer = csv.writer(file_out, delimiter='\t')
        writer.writerow(['Lable', 'Lemmas'])

        for i, line in enumerate(file_in):
            print("\r{0}".format(i), end="")
        
            lemma = []
        
            #Die ersten 3 Zeichen geben nur negativ / positiv an. Führen Sie daher keine nlp-Verarbeitung durch(Mach es so schnell wie möglich)
            doc = nlp(line[3:])
            for sentence in doc.sentences:
                lemma.extend([ps.stem(remove_symbols(word.lemma)) for word in sentence.words if is_stopword(word) is False])
            writer.writerow([1 if line[0] == '+' else 0, ' '.join(lemma)])

Antwortprogramm (Schulung) [073_2. Lernen (Schulung) .ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/08.%E6%A9%9F%E6%A2%B0%E5% AD% A6% E7% BF% 92 / 073_2.% E5% AD% A6% E7% BF% 92 (% E8% A8% 93% E7% B7% B4) .ipynb)

Dies ist der Trainingsteil des Hauptfachs.

import csv

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.base import BaseEstimator, TransformerMixin

#Klasse zur Verwendung der Wortvektorisierung in GridSearchCV
class myVectorizer(BaseEstimator, TransformerMixin):
    def __init__(self, method='tfidf', min_df=0.0005, max_df=0.10):
        self.method = method
        self.min_df = min_df
        self.max_df = max_df

    def fit(self, x, y=None):
        if self.method == 'tfidf':
            self.vectorizer = TfidfVectorizer(min_df=self.min_df, max_df=self.max_df)
        else:
            self.vectorizer = CountVectorizer(min_df=self.min_df, max_df=self.max_df)
        self.vectorizer.fit(x)
        return self

    def transform(self, x, y=None):
        return self.vectorizer.transform(x)
		
#Parameter für GridSearchCV
PARAMETERS = [
    {
        'vectorizer__method':['tfidf', 'count'], 
        'vectorizer__min_df': [0.0004, 0.0005], 
        'vectorizer__max_df': [0.07, 0.10], 
        'classifier__C': [1, 3],    #Ich habe auch 10 ausprobiert, aber der SCORE ist niedrig, nur weil er langsam ist
        'classifier__solver': ['newton-cg', 'liblinear']},
    ]

#Datei lesen
def read_csv_column(col):
    with open('./sentiment_stem.txt') as file:
        reader = csv.reader(file, delimiter='\t')
        header = next(reader)
        return [row[col] for row in reader]

x_all = read_csv_column(1)
y_all = read_csv_column(0)

def train(x_train, y_train, file):
    pipline = Pipeline([('vectorizer', myVectorizer()), ('classifier', LogisticRegression())])
    
    #clf steht für Klassifizierung
    clf = GridSearchCV(
            pipline, # 
            PARAMETERS,           #Parametersatz, den Sie optimieren möchten
            cv = 5)               #Anzahl der Kreuztests
    
    clf.fit(x_train, y_train)
    pd.DataFrame.from_dict(clf.cv_results_).to_csv(file)

    print('Grid Search Best parameters:', clf.best_params_)
    print('Grid Search Best validation score:', clf.best_score_)
    print('Grid Search Best training score:', clf.best_estimator_.score(x_train, y_train))    

train(x_all, y_all, 'gs_result.csv')

Antworterklärung (Training)

Wortvektorisierung

TfidfVectorizer oder CountVectorizer /sklearn.feature_extraction.text.CountVectorizer.html) wird für die Wortvektorisierung verwendet. Es ist etwas verwirrend, da es so klassifiziert ist, dass es mit der Funktion GridSearchCV verwendet werden kann, aber die wichtigen Punkte sind wie folgt.

def fit(self, x, y=None):
    if self.method == 'tfidf':
        self.vectorizer = TfidfVectorizer(min_df=self.min_df, max_df=self.max_df)
    else:
        self.vectorizer = CountVectorizer(min_df=self.min_df, max_df=self.max_df)
    self.vectorizer.fit(x)
    return self

def transform(self, x, y=None):
    return self.vectorizer.transform(x)

Verwenden Sie "fit", um aus allen Wörtern zu lernen, und "transformieren", um die Wortfolge zu transformieren. Die Parameter sind TfidfVectorizer und CountVectorizer. /generated/sklearn.feature_extraction.text.CountVectorizer.html) Beide verwenden die folgenden beiden.

--min_df: Wenn die Häufigkeit des Auftretens unter dem angegebenen Verhältnis liegt, wird es von der Vektorisierung ausgeschlossen. Es wird angegeben, weil davon ausgegangen wird, dass "Lernen nicht möglich ist, wenn die Häufigkeit des Auftretens zu gering ist". --max_df: Wird von der Vektorisierung ausgeschlossen, wenn sie häufiger als der angegebene Prozentsatz auftritt. Dieses Mal dachte ich, dass "Wörter wie" Film "bedeutungslos sind" und spezifizierte es.

Logistische Rückgabe

Ich trainiere mit LogisticRegression mit LogisticRegression. Die Erklärung der logistischen Regression finden Sie im Artikel "Coursera Machine Learning-Einführungskurs (3. Woche - logistische Regression, Regularisierung)". ・ ・). Dank des Coursera-Einführungskurses für maschinelles Lernen konnte ich mich mit einem Verständnis der Regularisierung nähern.

def train(x_train, y_train, file):
    pipline = Pipeline([('vectorizer', myVectorizer()), ('classifier', LogisticRegression())])

In der folgenden Parameterdefinition lautet der Regularisierungsterm "classifier__C" und der Optimierer "classifier__solver". Ich verstehe den Unterschied zwischen Optimierern nicht, aber ich habe ihn nicht mit dem Gefühl untersucht, dass "er durch Rastersuche optimiert werden sollte".

PARAMETERS = [
    {
        'vectorizer__method':['tfidf', 'count'], 
        'vectorizer__min_df': [0.0004, 0.0005], 
        'vectorizer__max_df': [0.07, 0.10], 
        'classifier__C': [1, 3],    #Ich habe auch 10 ausprobiert, aber der SCORE ist niedrig, nur weil er langsam ist
        'classifier__solver': ['newton-cg', 'liblinear']},
    ]

Pipeline

Ich verwende Pipeline, um den Trainingsteil mit Wortvektorisierung und logistischer Regression zu routen. Auf diese Weise können Sie zwei Prozesse gleichzeitig ausführen und gleichzeitig die Hyperparametersuche in der später beschriebenen Rastersuche verarbeiten.

def train(x_train, y_train, file):
    pipline = Pipeline([('vectorizer', myVectorizer()), ('classifier', LogisticRegression())])

Hyperparameter-Rastersuche

Ich suche mit [GridSearchCV] nach Hyperparametern (https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html). Da die Pipeline implementiert ist, können sowohl die Wortvektorisierung als auch der Trainingsteil durch logistische Regression gleichzeitig durchsucht werden. Das Suchziel wird durch "PARAMETER" definiert, und der "Zielverarbeitungsname" und der "Parametername" werden durch "__" kombiniert. Tatsächlich gibt es mehr durchsuchbare Parameter, die jedoch weggelassen werden, da die Verarbeitung lange dauert. Dieser Parameter dauert ca. 2 Minuten.

#Parameter für GridSearchCV
PARAMETERS = [
    {
        'vectorizer__method':['tfidf', 'count'], 
        'vectorizer__min_df': [0.0004, 0.0005], 
        'vectorizer__max_df': [0.07, 0.10], 
        'classifier__C': [1, 3],    #Ich habe auch 10 ausprobiert, aber der SCORE ist niedrig, nur weil er langsam ist
        'classifier__solver': ['newton-cg', 'liblinear']},
    ]

#clf steht für Klassifizierung
clf = GridSearchCV(
        pipline,
        PARAMETERS,           #Parametersatz, den Sie optimieren möchten
        cv = 5)               #Anzahl der Kreuztests

Suche nach Wortvektorisierungsmethoden mit Rastersuche

TfidfVectorizer und CountVectorizer /sklearn.feature_extraction.text.CountVectorizer.html) definiert die Klasse "myVectorizer", um herauszufinden, welche die beste ist. Der Vectorizer, der den Parameter method empfängt und mit dem bedingten Zweig if verarbeitet, wird geändert. Ich habe auf den folgenden Artikel verwiesen.

class myVectorizer(BaseEstimator, TransformerMixin):
    def __init__(self, method='tfidf', min_df=0.0005, max_df=0.10):
        self.method = method
        self.min_df = min_df
        self.max_df = max_df

    def fit(self, x, y=None):
        if self.method == 'tfidf':
            self.vectorizer = TfidfVectorizer(min_df=self.min_df, max_df=self.max_df)
        else:
            self.vectorizer = CountVectorizer(min_df=self.min_df, max_df=self.max_df)
        self.vectorizer.fit(x)
        return self

    def transform(self, x, y=None):
        return self.vectorizer.transform(x)

Raster-Suchergebnisse

Das Rastersuchergebnis wird in eine CSV-Datei ausgegeben. Vergleichen wir jedes Kriterium mit den Durchschnitts- und Höchstwerten (unter Verwendung von Excel).

pd.DataFrame.from_dict(clf.cv_results_).to_csv(file)

Ich habe die Parameter etwas erhöht. Daher dauerte das Training ca. 11 Minuten.

#Parameter für GridSearchCV
PARAMETERS = [
    {
        'vectorizer__method':['tfidf', 'count'], 
        'vectorizer__min_df': [0.0003, 0.0004, 0.0005, 0.0006], 
        'vectorizer__max_df': [0.07, 0.10], 
        'classifier__C': [1, 3],    #Ich habe auch 10 ausprobiert, aber der SCORE ist niedrig, nur weil er langsam ist
        'classifier__solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga']}
    ]

Hyperparameter mit der höchsten Punktzahl

Der höchste Hyperparameter war eine durchschnittliche korrekte Antwortrate von 75,6% in 5 Kreuzverifizierungen.

Vergleichen wir nun jeden der folgenden Parameter.

Vectorizer-Parameter

TfidfVectorizer/CountVectorizer tf-idf hat eindeutig eine bessere Punktzahl. image.png

min_df Je kleiner die min_df, desto besser die Punktzahl. image.png

max_df Für td-idf ist max_df eine bessere Punktzahl, wenn es weniger ist. image.png

Logistische Regressionsparameter

Durch Optimierer

Es gibt keinen großen Unterschied. image.png

Regularisierungsbegriff

Offensichtlich hat 1 eine bessere Punktzahl. image.png

Recommended Posts

100 Sprachverarbeitung Knock-73 (mit Scikit-Learn): Lernen
100 Sprachverarbeitung Knock-76 (mit Scicit-Learn): Beschriftung
100 Sprachverarbeitung Knock-74 (mit Scicit-Learn): Vorhersage
100 Sprachverarbeitung Knock-90 (mit Gensim): Lernen mit word2vec
100-Sprach-Verarbeitung Knock-79 (mit Scikit-Learn): Präzisions-Recall-Grafikzeichnung
100 Sprachverarbeitungsklopfen (2020): 28
Sprachverarbeitung 100 Knocks-31 (mit Pandas): Verben
100 Sprachverarbeitung Knock-38 (mit Pandas): Histogramm
100 Sprachverarbeitung Knock-77 (mit Scicit-Learn): Messung der korrekten Antwortrate
100 Sprachverarbeitung Knock-33 (mit Pandas): Sahen Nomen
100 Sprachverarbeitung Knock-39 (mit Pandas): Zipf-Gesetz
100 Sprachverarbeitung Knock-34 (mit Pandas): "B von A"
100 Sprachverarbeitung klopfen 2020 [00 ~ 39 Antwort]
100 Sprachverarbeitung klopfen 2020 [00-79 Antwort]
100 Sprachverarbeitung klopfen 2020 [00 ~ 69 Antwort]
100 Sprachverarbeitung Knock 2020 Kapitel 1
100 Amateur-Sprachverarbeitungsklopfen: 17
100 Sprachverarbeitung Knock-52: Stemming
100 Sprachverarbeitung Knock Kapitel 1
100 Amateur-Sprachverarbeitungsklopfen: 07
100 Sprachverarbeitung Knock 2020 Kapitel 3
100 Sprachverarbeitung Knock 2020 Kapitel 2
100 Amateur-Sprachverarbeitungsklopfen: 09
100 Sprachverarbeitung Knock-53: Tokenisierung
100 Amateur-Sprachverarbeitungsklopfen: 97
100 Sprachverarbeitung klopfen 2020 [00 ~ 59 Antwort]
100 Amateur-Sprachverarbeitungsklopfen: 67
100 Sprachverarbeitung Knock-20 (unter Verwendung von Pandas): Lesen von JSON-Daten
100 Sprachverarbeitung Knock-32 (mit Pandas): Prototyp des Verbs
100-Sprach-Verarbeitung Knock-98 (unter Verwendung von Pandas): Clustering nach Ward-Methode
100 Sprachverarbeitung Knock-99 (mit Pandas): Visualisierung durch t-SNE
100 Sprachverarbeitung Knock-95 (mit Pandas): Bewertung mit WordSimilarity-353
100 Sprachverarbeitung Knock-72 (unter Verwendung von Stanford NLP): Identitätsextraktion
100 Sprachverarbeitungsklopfen mit Python 2015
100 Sprachverarbeitung Knock-51: Wortausschnitt
100 Sprachverarbeitung Knock-57: Abhängigkeitsanalyse
100 Sprachverarbeitung Knock-50: Satzumbruch
100 Sprachverarbeitung Knock Kapitel 1 (Python)
100 Sprachverarbeitung Knock Kapitel 2 (Python)
100 Sprachverarbeitung Knock-25: Vorlagenextraktion
Sprachverarbeitung 100 Knock-87: Wortähnlichkeit
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020
100 Sprachverarbeitung Knock-56: Co-Referenz-Analyse
Lösen von 100 Sprachverarbeitungsklopfen 2020 (01. "Patatokukashi")
100 Amateur-Sprachverarbeitungsklopfen: Zusammenfassung
100 Sprachverarbeitung Knock-92 (mit Gensim): Anwendung auf Analogiedaten
100 Sprachverarbeitung Knock-36 (unter Verwendung von Pandas): Häufigkeit des Auftretens von Wörtern
100 Sprachverarbeitung Knock: Kapitel 2 UNIX-Befehlsgrundlagen (mit Pandas)
100 Sprachverarbeitung Knock-83 (mit Pandas): Messung der Wort- / Kontexthäufigkeit
100 Sprachverarbeitung Knock-30 (unter Verwendung von Pandas): Lesen der Ergebnisse der morphologischen Analyse
100 Sprachverarbeitung Knock-94 (mit Gensim): Ähnlichkeitsberechnung mit WordSimilarity-353
Lernen Sie mit "Google Colaboratory" ganz einfach 100 Sprachverarbeitungsklopfen 2020.
100 Sprachverarbeitung Knock 2020 Kapitel 2: UNIX-Befehle
100 Sprachverarbeitung Knock 2015 Kapitel 5 Abhängigkeitsanalyse (40-49)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 6: Maschinelles Lernen
100 Sprachverarbeitungsklopfen mit Python (Kapitel 1)
100 Sprachverarbeitung Knock Kapitel 1 in Python
100 Sprachverarbeitung Knock-84 (mit Pandas): Erstellen einer Wortkontextmatrix
100 Sprachverarbeitung Knock 2020 Kapitel 4: Morphologische Analyse
100 Sprachverarbeitungsklopfen mit Python (Kapitel 3)
100 Sprachverarbeitungsklopfen: Kapitel 1 Vorbereitungsbewegung