Python(機械学習)

機械学習とは、コンピューターに大量のデータを入力して、そのデータを解析し、そのデータから有用な規則やルールを抽出する手法のことです。
機械学習でできることを大まかに言うと「分類」「予測」「ルール抽出」です。

機械学習ライブラリ
  • TensorFlow
    https://www.tensorflow.org/
    Googleがオープンソースで公開した機械学習・深層学習・ニューラルネットワークなどのためのライブラリ。
    柔軟で汎用性があり、高いパフォーマンス、スケーラビリティが特徴
  • scikit-learn
    https://scikit-learn.org/stable/
    分類・回帰・クラスタリング・次元削減など、機械学習でよく使われる様々なアルゴリズムをサポート
  • Caffe
    https://caffe.berkeleyvision.org/
    C++で実装されており、高速な計算処理が可能な深層学習ライブラリ。
    GPUを利用した高速な演算が可能

他にも「Pylearn2」「Theano」「chainer」「PyML」などがある。

Scikit learnではじめる機械学習

  • 定義済み学習データを利用
# Scikit learnのサンプル学習データを取り込む
from sklearn import datasets

# 手書き数字データを読み込む
digits = datasets.load_digits()
digits.images.shape # (1797,8,8) 手書きの数字データが1797件

# 0番目のデータ-どの数字か
digits.target[0]

# 0番目のピクセルデータ
digits.images[0]
targetプロパティ
どの数字かを表すラベル情報のリスト
imagesプロパティ
ピクセルデータ(グレースケールの8x8ピクセル 16階調 0:薄い⇔15:濃い)
# Scikit learnのサンプル学習データを取り込む
from sklearn import datasets

# 描画のためにmatplotlibモジュールを取り込む
from matplotlib import pyplot as plt, cm

# 手書き数字データを読み込む
digits = datasets.load_digits()
data = digits.images[0]

# 描画
plt.imshow(data.reshape(8,8),cmap=cm.gray_r,interpolation="nearest")
plt.show()
matplotlibモジュール
データの描画

手書き数字認識

  • SVMアルゴリズムを利用して機械学習

    precision:精度、recall:再現率(実際に正解した割合)、fl-score:精度と再現率の調和平均、support:正解ラベルのデータ数
    precisionとrecallの違いは計算方法の違い
    どちらも予測が正しいことの指標
    モデルの判定結果が真かつ実際に正しい値を判定:True Positive(TP) 誤り:False Positive(FP)
    モデルの判定結果が偽かつ実際の値が真(予測と違う値):False Negative(TN) 実際の値も偽:True Negative(TN)
    precision(適合率)の計算
    TP / (TP + FP)
    recall(再現率)の計算
    TP / (TP + FN)
    実際の値が真 実際の値が偽
    判定結果が真 True Positive(TP) False Positive(FP)
    判定結果が偽 False Negative(TN) True Negative(TN)
from sklearn import datasets,svm, metrics
from sklearn.model_selection import train_test_split

# 手書き数字データを読み込む
digits = datasets.load_digits()

# 訓練用データとテスト用データに分ける
data_train, data_test, label_train, label_test = \
    train_test_split(digits.data, digits.target)

# SVMアルゴリズムを利用してモデルを構築する
clf = svm.SVC(gamma=0.001)
clf.fit(data_train,label_train)

# テストデータでの分析結果予測してみる
predict = clf.predict(data_test)

# 結果を表示する
ac_score = metrics.accuracy_score(label_test,predict)
cl_report = metrics.classification_report(label_test,predict)
print("分類器の情報=",clf)
print("正解率=",ac_score)
print("レポート=\n",cl_report)
train_test_split(digits.data, digits.target)
指定されたデータをランダムに訓練用とテスト用のデータに分ける。
手書き画像データ(digits.data)とラベルデータ(digits.target)を入力し、訓練用とテスト用のデータとラベルを出力
svm.SVC(gamma=0.001)
SVMアルゴリズムのSVCクラスを用いて分類。引数にパラメータを指定
SVMには、SVC/LinearSVC/NuSVCなどの種類があり、SVCは標準的実装。LinearSVCは線形カーネルに特化し、高速に計算ができる。種類によって実行速度や判定精度が変わる
引数のパラメータ: ガンマ値(gamma=) ソフトマージンのコストパラメータを表す(C)など指定できる
clf.fit(data_train,label_train)
fit()メソッドの第一引数は訓練データの本体、第二引数は訓練データに対するラベルを指定して学習させる。
clf.predict(data_test)
predict()メソッドで学習済みモデルを元に、テストデータの分類を予測する。

[SVC(gamma=0.001)の実行結果]

[LinearSVC()の実行結果]

手書き数字の画像を認識

  • コマンドラインで手書き数字の画像ファイルを指定すると、画像内に書かれている数字を認識するプログラム。
import os, sys, math
from sklearn import datasets, svm
from sklearn.externals import joblib

# モデルデータファイル名
DIGITS_PKL = "digit-clf.pkl"

# 予測モデルを作成する
def train_digits():
    # 手書き数字データを読み込む
    digits = datasets.load_digits()
    # 訓練する
    data_train = digits.data
    label_train = digits.target
    clf = svm.SVC(gamma=0.001)
    clf.fit(data_train,label_train)
    # 予測モデルを保存
    joblib.dump(clf,DIGITS_PKL)
    print("予測モデルを保存しました=",DIGITS_PKL)
    return clf

# データから数字を予測する
def predict_digits(data):
    # モデルファイルを読み込む
    if not os.path.exists(DIGITS_PKL):
        clf = train_digits() # モデルがなけれは生成
    clf = joblib.load(DIGITS_PKL)
    # 予測
    n = clf.predict([data])
    print("判定結果=", n)

# 手書き数字画像を8x8グレイスケールのデータ配列に変換
def image_to_data(imagefile):
    import numpy as np
    from PIL import Image
    image = Image.open(imagefile).convert('L')
    image = image.resize((8,8),Image.ANTIALIAS)
    img = np.asarray(image, dtype=float)
    img = np.floor(16 - 16 * (img / 256)) # 行列演算
    # 変換後の画像を表示
    import matplotlib.pyplot as plt
    plt.imshow(img)
    plt.gray()
    plt.show()

    img = img.flatten()
    print(img)
    return img

def main():
    # コマンドライン引数を得る
    if len(sys.argv) <= 1:
        print("USAGE:")
        print("python3 predict_digit.py imagefile")
        return
    imagefile = sys.argv[1]
    data = image_to_data(imagefile)
    predict_digits(data)

if __name__ == "__main__":
    main()    
joblib.dump(clf,DIGITS_PKL)
Scikit learnのサンプル手書きデータから生成した予測モデルをファイルに保存する。

(保存先はカレントディレクトリ Linuxコマンド【 pwd 】現在の作業ディレクトリを表示 )
Scikit learnのサンプル手書きデータ形式(numpy.ndarray型)
画像の左上から右下へ8x8ピクセル(合計64個の実数を持つ)型に、画像ファイルを変換する必要がある。
<PILモジュール>
画像ファイルの読み込みに利用。
Image.open(imagefile).convert('L')
PILモジュールのImage.open(imagefile)メソッドで画像を読み込む。
convert('L')メソッドで画像をグレースケールに変換する。
image.resize((8,8),Image.ANTIALIAS)
画像を8x8ピクセルにリサイズする。
<numpyモジュール>
数値計算を効率的に行うための拡張モジュール。
Pythonのリストデータは、大量のデータを扱う際には非効率だが、numpyでは、より効率的な処理を行うためのものが用意されている。
np.asarray(image, dtype=float)
np.asarray(image, dtype=float)メソッドで変換した画像データをnumpy.ndarray型に変換する。
多次元配列(ndarray)に対する行列計算
Scikit learnのサンプル手書きデータは、0(薄い)〜15(濃い)の16段階データ。
変換したグレースケールの画像データは、0(黒)〜255(白)の256段階データなので、1つ1つのピクセルに対して計算処理を行う。
img = np.floor(16 - 16 * (img / 256))
img変数に対して1回だけ計算しているように見えるが、imgは多次元配列(ndarray)なので、全要素に対して演算が行われる。
手書き数字の画像
変換した画像
手書き数字の画像と8X8ピクセル変換画像

[コマンドラインでのプログラム実行結果]

手書き数字の画像
変換した画像
手書き数字の画像と8X8ピクセル変換画像

[コマンドラインでのプログラム実行結果]

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください