scikit-learn

前回、ワインの分類で、意外とpHが強い事に驚いた。元データはポルトガルで採取された ものだそうだけど、みんなそんなものなの?

The Importance of pH in Wine Making によると、そんなものらしい。化学実験器具の写真が出てたので、本当にそんなの使ってるのと 思って当たってみたら、 初めてのワイン分析なんてのが出てきた。わーい、化学実験室だ。楽しそう。

糖度とアルコール度、酸度とpHの話なんてのも有った。なる程ね。

>> r = dlmread ('red.csv', ';');
>> w = dlmread ('white.csv', ';');
>> statistics (r(:,9))
ans =

   2.74000
   3.21000
   3.31000
   3.40000
   4.01000
   3.31111
   0.15439
   0.19350
   3.80067

>> statistics (w(:,9))
ans =

   2.72000
   3.09000
   3.18000
   3.28000
   3.82000
   3.18827
   0.15100
   0.45764
   3.52901

赤ワインと白ワインのpHの統計情報を、octaveに調べてもらった。白ワインの方が微妙に pHが低いな。

histするとヒストグラムが出てくるんだけど、これのCUI版って無いのかしら? そんなの shell技で何とかするんだ!

sakae@debian:/tmp$ cut -f9 -d';' red.csv | cut -c-3 | sort | uniq -c
      1 2.7
      8 2.8
     20 2.9
      6 3
     80 3.0
    234 3.1
    377 3.2
    449 3.3
    242 3.4
    127 3.5
     38 3.6
     12 3.7
      1 3.8
      2 3.9
      2 4.0
sakae@debian:/tmp$ cut -f9 -d';' white.csv | cut -c-3 | sort | uniq -c
      6 2.7
     64 2.8
    367 2.9
     74 3
    803 3.0
   1391 3.1
   1093 3.2
    664 3.3
    280 3.4
    106 3.5
     33 3.6
     13 3.7
      4 3.8

小数点以下2桁目を切り捨ての強引さを発揮。ph 3 と、pH 3.0X の揺れが有るんで、ちょいと 汚い統計データになっちゃったけど、まあ、これがunix流の解決方法。

sakae@debian:/tmp$ cut -f12 -d';' red.csv | sort | uniq -c
     10 3
     53 4
    681 5
    638 6
    199 7
     18 8
sakae@debian:/tmp$ cut -f12 -d';' white.csv | sort | uniq -c
     20 3
    163 4
   1457 5
   2198 6
    880 7
    175 8
      5 9

ついでに品質ランクの分布も見ておく。こういう風にランクと言うかクラスを上手に 学習するって、機械学習は苦手なの? 前回は余り良い結果が得られなかったけど。

scikit-learnに戻ってくる

という事で、svmにこだわる事なく、視野を広めてみるかな。

scikit-learn 0.18 チュートリアル 適切なモデルの選択

scikit-learn 0.18 チュートリアル scikit-learnによる機械学習の紹介

scikit-learn 0.18 User Guide 1.4 サポートベクターマシン

Scikit learnより グリッドサーチによるパラメータ最適化

再訪scikit-learn

scikit-leran on OpenBSD

この際だからLinuxのぬるま湯だけじゃなくて、BSD系にも入れてみよう。常用してるOpenBSDで やってみる。

scikit-learn 0.18.1を見ると、pipで入るよと書いてある。どのWebを検索しても同様。ならば、簡単々と思ってやって みたら、pipが途中でtimeoutしちゃう。時間を置いてからやってみても同様。 OpenBSDの秘密のセキュリティチェックに引っかかって、中止してくれたんですかね?

ならば、tar玉を落としてきてやってみれ。pipで玉を扱う方法を知らないので、取り合えず 展開して中を覗いてみたよ。Makefileが有ったんで、gmakeしたら、cythonが必要と抜かす。

pipでcythonを入れようとしたら、やっぱりtimeout。こうなるとOpenBSDの何処かがおかしいな。 先を急ぐので、tar玉から入れた。(結構時間がかかる)そして、scikitに戻ってgmakeしたら 無事にコンパイル出来た。続いてtestするように言われたけど、省略。

exampleが有ったので試してみると、scikitなんて入っていないと言われた。そうか、makeは コンパイルするだけなのねと合点承知の助。付近を見渡したら、python得意の setup.pyを発見。そうか、これを使えとな。

sudo python setup.py install

これで、再度cythonが長い時間をかけてコンパイル、そしてインストールが行われた。やれやれ ですよ。

examples/applications/svm_gui.py 面白いな。マウスの左か右ボタンをキャンバス上で 適当にクリックして点を置く。それから、3種の方法で評価をする。適当にやってみたら

bash-4.3# python svm_gui.py

==========
Libsvm GUI
==========

A simple graphical frontend for Libsvm mainly intended for didactic
purposes. You can create data points by point and click and visualize
the decision region induced by different kernels and parameter settings.

To create positive examples click the left mouse button; to create
negative examples click the right button.

If all examples are from the same class, it uses a one-class SVM.


fit the model (Linear)
Accuracy: 61.5384615385
fit the model (RBF)
Accuracy: 92.3076923077
fit the model (Poly)
Accuracy: 73.0769230769

同じデータでも、評価方法によって随分と差が出るものだな。

こうして、軽く動くのを確認。以前のやつを引っ張り出して、自分の土俵で動かしてみようと したら、pandasが入ってなかったので、手動で入れた。 numpyのconfigを確認しとく

In [2]: numpy.show_config()
openblas_info:
  NOT AVAILABLE
blas_info:
    library_dirs = ['/usr/local/lib']
    libraries = ['blas']
    language = f77
atlas_threads_info:
  NOT AVAILABLE
lapack_opt_info:
    library_dirs = ['/usr/local/lib']
    libraries = ['lapack', 'blas']
    define_macros = [('NO_ATLAS_INFO', 1)]
    language = f77
lapack_info:
    library_dirs = ['/usr/local/lib']
    libraries = ['lapack']
    language = f77

基本的なもので、出来上がっていた。intelさんにOpenBSDの支援を乞う。

import pandas as pd
from sklearn.neural_network import MLPClassifier
from sklearn import svm
from sklearn import preprocessing

def get_wine(file):
    a = pd.read_csv(file, delimiter=';')
    return a.iloc[:,:-1], a.iloc[:,-1]

def main():
    min_max_scaler = preprocessing.MinMaxScaler()
    X, Y = get_wine('red.csv')
    clf = svm.SVC(gamma=8, C=2)
#    clf = MLPClassifier(solver="sgd",random_state=0,max_iter=10000)
    clf.fit(min_max_scaler.fit_transform(X), Y)
    U, V = get_wine('red.csv')
    pred = clf.predict(min_max_scaler.fit_transform(U))
    print (clf.score(min_max_scaler.fit_transform(U), V))

if __name__ == "__main__":
    main()
In [11]: run -t wine.py
0.73153942428

IPython CPU timings (estimated):
  User   :       0.34 s.
  System :       0.25 s.
Wall time:       0.59 s.

In [12]: run -t wine.py
0.57634543179

IPython CPU timings (estimated):
  User   :       1.12 s.
  System :      10.70 s.
Wall time:      11.81 s.

svmとDNNの対決。これを見ると、svmは速い上手いという結論だな。

scikit-learnで糖尿病データの回帰分析をやってみた

sakae@debian:~/ML/sci$ ipython --matplotlib
In [2]: import pandas as pd

In [3]: import seaborn as sns

In [4]: a = pd.read_csv('red.csv', delimiter=';')

In [5]: a.iloc[1,:]
Out[5]:
fixed acidity            7.8000
volatile acidity         0.8800
citric acid              0.0000
residual sugar           2.6000
chlorides                0.0980
free sulfur dioxide     25.0000
total sulfur dioxide    67.0000
density                  0.9968
pH                       3.2000
sulphates                0.6800
alcohol                  9.8000
quality                  5.0000
Name: 1, dtype: float64

In [6]: sns.jointplot(x='quality', y='pH', data=a)
Out[6]: <seaborn.axisgrid.JointGrid at 0x7efc9fb642b0>

Seaborn: statistical data visualization

Pythonでのグラフ描画 seaborn

簡単に美しいグラフ描画ができるPythonライブラリSeaborn入門

grid-search

scikit-learn上でsvmを使うとなると(深層学習は火力が必要なので敬遠)やはり、パラメータ のチューニングをしたい。そんなの簡単、例が出てた。

Parameter estimation using grid search with cross-validation

それをアレンジするよ。下記は変更部分。フィーチャデータの全てで、一番大きいの、小さいのを 見つけてスケーリングしてたのを改め、列毎にスケーリングするようにしておいた。

import pandas as pd
from sklearn import preprocessing

def get_wine(file):
    a = pd.read_csv(file, delimiter=';')
    return a.iloc[:,:-1], a.iloc[:,-1]

X, y = get_wine('white.csv')
X_scaled = preprocessing.scale(X)

# Split the dataset in two equal parts
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.5, random_state=0)

# Set the parameters by cross-validation
tuned_parameters = [{'kernel': ['rbf'], 'gamma': [100,10,1,0.1,0.01],
                     'C': [1, 10, 100, 1000]}, ]
:

与えたファイルを半分に分け、一方をトレーニングに使用。最適なパラメータを見つけ出す。 もう半分のデータで実地試験と言う流れ。

# Tuning hyper-parameters for precision
{'kernel': 'rbf', 'C': 10, 'gamma': 10}
Detailed classification report:
             precision    recall  f1-score   support
          3       0.00      0.00      0.00        10
          4       1.00      0.08      0.15        88
          5       0.96      0.23      0.37       733
          6       0.50      0.99      0.66      1070
          7       1.00      0.25      0.40       461
          8       1.00      0.26      0.41        86
          9       0.00      0.00      0.00         1
avg / total       0.77      0.56      0.50      2449

# Tuning hyper-parameters for recall
{'kernel': 'rbf', 'C': 100, 'gamma': 0.1}
Detailed classification report:
             precision    recall  f1-score   support
          3       0.00      0.00      0.00        10
          4       0.18      0.18      0.18        88
          5       0.61      0.59      0.60       733
          6       0.58      0.68      0.63      1070
          7       0.57      0.44      0.50       461
          8       0.52      0.29      0.37        86
          9       0.00      0.00      0.00         1
avg / total       0.57      0.57      0.57      2449

precisionとrecallのどちらを優先させるかで、パラメータは変わってくるとな。 このprecisionとかの説明は、 適合率 precision 再現率 recall に有った。機械学習に限らず、ググル様とかも大事にする指標だな。

なお、表の左列の数字は、教師データの番号、一番右側のsupport列は、その個数。 資料が少ないと的中率も落ちるのね。

そこで、頻出するクラスを削ってみた。

sakae@debian:~/ML/sci$ egrep -v '(5|6)$' white.csv > z.csv
sakae@debian:~/ML/sci$ wc z.csv
 1244  1252 67289 z.csv
# Tuning hyper-parameters for recall
{'C': 100, 'gamma': 0.01, 'kernel': 'rbf'}
             precision    recall  f1-score   support
          3       0.00      0.00      0.00         6
          4       0.78      0.67      0.72        86
          7       0.79      0.97      0.87       437
          8       0.40      0.02      0.04        91
          9       0.00      0.00      0.00         2
avg / total       0.72      0.77      0.72       622

今度は、2つだけのクラス分類

# Tuning hyper-parameters for recall
{'C': 10, 'gamma': 0.1, 'kernel': 'rbf'}
             precision    recall  f1-score   support
          5       0.64      0.63      0.64       708
          6       0.77      0.78      0.77      1119
avg / total       0.72      0.72      0.72      1827

やはり、教師データが多い方が正確な予想が出来るって結論になるかな。

etc

大人になってからの再学習

filetype:pdf site:.ac.jp を加えて、ぐぐると良質な資料が得られるとな。