Prenons l'exemple ** "Identifions automatiquement le code postal manuscrit inscrit sur la carte postale" **.
Ceci est un article pour les débutants. Fondamentalement, il s'agit d'une collection de didacticiels et de documents scikit-learn, mais elle comprend également d'autres contenus. Nous utiliserons des chiffres pour l'ensemble de données et SVM (SVC pour être exact) pour la méthode d'apprentissage automatique.
chiffres est un ensemble de données composé d'une étiquette numérique et de données d'image numérique. Vous apprendrez cette paire d'étiquettes et d'images plus tard. Puisque les données sont préparées à l'avance par scikit-learn, n'importe qui peut facilement l'essayer.
Vous pouvez charger les chiffres du jeu de données avec datasets.load_digits ().
from sklearn import datasets
from matplotlib import pyplot as plt
# from sklearn import datasets
digits = datasets.load_digits()
Chaque image est une image de caractère manuscrite de 0 à 9. Ces images sont représentées par programme sous la forme d'un tableau à deux dimensions avec des valeurs comprises entre 0 et 255.
#Données du tableau d'image
print(digits.data)
[[ 0. 0. 5. ..., 0. 0. 0.]
[ 0. 0. 0. ..., 10. 0. 0.]
[ 0. 0. 0. ..., 16. 9. 0.]
...,
[ 0. 0. 1. ..., 6. 0. 0.]
[ 0. 0. 2. ..., 12. 0. 0.]
[ 0. 0. 10. ..., 12. 1. 0.]]
Il est difficile à comprendre même si vous regardez les données d'image sous forme de tableau, je voudrais donc l'afficher sous forme d'image.
Avant d'afficher l'image, vérifiez d'abord les données de l'étiquette. Comme indiqué ci-dessous, les étiquettes 0 à 9 sont correctement attribuées à l'avance.
#étiquette
print(digits.target)
[0 1 2 ..., 8 9 8]
En regardant le résultat ci-dessus, par exemple, la 0, 1, 2ème image du début reçoit l'étiquette 0, 1, 2 et la deuxième image de l'arrière reçoit l'étiquette 9. .. Vous pouvez utiliser matplotlib pour afficher ces images.
#Affichage de l'image
# number 0
plt.subplot(141), plt.imshow(digits.images[0], cmap = 'gray')
plt.title('number 0'), plt.xticks([]), plt.yticks([])
# number 1
plt.subplot(142), plt.imshow(digits.images[1], cmap = 'gray')
plt.title('numbert 1'), plt.xticks([]), plt.yticks([])
# number 2
plt.subplot(143), plt.imshow(digits.images[2], cmap = 'gray')
plt.title('numbert 2'), plt.xticks([]), plt.yticks([])
# number 9
plt.subplot(144), plt.imshow(digits.images[-2], cmap = 'gray')
plt.title('numbert 9'), plt.xticks([]), plt.yticks([])
plt.show()
De cette façon, vous pouvez voir que chaque image semble avoir la bonne étiquette.
** SVM (Support Vector Machine) ** est l'une des méthodes d'apprentissage supervisé avec d'excellentes performances de reconnaissance. Fondamentalement, la classification à deux classes est basée sur la maximisation de la marge. Bien sûr, il peut également être appliqué à la classification multi-classes (en effectuant plusieurs fois une classification à deux classes).
Avec un SVM strict, si les données à classer se chevauchent (c'est-à-dire si toutes les données ne peuvent pas être complètement séparées), il n'est pas possible d'obtenir une limite de classification appropriée. En revanche, les SVM qui tolèrent les erreurs sont appelés ** SVM à marge souple **. En donnant une pénalité C aux erreurs de classification, il est possible de tracer une frontière de classification qui minimise les erreurs de classification même pour les données qui ne peuvent pas être complètement séparées.
Il est important de noter que plus la pénalité C est grande, plus l'erreur est grave et, en même temps, plus elle est susceptible de provoquer un ** surajustement **.
(Remarque) Le surentraînement signifie que le modèle d'entraînement s'intègre dans des fonctionnalités aléatoires spécifiques (sans rapport avec les fonctionnalités que vous souhaitez entraîner à l'origine) dans les données d'entraînement. En cas de surentraînement, les performances des données d'entraînement s'amélioreront, mais les résultats seront pires avec d'autres données. (Référence: Over-fit-Wikipedia)
En fait, scikit-learn a des types légèrement différents de SVM tels que SVC, NuSVC et LinearSVC. NuSVC et SVC sont des techniques très similaires, mais ils ont des ensembles de paramètres légèrement différents et sont représentés mathématiquement par des formulations différentes. LinearSVC est un SVM qui utilise un noyau linéaire, et aucun autre noyau ne peut être spécifié.
Cette fois, nous utiliserons SVC et appliquerons une marge douce. Tout ce que vous avez à faire est ** (1) de créer un classificateur et (2) de l'appliquer à vos données **.
from sklearn import svm
# SVM
clf = svm.SVC(gamma=0.001, C=100.)
clf.fit(digits.data[:-10], digits.target[:-10])
SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma=0.001, kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
Bien que rarement spécifié ici, vous pouvez voir que le SVC a pas mal de paramètres (C, cache_size, class_weight, coef0, ...) comme indiqué ci-dessus. Ne vous inquiétez pas trop au début, les paramètres par défaut sont bons.
L'étiquette est en fait estimée à partir de l'image à l'aide du classificateur créé. Essayons avec les 10 dernières données que nous n'avons pas utilisées pour créer le modèle d'entraînement.
clf.predict(digits.data[-10:])
array([5, 4, 8, 8, 4, 9, 0, 8, 9, 8])
En regardant les données réelles,
print(digits.target[-10:])
[5 4 8 8 4 9 0 8 9 8]
Est en accord avec le résultat de l'estimation.
Cela confirme qu'une estimation approximativement correcte est possible à partir du modèle formé. Essayons différents paramètres.
Il existe plusieurs indices d'évaluation de la précision de classification du classificateur, mais il peut en principe être mesuré par les indices suivants.
Normalement, la précision du classificateur est souvent évaluée par la valeur F. Cependant, dans la pratique, il arrive souvent que l'accent soit mis sur le taux de précision ou le taux de rappel.
Par exemple, envisagez une inspection des pièces en usine. Ce n'est pas un gros problème si vous classez par erreur une pièce qui n'est cassée nulle part comme "cassée (erreur)". Cependant, si une pièce cassée est classée à tort comme "non cassée (correcte)", cela peut entraîner des plaintes et des rappels, voire même mettre la vie en danger selon le produit. Dans de tels cas, la précision est plus importante que le rappel. Par exemple, dans «Taux de conformité 99% + taux de rappel 70%» et «Taux de conformité 80% + taux de rappel 99%», ce dernier a une valeur F plus élevée, mais le premier est extrêmement pratique. C'est possible. En revanche, lors d'une recherche dans une base de données, le taux de rappel est souvent plus important que le taux de précision. En effet, même si vous obtenez beaucoup de mauvais résultats de recherche, c'est bien mieux que beaucoup de données qui ne peuvent pas être trouvées par la recherche.
Jusqu'à présent, les paramètres étaient en quelque sorte réglés sur des valeurs appropriées. Cependant, cela ne fournit souvent pas la précision de classification requise et, en pratique, l'optimisation des paramètres est essentielle. Alors, quels paramètres devraient être définis et comment devraient-ils être définis pour améliorer la précision de classification du classificateur? Vous pouvez régler manuellement les paramètres un par un, mais c'est très difficile. Il semble que l'on puisse savoir qu'une telle valeur est habituellement bonne selon l'ensemble de données et la méthode, mais elle ne peut pas être utilisée pour un ensemble de données inconnu. Par conséquent, une méthode appelée ** recherche de grille ** est souvent utilisée. En termes simples, le modèle est réellement entraîné lors de la modification des paramètres dans la plage de recherche et le paramètre avec la meilleure précision de résultat est recherché. De plus, la ** validation croisée ** est utilisée pour confirmer que le modèle d'apprentissage avec les paramètres obtenus ne provoque pas de surentraînement. Dans la méthode de vérification de k-intersection, les données sont d'abord divisées en k morceaux. C'est une méthode d'apprentissage avec k-1 d'entre eux et d'évaluation avec le reste, en répétant k fois (tout en changeant les données d'entraînement et les données de test) et en évaluant le modèle d'apprentissage avec la valeur moyenne. En faisant cela, vous pouvez évaluer les ** performances de généralisation ** du modèle d'entraînement.
(Remarque) Une bonne performance de généralisation est simplement la capacité du modèle d'apprentissage à identifier correctement les données inconnues. Rappelez-vous que si vous êtes surentraîné, vous pourrez identifier les données d'entraînement avec une grande précision, mais vous serez moins précis avec des données inconnues.
Avec scikit-learn, vous pouvez facilement effectuer une recherche de grille et une vérification d'intersection à l'aide de GridSearchCV (). Par exemple, vous pouvez spécifier les paramètres suivants:
Avant d'effectuer l'optimisation des paramètres, convertissez le format des données lues.
from sklearn import datasets
from sklearn.cross_validation import train_test_split
from sklearn.grid_search import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.svm import SVC
#Chargement du jeu de données Digits
digits = datasets.load_digits()
print(len(digits.images))
print(digits.images.shape)
1797
(1797, 8, 8)
# To apply an classifier on this data, we need to flatten the image, to
# turn the data in a (samples, feature) matrix:
n_samples = len(digits.images)
X = digits.images.reshape((n_samples, -1)) # reshape(cols, rows)Convertir en colonne de lignes de lignes cols avec(Un des arguments-Calcul automatique si 1)
y = digits.target
print(X.shape)
print(y)
(1797, 64)
[0 1 2 ..., 8 9 8]
Le code ci-dessous peut sembler intimidant, mais ce que vous faites en réalité est simple.
Vous essayez simplement toutes les combinaisons des cas ci-dessus pour trouver le paramètre (meilleur \ _params \ _) qui maximise chaque précision et rappel. (Notez que gamma est un paramètre lorsque le noyau est rbf, donc il n'est pas pertinent lorsque le noyau est linéaire)
Après cela, les résultats de la recherche dans la grille sont affichés en détail et le rapport détaillé des résultats est affiché avec classification_report ().
#Divisez l'ensemble de données en données d'entraînement et données de test
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.5, random_state=0)
#Définissez les paramètres que vous souhaitez optimiser avec la validation croisée
tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
'C': [1, 10, 100, 1000]},
{'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]
scores = ['precision', 'recall']
for score in scores:
print("# Tuning hyper-parameters for %s" % score)
print()
#Recherche de grille et méthode de vérification des intersections
clf = GridSearchCV(SVC(C=1), tuned_parameters, cv=5,
scoring='%s_weighted' % score)
clf.fit(X_train, y_train)
print("Best parameters set found on development set:")
print()
print(clf.best_params_)
print()
print("Grid scores on development set:")
print()
for params, mean_score, scores in clf.grid_scores_:
print("%0.3f (+/-%0.03f) for %r"
% (mean_score, scores.std() * 2, params))
print()
print("Detailed classification report:")
print()
print("The model is trained on the full development set.")
print("The scores are computed on the full evaluation set.")
print()
y_true, y_pred = y_test, clf.predict(X_test)
print(classification_report(y_true, y_pred))
print()
# Tuning hyper-parameters for precision
Best parameters set found on development set:
{'gamma': 0.001, 'kernel': 'rbf', 'C': 10}
Grid scores on development set:
0.987 (+/-0.018) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 1}
0.959 (+/-0.030) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 1}
0.988 (+/-0.018) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 10}
0.982 (+/-0.027) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 10}
0.988 (+/-0.018) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 100}
0.982 (+/-0.026) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 100}
0.988 (+/-0.018) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 1000}
0.982 (+/-0.026) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 1000}
0.974 (+/-0.014) for {'kernel': 'linear', 'C': 1}
0.974 (+/-0.014) for {'kernel': 'linear', 'C': 10}
0.974 (+/-0.014) for {'kernel': 'linear', 'C': 100}
0.974 (+/-0.014) for {'kernel': 'linear', 'C': 1000}
Detailed classification report:
The model is trained on the full development set.
The scores are computed on the full evaluation set.
precision recall f1-score support
0 1.00 1.00 1.00 89
1 0.97 1.00 0.98 90
2 0.99 0.98 0.98 92
3 1.00 0.99 0.99 93
4 1.00 1.00 1.00 76
5 0.99 0.98 0.99 108
6 0.99 1.00 0.99 89
7 0.99 1.00 0.99 78
8 1.00 0.98 0.99 92
9 0.99 0.99 0.99 92
avg / total 0.99 0.99 0.99 899
# Tuning hyper-parameters for recall
Best parameters set found on development set:
{'gamma': 0.001, 'kernel': 'rbf', 'C': 10}
Grid scores on development set:
0.986 (+/-0.021) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 1}
0.958 (+/-0.029) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 1}
0.987 (+/-0.021) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 10}
0.981 (+/-0.029) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 10}
0.987 (+/-0.021) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 100}
0.981 (+/-0.027) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 100}
0.987 (+/-0.021) for {'gamma': 0.001, 'kernel': 'rbf', 'C': 1000}
0.981 (+/-0.027) for {'gamma': 0.0001, 'kernel': 'rbf', 'C': 1000}
0.973 (+/-0.015) for {'kernel': 'linear', 'C': 1}
0.973 (+/-0.015) for {'kernel': 'linear', 'C': 10}
0.973 (+/-0.015) for {'kernel': 'linear', 'C': 100}
0.973 (+/-0.015) for {'kernel': 'linear', 'C': 1000}
Detailed classification report:
The model is trained on the full development set.
The scores are computed on the full evaluation set.
precision recall f1-score support
0 1.00 1.00 1.00 89
1 0.97 1.00 0.98 90
2 0.99 0.98 0.98 92
3 1.00 0.99 0.99 93
4 1.00 1.00 1.00 76
5 0.99 0.98 0.99 108
6 0.99 1.00 0.99 89
7 0.99 1.00 0.99 78
8 1.00 0.98 0.99 92
9 0.99 0.99 0.99 92
avg / total 0.99 0.99 0.99 899
Maintenant, d'après le résultat de print (clf.best \ _params \ _), 'gamma': 0.001, 'kernel': 'rbf', 'C': 10 sont les meilleurs des deux points de vue précision / rappel. Je comprends ça. Vous avez maintenant optimisé les paramètres.
Si nécessaire, essayez d'optimiser avec un noyau différent ou par rapport à des méthodes d'apprentissage autres que SVM.
[1]An introduction to machine learning with scikit-learn — scikit-learn 0.18.1 documentation http://scikit-learn.org/stable/tutorial/basic/tutorial.html#introduction [2]Parameter estimation using grid search with cross-validation — scikit-learn 0.18.1 documentation http://scikit-learn.org/stable/auto_examples/model_selection/grid_search_digits.html#example-model-selection-grid-search-digits-py [3]1.4. Support Vector Machines — scikit-learn 0.18.1 documentation http://scikit-learn.org/stable/modules/svm.html [4] F value-Machine learning "Toki no Mori Wiki" http://ibisforest.org/index.php?F%E5%80%A4 [5] Maître SVM! 8 points de contrôle-Qiita http://qiita.com/pika_shi/items/5e59bcf69e85fdd9edb2 [6] Optimisation des paramètres par recherche de grille de Scikit learn http://qiita.com/SE96UoC5AfUt7uY/items/c81f7cea72a44a7bfd3a [7] Introduction à l'optimisation bayésienne pour l'apprentissage automatique | Manatee de zone de livre technique https://book.mynavi.jp/manatee/detail/id=59393 [8]3.3. Model evaluation: quantifying the quality of predictions — scikit-learn 0.18.1 documentation http://scikit-learn.org/stable/modules/model_evaluation.html#scoring-parameter [9] Overfit - Wikipédia https://ja.wikipedia.org/wiki/%E9%81%8E%E5%89%B0%E9%81%A9%E5%90%88
Recommended Posts