AutoKeras Image Regressionを用いた画像解析サンプル(年齢判定)
AutoKerasの画像解析には・Image Classification
・Image Regression
の2つがあります。
Classificationは画像の分類で、よく見るMNISTの手書き数字が何であるかの判定に用いられています。
Regressionは直訳すると「回帰」で、どういった場面で使えるのかよくわかっていませんでした。
Image Regression(画像の回帰)
非常に参考になったのがこちらの記事です。
きゅうり画像で回帰問題を解いてみた
顔画像から年齢を予測
特に「顔画像から年齢」という用例が非常にしっくり来ました。
「犬、猫、馬のどれか」という問題ではなく、段階的に変化していく「年齢」や「サイズ」、「家の築年数」といった用途で使用できそうです。
AutoKerasでのサンプル
Image Regression
こちらのサンプルと、
顔画像から年齢を予測
こちらのサンプルを参考に、顔画像から年齢を判定するプログラムをAutoKerasを用いて作成してみます。
データはこちらから取得しました。
https://susanqq.github.io/UTKFace/
「Aligned&Cropped Faces」の「UTKFace.tar.gz」を使用します。
顔の画像が200x200ピクセルで切り出されたものが23,708ファイルあります。
ファイル名の先頭が年齢になっているので、ラベルとして使用します。
UTKFace.tar.gzを展開せずに中身の画像データを使用しました。
Python tar.gzファイルを解凍せずに中身の画像ファイルを読み込む
・sample.py
- import os
- import random
- import tarfile
- import numpy as np
- from PIL import Image
- # from sklearn.model_selection import train_test_split
- import tensorflow as tf
- import autokeras as ak
- train_images = []
- train_labels = []
- test_images = []
- test_labels = []
- with tarfile.open(name='UTKFace.tar.gz', mode='r') as tar:
- for info in tar.getmembers():
- if not info.isfile():
- continue
- # ファイル名から年齢を取得し、ラベルに採用
- # UTKFace/82_0_2_20170111210110290.jpg.chip.jpg -> 82
- print(info.name)
- age = os.path.basename(info.name).split('_')[0]
- # 内容をio.BufferedReaderで取り出し
- f = tar.extractfile(info)
- img = Image.open(f)
- # メモリに乗らないのでリサイズ
- img = img.resize((64, 64))
- # 学習用とテスト用に分割
- if random.randint(1, 10) <= 1:
- test_images.append(np.asarray(img))
- test_labels.append(int(age))
- img.save(os.path.join('test', os.path.basename(info.name)))
- else:
- train_images.append(np.asarray(img))
- train_labels.append(int(age))
- train_images = np.array(train_images,dtype=np.float32)
- train_labels = np.array(train_labels)
- test_images = np.array(test_images,dtype=np.float32)
- test_labels = np.array(test_labels)
- # メモリーエラーで強制終了したので、自前で分割
- # x_train, x_test, y_train, y_test = train_test_split(images, labels, test_size=0.1, shuffle = False)
- print(len(train_images))
- print(len(train_labels))
- print(len(test_images))
- print(len(test_labels))
- print(test_images.shape)
- reg = ak.ImageRegressor(
- overwrite=True,
- max_trials=3)
- reg.fit(train_images, train_labels, epochs=10)
- predicted_y = reg.predict(test_images)
- print(predicted_y)
- print(reg.evaluate(test_images, test_labels))
- # モデルの保存
- model = reg.export_model()
- model.save('model.h5')
200x200の画像そのままだとメモリにデータが乗らず、プログラムが強制終了しました。
64x64の画像にリサイズして解析に利用しています。
トレーニングとテストデータに分割するのによく用いられる「train_test_split」も
メモリ使用量が大きいため、自前で適当に分割しています。
テストに分類した画像は、後の確認用に保存しておきました。
出来上がったモデルの内容を見てみます。
- import tensorflow as tf
- # 出力したモデルの読み込み
- model = tf.keras.models.load_model('model.h5')
- # 内容出力
- print(model.summary())
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 64, 64, 3)] 0
_________________________________________________________________
resizing (Resizing) (None, 71, 71, 3) 0
_________________________________________________________________
xception (Functional) (None, 3, 3, 2048) 20861480
_________________________________________________________________
flatten (Flatten) (None, 18432) 0
_________________________________________________________________
regression_head_1 (Dense) (None, 1) 18433
=================================================================
Total params: 20,879,913
Trainable params: 20,825,385
Non-trainable params: 54,528
_________________________________________________________________
None
ポイントは最終的なアウトプットが(None, 1)になっている点でしょうか。
Classificationでは解析対象とした年齢分の出力となるはずです。
簡単な評価プログラム
出力したモデルを用いて年齢を判定してみます。
・check.py
- import os
- import tkinter as tk
- import numpy as np
- from PIL import Image, ImageTk
- import tensorflow as tf
- # 画像ファイルの読み込み
- face_files = [
- 'test/14_1_0_20170109204321875.jpg.chip.jpg',
- 'test/25_0_4_20170117193004258.jpg.chip.jpg',
- 'test/41_0_0_20170117140625076.jpg.chip.jpg',
- 'test/54_1_0_20170104235918548.jpg.chip.jpg',
- 'test/64_1_1_20170112233355207.jpg.chip.jpg',
- 'test/80_0_0_20170111205541652.jpg.chip.jpg'
- ]
- images = []
- ages = []
- train_images = []
- for face_file in face_files:
- img = Image.open(face_file)
- images.append(img)
- ages.append(os.path.basename(face_file).split('_')[0])
- train_images.append(np.array(img))
- train_images = np.array(train_images,dtype=np.float32)
- # 出力したモデルの読み込み
- model = tf.keras.models.load_model('model.h5')
- # 解析実行
- predicted_y = model.predict(train_images)
- print(predicted_y)
- # 結果を表示
- root = tk.Tk()
- root.geometry('500x200')
- root.title('face image')
- tk_images = []
- for i in range(len(face_files)):
- tk_images.append(ImageTk.PhotoImage(images[i]))
- for i in range(len(face_files)):
- label = tk.Label(root, image = tk_images[i])
- label.grid(column=i, row=0)
- label = tk.Label(root, text = 'real:%s' % (ages[i]))
- label.grid(column=i, row=1)
- label = tk.Label(root, text = 'predict:%.1f' % (predicted_y[i]))
- label.grid(column=i, row=2)
- root.mainloop()
そこまで学習に時間をかけていないモデルとしては、とんでもないハズレもなくそれなりの結果が出たのではないかと思います。
【参考URL】
きゅうり画像で回帰問題を解いてみた
顔画像から年齢を予測
https://susanqq.github.io/UTKFace/
Image Regression
- 関連記事
コメント