nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

mnist手書き数字画像データ学習モデル活用でjpeg画像を予測します [Python]

はじめに

手書き文字の認識をNeuralnetworkを用いて行います。 Kerasから手書き文字のデータをダウンロードして、そのデータを用いて、NeuralnetworkのTrainingを行い、その後に下記のnumber_fileをTest dataとして数字の認識を実施します。

コード例

from keras import backend as K
from keras.datasets import mnist
from keras.layers import Activation, Dense, Dropout
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
from keras.utils.np_utils import to_categorical
import numpy as np
from sklearn.metrics import classification_report, confusion_matrix

# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train, labels_train), (X_test, labels_test) = mnist.load_data()

# Traning setのラベルを確認
labels_train

# Training setの概要確認
print(X_train.shape, labels_train.shape, sep='\n')

# Test setの概要確認
print(X_test.shape, labels_test.shape, sep='\n')

# Training setの画像を表示
import matplotlib.pyplot as plt
%matplotlib inline

label_images = {label: [] for label in set(labels_train.tolist())}
for x, label in zip(X_train, labels_train):
    if all(len(images) >= 10 for images in label_images.values()):
        break
    if len(label_images[label]) >= 10:
        continue
    label_images[label].append(x)
    
for j, (label, images) in enumerate(label_images.items()):
    plt.subplot(10, 11, j * 11 + 1)
    plt.text(0.5, 0.5, label, ha='center', va='center')
    plt.axis('off')
    for i, image in enumerate(images):
        if i >= 10:
            continue
        plt.subplot(10, 11, j * 11 +  i + 2)
        plt.imshow(image, cmap='Greys_r')
        plt.axis('off')
plt.show()
    
del label_images

# Test dataの画像表示

label_images = {label: [] for label in set(labels_test.tolist())}
for x, label in zip(X_test, labels_test):
    if all(len(images) >= 10 for images in label_images.values()):
        break
    if len(label_images[label]) >= 10:
        continue
    label_images[label].append(x)
    
for j, (label, images) in enumerate(label_images.items()):
    plt.subplot(10, 11, j * 11 + 1)
    plt.text(0.5, 0.5, label, ha='center', va='center')
    plt.axis('off')
    for i, image in enumerate(images):
        if i >= 10:
            continue
        plt.subplot(10, 11, j * 11 +  i + 2)
        plt.imshow(image, cmap='Greys_r')
        plt.axis('off')
plt.show()
    
del label_images


##  画像データを特微ベクトルに変換します

# 各画像は行列なのでベクトルに変換→X_trainとX_testを作成
X_train = X_train.reshape(len(X_train), -1)
X_test = X_test.reshape(len(X_test), -1)

print(X_train.shape)
print(X_train[:5])

# ラベルをone-hotベクトル(値がひとつだけ1で他が0のベクトル)に変換→Y_trainとY_testを作成
Y_train = to_categorical(labels_train)
Y_test = to_categorical(labels_test)

print(Y_train)

print(Y_test)

##  Deep learningの実施

# モデルの準備
model = Sequential()
model.add(Dense(10, input_shape=(784,)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

# Trainingの実施
model.fit(X_train, Y_train, batch_size=128, nb_epoch=10, verbose=1)

# Test dataを用いてモデルを評価(accuracyを算出)
_, acc = model.evaluate(X_test, Y_test, verbose=0)
print('accuracy: {}'.format(acc))

# Classification_report関数で評価結果を表示
labels_pred = model.predict_classes(X_test, verbose=0)
print(confusion_matrix(labels_test, labels_pred))
print(classification_report(labels_test, labels_pred))

# Training後のモデルを用いてnumber_file中の画像の数字を予測

# 必要なモジュールの読み込み
import glob
import os
from PIL import Image

(x_train, y_train), (x_test, y_test) = mnist.load_data()

print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)

img_dir = 'number_file'
os.makedirs(img_dir, exist_ok=True)

# 全画像分を保存するようにする
for data, label in zip(x_test[:1000], y_test[:1000]):
    img = Image.fromarray(data)
    # グレースケール形式で保存する。
    img.save(os.path.join(img_dir,
             'gray_{}.png'.format(label)))

    # RGB 形式で保存する。
    img = img.convert('RGB')
    img.save(os.path.join(img_dir,
             'color_{}.png'.format(label)))

# フォルダ内の画像を読み込み、予測する。
for img_path in glob.glob(os.path.join(img_dir, '*.png')):
    # 画像を読み込む。
    img = Image.open(img_path)

    # 画像が RGB ならグレースケールに変換する。(28, 28, 3) -> (28, 28)
    if img.mode == 'RGB':
        img = img.convert("L")
    # 行列を1次元に変換する(28, 28) -> (1, 784) にする。
    data = np.array(img).reshape(1, -1)

    # データをモデルに入れて予測
    pred_y = model.predict_classes(data, verbose=0)
    print(img_path, pred_y)

主な出力イメージ

accuracy: 0.9061

[[ 961    0    2    3    0    3    8    1    2    0]
 [   0 1091   25    3    1    1    3    2    9    0]
 [   3    0  967    5   16    3    7    9   19    3]
 [   4    0   56  870    4   37    1    8   21    9]
 [   2    1    8    0  933    0    9    2    8   19]
 [  11    1   15   23   24  762   10    6   36    4]
 [  14    1   28    0   12   25  867    1   10    0]
 [   2    5   33    4   15    0    0  943    4   22]
 [   5    3   36   12   20   19    3   16  856    4]
 [   9    4    2    9  109   15    1   33   16  811]]
              precision    recall  f1-score   support

           0       0.95      0.98      0.97       980
           1       0.99      0.96      0.97      1135
           2       0.83      0.94      0.88      1032
           3       0.94      0.86      0.90      1010
           4       0.82      0.95      0.88       982
           5       0.88      0.85      0.87       892
           6       0.95      0.91      0.93       958
           7       0.92      0.92      0.92      1028
           8       0.87      0.88      0.88       974
           9       0.93      0.80      0.86      1009

   micro avg       0.91      0.91      0.91     10000
   macro avg       0.91      0.90      0.91     10000
weighted avg       0.91      0.91      0.91     10000

number_file\color_0.png [0]
number_file\color_1.png [1]
number_file\color_2.png [2]
number_file\color_3.png [3]
number_file\color_4.png [4]
number_file\color_5.png [5]
number_file\color_6.png [6]
number_file\color_7.png [7]
number_file\color_8.png [8]
number_file\color_9.png [9]
number_file\gray_0.png [0]
number_file\gray_1.png [1]
number_file\gray_2.png [2]
number_file\gray_3.png [3]
number_file\gray_4.png [4]
number_file\gray_5.png [5]
number_file\gray_6.png [6]
number_file\gray_7.png [7]
number_file\gray_8.png [8]
number_file\gray_9.png [9]

参考リンク

Python - mnist手書き数字画像データ学習モデル活用でjpeg画像の予測ができません。|teratail

深層学習 TensorFlow を MNIST で試す(2) | ecobioinfo.com – 環境・生物・情報処理 -

GraphViz'sで可視化する (Windows)

はじめに

Windowsで、GraphViz'sで可視化する場合は大変です。

環境

  • Python 3.6

手順

(1) Anaconda Promptで、以下のようにgraphvizとpydotをインストール

conda install graphviz

pip install pydotplus

(2) graphvizを公式ホームページからインストールしてください。

(3) システム環境パスを通すか、もしくは直接コードにパスを埋め込みます。(本例は後者)

u"""
    決定木系モデルを視覚化する。
    Graphviz を用いて、決定木のモデルを視覚化する。
    決定木だけでなく、ランダムフォレストなど木構造のモデルに適用できる。

"""

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection  import train_test_split
from sklearn.model_selection import cross_val_score

# モデルの木構造の視覚化に必要なパッケージ
from sklearn import tree
import pydotplus as pdp

import pandas as pd
import numpy as np

# パスを手動で追加します (システムの環境設定を通してもうまくいかなかったため、パスを仕方なく追加しました。)
# InvocationException: GraphViz's executables not found
import os     
os.environ["PATH"] += os.pathsep + "C:/Users/uv2ut/Anaconda3/Library/bin/graphviz"

iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)

print(df.head(5))
print(iris.target)
print(iris.target_names)
df['species'] = pd.Categorical.from_codes(iris.target, iris.target_names)
print(df.head(5))

# 学習データとテストデータを分ける

features = df.columns[:4]
label = df["species"]
print(features)
print(label)
print(df[features].head(5))
df_train, df_test, label_train, label_test = train_test_split(df[features], label)

clf = RandomForestClassifier(n_estimators=150)
clf.fit(df_train, label_train)
print("========================================================")
print("予測の精度")
print(clf.score(df_test, label_test))

# 試しに木の一つを視覚化する
estimators = clf.estimators_
file_name = "./tree_visualization.png"
dot_data = tree.export_graphviz(estimators[0], # 決定木オブジェクトを一つ指定する
                                out_file=None, # ファイルは介さずにGraphvizにdot言語データを渡すのでNone
                                filled=True, # Trueにすると、分岐の際にどちらのノードに多く分類されたのか色で示してくれる
                                rounded=True, # Trueにすると、ノードの角を丸く描画する。
                                feature_names=features, # これを指定しないとチャート上で特徴量の名前が表示されない
                                class_names=iris.target_names, # これを指定しないとチャート上で分類名が表示されない
                                special_characters=True # 特殊文字を扱えるようにする
                                )
graph = pdp.graph_from_dot_data(dot_data)

# 以下の命令で、ipynbと同じフォルダに、fileNameの画像ファイルが保存されます。
graph.write_png(file_name)
from IPython.display import Image
Image(graph.create_png())

表示イメージ

f:id:nprogram:20190404063519p:plain

リンク

あとがき

システム環境設定のパスが重要らしい

仮想環境を利用しているときは下記のgraphvizのフォルダパスをPathに追加します。

C:\Users\ユーザー名\Anaconda3\envs\仮想環境名\Library\bin\graphviz

仮想環境を利用していないときは下記のgraphvizのフォルダパスをPathに追加します。

C:\Users\ユーザー名\Anaconda3\Library\bin\graphviz

TensorFlow GPU導入 [Windows 10] [tensorflow-gpu : version 1.8.0] [GPU : GEFORCE RTX 2060]

本記事の前に

Windows環境のTensorFlow GPU導入方法は、

以下の国立研究開発法人 産業技術総合研究所 安全科学研究部門様の記事がとてもわかりやすいです。

WindowsでKerasを用いたDeep Learning開発環境を整備する | 産総研:安全科学研究部門– 持続可能な社会実現に向けた評価研究部門 | 産総研 AIST RISS

本記事について

Windows環境へのTensorFlow GPUに非常に苦労したため、記事にします。

この記事では、tensorflow-gpu : verseion 1.8.0を扱います。

最新のtensorflow-gpuバージョンを取り扱ったものではありません。

本記事は、以下のSamurai Blog様の2018年度版】TensorFlow 1.5のインストール方法を解説!【Windows 10】の情報を参考に作成しました。

【2019年度版】TensorFlow 1.5のインストール方法を解説!【Windows 10】 | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

注意事項

CUDA、cuDNN 、tensorflow-gpuのバージョンの組み合わせがとても重要です。正しい組み合わせでなければ、tensorflow-gpuが正常に動作しません。

詳細は、Qiitaの記事(NvidiaドライバとCUDAとcuDNNとTensorflow-gpuとPythonのバージョンの対応)をご確認ください。

NvidiaドライバとCUDAとcuDNNとTensorflow-gpuとPythonのバージョンの対応 - Qiita

Build from source on Windows  |  TensorFlow

構築環境

本記事では、TensorFlow GPU環境は、Anaconda3の仮想環境上に作成します。以下、環境情報です。

  • OS : Windows 10
  • GPU : GEFORCE RTX 2060 GAMING Z
  • tensorflow-gpu : verseion 1.8.0
  • CUDA : version 9.0
  • cuDNN : version 7.4
  • Python 3.6 (Python 3.7ではtensorflow-gpuが動きません) (Anaconda 3で仮想環境を作成するときに、Python versionを3.6に指定します)

手順

GPUのドライバーはインストール済みであることが前提条件です。

また、TensorFlow GPU環境は、Anaconda3の仮想環境上に作成します。

(1) まず、visual_studio_community_2015_with_update_3のインストールが必要です。CUDAのインストールに必要であるためです。(参考リンク参照)

ja_visual_studio_community_2015_with_update_3_x86_x64_web_installer_8922964.exe

(2) 次に、CUDAのインストールを行います。必ずベースファイルからインストールしてください。 (本例では、cuda_9.0.176_win10_network.exeがベースファイル)

ベースファイルインストール途中でエラーが発生しますが、GPUのドライバーを古いドライバーで上書きしようとしています。

GPUドライバーのインストールのみ、チェックを外せば問題ありません。(参考リンク参照)

その後、パッチを順番に4つインストールします。

  • cuda_9.0.176_win10_network.exe
  • C:\Users\uv2ut\Downloads\cuda_9.0.176.1_windows.exe
  • C:\Users\uv2ut\Downloads\cuda_9.0.176.2_windows.exe
  • C:\Users\uv2ut\Downloads\cuda_9.0.176.3_windows.exe
  • C:\Users\uv2ut\Downloads\cuda_9.0.176.4_windows.exe

(3) 次に、cuDNN (Version 7.4)をインストールします。参考リンク参照

  • cudnn-9.0-windows10-x64-v7.4.2.24.zip

(4) Anaconda Promptで、まず仮想環境を作成します。

conda create -n tensorflow-gpu python=3.6
activate tensorflow-gpu

次に、各モジュールをインストールします。

モジュールのバージョンに気を付けてください。 (特にtensorflow-gpuとkeras-gpu)

また、コマンドの実行順序も影響するため、以下の順に入力してください。

pip install --upgrade pip
conda install pandas matplotlib jupyter notebook scipy scikit-learn scikit-image h5py seaborn
pip install opencv-python
conda install tensorflow-gpu==1.8.0
conda install keras-gpu==2.1.6

動作確認

jupyter notebook上で確認するとよいと思います。

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))
sess.close()
b'Hello, TensorFlow!'

古いマザーボード(Z77X-UD3H)に新しいグラフィックボード(GEFORCE RTX-2060 GAMING Z )を搭載してみた

はじめに

高速なGPUが欲しかったので、古いマザーボード(Z77X-UD3H)に新しいグラフィックボード(GEFORCE RTX-2060 GAMING Z )を搭載してみました。

新しいグラフィックボードを起動するのに、一晩かかりましたので、展開します・・・。

手順

Z77などの70番台のマザーボードで最新のグラフィックボードを乗せようとすると、マザーボードとグラフィックボードとの間の相性問題がおきやすいらしいです。

私は、グラフィックボードをPCに接続すると、電源をいれても全く画面が移りませんでした・・・。なお、電源容量が足りていました。

私の解決方法は以下でできました。

(1) BIOSのアップデート

私は、以下のサイトを見ながら、Q-FlashによるUEFIアップデートを行いました。

GIGABYTE製マザーボードのUEFI(BIOS)アップデート

(2) BIOS画面でPCI ROM Priority の設定をEFI Compatible ROM→Legacy ROMへ変更しました。

グラボが認識できません。BIOS設定教えてください。 -当方のシステムは- ビデオカード・サウンドカード | 教えて!goo

マザーボード情報

f:id:nprogram:20190402075440p:plain

あとがき

最新のグラフィックボードを使用したい場合は、新しいマザーボードを使用したほうがトラブルは少ないと思います。

参考情報

以下、ツクモ福岡店の最新情報ブログからの情報

最新のグラフィックボードを増設しようとしているパソコンやマザーボードが2012年頃に購入している製品の場合は注意が必要です。 ある世代以降のグラフィックボードが使用できない可能性があります。

具体的には下記の様な症状が発生します。 「画面が全く映らない」 「BIOSメニューには入れるがOSの起動には至らない」 「電源を入れ、メーカーのロゴが表示されたまま先に進まない」 「画面左上でアンダーバーが点滅表示されたまま先に進まない」

この問題はマザーボードとグラフィックボードの双方のBIOSに起因しています。 「ファストブート」や「セキュアブート」といった新しい機能に対応していくために、グラフィックボードのBIOSが「UEFI」方式へと切り替わって移行が進んでいます。 このUEFI方式のBIOSを搭載したグラフィックボードと、2012年頃に販売されていたパソコンやマザーボードとの組み合わせで多数の不具合報告が上がっています。

▼特に症例報告が多いマザーボード(チップセット) インテルP67・Z68などの60番台および、H77・Z77・X79など70番台チップセットを搭載しているマザーボード

そうだ、グラフィックボードを増設しよう! でも、その前に... - ツクモ福岡店 最新情報

単純パーセプトロンの学習

はじめに

単純パーセプトロンを学習していきます。

パーセプトロンで論理演算のANDを実装することを考えます。 x1,x2:入力層 y:出力層 w1,w2:入力層と出力層のユニット(ニューロン)の結合の強さを表す係数 (結合係数) b:バイアス θ:ステップ関数

ちなみにここでいうバイアスというのは偏りのことです

f:id:nprogram:20190331233357p:plain

このネットワークは,2入力,1出力です。

いつも1が入力されてくるユニットを付け加えて3入力1出力のネットワークとみなすとプログラムしやすくなります。

その場合、以下のような図になります。

f:id:nprogram:20190331233404p:plain

次に、ステップ関数を定義します。

ステップ関数とは、入力が0を超えたら1を出力し、それ以外は0を出力する関数です。

def step(x):
    if x > 0 :
        return 1
    else :
        return 0


def And(x1, x2):
    x = np.array([1, x1, x2])
    
    # 結合係数 w1 = 0.5 w2 = 0.5 バイアス b = -0.7
    b = -0.7
    
    w = np.array([b, 0.5, 0.5])
    
    # 以下は「tmp = np.sum(x * w)」と同一
    tmp = np.sum(np.dot(x, w))
    
    return step(tmp)


print(And(0,0))
print(And(1,0))
print(And(0,1))
print(And(1,1))
0
0
0
1

今度は学習によって結合係数とバイアスを求めます

今はANDになるように、結合係数(w1,w2)やバイアス(b)は手動で与えましたが、学習によって決めます。

def step(x):
    if x > 0 :
        return 1
    else :
        return 0


# 各点での学習を50回繰り返す
epoch = 50

# 学習の進み方を調節するパラメータ
eta = 0.1

# 係数の初期設定 (b, w1, w2)
w = np.array([0.0, 0.0, 0.0])

print(f"w = {type(w)}")

# 1つ前のステップでの係数を入れておくための変数
w_prev = w

# 学習の書くステップでの係数を追加していくためのnumpy配列
ws = w

# 学習データ
x_train = [[1,0,0], [1,0,1], [1,1,0], [1,1,1]]

# 教師ラベル
y_train = [0, 0, 0, 1]

for i in range(epoch):
    for x, y in zip(x_train, y_train):
        output = step(np.sum(w*x))
        
        # b, w1, w2の係数を決めます
        for j in range(len(w)):
            w[j] = w[j] + (y-output) * x[j] * eta
        
    # 各ステップでの係数を追加したnumpy配列を作る
    ws = np.append(ws, w)
    
    # print(w)
    # 1つ前のステップの係数を新しく求められた係数に置き換える
    w_prev = w

# 各ステップの係数を貯めたwvecsは1次元のnumpy配列にしていたので
# 各ステップ毎の多次元配列になるように整形する
ws = ws.reshape(-1,3)

print(ws)
[[ 0.1  0.1  0.1]
 [ 0.1  0.1  0.1]
 [ 0.   0.2  0.1]
 [-0.1  0.2  0.1]
 [-0.1  0.2  0.2]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]
 [-0.2  0.2  0.1]]

上記の学習で求めたバイアス、結合係数をAndの演算結果を求める式に適用します。

def And2(x1, x2):
    x = np.array([1, x1, x2])
    
    # バイアス b = -0.2
    # 結合係数 w1 = 0.2
    # 結合係数 w2 = 0.1
    b = -0.2
    w1 = 0.2
    w2 = 0.1
    
    w = np.array([b, w1, w2])
    
    # 以下は「tmp = np.sum(x * w)」と同一
    tmp = np.sum(np.dot(x, w))
    
    return step(tmp)


print(And2(0,0))
print(And2(1,0))
print(And2(0,1))
print(And2(1,1))
0
0
0
1

参考リンク

ディープラーニング学習

はじめに

ディープラーニング学習に役立ちそうなページをまとめます。