ニューラルネットワークで顔を学習

ゆうき( @BASEBALLY15 )です^^

第1章では,カスケードファイルを使って,顔を判断し画像として保存しましたね.

そうですね^^

第2章の前半では,保存した画像を学習用とテスト用に分けて,
畳み込みニューラルネットワークで学習させたいと思います^^

第1章から第3章までの構成要素

ニューラルネットワークによる顔認識の構成要素
(PowerPointで作成)

今回は,第2章の『face_generation_aug.py』と『face_cnn.py』を作っていきたいと思います.

face_generation_aug.py』 では,第1章で保存した画像を学習用とテスト用に分けます.

そして, 『face_cnn.py』 では,分けた画像を,ニューラルネットワークによって判定し.

その結果をファイルに保存します.

畳み込みニューラルネットワークによる画像判定の流れ
(PowerPointで作成)

それでは,コードを見ていきましょう^^

まずは, 『face_generation_aug.py』 を作ります.

画像を学習用とテスト用に分けよう!

ファイル名: face_generation_aug.py

ライブラリ

#画像に処理をするためのライブラリ
from PIL import Image

#ディレクトリやファイルに処理をするためのライブラリ
import os, glob

import numpy as np

#データを学習用とテスト用に分けるためのライブラリ
from sklearn import model_selection

コード

def generate():

    #-------------------------------------------------------------

    #クラスを作成
    face_classes = ["my_face", "other_face", "other_face2"]
    
    #クラスの数(=3)
    num_face_classes = len(face_classes)
    
    #画像のサイズを指定
    image_size = 50
    
    #使うデータ数(コマンドプロンプト上で指定する)
    use_count = int(input("使うデータ数="))
    
    #半分のデータをテストデータに使う(全データの3割)
    test_data_count = int(use_count*0.3 )

    #-------------------------------------------------------------

    ##画像の読み込みを行う##
    #画像データの配列を用意
    X_train = []
    
    X_test = []
    
    #ラベルのデータを用意
    Y_train = []
    
    Y_test = []

    #-------------------------------------------------------------

    #画像データとラベルデータに分割
    for index, classlabel in enumerate(face_classes):
        
        #画像のディレクトリ名
        photo_dir = "./" + classlabel
        
        #画像を一枚ずつ取得
        files = glob.glob(photo_dir + "/*.jpg")
        
        #写真をRGB化し,変更を加える
        for i, file in enumerate(files):
            
            #もし,100枚以上なら,終了
            if i >= use_count: break
        
            #画像を開く
            image = Image.open(file)
            
            #RGB化する
            image = image.convert("RGB")
            
            #サイズを50×50にリサイズする
            image = image.resize((image_size, image_size))
            
            #画像データを数値に変換する
            data = np.asarray(image)

    #-------------------------------------------------------------

            #もし,枚数がtest_data_countまでなら
            if i < test_data_count:
                #テストデータに加える
                X_test.append(data)
                
                Y_test.append(index)
                
            #それ以外なら
            else:
                
                #学習用の画像に変更を加える
                for face_angle in range(-5, 5, 5):
                   
                    #回転(-5度から5度までを5度ずつ)
                    img_roll = image.rotate(face_angle)
                    
                    #画像データを数値に変換する
                    data = np.asarray(img_roll)
                    
                    #学習用のリストに追加
                    X_train.append(data)
                    
                    Y_train.append(index)
                    
                    #反転(左右)
                    img_rurn1 = img_roll.transpose(Image.FLIP_LEFT_RIGHT)
                    
                    #画像データを数値に変換する
                    data = np.asarray(img_rurn1)
                    
                    #学習用のリストに追加
                    X_train.append(data)
                    
                    Y_train.append(index)

    #-------------------------------------------------------------
                    
    #XとYをnumpy形式に変換する(TensorFlowでは,numpy形式の方が扱いやすい)
    X_train = np.array(X_train)
    
    X_test = np.array(X_test)
    
    Y_train = np.array(Y_train)
    
    Y_test = np.array(Y_test)

    #-------------------------------------------------------------

    #学習用とテスト用のデータをまとめておく
    xy_box = (X_train, X_test, Y_train, Y_test)
    
    #Numpy形式でファイルを保存しておく
    np.save("./face.npy", xy_box)

このコードを書くと,このように『face.npy』というファイルが作られます.

学習用のテスト用を分けたファイル

そして,このファイルを使って,ニューラルネットワークで画像の判定を行っていきたいと思います.

畳み込みニューラルネットワークで画像を判定してみよう!

ファイル名: face_cnn.py

ライブラリ

import keras

#ニューラルネットワークのモデルを定義するためのライブラリ
from keras.models import Sequential

#畳み込みの処理やプーリングの処理をするためのライブラリ
from keras.layers import Conv2D, MaxPooling2D

#Activationは活性化関数,Dropoutはドロップアウト処理,
#Flattenはデータを1次元に変換,Denseは全結合
from keras.layers import Activation, Dropout, Flatten, Dense

#0と1に分割するために使う
from keras.utils import np_utils

import numpy as np

コード

まずは,クラスと画像のサイズを決めます.

クラスを作成し,画像サイズを決めよう!

#クラスを作成
face_classes = ["my_face", "other_face", "other_face2"]

#クラスの数(=3)
num_face_classes = len(face_classes)

#画像のサイズを指定
image_size = 50

そして,メインとなる関数を作ります.

メインとなる関数を作ろう!

###メインの関数###
def cnn_main():
       
    #ファイルからデータの配列に読み込む
    X_train, X_test, Y_train, Y_test = np.load("./face.npy", allow_pickle=True)
    
    #読み込んだデータの正規化
    X_train = X_train.astype("float")/256
    
    X_test = X_test.astype("float")/256
    
    #ラベルを1と0に分ける(One-Hotベクトル化)
    Y_train = np_utils.to_categorical(Y_train, num_face_classes)
    
    Y_test = np_utils.to_categorical(Y_test, num_face_classes)
    
    
    #学習用とテスト用の関数を持ってくる
    model = train_model(X_train, Y_train)
    
    evaluate_model(model, X_test, Y_test)

次に,学習用の関数を用意します.

※畳み込みニューラルネットワークの肝となる部分です!

畳み込みニューラルネットワークの関数を作ろう!

##学習用の関数を用意する##
def train_model(X, Y):
    
    #------------------------------------------------

    model = Sequential()
        
    model.add(Conv2D(32, 
                     kernel_size=(3,3), 
                     padding="same",
                     input_shape=X.shape[1:]))
    
    #マイナスの値を除去
    model.add(Activation("relu"))
    
    #------------------------------------------------ 
    
    model.add(Conv2D(32, 
                     kernel_size=(3,3)))
    
    #0以下を除去(活性化関数)
    model.add(Activation("relu"))
    
    #2×2の範囲で,最大の値を取得
    model.add(MaxPooling2D(pool_size=(2,2))) 
    
    #過学習の抑制(ランダムでニューロンを無効化)
    #偏ったニューロンに依存しないため
    #25%無効化
    model.add(Dropout(rate=0.25))
    
    #------------------------------------------------
    
    model.add(Conv2D(64, 
                     kernel_size=(3,3), 
                     padding="same"))
    
    model.add(Activation("relu"))
    
    #------------------------------------------------
    
    model.add(Conv2D(64, 
                     kernel_size=(3,3)))
    
    model.add(Activation("relu"))
    
    model.add(MaxPooling2D(pool_size=(2,2)))
    
    model.add(Dropout(0.25))
    
    #------------------------------------------------
    
    model.add(Flatten())
    
    model.add(Dense(512))
    
    model.add(Activation("relu"))
    
    model.add(Dropout(0.5))
    
    model.add(Dense(num_face_classes))
    
    model.add(Activation("softmax"))
     
    #------------------------------------------------
   
    #オプティマイザーを作成
    opt = keras.optimizers.RMSprop(learning_rate=0.0001, 
                                   decay=1e-6)
    
    #コンパイル
    model.compile(loss="categorical_crossentropy", 
                  optimizer=opt, 
                  metrics=["accuracy"])
    
    #学習
    model.fit(X, Y, batch_size=32, epochs=20)
    
    #モデルの保存
    model.save("./face_cnn.h5")
    
    #modelを結果として返す
    return model

そして,テスト用の関数を用意します.

テスト用の関数を作ろう!

###テスト用の関数を用意する###
def evaluate_model(model, X, Y):
    
    scores = model.evaluate(X, Y, verbose=1)
    
    print("Test Loss:", scores[0])
    
    print("Test Accuracy:", scores[1])

最後に,Anaconda Peompt上で,実行するために以下のコードを書いておきます.

#cnn_data()関数をコマンドプロンプト上で呼び出す
if __name__ == "__main__":

    cnn_main()

Anaconda Prompt上で実行してみよう!

Anaconda Promptを開き,以下の文字を書きます.

  • activate tf140
  • cd Desktop
  • cd face_cnn.pyがあるディレクトリ名
  • python face_cnn.py

これを実行すると,ニューラルネットワークによって,画像の判定を行ってくれます.

そして,このようにファイルが作られます.

畳み込みニューラルネットワークによって判定した結果

(※だいたい10分から20分くらいかかります.)

終わりに

今回は,画像を学習用とテスト用に分けて,

畳み込みニューラルネットワークによって,判定を行いました.

次回(第2章 後半)では,畳み込みニューラルネットワークによって判定した結果を使って,

自分の顔や他人の顔の画像を判定したいと思います.

それでは・・・

Q &A

コメントを残す

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

CAPTCHA