[Python] AI 05 手書き数字の認識 SVCによる予測

手書き数字の画像データ群を使ってSVCで学習させ、学習能力を検証しました。

digitsデータ1797個の内、1500個を学習、297個は検証に使いました。正解率は3の読み間違いが多いという結果でした。

ただdigits.dataというフラットなデータがあるにもかかわらず、何故わざわざ入れ子リストのdigits.imagesを平滑化するのかが分かりませんでした。

from sklearn import datasets
import sklearn.svm as svm
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report

# 手書き数字のデータをロード
digits = datasets.load_digits()

# 画像データを変数all_featuresに、画像内容(数字)を変数teacher_labelsに格納
all_features = digits.data
teacher_labels = digits.target

num_samples = len(all_features)

model = svm.SVC(gamma = 0.001)

# 学習用の学習データと教師データ(1500個)
train_features=all_features[ : 1500 ]
train_teacher_labels=teacher_labels[ : 1500 ]
print(len(train_features))

# 検証用の学習データと教師データ(297個)
test_feature=all_features[1500 : ]
test_teacher_labels=digits.target[1500 : ]
print(len(test_feature))

# 学習実行
model.fit(train_features,train_teacher_labels)

# 正解と数値予測データ
expected = test_teacher_labels
predicted = model.predict(test_feature)

print(f"分類機による分類結果 {model}: \n {classification_report(expected, predicted)} \n")

print(f"コンフュージョンマトリックス:\n {confusion_matrix(expected, predicted)}")
--------------------------------------------------

出力
--------------------------------------------------
1500
297
分類機による分類結果 SVC(gamma=0.001): 
               precision    recall  f1-score   support

           0       1.00      0.96      0.98        27
           1       0.97      1.00      0.98        31
           2       1.00      1.00      1.00        27
           3       0.96      0.77      0.85        30
           4       0.97      0.91      0.94        33
           5       0.91      1.00      0.95        30
           6       1.00      1.00      1.00        30
           7       0.97      1.00      0.98        30
           8       0.79      0.96      0.87        28
           9       1.00      0.94      0.97        31

    accuracy                           0.95       297
   macro avg       0.96      0.95      0.95       297
weighted avg       0.96      0.95      0.95       297
 

コンフュージョンマトリックス:
 [[26  0  0  0  1  0  0  0  0  0]
 [ 0 31  0  0  0  0  0  0  0  0]
 [ 0  0 27  0  0  0  0  0  0  0]
 [ 0  0  0 23  0  2  0  1  4  0]
 [ 0  0  0  0 30  0  0  0  3  0]
 [ 0  0  0  0  0 30  0  0  0  0]
 [ 0  0  0  0  0  0 30  0  0  0]
 [ 0  0  0  0  0  0  0 30  0  0]
 [ 0  1  0  0  0  0  0  0 27  0]
 [ 0  0  0  1  0  1  0  0  0 29]]

[Python] AI 04 手書き数字の認識 データセット3D描画

手書き数字画像のデータセットについて64因子を3因子に減らし、3D散布図を描画しました。

分かりやすくするためとは言え、elifが8つも連なるようなコードは書かない方がいいと思います(教本P232)。AI専業であっても最低限のコーディング力は必要でしょう。

from sklearn import decomposition
from sklearn import datasets
import matplotlib.pyplot as plt

def getcolor(num):
    color_list = ['red','orange','yellow','greenyellow','green','cyan','blue','navy','purple','black']
    return color_list[num]

# 手書き数字のデータをロード
digits = datasets.load_digits()

# 画像データを変数all_featuresに、画像内容(数字)を変数teacher_labelsに格納
all_features = digits.data
teacher_labels = digits.target

# 主成分分析(3因子に減らす)
pca = decomposition.PCA(n_components=3)

# 64因子のall_featuresを3因子のthree_featuresに変換
three_features = pca.fit_transform(all_features)

# figureオブジェクト作成サイズを800*800とする
fig = plt.figure(figsize=(8, 8))

# 1*1グリッドのサブプロット1に3D描画する
subfig = fig.add_subplot(111, projection = '3d')

# teacher_labelsに対応する色のリストを作成
colors = list(map(getcolor, teacher_labels))

# データの3Dカラー散布図描画設定
subfig.scatter(three_features[ : , 0 ], three_features[ : , 1 ], three_features[ : , 2 ], s=50, c=colors, alpha=0.3)

# グラフを表示
plt.show()

[Python] AI 03 手書き数字の認識

sklearnのdatesetsにあるdigitsという手書き数字の画像データを使ってデータの一部を表示しました。

今回はdigitsの最初の16個の画像データを4行*4列に並べました。

ここまで教本を読んで、スクリプトを書いた方のPython記述スキルが相当怪しいということが判明しました。あくまで対話式のPythonをある程度使えるAIの専門家なのでしょう。

なのでプログラミングの心得がある方は、スクリプトの意図を理解して自分でコードを書くのが賢明かと思います。

今回のスクリプトにしても意味不明な箇所があり、自分で整理すると13行が10行になりました(画像間の隙間調整は省略)。

from sklearn import datasets
import matplotlib.pyplot as plt

digits = datasets.load_digits()
ROWS_COUNT = 4
COLUMNS_COUNT = 4
DIGIT_GRAPH_COUNT = ROWS_COUNT * COLUMNS_COUNT

# figureオブジェクト作成サイズを1200*900に設定
fig = plt.figure(figsize=(12, 9)) 

for i in range(1, DIGIT_GRAPH_COUNT + 1):
    (fig.add_subplot(ROWS_COUNT, COLUMNS_COUNT, i)).imshow(digits.images[i],interpolation='bicubic', cmap='Set2')

plt.show()

[Python] AI 02 アヤメの分類 超平面作成

前回の続きです。

アヤメの花弁データ(3列目と4列目)をサポートベクターマシン(SVM)を使って超平面で分類できるようにしました。

手順としては、データを標準化してからSVMのインスタンスを生成してモデル学習させ散布図を作成します。最後に適当な花弁データを入力してアヤメのどの種に該当するのか判定させています。

私の教本ではその前にデータを交差検証するために学習データと検証データに分けて、検証後に標準化データを結合して超平面を作成しています。

本の構成のためでしょうが、教本の方法は少々荒っぽいかと思います。統計学をかじったことのある方でしたら理由は分かるでしょう。

import numpy as np
import matplotlib.pyplot as plt
from mlxtend.plotting import plot_decision_regions as pdr
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

def test():
    model = analize()
    test_data=np.array([[3.0,4.0]])
    print(test_data)
    test_result = model.predict(test_data)
    print(test_result)
    plt.show()

def analize():
    iris = datasets.load_iris()

    features = iris.data[:,[2,3]]
    print(features)
    labels = iris.target

    sc = StandardScaler()
    sc.fit(features)

    # データの標準化(中心を0にするための変換)
    features_std = sc.transform(features)
    print(features_std)

    # 線形SVMのインスタンスを生成
    model = SVC(kernel='linear', random_state=None)

    # モデル学習
    model.fit(features_std, labels)

    fig = plt.figure(figsize=(12,8))

    # 散布図関連設定
    scatter_kwargs = {'s': 300, 'edgecolor': 'white', 'alpha': 0.5}
    contourf_kwargs = {'alpha': 0.2}
    scatter_highlight_kwargs = {'s': 200, 'label': 'Test', 'alpha': 0.7}
    
    pdr(features_std, labels, clf=model, scatter_kwargs=scatter_kwargs,
                        contourf_kwargs=contourf_kwargs,
                        scatter_highlight_kwargs=scatter_highlight_kwargs)

    return model

if __name__ == "__main__":
    test()
--------------------------------------------------

出力(検証データと判定結果のみ)
--------------------------------------------------
[[3. 4.]]
[2]

[Python] AI 01 アヤメの分類

せっかくPythonを扱っているのですから、AIや機械学習についても一通り学ぶことにしました。まずは統計に関する知識の整理です。

有意差検定など統計の勉強でお世話になったアヤメのデータを使って主成分分析し、因子数を4から3に減らして3D散布図を作成しました。

選んだ教本ではJupyter Notebookを使った対話式Pythonですが、プログラムで書いていきます。

3000円を超える本なのにグラフが白黒なのが惜しいところです。

2021/10/1追記:グラフはGitHubからダウンロードしたipynbファイルにてカラーで見ることができました。

pip install -U scikit-learn
pip install matplotlib
import matplotlib.pyplot as plt
from sklearn import datasets
from mpl_toolkits.mplot3d import Axes3D
from sklearn.decomposition import PCA

iris = datasets.load_iris()
all_features = iris.data
teacher_labels = iris.target

fig = plt.figure(1,figsize=(12,9))
ax = Axes3D(fig,elev=-140,azim=100)

# 主成分分析(4→3)
reduced_features = PCA(n_components=3).fit_transform(all_features)

# 散布図作成
ax.scatter(reduced_features[:,0],reduced_features[:,1],reduced_features[:,2],c = teacher_labels,cmap = plt.cm.Set2,edgecolor='darkgray',s=200)
plt.show()

[C++] Eclipse内エディタのフォント設定

開発中のGUIアプリをJavaとPythonで書いています。処理速度的に不満はないのですが、さらにスキルアップするためC++を試してみることにしました。C++がひと段落したらJavaScript(Electron)での開発に着手の予定です。しばらく先になりそうです。

開発環境はEclipseです。過保護な環境ではありますが、開発環境構築で消耗したくないですから。と言いながら比較的簡単なEclipseでもHello Worldを表示させるだけで手間取ってしまいました。

いつもフォントサイズの設定箇所で迷ってしまうので、今後のために画像をアップしておきます。

[Java] Javaアセンブラ “Jasmin”

Javaアセンブラ “Jasmin”でアセンブラファイルをコンパイルするコマンドです。

java -jar jasmin.jar [Javaアセンブラファイル]

classファイルを逆アセンブラするコマンドは以下の通りです。

javap -c [classファイル]

Hello WorldをJavaアセンブラで書くとこんな感じになります(Jasminのexamplesから)。

.class public examples/HelloWorld
.super java/lang/Object

; standard initializer
.method public <init>()V
   aload_0
   invokenonvirtual java/lang/Object/<init>()V
   return
.end method

.method public static main([Ljava/lang/String;)V
   .limit stack 2

   ; push System.out onto the stack
   getstatic java/lang/System/out Ljava/io/PrintStream;

   ; push a string onto the stack
   ldc "Hello World!"

   ; call the PrintStream.println() method.
   invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V

   ; done
   return
.end method

JASMIN HOME PAGE

[Pascal] 01 Hello World

[macOS Catalina 10.15.7]

初めて学んだプログラミング言語はPascalでした。

今でもFree Pascalとして使われていると知り、少しいじってみることにしました。

最新バージョンは3.2.2でした。インストール先は/usr/local/bin/fpcです。

GUIアプリも作れるらしいです。Java&Pythonで製作中の競馬データベースアプリを移植できるだろうか。

program Hello_World (output) ;
begin
writeln('Hello World')
end.