[PYTHON] 100 langage de traitement knock-79 (en utilisant scikit-learn): dessin de graphe avec rappel de précision

Il s'agit de l'enregistrement du 79e "Graphique du taux de rappel du taux de conformité - Dessin" de Traitement du langage 100 coups 2015. Un graphique montrant comment les relations de précision et de rappel qui sont dans une relation de compromis sont liées. La courbe ROC est également sortie sous la forme d'un graphique similaire. Jusqu'à présent, je ne l'ai pas posté dans le bloc car c'était fondamentalement la même chose que "Traitement du langage amateur à 100 coups". , "Chapitre 8: Machine Learning" a été pris au sérieux et modifié dans une certaine mesure. Je posterai. J'utilise principalement scikit-learn.

Lien de référence

Lien Remarques
079.Taux de conformité-Dessiner un graphique de rappel.ipynb Lien GitHub du programme de réponse
100 coups de traitement du langage amateur:79 Je vous suis toujours redevable de 100 coups de traitement linguistique
Introduction à Python avec 100 coups de traitement du langage#79 -Apprentissage automatique, scikit-Match taux avec apprentissage-Rappel&Dessiner un graphique scikit-Résultat Knock en utilisant Learn

environnement

type version Contenu
OS Ubuntu18.04.01 LTS Il fonctionne virtuellement
pyenv 1.2.15 J'utilise pyenv car j'utilise parfois plusieurs environnements Python
Python 3.6.9 python3 sur pyenv.6.J'utilise 9
3.7 ou 3.Il n'y a aucune raison profonde de ne pas utiliser la série 8
Les packages sont gérés à l'aide de venv

Dans l'environnement ci-dessus, j'utilise les packages Python supplémentaires suivants. Installez simplement avec pip ordinaire.

type version
matplotlib 3.1.1
numpy 1.17.4
pandas 0.25.3
scikit-learn 0.21.3

Tâche

Chapitre 8: Machine Learning

Dans ce chapitre, [jeu de données de polarité des phrases] de Movie Review Data publié par Bo Pang et Lillian Lee. v1.0](http://www.cs.cornell.edu/people/pabo/movie-review-data/rt-polaritydata.README.1.0.txt) est utilisé pour rendre la phrase positive ou négative. Travaillez sur la tâche (analyse de polarité) à classer comme (négative).

79. Graphique de rappel du dessin de conformité

Dessinez un graphique de rappel de précision en modifiant le seuil de classification du modèle de régression logistique.

Non seulement le graphique du taux de rappel de précision, mais également la courbe ROC sont générés. De plus, la courbe d'apprentissage est également sortie en prime. C'est un "bonus" complet quel que soit le graphique de rappel de précision ou la courbe ROC.

Répondre

Programme de réponse [079. Compliance rate-Recall rate graph.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/08.%E6%A9%9F%E6%A2%B0%E5%AD% A6% E7% BF% 92 / 079.% E9% 81% A9% E5% 90% 88% E7% 8E% 87-% E5% 86% 8D% E7% 8F% BE% E7% 8E% 87% E3% 82% B0% E3% 83% A9% E3% 83% 95% E3% 81% AE% E6% 8F% 8F% E7% 94% BB.ipynb)

En gros [précédent [077.Measurement of correct answer rate.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/08.%E6%A9%9F%E6%A2%B0%E5%] AD% A6% E7% BF% 92 / 077.% E6% AD% A3% E8% A7% A3% E7% 8E% 87% E3% 81% AE% E8% A8% 88% E6% B8% AC.ipynb ) Avec trois logiques de sortie graphique ajoutées.

import csv

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, train_test_split, learning_curve
from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc, precision_recall_curve
from sklearn.pipeline import Pipeline
from sklearn.base import BaseEstimator, TransformerMixin

#Classe d'utilisation de la vectorisation de mots dans 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)
		
#Paramètres de GridSearchCV
PARAMETERS = [
    {
        'vectorizer__method':['tfidf', 'count'], 
        'vectorizer__min_df': [0.0003, 0.0004], 
        'vectorizer__max_df': [0.07, 0.10], 
        'classifier__C': [1, 3],    #J'ai aussi essayé 10 mais le SCORE est faible juste parce qu'il est lent
        'classifier__solver': ['newton-cg', 'liblinear']},
    ]

#Lire le fichier
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)
x_train, x_test, y_train, y_test = train_test_split(x_all, y_all)

def train(x_train, y_train, file):
    pipline = Pipeline([('vectorizer', myVectorizer()), ('classifier', LogisticRegression())])
    
    #clf signifie classification
    clf = GridSearchCV(
            pipline, # 
            PARAMETERS,           #Jeu de paramètres que vous souhaitez optimiser
            cv = 5)               #Nombre de tests croisés
    
    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))    
    
    #Sortie de poids d'élément
    output_coef(clf.best_estimator_)
    
    return clf.best_estimator_

#Sortie de poids d'élément
def output_coef(estimator):
    vec = estimator.named_steps['vectorizer']
    clf = estimator.named_steps['classifier']

    coef_df = pd.DataFrame([clf.coef_[0]]).T.rename(columns={0: 'Coefficients'})
    coef_df.index = vec.vectorizer.get_feature_names()
    coef_sort = coef_df.sort_values('Coefficients')
    coef_sort[:10].plot.barh()
    coef_sort.tail(10).plot.barh()

def validate(estimator, x_test, y_test):
    
    for i, (x, y) in enumerate(zip(x_test, y_test)):
        y_pred = estimator.predict_proba([x])
        if y == np.argmax(y_pred).astype( str ):
            if y == '1':
                result = 'TP:La bonne réponse est positive et la prédiction est positive'
            else:
                result = 'TN:La bonne réponse est négative et la prédiction est négative'
        else:
            if y == '1':
                result = 'FN:La bonne réponse est positive et la prédiction est négative'
            else:
                result = 'FP:La bonne réponse est négative et la prédiction est positive'
        print(result, y_pred, x)
        if i == 29:
            break

    #Sortie de liste TSV
    y_pred = estimator.predict(x_test)
    y_prob = estimator.predict_proba(x_test)

    results = pd.DataFrame([y_test, y_pred, y_prob.T[1], x_test]).T.rename(columns={ 0: 'Bonne réponse', 1 : 'Prévoir', 2: 'Prévoir確率(positif)', 3 :'Chaîne de mots'})
    results.to_csv('./predict.txt' , sep='\t')

    print('\n', classification_report(y_test, y_pred))
    print('\n', confusion_matrix(y_test, y_pred))

#Sortie graphique
def output_graphs(estimator, x_all, y_all, x_test, y_test):
    
    #Sortie de courbe d'apprentissage
    output_learning_curve(estimator, x_all, y_all)
    
    y_pred = estimator.predict_proba(x_test)
    
    #Sortie de la courbe ROC
    output_roc(y_test, y_pred)
    
    #Taux de conformité-Sortie graphique de taux de rappel
    output_pr_curve(y_test, y_pred)

#Sortie de courbe d'apprentissage
def output_learning_curve(estimator, x_all, y_all):
    training_sizes, train_scores, test_scores = learning_curve(estimator,
                                                               x_all, y_all, cv=5,
                                                               train_sizes=[0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0])
    plt.plot(training_sizes, train_scores.mean(axis=1), label="training scores")
    plt.plot(training_sizes, test_scores.mean(axis=1), label="test scores")
    plt.legend(loc="best")
    plt.show()

#Sortie de la courbe ROC
def output_roc(y_test, y_pred):
    # FPR, TPR(,Seuil)Calculer
    fpr, tpr, thresholds = roc_curve(y_test, y_pred[:,1], pos_label='1')

    #Au fait, AUC
    auc_ = auc(fpr, tpr)

    #Tracer la courbe ROC
    plt.plot(fpr, tpr, label='ROC curve (area = %.2f)'%auc_)
    plt.legend()
    plt.title('ROC curve')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.grid(True)
    plt.show()    

#Taux de conformité-Sortie graphique de taux de rappel
def output_pr_curve(y_test, y_pred):
    #Taux de correspondance et taux de rappel à un certain seuil,Obtenir la valeur seuil
    precisions, recalls, thresholds = precision_recall_curve(y_test, y_pred[:,1], pos_label='1')
    
    #0 à 1 0.Tracer ○ par incréments de 05
    for i in range(21):
        close_point = np.argmin(np.abs(thresholds - (i * 0.05)))
        plt.plot(precisions[close_point], recalls[close_point], 'o')

    #Taux de conformité-Courbe de taux de rappel
    plt.plot(precisions, recalls)
    plt.xlabel('Precision')
    plt.ylabel('Recall')
 
    plt.show()

estimator = train(x_train, y_train, 'gs_result.csv')
validate(estimator, x_test, y_test)
output_graphs(estimator, x_all, y_all, x_test, y_test)

Répondre au commentaire

Graphique de rappel de conformité

Le precision_recall_curve` de scikit-learn est utilisé pour recevoir les valeurs de précision, de rappel et de seuil et les afficher sous forme de graphique.

#Taux de conformité-Sortie graphique de taux de rappel
def output_pr_curve(y_test, y_pred):
    #Taux de correspondance et taux de rappel à un certain seuil,Obtenir la valeur seuil
    precisions, recalls, thresholds = precision_recall_curve(y_test, y_pred[:,1], pos_label='1')
    
    #0 à 1 0.Tracer ○ par incréments de 05
    for i in range(21):
        close_point = np.argmin(np.abs(thresholds - (i * 0.05)))
        plt.plot(precisions[close_point], recalls[close_point], 'o')

    #Taux de conformité-Courbe de taux de rappel
    plt.plot(precisions, recalls)
    plt.xlabel('Precision')
    plt.ylabel('Recall')
 
    plt.show()

C'est un graphique du résultat de sortie.

image.png

Vous pouvez voir les compromis suivants.

Pour plus de détails sur la matrice mixte, voir [Article séparé "[Pour les débutants] Explication des index d'évaluation des problèmes de classification pour l'apprentissage automatique (taux de réponse correct, taux de précision, taux de rappel, etc.)" (https://qiita.com/FukuharaYohei/items/be89a99c53586fa4e2e4) ).

Courbe ROC et AUC

Utilisez la fonction roc_curve pour obtenir le taux de faux positifs, le taux de vrais positifs et le seuil. Calculez également la valeur de auc avec la fonction ʻauc`. Enfin, imprimez le graphique (les valeurs AUC sont affichées dans la légende).

def output_roc(y_test, y_pred):
    # FPR, TPR(,Seuil)Calculer
    fpr, tpr, thresholds = roc_curve(y_test, y_pred[:,1], pos_label='1')

    #Au fait, AUC
    auc_ = auc(fpr, tpr)

    #Tracer la courbe ROC
    plt.plot(fpr, tpr, label='ROC curve (area = %.2f)'%auc_)
    plt.legend()
    plt.title('ROC curve')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.grid(True)
    plt.show()

Même si vous n'êtes pas confiant, vous pouvez voir qu'en jugeant positif, le nombre de vrais positifs augmente et le nombre de faux positifs augmente également. image.png

Courbe d'apprentissage

À la fin, la signification est différente des deux premiers graphiques, mais j'écrirai la courbe d'apprentissage en prime. Je voulais voir s'il s'agissait d'un biais élevé ou d'une variance élevée, alors je l'ai sorti. À propos du biais élevé et de la variance élevée Article séparé «Cours d'introduction à l'apprentissage automatique de Coursera (6e semaine - Conseils divers)» J'ai écrit dans (C'est un article approximatif ...). fonction learning_curve avec variables explicatives et étiquettes, nombre de validations croisées (5 fois), taille des données d'entraînement Passez la liste. Cela renverra le taux de réponse correct pour l'entraînement et les tests en fonction de la taille des données d'entraînement.

#Sortie de courbe d'apprentissage
def output_learning_curve(estimator, x_all, y_all):
    training_sizes, train_scores, test_scores = learning_curve(estimator,
                                                               x_all, y_all, cv=5,
                                                               train_sizes=[0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0])
    plt.plot(training_sizes, train_scores.mean(axis=1), label="training scores")
    plt.plot(training_sizes, test_scores.mean(axis=1), label="test scores")
    plt.legend(loc="best")
    plt.show()

En regardant les résultats de sortie, j'ai pensé que la différence entre la formation et les tests se rétrécissait encore, alors j'ai essayé ce qui suit, mais la précision ne s'est pas améliorée. Les deux sont des options pour la recherche de grille.

image.png

Recommended Posts

100 langage de traitement knock-79 (en utilisant scikit-learn): dessin de graphe avec rappel de précision
100 traitement du langage knock-76 (en utilisant scicit-learn): étiquetage
100 traitement du langage knock-73 (en utilisant scikit-learn): apprentissage
100 traitement du langage knock-74 (en utilisant scicit-learn): prédiction
100 traitement du langage knock-97 (en utilisant scicit-learn): clustering k-means
100 traitement du langage knock-75 (en utilisant scicit-learn): poids de l'identité
100 traitement du langage knock-31 (en utilisant des pandas): verbe
100 traitement du langage knock-38 (en utilisant des pandas): histogramme
100 traitements linguistiques knock-77 (en utilisant scicit-learn): mesure du taux de réponse
100 coups de traitement linguistique (2020): 28
100 coups de traitement linguistique (2020): 38
100 traitement de la langue frapper 00 ~ 02
100 Language Processing Knock-33 (en utilisant des pandas): nom sahen
100 Language Processing Knock-71 (en utilisant Stanford NLP): Stopword
100 traitement du langage knock-35 (utilisant des pandas): concaténation de nomenclature
100 Language Processing Knock-39 (en utilisant des pandas): la loi de Zipf
100 traitement de langage knock-34 (utilisant des pandas): "B of A"
100 traitements linguistiques Knock 2020 [00 ~ 39 réponse]
100 langues de traitement knock 2020 [00-79 réponse]
100 traitements linguistiques Knock 2020 [00 ~ 69 réponse]
100 Language Processing Knock 2020 Chapitre 1
100 coups de traitement du langage amateur: 17
100 traitements linguistiques Knock 2020 [00 ~ 49 réponse]
100 Traitement du langage Knock-52: Stemming
100 Traitement du langage Knock Chapitre 1
100 coups de langue amateur: 07
100 langage de traitement knock-20 (à l'aide de pandas): lecture de données JSON
100 Language Processing Knock-32 (utilisant des pandas): Prototype de verbe
Traitement de 100 langues knock-98 (en utilisant des pandas): Clustering par méthode Ward
100 Language Processing Knock 2020 Chapitre 3
100 Language Processing Knock 2020 Chapitre 2
100 coups de traitement du langage amateur: 09
100 traitement du langage knock-99 (à l'aide de pandas): visualisation par t-SNE
100 coups en traitement du langage amateur: 47
Traitement 100 langues knock-53: Tokenisation
100 traitement du langage knock-95 (en utilisant des pandas): Note avec WordSimilarity-353
100 coups de traitement du langage amateur: 97
100 traitements linguistiques Knock 2020 [00 ~ 59 réponse]
100 coups de traitement du langage amateur: 67
100 traitement du langage knock-72 (en utilisant Stanford NLP): Extraction d'identité
100 langage traitement knock-92 (utilisant Gensim): application aux données d'analogie
100 traitement du langage knock-36 (en utilisant des pandas): fréquence d'occurrence des mots
100 Language Processing Knock: Chapitre 2 Principes de base des commandes UNIX (à l'aide de pandas)
100 Language Processing Knock-83 (en utilisant des pandas): Mesure de la fréquence des mots / contextes
100 Language Processing Knock-30 (en utilisant des pandas): lecture des résultats de l'analyse morphologique
100 traitement de langage knock-94 (en utilisant Gensim): calcul de similarité avec WordSimilarity-353
100 coups de traitement du langage avec Python 2015
100 traitement du langage Knock-51: découpage de mots
100 Language Processing Knock-58: Extraction de Taple
100 Language Processing Knock-57: Analyse des dépendances
100 traitement linguistique knock-50: coupure de phrase
100 Language Processing Knock Chapitre 1 (Python)
100 Language Processing Knock Chapitre 2 (Python)
100 Language Processing Knock-25: Extraction de modèles
Traitement du langage 100 Knock-87: similitude des mots
J'ai essayé 100 traitements linguistiques Knock 2020
100 Language Processing Knock-56: analyse de co-référence
Résolution de 100 traitements linguistiques Knock 2020 (01. "Patatokukashi")
100 coups de traitement du langage amateur: Résumé
100 Language Processing Knock-84 (en utilisant des pandas): Création d'une matrice de contexte de mots
100 langage de traitement knock-70 (en utilisant Stanford NLP): Obtention et formatage des données