目次
- はじめに
- 本記事の概要
- 作成したプログラム
- Googleドライブから画像を読み込めるようにする
- モジュールのインポート
- ハイパーパラメータの設定
- 乱数を固定する
- 画像を読み込む
- 画像を加工する
- 正解ラベルを付与する
- データを結合しランダムに並び替える
- データをTensorflowの学習に適した形に変更する
- モデルの学習をし、エポックごとの予測精度を取得します
- 予測精度をグラフで可視化する
- おわりに
- 参考にしたサイト
1,はじめに
※このブログはAidemy Premiumのカリキュラムの一環で、受講修了条件を満たすために公開しています。
Aidemyの「データ分析講座」で学習した成果を、本ブログに投稿させていただきます。
2,本記事の概要
本記事では、データセットに kaggle の「Cat and Dog」、モデルとして Tensorflowを使用して、犬と猫の画像判定をするモデルを作成します。
使用するデータセット「Cat and Dog」には、犬と猫の画像が大量に格納されていますが、今回は訓練データから1000枚ずつ、テストデータから100枚ずつの計2200枚をランダムに選択して使用します。
また、使用する画像は 100x100 の大きさに統一し、グレースケールを施します。
Tensorflowのバージョンは「2.15.0」を使用しています。
※以下を実行して確認できます。
import tensorflow as tf
print(tf.__version__)
3,作成したプログラム
3-1,Googleドライブから画像を読み込めるようにする
まずはGoogleドライブから画像を読み込めるようにします。
以下のURLから、Cat and Dog のテストデータと訓練データをダウンロードします。
https://www.kaggle.com/datasets/tongpython/cat-and-dog
ダウンロードしたzipファイルを展開します。
私の場合は、マイドライブに「/Aidemy/dataset/」フォルダを作成し、その下に展開しました。
以上が終わればコーディングに移ります。
以下を実行して、Googleドライブのデータにアクセス出来るようにします。
from google.colab import drive
drive.mount('/content/drive')
3-2,モジュールのインポート
必要なモジュールをインポートします。
# ファイルを扱うためのモジュール
import os
# 画像を加工するためのモジュール
import cv2
# 配列を扱うためのモジュール
import numpy as np
# グラフや画像を描画するためのモジュール
import matplotlib.pyplot as plt
# 配列をランダムに並び替えるためのモジュール
import random
# Tensorflowのモデル
import tensorflow as tf
# ラベルをOne-hot表現にするための関数
from tensorflow.keras.utils import to_categorical
# Tensorflowにレイヤーを追加するためのモジュール
from tensorflow.keras.layers import Dense, Activation, Dropout
3-3,ハイパーパラメータの設定
以降で使用するパラメータを設定します。
# 乱数のシード値
random_seed = 0
# 訓練データの数(犬猫それぞれ1000枚)
train_dataset_num = 1000
# テストデータの数(犬猫それぞれ100枚)
test_dataset_num = 100
# 画像データのサイズ(画像データの縦幅・横幅は同じにします)
img_size = 100
# Tensorflow の1エポックで使用する画像データの数
batch_size = 64
# Tensorflow の学習回数
epochs = 5
3-4,乱数を固定する
再現性を担保するために乱数を固定します。
# Python固有の乱数シードの固定
random.seed(random_seed)
# Numpyの乱数シードの固定
np.random.seed(random_seed)
# Tensorflowの乱数シードの固定
tf.random.set_seed(random_seed)
3-5,画像を読み込む
Gドライブにダウンロードしたデータを読み込みます。
また、読み込んだデータから使用するデータをランダムに取得します。
# 画像が格納されているパスを作成します
# 画像の格納場所に合わせて変更してください
train_dog_folder_path = "/content/drive/MyDrive/Aidemy/dataset/training_set/dogs/"
train_cat_folder_path = "/content/drive/MyDrive/Aidemy/dataset/training_set/cats/"
test_dog_folder_path = "/content/drive/MyDrive/Aidemy/dataset/test_set/dogs/"
test_cat_folder_path = "/content/drive/MyDrive/Aidemy/dataset/test_set/cats/"
# folder_path に格納されているファイル名一覧を取得します
train_dog_datalist = os.listdir(train_dog_folder_path)
train_cat_datalist = os.listdir(train_cat_folder_path)
test_dog_datalist = os.listdir(test_dog_folder_path)
test_cat_datalist = os.listdir(test_cat_folder_path)
# ファイル名からランダムにデータを選択します
train_dog_image_filename = random.sample(train_dog_datalist, train_dataset_num)
train_cat_image_filename = random.sample(train_cat_datalist, train_dataset_num)
test_dog_image_filename = random.sample(test_dog_datalist, test_dataset_num)
test_cat_image_filename = random.sample(test_cat_datalist, test_dataset_num)
3-6,画像を加工する
取得したデータに対して、
・リサイズ
・グレースケール
を施します
※このコードの完了には時間がかかります。
# 加工後のデータを格納するための変数を定義します
train_dog_imgset = []
train_cat_imgset = []
test_dog_imgset = []
test_cat_imgset = []
# データを加工するための関数
def get_proccesing_imgset_from_filename_list(folder_path, filename_list):
result_array = []
for filename in filename_list:
img = cv2.imread(folder_path + filename)
img = cv2.resize(img, (img_size, img_size))
img = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2GRAY)
result_array.append(img)
return result_array
# 加工したデータを変数に格納します
train_dog_imgset = get_proccesing_imgset_from_filename_list(train_dog_folder_path, train_dog_image_filename)
train_cat_imgset = get_proccesing_imgset_from_filename_list(train_cat_folder_path, train_cat_image_filename)
test_dog_imgset = get_proccesing_imgset_from_filename_list(test_dog_folder_path, test_dog_image_filename)
test_cat_imgset = get_proccesing_imgset_from_filename_list(test_cat_folder_path, test_cat_image_filename)
3-7,正解ラベルを付与する
今回は犬のラベルを0、猫のラベルを1として付与します。
train_dog_label = [0]*len(train_dog_imgset)
train_cat_label = [1]*len(train_cat_imgset)
test_dog_label = [0]*len(test_dog_imgset)
test_cat_label = [1]*len(test_cat_imgset)
3-8,データを結合しランダムに並び替える
学習の偏りが生じないようにするため、データをランダムに並び替えます。
また、データとそれに対応するラベルを同様に並び替える必要があります。
そのため、zip関数でデータとラベルを対応付けたのち並び替えを行います。
# データとラベルを結合します
train_imgset = train_dog_imgset + train_cat_imgset
train_label = train_dog_label + train_cat_label
test_imgset = test_dog_imgset + test_cat_imgset
test_label = test_dog_label + test_cat_label
# データとラベルを同様に並び替えるための関数
def get_similarly_shuffled_list(list1, list2):
temp_list = list(zip(list1, list2))
random.shuffle(temp_list)
list1, list2 = zip(*temp_list)
return list1, list2
# データとラベルを対応付けて並び替えます
train_imgset, train_label = get_similarly_shuffled_list(train_imgset, train_label)
test_imgset, test_label = get_similarly_shuffled_list(test_imgset, test_label)
3-9,データをTensorflowの学習に適した形へ変形する
現在のままでは、Tensorflowでは学習できないため、データとラベルを学習に適した形へ変形します。
# データとラベルをNumpy配列に変形します
train_imgset = np.array(train_imgset)
train_label = np.array(train_label)
test_imgset = np.array(test_imgset)
test_label = np.array(test_label)
# データの形を変形します (2000,50,50)→(2000,2500)
train_imgset = train_imgset.reshape(train_imgset.shape[0], train_imgset.shape[1] * train_imgset.shape[2])
test_imgset = test_imgset.reshape(test_imgset.shape[0], test_imgset.shape[1] * test_imgset.shape[2])
# ラベルをOne-hot表現に変形する
train_label = to_categorical(train_label)
test_label = to_categorical(test_label)
3-10,モデルの学習をし、エポックごとの予測精度を取得します
モデルの設定をした後、学習を行いエポックごとの予測精度を取得します。
# 最初のレイヤーで入力する要素のサイズを取得しておきます
input_dim = train_imgset.shape[1]
# モデルを定義します
model = tf.keras.Sequential()
# ニューラルネットワークを構築します
model.add(Dense(256, input_dim=input_dim))
model.add(Activation("sigmoid"))
model.add(Dropout(rate=0.2))
model.add(Dense(128))
model.add(Activation("sigmoid"))
model.add(Dropout(rate=0.2))
model.add(Dense(2))
model.add(Activation("softmax"))
# モデルを確定します
model.compile(optimizer="sgd", loss="categorical_crossentropy", metrics=['accuracy'])
# モデルの学習を実行し、エポックごとの予測精度を取得する
history = model.fit(train_imgset, train_label, batch_size=batch_size, epochs=epochs, verbose=0, validation_data=(test_imgset, test_label))
3-11,予測精度をグラフで可視化する
取得した予測精度をグラフで可視化します。
# 取得した予測精度「acc」と「val_acc」をグラフで可視化します
plt.plot(history.history['accuracy'], label="acc", ls="-", marker="o")
plt.plot(history.history["val_accuracy"], label="val_acc", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
グラフで可視化した結果は以下のようになります。
ハイパーパラメータの設定に問題があったのか、あまり良い精度は得られませんでした
4,おわりに
今回はTensorflowを用いて犬と猫の画像の予測精度を調べました。
また、ハイパーパラメータを変更して何回か試してみましたが、予測精度はあまり改善されませんでした。
モデルに対して最適なパラメータを探すには、グリッドサーチ・ランダムサーチ・ベイズ最適化などがありますので、そちらを試すのが良いと思われます。
これからもデータ分析やAIについての学習をすすめつつ、より最適なモデルの構築を目指していきたいと思います。
5,参考にしたサイト
【Python初心者が犬・猫の画像認識をやってみる】
https://qiita.com/AnnoJou/items/86ba0f91b8c2cc747573
【[TensorFlow 2.x (tf.keras)] 乱数シードを固定して再現性を向上】
https://qiita.com/bee2/items/08eab7a899c9ff56eb35
【[TensorFlow]インストールされているTensorFlowのバージョンを調べる】
https://www.curict.com/item/6c/6c3a76c.html
【【Python】 二つのリストの対応関係を保ったままシャッフルする】
https://ni4muraano.hatenablog.com/entry/2017/01/30/182447