# 【初心者向け】画像認識AIを作って犬・猫の判別をしてみた

> AI・Python初心者が実際に簡単なDeepLearningを用いた画像認識の人工知能（AI）を作ってみて、犬・猫の画像のデータから分析・分類をします。

- 公開日: 2024-08-06
- 著者: Matsu
- タグ: Python, AI
- URL: https://tech.anycloud.co.jp/articles/ai-identification-dog-cat

---

最近、「AI」と耳にすることが多いのですが、「どういう仕組み？Pythonでどうやって作るの？」と疑問に思っていたので、これを機に今回は、Pythonを使って簡単な人工知能（AI）を作ってみます。

ちなみに、僕自身エンジニアではありますが、Pythonは使ったことがなく、知識0です…

そんな僕でも理解できた簡単な犬・猫の判別AIの作り方を簡単にまとめていきます。

PythonやAIに興味あるけど、ハードル高そう…難しそう…と思っている方は、ぜひこの記事から一緒に触ってみましょう。

## 画像認識AIとは？

言葉の通りですが、改めて説明をしておきます。

画像認識AIは、機械学習の一分野でコンピュータに画像を「見て理解する」能力を持たせる技術です。

この技術は、皆さんの日常生活において、医療やセキュリティなど幅広く応用されていて、今回作る犬と猫の判別AIは、画像認識の入門として最適な例となっています。

## 全体の流れ

まずは全体を通して何をするのか、大枠を掴むために、各ステップごとの流れを簡単に説明します。

1.  環境準備
    -   必要なライブラリをインストール
2.  データセットの準備
    -   [kaggle](https://www.kaggle.com/competitions/dogs-vs-cats/data?select=train.zip)（世界中の機械学習を学ぶ人のためのプラットフォーム）から犬と猫の画像をダウンロードする
3.  前処理
    -   画像をAIが処理しやすいようにサイズ調整や色の正規化などの前処理をする
4.  モデルの構築
    -   AIの「脳」にあたるモデルを構築
    -   犬と猫を見分けるためのルール（モデルの構造）を定義する
5.  モデルの学習
    -   モデルに画像を見せながら正解を教え、犬と猫を見分ける方法を学ばせる
6.  性能の評価
    -   モデルがどれだけ正確に犬と猫を見分けられるかをテスト
    -   まだ学習していない新しい画像を使って、モデルの判定が正しいかどうかを確認

それでは、それぞれをステップを見ていきましょう。

## **実際にPythonを使ってAIを作成していく**

ここからは手を動かして、全体の流れに沿って、実際に画像認識AIを作っていきます。

今回の全体コードは、以下のリポジトリにまとめておきました。

<div class="link-card-wrap"><a class="link-card" href="https://github.com/investment4057/image-recognition-ai-dog-cat" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">GitHub - MatsuuraTakumi/image-recognition-ai-dog-cat: 画像認識AIで犬・猫判別</span><span class="link-card-description">画像認識AIで犬・猫判別. Contribute to MatsuuraTakumi/image-recognition-ai-dog-cat development by creating an account on GitHub.</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-01-favicon.svg" alt=""><span class="link-card-domain">github.com</span></span></span><img class="link-card-image" src="./linkcard-01-image.webp" alt=""></a></div>

### **①環境準備**

Pythonなどのインストールは済んでいる前提で進めていきます。

まずは、コマンドから各ライブラリをインストールします。

```shell
% pip install numpy tensorflow keras pillow
```

各ライブラリが何をしているのかについては以下の通りです。

-   NumPy
    -   数値計算を効率的に行うためのライブラリ
    -   多次元配列や行列計算のサポートが充実
-   TensorFlow
    -   Googleによって開発されたオープンソースの機械学習ライブラリ
    -   ディープラーニングを中心に幅広い機械学習のアルゴリズムをサポート
-   Keras
    -   簡単にニューラルネットワークを構築、訓練、評価ができる
    -   複雑なモデルも短いコードで記述できるので初心者でも使いやすい
-   Pillow
    -   画像の読み込み、処理、保存などを簡単にできる

### **②データセットの準備**

のちに説明するモデルの学習のために、犬・猫の画像を集めなければいけません。

幸い、自分で画像を探さなくても、kaggleの[Dogs vs. Cats](https://www.kaggle.com/competitions/dogs-vs-cats/data?select=train.zip)ページから学習用の画像をダウンロードできます。

<figure><img src="./image-001.webp" alt="kaggle Dogs vs. Cats" width="3024" height="1642"></figure>

<figure><img src="./image-002.webp" alt="kaggleからダウンロードした画像一覧" width="968" height="792"></figure>

### **③前処理**

画像をAIが処理しやすいようにサイズ調整などの前処理をしてあげます。

```python
# データセットのディレクトリ
base_dir = './'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')

# 画像データの前処理
# ピクセル値を[0, 255]から[0, 1]にスケーリング。これにより、ネットワークがデータをより効率的に処理できる。
train_datagen = ImageDataGenerator(rescale=1.0/255)
validation_datagen = ImageDataGenerator(rescale=1.0/255)

# 指定されたディレクトリから画像を読み込む
train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(150, 150), # 150x150のサイズにリサイズ
    batch_size=20, # 一度に20枚の画像を処理
    
    # ↓ターゲットをどのように処理するかを指定
    #  この設定が 'binary' である場合、各画像が二つのクラスのうちの一つに属するということを意味
    #  例えば、犬か猫かの分類問題において、犬を1、猫を0のように表現
    class_mode='binary'
)

validation_generator = validation_datagen.flow_from_directory(
    validation_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode='binary'
)
```

### **④モデルの構築**

ニューラルネットワーク（CNN）を用いた画像分類モデルを構築しました。

このモデルは、画像から特徴を抽出し、最終的には「犬」または「猫」の2つのクラスのどちらかを識別するために設計しています。

```python
# モデルの構築
# Kerasでニューラルネットワーク層を線形に積み重ねる方法
model = Sequential([
    # Conv2Dは畳み込み層で、画像の空間情報を保持しながら、エッジ、テクスチャ、形状などの基本的なビジュアル要素を検出
    # activation='relu'は活性化関数としてReLU（Rectified Linear Unit）を使用することを意味する
    # 非線形性を導入し、モデルがより複雑な関数を学習可能にする
    Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),
    
    # MaxPooling2Dはプーリング層で、サイズを小さくするすることにより、計算量を減らし、過学習を防ぐ効果がある
    # 2, 2はプールのサイズで、空間的サイズを半分に減少させます
    MaxPooling2D(2, 2),
    
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Conv2D(128, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    
    # Flattenは特徴マップを1次元のベクトルに平滑化する
    # これにより、畳み込み層やプーリング層からの出力を、全結合層（Dense層）で処理できる形に変換される
    Flatten(),
    
    # 全結合層で、ニューロンが前の層の全ニューロンと接続されている
    Dense(512, activation='relu'),
    
    # トレーニング中にニューロンの50%を無作為に無効にし、過学習を防ぐための正則化手法
    Dropout(0.5),
    
    # 最終的な予測を0から1の間の値（犬か猫かの確率）に制限
    Dense(1, activation='sigmoid')
])

# モデルが学習するための設定
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
```

### **⑤モデルの学習**

トレーニングデータとバリデーションデータを使用して、ニューラルネットワークモデルを学習させ、その性能を評価しています。

※エポックについては以下の記事がわかりやすくて参考になります

<div class="link-card-wrap"><a class="link-card" href="https://zenn.dev/nekoallergy/articles/ml-basic-epoch" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">【初心者】ネコでも分かる「学習回数」ってなに？【図解】</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-02-favicon.webp" alt=""><span class="link-card-domain">zenn.dev</span></span></span><img class="link-card-image" src="./linkcard-02-image.webp" alt=""></a></div>

```python
history = model.fit(
    train_generator,

    # トレーニングデータセットの全画像が1エポックで一度ずつ処理されることを保証
    steps_per_epoch=train_steps,
    
    # モデルをトレーニングする全エポック数
    epochs=15,

    # モデルのトレーニング中にパフォーマンスを評価するために使用
    # 各エポックの終わりにモデルが新しいデータにどの程度適応しているかが評価される
    validation_data=validation_generator,

    # バリデーションデータセットの全画像が各エポックで処理
    validation_steps=val_steps
)
```

### **⑥性能の評価**

実際に、用意したデータセットをもとに、処理を実行すると、評価結果は以下のようになりました。

#### **トレーニングとバリデーションの精度**

<figure><img src="./image-003.webp" alt="トレーニングとバリデーションの精度" width="640" height="480"></figure>

トレーニング精度は非常に高く、ほぼ完璧に近い精度 (ほぼ1.0) に到達していることがわかります。

作成したモデルとトレーニングデータに非常によく適合しているみたいですね。

バリデーション精度に関しては、初期の段階で低く始まり、徐々に改善していますが、トレーニング精度と比較するとかなり低いままとなっており、改善余地がありそうです。

#### **トレーニングとバリデーションの損失**

<figure><img src="./image-004.webp" alt="トレーニングとバリデーションの損失" width="640" height="480"></figure>

トレーニング損失は安定して減少しており、モデルがトレーニングデータに非常によく適合しています。

バリデーション損失は、初期の段階で減少していたものの、その後は増加しています。

## **番外編：性能の評価の改善**

先ほどの結果の通り、トレーニングデータは良かったのですが、バリデーションデータがうまくいっていない傾向にあります。

（ここで記事終わろうと思ってたのですが、なんとかこの精度改善に繋げられないか試行錯誤していました…）

今回、色々と触ってみて、バリデーションデータがうまくいかない原因として、モデルが新しい・見かけたことのないデータに対してうまく一般化できていない可能性があり、過学習の典型的な兆候だと判断しました。

※過学習・・・学習データにだけ適応した学習ばかりが過剰に進んでしまうことで、AIの未知のデータに対して推定する性能が下がってしまうこと

実際に、さまざまなパターンの画像（正面、横から、上からなど）をトレーニングした上で、バリデーションデータを確認すると以下のように、ほぼ完璧な精度を叩き出すことができました。

<figure><img src="./image-005.webp" alt="" width="640" height="480"></figure>

<figure><img src="./image-006.webp" alt="" width="640" height="480"></figure>

## まとめ：Pyhonすごい！**AIに触れてみるの面白い！**

Python初心者が画像認識AIを作って犬・猫の判別をしてみた結果はいかがでしたか？

改めて、AIって奥が深いなぁ…と感じさせられました。

僕としても、まだまだPythonやAIに関しての解像度が浅く、分かりにくかった部分もあると思いますが、「これを機にAIに触ってみよう！」と思っていただけたら嬉しいです。
