「説明可能なAI」で漢（オトコ）を磨く

# 動機
弊社AI Dynamics Japan提供のサービス「[Package 20™ Online](https://package20online.aidynamics.jp/)」には、「[顧客属性推定](https://package20online.aidynamics.jp/customer_attributes)」という、性別と年齢を推定するAIがラインナップの一つとして存在するのだが、筆者の顔写真を判定させると、、、
![スクリーンショット 2022-10-24 174530.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/7dd1f851-e267-3792-7360-b8267b6694d4.jpeg)
どうも「female（女性）」と判定されてしまう傾向がある（念のため断っておくと、筆者は男性である）。昨今は中性的男子がモテると言われているとはいえ、自分とて男として生まれた身。男性力を高め、AIにもどうにか「男性」とのお墨付きを得た上で、与えられた性分をこの世で全うしたいと考えるに至った。

男に至るステップとして、まずはそもそもAIに「なぜ己を『女性』と判断したか」を問いただす必要がある。このための手法として、本記事では **「説明可能なAI（Explainable AI：XAI）」** の技術の一つであるLIMEを用いる。LIMEによる試行と考察により、男性が男性足り得るための特徴を明示化し、現実の自身の容姿に反映するというのが今回の戦略である。

読者は本記事を読むことにより、単にAIを実行して結果を鵜呑みにするという方略を採るのみならず、自身のAIの判定の根拠を手に入れ、自信を持って自身のビジネスに適用することを可能にするツールの知見を得ることができる。是非最後まで読了されたし。[^1]

[^1]:ちなみに今回記事に限って文体がやけに文語的であるが、これは[最近筆者が呼んだ小説](https://www.kadokawa.co.jp/product/322107000430/)による影響が大きい

# LIME [^2] [^3]について
[^2]:LIME Github：https://github.com/marcotcr/lime
[^3]:LIME 論文：https://arxiv.org/abs/1602.04938

LIMEとは、「説明可能なAI」を実現するための技術として、SHAP [^4]と並んで取り上げられることが多い技術である。
本手法は画像分析AIに限らず表形式データなどあらゆるデータの分析AIに応用できるものであるが、画像データを例にLIMEの手法についてステップごとに概略を示すと以下のようになる。
1. 画像をいくつかの境界によって区切る（セグメント化）
2. 各セグメントをランダムにマスクし、AIの推論結果の変化を記録する
あるセグメントをマスクした際、AIの推論結果が大きく変化した場合、そのセグメントはAIのもともとの推論結果にとって重要度の高いセグメントということになる。逆に推論結果が変化しない場合、そのセグメントは推論結果にとってあまり重要ではなかったということになる。

LIMEの説明については以下の記事が大変参考になった。
[https://kentapt.hatenablog.com/entry/2021/12/06/224424](https://kentapt.hatenablog.com/entry/2021/12/06/224424)

[^4]:SHAP 論文：https://arxiv.org/abs/1705.07874

# 動作環境構築
プログラム動作検証には[Google Colaboratory](https://colab.research.google.com/)を使用した。
今回記事ではAIモデル構築などの詳細は対象外のため、Tensorflowなどのパッケージのバージョンについては割愛する。

LIMEを使用するにはGoogle Colaboratory上で以下のコードを実行するだけでインストールは完了する。
``` python:LIMEパッケージインストール
pip install lime
```

# 性別推定AIモデルの実行
性別推定AIモデルの実行には、①画像、②AIモデルの２つの準備が必要となる。

画像は人物の顔が含まれるものを使用する。ここで、AI推論には顔面のみ（髪部分は不要）を使用する[^5]ため、適宜画像をトリミング加工するか、画像をロード後プログラミング上で不要部分を削除する。画像ロード後、AI処理に必要な前処理を数ステップ行い、入力画像の準備は完了とする。

[^5]:なので筆者が長髪であることとAIの推論結果とは無関係である

``` python:画像の準備
import cv2

# 画像読み込み（顔部分のみトリミング済み）
img = cv2.imread('./mikio_face.png')

# 前処理
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # BGR（OpenCV標準）をRGBに変換
img = cv2.resize(img, (100, 100))           # 画像サイズを100x100にリサイズ
img = img.astype('double') / 255            # スケールを0-255から0-1に変換

# AIモデルは複数画像を同時処理するため、配列の次元を追加
imgs = np.expand_dims(img, 0)

imgs.shape
# (1, 100, 100, 3)
```

今回使用する性別推定AIモデルは、以下のリンクを参考に作成した。
[https://qiita.com/ha9kberry/items/ae0eabc50a3974c2d92e](https://qiita.com/ha9kberry/items/ae0eabc50a3974c2d92e)

本記事ではモデル構築・学習については割愛し、モデルの読み込みと推論コードのみ記載する。

``` python:AI推論実行
model = load_model('./gender_prediction.hdf5')
model.predict(imgs)
# 1/1 [==============================] - 0s 33ms/step
# array([[0.01118726, 0.98881274]], dtype=float32)
```

出力に表示される配列に含まれる数値が、それぞれ「男性の確率」「女性の確率」を表す数値となる。
今回の場合、２番目の数値が高いため、AIは画像の人物を「女性」と判定したことになる。98%とは、相当な自信を持って「女性」と判定したことになる。ちなみにこちらは筆者の画像を推論させた際の結果である。無念極まりない。

# LIMEによる推論結果の説明
いよいよLIMEを使ったプログラムを紹介する。
LIMEパッケージの使い方は非常に簡単で、画像の説明であればLimeImageExplainerクラスを使用し、対象画像、AI実行関数、試行回数などを指定すると自動で分析を開始してくれる。分析完了後、AIの着目エリア（セグメント）と重要度の高いセグメントをそれぞれ可視化することが可能となる。

``` python:LIMEによる分析・可視化
from lime import lime_image
from skimage.segmentation import mark_boundaries

# 説明用オブジェクト作成
explainer = lime_image.LimeImageExplainer()
explanation = explainer.explain_instance(
    imgs[0], model.predict, top_labels=2, hide_color=0, num_samples=1000)

# セグメントを表示
plt.imshow(explanation.segments)

# 重要着目セグメントを表示
temp, mask = explanation.get_image_and_mask(
    explanation.top_labels[0], positive_only=False, num_features=1, hide_rest=False)
plt.imshow(mark_boundaries(temp, mask))
```

![lime_mikio_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/eb66da98-5ffb-a792-eff6-0f1bbcacd330.png)
左図が着目エリア（セグメント）を、右図が判定に判定結果に対してプラスに作用したセグメント（緑）とマイナスに作用したセグメント（赤）をそれぞれ表している。人間の直感のように、「目」「鼻」「口」といったような分割をAIが行うとは限らないため、この画像だけでは何の特徴を以って「女性」と判定されたのか判断しづらくなっている。

# 男力（おとこりょく）アップの方針と試行
筆者画像のLIME分析だけでは男力アップのための十分な手掛かりが得られなかったため、まずは幾つかのサンプル画像をLIMEによって分析することで、「男性」「女性」の判定根拠の一般的な傾向を探る。

以下、UTKFaceデータセットから20～30台の年齢の男性・女性の顔画像をLIMEで分析した結果である。
![lime_males.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/790a3d56-6a6b-0d15-26c0-7ff58aab1089.png)
![lime_females.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/510366e4-e188-8cc4-ddba-f784c010b2ef.png)
これらの結果からの推測として、今回の性別推定AIは顔面の個々のパーツ（目、鼻、口など）よりも、顔面の大部分を占める肌（額、頬）の部分を主要なファクターとして性別推定しているのではないかという仮説に至った。興味深い点として、男性の顎髭箇所が判定に利用されない傾向にあることが判明した。おそらく顎部分は画像の見切れや影の影響などで、常に男性・女性の特徴を表す箇所として利用できないのではないかと推測される。

そのため、この後筆者の顔写真に加工を加えて再度性別推定とLIMEによる説明を試みるが、加工の方針として、主に肌の表面（額から上顎高さまでの頬）に対する加工を行うこととする。

この方針を以って作成されたのが、以下の画像（mikio_face_v2）である。
![mikio_face_male_margin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/176085dd-a5e1-06fe-798f-0b52a32cb940.png)
いかにも昭和感漂う男像になってしまったのは一重に筆者の画像加工技術の未熟さゆえである。
こちらの画像を使用して再度年齢推定、LIME分析した結果は以下のようになった。

``` python:AI推論実行（mikio_face_v2）
model.predict(imgs)
# 1/1 [==============================] - 0s 33ms/step
# array([[0.14140189, 0.85859805]], dtype=float32)
```
![lime_mikio_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/76d11be6-e840-c60c-384c-caa9889a2d52.png)
少し男性確率は上がった（0.011 => 0.14）が、依然として「女性」として判定されてしまっている。斯様な顔面の女性が現世に存在するかとツッコミを入れたくなるが、相手はAIである。先の仮説の通り、おでこのおっさん臭さが男性確率にプラスに働いている反面、頬の大部分には加工を加えていないため、口髭の小部分の加工だけでは頬の女性らしさを隠しきれていないと考えられる。

もはや筆者の女性らしさの大部分を占めていると判定されている頬の大部分まで加工するしか手立てが無くなった。このようにして作成されたのが、以下の画像（mikio_face_v3）である。
![mikio_face_male_2_margin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/6f0df581-46f7-10ee-c930-db65e9ddc303.png)
ここまでくるともはや自棄（やけ）の領域である。頬毛を生やすには顎鬚も生やす必要もあるため、結局顎にかけてまで加工を加えることとなった。
こちらの画像を使用して再度年齢推定、LIME分析した結果は以下のようになった。

``` python:AI推論実行（mikio_face_v3）
model.predict(imgs)
# 1/1 [==============================] - 0s 33ms/step
# array([[0.61001605, 0.38998398]], dtype=float32)
```

![lime_mikio_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/6756038f-78d5-ec4f-1779-86e4627f968b.png)
ここにきてようやく男性確率が女性確率を上回り（0.011=>0.61）、AIから無事「男性」と判定されるようになった。LIMEの分析画像を顧みると、髭部分は男性確率を上げるのではなく、あくまでも女性確率を上げる肌の露出部分面積の削減に寄与していると考えられる。一部の民族には女性が公共の場で肌を完全に覆い隠すという風習があるが、みだりに女性性を披露しないという点において、今回のLIMEの一連の分析結果が裏付けになっていると考えられる。

# そして辿り着いた究極の男性像とは
以上の試行を経て筆者もAI領域において「男性」と認められるに至ったわけであるが、現実世界においても今回の検証を通じて得られた知見を十分に活かすべきである。というわけで、筆者が辿り着いた最上級の男性像がこちらである。
![mikio_final_trim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/f5039cb7-688f-79f9-f520-66dffebcff89.png)
額前面を利用して男性らしさを表現するのに加え、十分な顎髭により、女性らしさの象徴となる頬部分の面積削減に成功している。

実際に職場に出社してみると、確かに普段と比較して周囲の女性からの視線の劇的な変化を感じる。何か大事な物を喪失している感も否めないが、人間足るもの成長のためには一定の犠牲も致し方無い。晴れて男になった暁には、精神面においても磨きをかけ、より高位の『漢』になるべく、今後も精進を重ねていく所存である。
![matome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927556/1db5577d-b146-49fe-20f6-9904bca7dd6b.png)

# まとめ
今回の記事では、性別推定AIを検証対象として、AIの判定結果を説明可能にする技術としてLIMEを取り上げ、基本概念からツールの活用方法に至るまで紹介をした。AIのブラックボックス性ゆえに頓挫するAIプロジェクトが多い昨今の状況において、本記事をお読みいただいた読者が自身のAIシステムの信頼度を向上する上で、本記事で取り上げた内容を参考にしていただくことがあれば、筆者としてこの上ない喜びである。