3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画像分類モデルを作ってみる

Last updated at Posted at 2025-05-12

きっかけ


昨今話題の生成系AIのコア技術となるニューラルネットワークやディープラーニングの概念を理解したものの、実際に触ってみないと理解できない部分があるなと思い、今更ながらTensorFlowで画像分類モデルを作り、分析させてみました。

やってみる


今回はさくっと試すだけなのでGoogle Colaboratoryで実装していきます。

まずは学習対象とするデータをDLする。
なお、今回は、cifar10のデータを使います。

import tensorflow as tf
from tensorflow.keras.datasets import cifar10

# データセットをロードする(10クラスの画像セット)
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# データの正規化(0~1の範囲に変換)
x_train, x_test = x_train / 255.0, x_test / 255.0
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 2s 0us/step

DLした中身を確認してみます。

import numpy as np

# データセットの中身を確認

#######################################
# x_train(数値化された画像データ)
#######################################
# データタイプ
print("x_train type : ", type(x_train))

# サンプルデータ(数値化された画像データ)
print("x_train sample : ", x_train[0])

# 形
print("x_train shape:", x_train.shape)

#######################################
# y_train(数値化されたラベル)
#######################################
# データタイプ
print("y_train type : ", type(y_train))

# サンプル
print("y_train sample : ", y_train[0])

# 形
print("y_train shape:", y_train.shape)

# ラベルのはんい
print("y_train unique : ", np.unique(y_train))

50000枚の画像ファイルが数値配列としてデータ化され、0~9までのラベルが付与されていることがわかります。
0~9のラベルの意味は、cifar10の説明を参照ください。

x_train type :  <class 'numpy.ndarray'>
x_train sample :  [[[0.23137255 0.24313725 0.24705882]
  [0.16862745 0.18039216 0.17647059]
  ...
  [0.48235294 0.36078431 0.28235294]]]
x_train shape: (50000, 32, 32, 3)
y_train type :  <class 'numpy.ndarray'>
y_train sample :  [6]
y_train shape: (50000, 1)
y_train unique :  [0 1 2 3 4 5 6 7 8 9]

モデルを定義して、コンパイルします。
コンパイルしたモデルに先ほどの画像データを食わせて今回は学習回数を10として、学習させます。

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Input

# モデル定義(ハイパーパラメータ調整)
model = Sequential([
    Input(shape=(32, 32, 3)),
    Conv2D(32, (3, 3), activation='relu'),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    Flatten(),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
# 学習開始(epochsはトレーニングデータセットに対する学習回数)
model.fit(x_train, y_train, epochs=10, validation_data=(x_test, y_test))

回数を重ねるうちに、accuracyは上がり、lossは下がっているため、精度向上していることがわかります。

Epoch 1/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 73s 45ms/step - accuracy: 0.3594 - loss: 1.7277 - val_accuracy: 0.5505 - val_loss: 1.2381
Epoch 2/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 69s 44ms/step - accuracy: 0.5748 - loss: 1.2031 - val_accuracy: 0.6137 - val_loss: 1.0965
Epoch 3/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 82s 44ms/step - accuracy: 0.6431 - loss: 1.0152 - val_accuracy: 0.6683 - val_loss: 0.9622
Epoch 4/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 82s 44ms/step - accuracy: 0.6858 - loss: 0.9056 - val_accuracy: 0.6748 - val_loss: 0.9317
Epoch 5/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 69s 44ms/step - accuracy: 0.7156 - loss: 0.8135 - val_accuracy: 0.6782 - val_loss: 0.9206
Epoch 6/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 85s 46ms/step - accuracy: 0.7324 - loss: 0.7630 - val_accuracy: 0.6896 - val_loss: 0.8914
Epoch 7/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 83s 47ms/step - accuracy: 0.7534 - loss: 0.7036 - val_accuracy: 0.6996 - val_loss: 0.8631
Epoch 8/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 77s 44ms/step - accuracy: 0.7710 - loss: 0.6543 - val_accuracy: 0.7051 - val_loss: 0.8716
Epoch 9/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 82s 44ms/step - accuracy: 0.7836 - loss: 0.6162 - val_accuracy: 0.6952 - val_loss: 0.9014
Epoch 10/10
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 81s 44ms/step - accuracy: 0.7961 - loss: 0.5739 - val_accuracy: 0.7039 - val_loss: 0.8824

モデルができたので、cifar10内のテストデータを使って、モデルを評価してみます。

# テストデータ(事前に用意された10カテゴリのテストファイル)を使ってモデルを評価
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
# テストデータに対しての正答率を出力する
print("\nTest accuracy:", test_acc)

正答率7割と、まぁまぁの結果になりました。

313/313 - 4s - 11ms/step - accuracy: 0.7039 - loss: 0.8824

Test accuracy: 0.7038999795913696

今度は自前で用意したファイルを使って分析させてみます。
ファイルはGDrive上に配置したものを使うので、認証を通してドライブをマウントします。

from google.colab import drive

# あくまでも自身のドライブへのアクセス権しか持たない
drive.mount('/content/drive')

画像を出力してみます。
(確認のために出力してるだけなので分析とは関係ないです)

from PIL import Image
import matplotlib.pyplot as plt

# 画像を読み込む
image_path = '/content/drive/My Drive/etc/TensorFlow/airplane_test.jpg'
test_img = Image.open(image_path)

# 画像を表示する
plt.imshow(test_img)
plt.axis('off')
plt.show()

ちなみに、画像はGeminiに作ってもらいましたw
Image description

実際に分析させてみます。

# 画像を32x32にリサイズ
image = test_img.convert('RGB')
image = image.resize((32, 32))

# 画像をnumpy配列に変換し、正規化
image_array = np.array(image) / 255.0
image_array = image_array.reshape((1, 32, 32, 3))

# モデルによる予測
predictions = model.predict(image_array)

# 予測結果の確認
predicted_class = np.argmax(predictions, axis=1)

# CIFAR-10のクラスラベル
class_labels = ['airplane', 'automobile', 'bird', 'cat', 'deer',
                'dog', 'frog', 'horse', 'ship', 'truck']

# 出力結果のrawデータ(各カテゴリの確率を配列にしたもの)
print(predictions)
# 一番可能性の高い配列index
print(predicted_class)
# 配列indexに応じたラベル
print("Predicted class name:", class_labels[predicted_class[0]])

出力としては、10分類の各指標が得られており、そのうち、最も高い数値は1つ目(index:0)という結果になりました。
1つ目のラベルはairplaneなので、正しい分類が行われたことがわかります。

1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 126ms/step
[[9.7352397e-01 5.4320579e-05 7.3415530e-03 4.5001831e-05 2.6936505e-03
  9.7711506e-07 2.2104199e-05 1.9527099e-07 1.6267302e-02 5.0913233e-05]]
[0]
Predicted class name: airplane

感想


こんなにも簡単にモデルができるとは思ってませんでしたが、データが事前に用意されてたからなんですよね。
本当に有用なモデルを作ろうとすると、学習データも大量に必要だし、そこにラベルも付与しないといけないし、学習も相当な時間がかかる(無料のGPUだったのもあるが、今回の学習だけでも数分かかってる)し、ハイパーパラメータの調整もいるし、、、と大変な作業だなというのが想像できます。

また、今まではAIは未知のものって感覚だったんですが、実際に触ってみることで、生の数値データを確認で、処理イメージがなんとなくですが、湧きました。

おまけ


Geminiに「ネコっぽいイヌのイラスト」を描かせて分析してみる。
Image description

結果。
イヌとネコの数値も高いが、馬が一番...w
調整って難しそうですね。

[[3.8005831e-04 6.1818724e-07 2.7024343e-03 1.8570235e-02 6.6630021e-03
  6.2341474e-02 1.8024031e-06 9.0927386e-01 4.4260210e-06 6.2017134e-05]]
[7]
Predicted class name: horse
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?