Il s'agit du record de la 77ème «Mesure du taux de précision» de Traitement du langage 100 coups 2015. Le contenu de la question knock est la mesure du taux de réponse correct pour les données d'entraînement, mais cette fois, nous osons utiliser les données de test comme dans le temps précédent. Jusqu'à présent, je ne l'ai pas posté sur le blog 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.
GridSearchCV
a déjà été utilisée pendant l'entraînement pour effectuer un test d'intersection à 5 divisions (pour être exact, je ne l'ai pas fait sans demander le taux de précision, etc. avec le test d'intersection à 5 divisions, mais c'est gênant, je vais donc l'omettre. Faire).Lien | Remarques |
---|---|
077.Mesure du taux de réponse correcte.ipynb | Lien GitHub du programme de réponse |
100 coups de traitement du langage amateur:77 | Je vous suis toujours redevable de 100 coups de traitement linguistique |
Introduction à Python avec 100 coups de traitement du langage#77 -Apprentissage automatique, scikit-Mesure du taux de réponse correct avec apprentissage | scikit-Résultat Knock en utilisant Learn |
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 |
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).
Créez un programme qui reçoit plus de 76 sorties et calcule le taux de réponse correct de la prédiction, le taux de réponse correct pour l'exemple correct, le taux de rappel et le score F1.
Cette fois, j'ai ignoré la partie "Recevoir 76 sorties" et l'ai implémentée pour les données de test. C'est parce que je pensais que les données de test seraient plus utiles que les données d'entraînement comme avant.
En gros [précédent "076. Labeling.ipynb"](https://github.com/YoheiFukuhara/nlp100/blob/master/08.%E6%A9%9F%E6%A2%B0%E5%AD % A6% E7% BF% 92 / 076.% E3% 83% A9% E3% 83% 99% E3% 83% AB% E4% BB% 98% E3% 81% 91.ipynb) Taux de réponse correcte et indicateurs associés Il s'agit simplement d'ajouter une logique de sortie.
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
from sklearn.metrics import classification_report, confusion_matrix
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))
estimator = train(x_train, y_train, 'gs_result.csv')
validate(estimator, x_test, y_test)
J'utilise juste le classification_report
de scikit-learn, et je n'ai pas beaucoup écrit à ce sujet.
Le résultat «y_pred» de la fonction «prédire» utilisée dans le «étiquetage» précédent est utilisé.
y_pred = estimator.predict(x_test)
Tout ce que vous avez à faire est de le passer à la fonction classification_report
avec l'étiquette correcte d'origine y_test
.
print('\n', classification_report(y_test, y_pred))
Le taux de précision, le taux de rappel, le score F1, le taux de réponse correcte, etc. sont affichés.
precision recall f1-score support
0 0.75 0.73 0.74 1351
1 0.73 0.75 0.74 1315
accuracy 0.74 2666
macro avg 0.74 0.74 0.74 2666
weighted avg 0.74 0.74 0.74 2666
Puisque les paramètres à passer sont les mêmes, la fonction confusion_matrix
produit également la matrice de confusion.
print('\n', confusion_matrix(y_test, y_pred))
Une matrice mixte apparaît sous une forme simple. 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) ).
[[992 359]
[329 986]]