Un SVM linéaire (Support Vector Machine) est un modèle d'apprentissage automatique qui sépare et classe linéairement les espaces d'entités. S'il ne peut pas être séparé linéairement, il peut être séparé non linéairement par SVN en utilisant la méthode du noyau.
Jusqu'à présent, je ne comprenais pas vraiment la méthode du noyau, mais l'article suivant était très facile à comprendre.
À propos de la méthode du noyau dans l'apprentissage automatique-Memomemo
Après cela, je l'essaye dans l'environnement de Jupyter Notebook préparé selon l'article suivant. Installation et démarrage faciles de Jupyter Notebook à l'aide de Docker (prend également en charge nbextensions et Scala) --Qiita
Dans cet environnement, vous pouvez accéder au port 8888 avec un navigateur et utiliser Jupyter Notebook. Vous pouvez ouvrir une nouvelle note en suivant Nouveau> Python 3 sur le bouton en haut à droite.
Aussi, un fichier CSV créé au hasard https://github.com/suzuki-navi/sample-data/blob/master/sample-data-1.csv J'utilise.
Lisez les données d'un fichier CSV et en faites un objet DataFrame.
import pandas as pd
from sklearn import model_selection
df = pd.read_csv("sample-data-1.csv", names=["id", "target", "data1", "data2", "data3"])
df
est un objet Pandas DataFrame.
référence Essayez les opérations de base pour Pandas DataFrame sur Jupyter Notebook - Qiita
Les variables caractéristiques de ces données CSV sont «data1», «data2» et «data3», mais vérifions l'état des données avec un diagramme de dispersion.
%matplotlib inline
import matplotlib.pyplot as plt
plt.scatter(df["data1"], df["data2"], c = df["target"])
plt.scatter(df["data1"], df["data3"], c = df["target"])
plt.scatter(df["data2"], df["data3"], c = df["target"])
référence Afficher l'histogramme / diagramme de dispersion sur Jupyter Notebook - Qiita
En regardant le diagramme de dispersion, il semble qu'il puisse être classé en deux, data2
et data3
, donc je vais l'essayer.
feature = df[["data2", "data3"]]
target = df["target"]
feature
est un objet Pandas DataFrame et target
est un objet Pandas Series.
Il existe 300 enregistrements, qui sont respectivement divisés en données d'apprentissage et données de validation pour les variables de caractéristiques et les variables d'objectifs. Il divise simplement l'enregistrement en deux, mais vous pouvez facilement le diviser avec model_selection.train_test_split
. Cela le divisera au hasard.
feature_train, feature_test, target_train, target_test = model_selection.train_test_split(feature, target, test_size=0.2)
test_size = 0.2
est une spécification pour utiliser 20% de toutes les données comme données de vérification.
Les variables de fonctionnalité (df [[" data2 "," data3 "]]
, feature_train
, feature_test
) sont des objets Pandas DataFrame, des variables objectives (df [" target "]
, target_train
,target_test
) Est un objet Série.
Apprenez en fonction des données d'entraînement créées (feature_train
, target_train
).
from sklearn import svm
model = svm.SVC(kernel="linear")
model.fit(feature_train, target_train)
SVC (kernel =" linear ")
est un modèle de classificateur SVM qui sépare linéairement. Apprenons avec fit
.
référence sklearn.svm.SVC — scikit-learn 0.21.3 documentation
Créez un résultat d'inférence (pred_train
) à partir de la variable de fonction ( feature_train
) des données d'entraînement avec le modèle entraîné, comparez-le avec la variable objectif (target_train
) et évaluez le taux de précision. Vous pouvez facilement l'évaluer avec une fonction appelée metrics.accuracy_score
.
from sklearn import metrics
pred_train = model.predict(feature_train)
metrics.accuracy_score(target_train, pred_train)
En raison du caractère aléatoire de la logique, le résultat peut être différent à chaque fois, mais il indique «0,95».
Évaluer avec les données d'entraînement pour voir s'il est surentraîné ou généralisé.
pred_test = model.predict(feature_test)
metrics.accuracy_score(target_test, pred_test)
Il était affiché sous la forme "0.9333333333333333". Je ne sais pas si ça va.
En dehors de scikit-learn, vous pouvez utiliser plotting.plot_decision_regions
inclus dans le package mlxtend
pour visualiser comment il est classé dans un diagramme de dispersion. Vous devez passer un tableau de NumPy à plot_decision_regions
au lieu d'un objet Pandas, alors convertissez-le avec la méthode to_numpy ()
.
from mlxtend import plotting
plotting.plot_decision_regions(feature.to_numpy(), target.to_numpy(), clf=model)
Bonnes vibrations.
référence plot_decision_regions - Mlxtend.plotting - mlxtend pandas.DataFrame.to_numpy — pandas 0.25.3 documentation
Je voudrais essayer la séparation non linéaire. Utilisons le noyau RBF.
Tout ce que vous avez à faire est de changer svm.SVC (kernel =" linear ")
en svm.SVC (kernel =" rbf ", gamma =" scale ")
. gamma =" scale "
est un hyper paramètre pour le noyau RBF, et si vous spécifiez " scale "
, il sera calculé automatiquement à partir du nombre de données d'entraînement et de la distribution des variables de caractéristiques.
Le code ci-dessous va créer, entraîner, déduire et même évaluer le modèle.
model = svm.SVC(kernel="rbf", gamma="scale")
model.fit(feature_train, target_train)
pred_train = model.predict(feature_train)
metrics.accuracy_score(target_train, pred_train)
Il était affiché comme «0,95».
Évaluez avec les données d'entraînement pour voir les performances de généralisation.
pred_test = model.predict(feature_test)
metrics.accuracy_score(target_test, pred_test)
Il était affiché comme «0,95». C'est un peu mieux que la séparation linéaire dont j'ai parlé plus tôt.
plotting.plot_decision_regions(feature.to_numpy(), target.to_numpy(), clf=model)
Puisqu'il n'est pas linéaire, il est certainement séparé par une courbe.
Cet échantillon était facile à séparer linéairement, il n'a donc peut-être pas été suffisant pour le rendre non linéaire.
Puisque «data2» et «data3» peuvent être séparés linéairement, essayez le noyau RBF avec d'autres combinaisons de données.
Tout d'abord, «data1» et «data2». Faites uniquement la figure qui semble être séparée par le code suivant.
feature = df[["data1", "data2"]]
target = df["target"]
feature_train, feature_test, target_train, target_test = model_selection.train_test_split(feature, target, test_size=0.2)
model = svm.SVC(kernel="rbf", gamma="scale")
model.fit(feature_train, target_train)
plotting.plot_decision_regions(feature.to_numpy(), target.to_numpy(), clf=model)
Voyons le taux de réponse correct.
pred_train = model.predict(feature_train)
metrics.accuracy_score(target_train, pred_train)
C'était "0,7583333333333333".
pred_test = model.predict(feature_test)
metrics.accuracy_score(target_test, pred_test)
C'était "0,7833333333333333".
Au fait, même si j'ai essayé linéairement (kernel =" linear "
) avec les mêmes données, c'était de 0,71 à 0,74. En regardant la figure, il semble que la méthode du noyau travaille dur, mais n'y a-t-il pas une grande différence dans les valeurs numériques? Ne devrions-nous pas en attendre trop simplement parce que nous pouvons faire de la non-linéarité?
J'ai aussi essayé avec data1
et data3
, mais c'était similaire, donc je l'ai omis ...
c'est tout.
Suite Essayez le clustering avec un modèle gaussien mixte sur Jupyter Notebook - Qiita
Recommended Posts