LoginSignup
0
1

More than 5 years have passed since last update.

サポートベクターマシーンのパラメータをいろいろといじってみる(画像データの分類問題)

Posted at

初めに

機械学習の教科書では(紙面の都合上やらなさそうな)様々なパラメータを変えた際にどのように変化するのかについて、SVCを用いてやってみました。
ちなみに使用したのは0~9までの数字が書かれたDigitsの画像データ。
68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3134313939332f63636565353763652d363234612d363964662d613731392d6663306366656430633838382e706e67.png

Digitsのデータについてこちらで可視化等は行ってみています。

LinearSVC

まずはsvm.LinearSVCで正則化定数Cのチューニングを行ってみたいと思います。カーネル法を試す前に線形のSVMから始めた方が良いらしいです。結果はロジスティクス回帰分析とだいたい同じような感じになります。
svm.LinearSVCはLinearに特化したアルゴリズムのため、svm.SVCよりも高速で動くとのこと(未検証)
交差検証は10分割で行い、正答率の平均値を今回はscoreとして、プロットしてみました。(本来はテストデータを訓練データを分けてから交差検証した方が、よいでしょうが、今回は省略)

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn import datasets
from sklearn import svm

digits = datasets.load_digits()
data = digits["data"]
target = digits["target"]

#正則化の変数
alpha = [0.0001,0.001,0.01,0.1,1.,10.,100.,1000.]

#alphaに対応する交差検証の精度を記録する配列
accuracy = np.empty([len(alpha)])
for i in np.arange(len(alpha)):    
    clf = svm.LinearSVC(C=alpha[i])
    #cross validation
    cv_clf = model_selection.cross_validate(clf,data,target,cv=10)
        #test_scoreの平均値をscoreとして記録
    accuracy[i]= np.mean(cv_clf["test_score"])

plt.subplot(211)
plt.plot(alpha,accuracy)
plt.ylim(0,1)
plt.xscale("log")
plt.xlabel("C")
plt.ylabel("accuracy score")

plt.subplot(212)
plt.plot(alpha,accuracy)
plt.ylim(0.9,1)
plt.xscale("log")
plt.xlabel("C")
plt.ylabel("accuracy score")
plt.show()

結果の上のグラフは正答率スコアが0~100%の範囲、下のグラフは正答率スコアが90~100%の範囲に拡大したものである。
figure1.png
最大の正答率はC=0.001の時の93.9%でした。

Digitsのそれぞれのピクセルは0~16までの数字で明るさが表現されています。そこでピクセルの明るさを0~1になるように変更。

digits = datasets.load_digits()
data = digits["data"]
target = digits["target"]

#データが0~1の範囲になるように変更
data/=16

#正則化の変数
alpha = [0.00001,0.0001,0.001,0.01,0.1,1.,10.,100.,1000.,10000.]

正答率はC=1.0で最大で94.0%。0.1%良くなっているけど、誤差の範囲かな…。正答率が高いCの値が最初より大きくなった。
figure2.png

主成分分析+LinearSVC

今度はLinearSVCの前に主成分分析を行ってからLinearSVCをやってみる。


digits = datasets.load_digits()
data = digits["data"]
target = digits["target"]

#データが0~1の範囲になるように変更
data/=16

#dataに主成分分析
pca = PCA()
data = pca.fit_transform(data)

#正則化の変数
alpha = [0.00001,0.0001,0.001,0.01,0.1,1.,10.,100.,1000.,10000.]

figure3.png

正答率最大はC=0.1の時の94.1%、やっぱり0.1%良くなっているけど、誤差の範囲かな…。

SVCのlossを変更してみる

svm.LinearSVCのlossはsquared_hinge(デフォルト)
lossにhinge変更

digits = datasets.load_digits()
data = digits["data"]
target = digits["target"]

#正則化の変数
alpha = [0.0001,0.001,0.01,0.1,1.,10.,100.,1000.,10000.]

#alphaに対応する交差検証の精度を記録する配列
accuracy = np.empty([len(alpha)])
for i in np.arange(len(alpha)):    
    clf = svm.LinearSVC(C=alpha[i],penalty="l2",loss="hinge")
    #cross validation
    cv_clf = model_selection.cross_validate(clf,data,target,cv=10)
        #test_scoreの平均値をscoreとして記録
    accuracy[i]= np.mean(cv_clf["test_score"])

ssss.png
94.0%で変わらず…

カーネルSVM

非線形問題にも対応できるカーネルSVMを使ってチューニングしてみる。linearは上でやったのでkernel="rbf"で固定。


# -*- coding: utf-8 -*-
"""
sklearn 0.19.1
"""

import numpy as np
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn import datasets
from sklearn import svm

digits = datasets.load_digits()
data = digits["data"]
target = digits["target"]

#正則化の変数
alpha = [0.0001,0.001,0.01,0.1,1.,10.,100.,1000.]

#jはsvcのパラメーターガンマ
for j in [0.0001,0.001,0.01,0.1]:
    #alphaに対応する交差検証の精度を記録する文字列
    accuracy = np.empty([len(alpha)])
    for i in np.arange(len(alpha)):        
        clf = svm.SVC(gamma=j,C=alpha[i],kernel="rbf")
        #cross validation
        cv_clf = model_selection.cross_validate(clf,data,target,cv=10)
        accuracy[i]= np.mean(cv_clf["test_score"])

    plt.subplot(211)
    plt.plot(alpha,accuracy,label=str(j))
    plt.ylim(0,1)
    plt.xscale("log")
    plt.ylabel("accuracy score")

    plt.subplot(212)
    plt.plot(alpha,accuracy,label=str(j))
    plt.ylim(0.9,1)
    plt.xscale("log")
    plt.xlabel("C")
    plt.ylabel("accuracy score")

plt.subplot(211)
plt.legend(loc="upper left")
plt.subplot(212)
plt.legend(loc="upper left")
plt.show()

γが0.1の時に赤,γが0.01の時に緑,0.001の時にオレンジ,0.0001の時青である。

sv.png

正答率は最大でγ=0.001,C=10の時で98.1%。Cの値が10より大きくなっても同様の正答率を維持していた。やはりLinearSVCよりかなり精度が高い。

kernelを変更してみる

kernel="rbf"をkernel="poly"に変更するだけ!

clf = svm.SVC(gamma=j,C=alpha[i],kernel="poly")

poly.png
正答率は97.8%でrbfには及ばず。

最後に

scikit_learnのSVMのパラメータをいろいろと変更してみました。
defaultと比較して、中々精度は向上せず、残念。
defaultが良い案配の設定になっています。
SVMを試す際はまずはdefaultでいったん精度を確認した方が良さそうですね。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1