yana_lab

Python機械学習

最終更新:

yana_lab

- view
だれでも歓迎! 編集

Python機械学習

ここではSVMによる識別は交差検定について簡単にまとめます.
sklearn-learnはリファレンスも親切ですので,そちらも確認してみてください.

1.SVMに挑戦

#####################################
#SVMによる機械学習
#編集日:2016/9/5
#製作者:栁澤
#プログラムを書き換える必要は特にないです.
#####################################

from sklearn.svm import LinearSVC
import numpy as np
from sklearn.preprocessing import StandardScaler #正規化(標準得点化)するのに使う 
from sklearn.metrics import accuracy_score #正解率を求めるのに使う

# 学習データ(1列目:時間、2列目:教師信号、3列目以降:使用するデータ)###################
data = np.loadtxt('data.csv', delimiter=',')#学習データの読み込み
print("学習データ")
print(data)
 
timedata = data[:,0] #時間データ
t_signal = data[:,1] #教師信号
data_training = data[:,2::] #学習信号
label_training = [int(x) for x in t_signal] #教師信号の形式を加工

#標準得点化
scaler = StandardScaler()
scaler.fit(data_training)
data_training = scaler.transform(data_training)
##########################################################################################

# 評価データ(1列目:時間、2列目:教師信号、3列目以降:使用するデータ)###################
data_test = np.loadtxt('testdata.csv', delimiter=',')#評価データの読み込み
print("評価データ")
print(data_test)
 
true_singal =  data_test[:,1] ##正解の情報
data_test = data_test[:,2::] #学習信号

#標準得点化
scaler = StandardScaler()
scaler.fit(data_test)
data_test = scaler.transform(data_test)
##########################################################################################
# 学習(ソフトマージンSVM(線形))
estimator = LinearSVC(C=1)#コストパラメータCを調整すること(Cが大きいほどハードマージンSVMに近づく)
estimator.fit(data_training, label_training)#上で作った識別器に学習データの教師信号を入力する

# 予測する
label_prediction = estimator.predict(data_test)
 
print("識別結果")
print(label_prediction)#識別結果を表示

correct_rate = accuracy_score(true_singal, label_prediction)
print("正解率 " + str(correct_rate*100) +"%")
 

2.交差検定(クロスバリデーション)

上の方法は学習データと評価データを分けて作成しておく必要があったが,これらの方法を使えば自動的にデータを学習データと評価データに分けてくれる.

2.1 KFold

#単純にn_splitsの数でデータを分割する
from sklearn.model_selection import KFold
from sklearn import datasets
 
iris = datasets.load_iris()#アイリスのデータを読み込む(iris.dataが数値データでiris.targetが教師信号(正解))

kf = KFold(n_splits=3, random_state=None, shuffle=False)#KFoldで交差検定をするための準備
for train_index, test_index in kf.split(iris.data):
  print("TRAIN:", train_index, "TEST:", test_index)
  X_train, X_test = iris.data[train_index], iris.data[test_index]
  y_train, y_test = iris.target[train_index], iris.target[test_index]
 
注意:例えば 最初の50個がクラスAのデータ,次の50個がクラスB,最後の50個がクラスCのようなデータセットをKFold でデータを3分割すると,学習データに全く含まれていないクラスが出てくるので,その場合は,StratifiedKFoldを使うこと.

2.2 StratifiedKFold

#単純にn_splitsの数でデータを分割せずに、全体のクラスの比率を反映して分割する
from sklearn.model_selection import StratifiedKFold
from sklearn import datasets
 
iris = datasets.load_iris() #アイリスのデータを読み込む(iris.dataが数値データでiris.targetが教師信号(正解))

skf = StratifiedKFold(n_splits=3, random_state=None, shuffle=False)#StratifiedKFoldで交差検定をするための準備

#このも方法だけは、教師信号(ラベルデータ、target)もここに入力する(おそらく、クラスの比率を変えないために、ラベルの情報が必要だから)
for train_index, test_index in skf.split(iris.data,iris.target): 
  print("TRAIN:", train_index, "TEST:", test_index)
  X_train, X_test = iris.data[train_index], iris.data[test_index]
  y_train, y_test = iris.target[train_index], iris.target[test_index]
 

2.3 LeaveOneOut

#テストデータは1サンプルのみ、その他全部で学習する
from sklearn.model_selection import LeaveOneOut
from sklearn import datasets
 
iris = datasets.load_iris()#アイリスのデータを読み込む(iris.dataが数値データでiris.targetが教師信号(正解))

loo = LeaveOneOut()
for train_index, test_index in loo.split(iris.data):
  #print("TRAIN:", train_index, "TEST:", test_index)
  X_train, X_test = iris.data[train_index], iris.data[test_index]
  y_train, y_test = iris.target[train_index], iris.target[test_index]
 

3. SVMの正解率を求める(交差検定を利用)

#########################
#日付:2017年4月13日
#作成者:栁澤
#内容: 交差検定用 3種類あるよ!
#########################

from sklearn.model_selection import cross_val_score
from sklearn import svm
from sklearn.model_selection import KFold
from sklearn.model_selection import LeaveOneOut
from sklearn.model_selection import StratifiedKFold
import numpy as np
from sklearn.svm import LinearSVC
 
nn = 5 #交差検定するときの分割数
dataname = 'B' #ファイル名
filename = dataname + '.csv'
 
data = np.loadtxt(filename, delimiter=',') #データの読み込み
data = np.array(data,dtype=np.float32) #データをfloat32にする
row,col = data.shape #データの大きさを調べる
label_data = data[:,1] #教師信号
nirs_data = data[:,2:col]  #計測データ

 
#①単純にn_splitsの数でデータを分割する
kf = KFold(n_splits=nn, random_state=None, shuffle=False) 
 
#②テストデータは1サンプルのみ、その他全部で学習する
loo = LeaveOneOut()
 
#③単純にn_splitsの数でデータを分割せずに、全体のクラスの比率を反映して分割する
skf = StratifiedKFold(n_splits=nn, random_state=None, shuffle=False) 
 
clf = LinearSVC(C=10) #線形SVM(いままで使っていたやつ)
#clf = svm.SVC(kernel='linear', C=1) #非線形も対応(これはlinerだけど)
#clf = svm.SVC(kernel='rbf', C=1, gamma=0.1) #カーネル関数fbfで非線形SVM
scores = cross_val_score(clf, nirs_data, label_data, cv=skf) #cvの交差検定でclfの識別器で正答率を求める
print(scores)#交差検定でわけたそれぞれのセットの正答率を表示

correct_rate = 100*sum(scores)/len(scores)#平均正答率を求める
print(correct_rate)#平均正答率を表示

#loo(LeaveOneOut)のときのみコメントアウト
#print(100*sum(scores)/16)#これが平均正答率になる
 

4.パラメータの決定方法(グリッドリサーチ)

最適なパラメータを見つけたいときは以下のように書けば,各条件での正答率と標準偏差を計算してくれる.
#########################
#日付:2017年4月13日
#作成者:栁澤
#内容: パラメータ検討用

#########################

from sklearn.model_selection import GridSearchCV
from sklearn import svm, grid_search
import numpy as np
import csv
 
nn = 4 #交差検定するときの分割数
dataname = 'B'
filename = dataname + '.csv'
 
data = np.loadtxt(filename, delimiter=',')
data = np.array(data,dtype=np.float32) #データをfloat32にする
row,col = data.shape #データの大きさを調べる
label_data = data[:,1] #教師信号
nirs_data = data[:,3:col]  #計測データ

#検討するパラメータ
parameters ='kernel':('linear', 'rbf'), 'C':[0.1, 1, 10, 100] ,'gamma':[0.001, 0.01, 0.1 ,1 ,10]}
svr = svm.SVC()#使用する識別器
clf = grid_search.GridSearchCV(svr, parameters, n_jobs = -1, cv=nn)#グリッドサーチの設定
clf.fit(nirs_data, label_data)#学習

savedata = ['params','mean_score','sd']
for params, mean_score, all_scores in clf.grid_scores_:
    print ("{:.3f} (+/- {:.3f}) for {}".format(mean_score, all_scores.std() / 2, params))
    savedata = np.vstack([savedata,[params,mean_score, all_scores.std() / 2]])
 
savefilename = 'result_' + dataname + '.csv'
with open(savefilename, 'w') as f:
    writer = csv.writer(f, lineterminator='\n') # 改行コード(\n)を指定しておく
    writer.writerows(savedata) # 2次元配列も書き込める
 
@wikiの入力上?の問題から「parameters ={'kernel':('linear', 'rbf'), 'C':[0.1, 1, 10, 100] ,'gamma':[0.001, 0.01, 0.1 ,1 ,10]}」の大括弧{}は全角になっていますので,使うときは半角に修正してね.

参考

読み込んでいるデータの形式について説明しておく.

時間 教師信号 データ1 データ2 ・・・ データn
0 0 x11 x21 ・・・ xn1
1 0 x12 x22 ・・・ xn2
2 1 x13 x23 ・・・ xn3
3 1 x14 x24 ・・・ xn4
・・・ ・・・ ・・・ ・・・ ・・・ ・・・
t 0 x1t x2t ・・・ xnt
+ タグ編集
  • タグ:
  • Python
  • SVM
  • sklearn-learn
ウィキ募集バナー