紙とペンで挑んだ画像認識モデル ～ディープラーニングの世界を体験～

# イントロ
はじめまして。セゾンテクノロジーの野見山と申します。今回、Qiitaに初めて投稿させていただきます。


昨今、ChatGPTを中心とした生成AIや画像認識が急速に進展し、多くの人々がその効果を実感しています。しかし、これらの背後にあるロジックを理解したいという思いが湧き上がりました。
そこで私が挑戦したのは、「**任意の色が暖色か寒色かを判定するモデル**」を紙とペンを用いて作成することです。
この記事では、プログラムのソースコードは一切登場しません。「画像認識」という魔法のようなブラックボックスの背後に隠れたディープラーニングのロジックと少しの数学の知識を、かみ砕きながら解説していきます。
皆さんにも、少しでも気づきや興味を感じ取っていただければ嬉しいです。

# 目次
[1.挑戦の概要](#1-挑戦の概要)
[2.学習前と学習後の結果比較](#2-学習前と学習後の結果比較)
[3.「判定」と「学習」のプロセス解明](#3-判定と学習のプロセス解明)
[4.実際の計算手順を見てみよう](#4-実際の計算手順を見てみよう)
[5.約30ページによる計算結果](#5-約30ページによる計算結果)
[6.挑戦を通じて得た気づき](#6-挑戦を通じて得た気づき)

## 1. 挑戦の概要

任意の色を暖色か寒色かを判定するモデルを構築しました。
暖色・寒色は多くの人に共通認識がありますが、明確な分類基準は定まっていないと感じています。
色はR(Red)、G(Green)、B(Bule)の成分を0～255で表し、この数値を使って二択判定を行います。
シンプルながら、ディープラーニングの仕組みを体感するのに適したテーマだと考えています。

## 2. 学習前と学習後の結果比較

まず、今回の記事で重要となる **「判定」** と **「学習」** について説明します。
**「判定」** とは、色のデータ(R,G,B)に基づいて、あるパラメータを利用し、その色が暖色か寒色かを決定するプロセスです。
**「学習」** とは、パラメータを調整し、より適切なパラメータに修正していくプロセスです。

これらのプロセスを通じて得られた結果を先にお伝えします。
テスト用データとして、以下の10色（暖色5色、寒色5色）を用いました。 
#### テスト用データ
![検証用_色.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954670/95d50683-4ec6-ee06-c50f-8681bfe9bebd.png)

このテスト用データに対し、**適当なパラメータ**と**特定の関数、判定基準**を使って、「この色は暖色か寒色か？」というテストを実施しました。

 
### 学習前の結果
#### ~テスト用データで判定を実施~
![検証前_色.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954670/1f262136-9db1-9845-fa4a-6e699e975ecf.png)

ご覧の通り、学習前の正解率は50%で、明確な青色が含まれていてもすべて暖色と判断してしまいました。
これは初期パラメータが適切でなかったためです。
そこで、学習を実施し、パラメータを調整して精度を向上させました。


### 学習後の結果
#### ~テスト用データで判定を実施~
![検証後_色.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954670/f1e6ac39-5b8a-fc1a-8f99-470b0e813773.png)

結果、正解率はなんと90%に改善されました！
それでは、次の章より暖色か寒色かを判定するためのロジックと学習のプロセスについてご説明します。

## 3. 「判定」と「学習」のプロセス解明

このセクションでは、**判定**と**学習**のプロセスを段階を追って説明します。

### 判定プロセス
#### １．スコア計算
最初のステップでは、入力データ(色の数値)を使用してスコアを計算します。この際、各入力には**重み**が掛け合わされ、**バイアス**が加算されます。
この**重み**と**バイアス**は初期に定め、学習を通じて最適化していくパラメータです。

**今回利用した方法：単純パーセプトロン**
$$ y = w_1 x_1 +w_2 x_2 + w_3 x_3 + b $$

|変数|定義・説明
|:--:|:--:|
|$y$|計算されたスコア
|$\boldsymbol{x} = (x_1,x_2,x_3)$|入力データ(RGB成分)
|$\boldsymbol{w} = (w_1,w_2,w_3)$|重み
|$b$|バイアス

#### ２．活性化関数

次に、計算されたスコアに対して活性化関数を適用します。
活性化関数は、計算されたスコアを0から1の範囲に変換し、最終的な出力を得るために使用されます。

**今回利用した方法：シグモイド関数**
$$\sigma (y) = \frac{1} {{1 + e^{-y}}}$$

この関数の特徴は、入力値が変化する際に出力が滑らかに変わることです。
特に、出力が0または1に近づくとき、その変化が自然に見られます。

|変数|定義・説明
|:--:|:--:|
|$\sigma (y)$|シグモイド関数の出力。色を暖色か寒色か判定するための値
|$y$|単純パーセプトロンで計算されたスコア

今回は判定基準を以下のように定めています：
　$\sigma (y) \geqq 0.5 $：暖色
$　\sigma (y) < 0.5 $：寒色


### 学習プロセス

#### ３．誤差関数

学習では、予測値が最適な状態からどれくらい誤差があるのかを計算します。
この誤差はモデルの性能を評価するための重要な指標です。
**今回利用した方法：交差エントロピー誤差関数**
$$E(\boldsymbol{w},b)= -t \log \sigma (y) - (1-t) \log (1-\sigma (y)) $$

|変数|定義・説明
|:--:|:--:|
|$E(\boldsymbol{w},b)$|誤差
|$\sigma (y)$|シグモイド関数の出力
|$t$|正解ラベル($t=1$は正解、$t=0$は不正解)



#### ４．最適化 (学習)

最後に、誤差を最小化するために、**重み**と**バイアス**を修正します。
**今回利用した方法：確率的勾配下降法 (SGD)**
$$\boldsymbol{w}^{'} = \boldsymbol{w} - \eta \frac{\partial E(\boldsymbol{w},b)}{\partial \boldsymbol{w}}$$ $$ b^{'} = b - \eta \frac{\partial E(\boldsymbol{w},b)}{\partial b}$$

|変数|定義・説明|
|:--:|:--:|
|$\boldsymbol{w}^{'}$|修正後の重み
|$b^{'}$|修正後のバイアス
|$\boldsymbol{w}$|判定時に利用した重み
|$b$|判定時に利用したバイアス
|$E(\boldsymbol{w},b)$|誤差
|$\eta$|学習率（重みやバイアスの更新量を決定するパラメータ）


$\eta$：学習率は一般的には0.1や0.01といった適当な小さい値が用いられます。

## 4. 実際の計算手順を見てみよう

この章では、３章で説明したステップを順を追って計算していきます。
数学的内容が含まれますので、苦手な方は５章にスキップしていただいても問題ありません。

### 初期パラメータの設定
今回は、初期パラメータとして以下の値を定めました(適当に選択した値です)。
※各変数の定義については、3章の表をご確認ください。

$ \boldsymbol{w} = (w_1,w_2,w_3) = (0.4, -0.3, 0.1259)$
$ b = 0.2 $
$ \eta = 0.1 $

### 判定と学習
本記事では、オレンジ色(RGB)=(255,165,0)を対象に判定および学習を行った計算結果を紹介します。
前提として、入力値$ \boldsymbol{x} $の値がバイアス$ \boldsymbol{b} $とバランスが取れるように、全体を255で割った値を利用しています。
また、小数点は第4位まで使用し、第5位を四捨五入します。
オレンジ：$ \boldsymbol{x} = (x_1,x_2,x_3) =  \left( \frac{255}{255}, \frac{165}{255}, \frac{0}{255} \right) = \left( 1, 0.6471, 0 \right)$

#### 【判定】1. スコア計算
:::note
単純パーセプトロン
$$ y = w_1 x_1 +w_2 x_2 + w_3 x_3 + b $$
:::

```math
\begin{align}
y &= 0.4 \times 1 -0.3 \times 0.6471 + 0.1259 \times 0 + 0.2 \\
&= 0.4059
\end{align}
```

#### 【判定】2. 活性化関数
:::note
シグモイド関数
$$\sigma (y) = \frac{1} {{1 + e^{-y}}}$$
:::


```math
\begin{align}
\sigma (y) &= \frac{1} {{1 + e^{-0.4059}}} \\
&= \frac{1} {1.6664} \\
&= 0.6001
\end{align}
```
オレンジの判定結果は$0.6001$となり、
```math
\begin{align}
0.6001 \geqq 0.5
\end{align}
```
のため、**暖色**と判定されます。
正解した場合でも、より最適なパラメータを求めるために学習を行います。

#### 【学習】３. 誤差関数
:::note
交差エントロピー誤差関数
$$E(\boldsymbol{w},b)= -t \log \sigma (y) - (1-t) \log (1-\sigma (y)) $$
:::
オレンジは暖色であるため、正解のラベルとして$$t=1$$を採用します。


```math
\begin{align}
E(\boldsymbol{w},b) &= -\log 0.6001 \\
&= 0.5107
\end{align}
```
つまり、誤差は0.5107となりました。

#### 【学習】4. 最適化 (学習)
:::note
確率的勾配下降法 (SGD) 
$$\boldsymbol{w}^{'} = \boldsymbol{w} - \eta \frac{\partial E(\boldsymbol{w},b)}{\partial \boldsymbol{w}}$$ $$ b^{'} = b - \eta \frac{\partial E(\boldsymbol{w},b)}{\partial b}$$
:::
本ケースでは、上記の式は以下のように簡略化されます。(計算は割愛します)：

:::note
確率的勾配下降法 (SGD) 
```math
\begin{align}
\boldsymbol{w}^{'} &= \boldsymbol{w} + \eta (t-y)\boldsymbol{x} \\
b &= b + \eta (t-y)
\end{align}
```
:::

```math
\begin{align}
\boldsymbol{w}^{'} &= \begin{pmatrix}0.4 \\ -0.3 \\ 0.1259 \end{pmatrix}
+ 0.1 (1-0.6001)
\begin{pmatrix}1 \\ 0.647 \\ 0 \end{pmatrix}
\\
&= \begin{pmatrix}0.4259 \\ -0.2741 \\ 0.1259 \end{pmatrix}
\\
b^{'} &= 0.2 +0.1 (1-0.6001)
\\
&= 0.24
\end{align}
```
つまり、パラメータ$\boldsymbol{w},b$は以下のように修正されました。
```math
\begin{align}
\boldsymbol{w} &= \begin{pmatrix}0.4 \\ -0.3 \\ 0.1259 \end{pmatrix}
\Rightarrow
\begin{pmatrix}0.4259 \\ -0.2741 \\ 0.1259 \end{pmatrix}
\\
b &= 0.2
\Rightarrow
0.24
\end{align}
```

## 5. 約30ページによる計算結果

4章で説明した計算方法を用いて学習を実施しました。
学習には、テスト用とは別の10色を使用しました。

#### 学習用データ　**※テスト用データとはすべて異なる色(データ)です**
![学習用データ_色.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954670/2f36d2f5-ae8e-695e-91c7-1fdb075305e0.png)

#### 学習の順番と量
上図の左上から順に、
「オレンジ」×3回 →　「スカイブルー」×3回　→ 「ライトオレンジ」×3回　→ ・・・
というように、各色ごとに3回ずつ判定と学習を行い、合計30回のパラメータを更新しました。

なお、紙とペンで計算を実施したため、計算ミスがある可能性もありますのでご了承ください。
また、電卓と指数/対数計算ツールは利用しています。

![学習.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954670/c54b02f8-a04e-daad-cd56-4124cc340200.png)

### 計算結果


|No.|色|判定|誤差|$w^{'}_1$|$w^{'}_2$|$w^{'}_3$|$b^{'}$|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|1-1|オレンジ<br>(暖色)|正解<br>(暖色)|0.5107|0.4259|-0.2741|0.1259|0.24|
|1-2|オレンジ<br>(暖色)|正解<br>(暖色)|0.4784|0.4639|-0.2495|0.1259|0.278|
|1-3|オレンジ<br>(暖色)|正解<br>(暖色)|0.4444|0.4998|-0.2263|0.1259|0.3139|
|2-1|スカイブルー<br>(寒色)|不正解<br>(暖色)|1.1718|0.4917|-0.2653|$0.0569^{※1}$|0.2449|
|2-2|スカイブルー<br>(寒色)|不正解<br>(暖色)|0.8036|0.4852|-0.2965|0.0017|0.1897|
|…||||||||
|6-1|ターコイズ<br>(寒色)|正解$^{※2}$<br>(寒色)|0.6555|0.6751|-0.3227|-0.1188|0.1693|
|…||||||||
|10-3|ライトシアン<br>(寒色)|正解<br>(寒色)|0.556|0.6667|-0.5958|-0.4043|-0.0066|

※１：初めて不正解(寒色を暖色と判断した)となり、色のR,G,BにおけるBlueに関連するパラメータ$w_3$が大幅に修正されました。
※２：折り返しを過ぎ、初めて寒色と判定しました。少し感動しました。

このように、A4用紙30ページにわたる計算を終え、パラメータは次のように更新されました。

#### 初期パラメータ

$ \boldsymbol{w} = (w_1,w_2,w_3) = (0.4, -0.3, 0.1259)$
$ b = 0.2 $

#### 学習後パラメータ

$ \boldsymbol{w} = (w_1,w_2,w_3) = (0.6667,-0.5958,-0.4043)$
$ b = -0.0066 $

2章でも述べた通り、この学習後パラメータを利用して、テスト用データで判定すると、正解率が90%に改善されました！

## 6. 挑戦を通じて得た気づき
この挑戦を通じて、学習する色や各パラメータの特徴（R, G, B）、およびその値によってパラメータの更新速度が異なることを実感しました。この点は理論的には理解していても、実際に計算過程を追うことで改めて理解が深まりました。

一つ一つのパラメータの変化を地道に確認していく過程は、育てた花がつぼみから開花する過程を見守るように、少しずつ確実に進歩が見えてくるものでした。
このような経験を通じて、地道な作業の重要性とその価値を認識しました。

一方で、今回実施した手法は非常に簡易的なモデルであり、計算量も微々たるものです。
より高度なモデルや大量なデータを取り扱う場合、人間業だけでは太刀打ちできないとも実感しました。

長文になりましたが、最後まで読んでいただき誠にありがとうございました。
少しでも皆さんが気づきや興味を感じ取っていただければ嬉しいです。

以上です。

### 参考文献
巣籠悠輔, 『詳解 ディープラーニング TensorFlow・Kerasによる時系列データ処理』, マイナビ出版, 2017年.