CNN から LLM へ。 Amazon SageMaker AI や Amazon Bedrock で実現した JINS BRAIN の「似合う」の言語化
2026-06-02 | Author : 佐藤 拓磨 (株式会社ジンズ)
はじめに
この記事では、JINS が 2016 年から提供しているメガネの似合い度判定サービス「似合い度判定」(旧称 JINS BRAIN) を、CNN (畳み込みニューラルネットワーク) ベースの機械学習モデルから、LLM (大規模言語モデル) を組み合わせた新しいアーキテクチャへと刷新した取り組みをご紹介します。Amazon SageMaker AI、Amazon Bedrock、Amazon Rekognition といった AWS の AI サービスをどのように組み合わせ、判定結果を数値だけでなく、納得感のある言葉としてお客様にお届けできるようにしたのか、その設計と実装の勘所を解説します。
従来のモデルは、似合い度を数値として算出することには成功した一方で、「なぜその数値になったのか」を言語化してお伝えすることが難しく、お客様の納得感を醸成する点に課題が残りました。昨今の LLM (大規模言語モデル) や生成 AI の台頭に伴い、Amazon Bedrock を用いることで、主要な基盤モデルを容易に利用することができるほか、 Amazon SageMaker AI のサーバレス推論のように処理実行のコンピューティングリソースに対するプロビジョニングを意識しなくてもシステム環境を構築できるようになってきています。
こうした背景から、私たちは「最高の顧客体験の実現」に向けた、新たなシステムアーキテクチャの構築が必要であると考えました。そこで、これからの似合い度判定では、新たに「JINS の考えるメガネが似合う黄金比」を定義し、この独自のロジックに LLM を掛け合わせることで、メガネが似合う理由を解説するコメントの生成が可能となり、お客様により高い納得感を提供できるサービスへの進化を目指しています。
builders.flash メールメンバー登録
builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。
従来の似合い度判定は機械学習で構築
従来の似合い度判定は、その中核に高度な機械学習アルゴリズムを据えて構築しました。JINS として「これはお似合いである」という判断はある程度のロジックに基づくものの、感覚的な要素も多くを占めており、ルールとして定義することが困難でした。そこで、店舗スタッフのセンスをデータセット化するアプローチを採用しています。具体的には、店舗スタッフ約 3,000 名の顔とメガネのペアを撮影し、社内の有識者を含む社員が似合い度をラベル付けした 6 万枚におよぶ画像を教師データとして活用し、CNN (畳み込みニューラルネットワーク) を用いた設計を行っています。
教師データを「6 万枚」と定めた当時の背景としては以下の 3 つの要諦に基づいています。
- 品質の担保 : レコメンドサービスとして、最低限遵守すべきサービス品質を確実なものとすること
- 汎用性の維持 : 過学習による品質の劣化を未然に防ぎ、モデルの堅牢性を保つこと
- アジャイルな展開 : 迅速な市場投入 (スピードローンチ) を実現するため、開発サイクルを最適化すること
CNN の構築にあたっては、以下の 4 つの標準的なモデルアーキテクチャにて多層的な解析を実現しました。
- Convolution (畳み込み) : 画像から本質的な特徴を検出する
- Activation (活性化) : 検出された特徴を非線形変換し複雑なパターンを表現可能にする
- Pooling (プーリング) : 重要な情報を維持しつつ次元削減を行い、計算効率を高める
- Fully Connected Layer (全結合層) : 抽出された要素を統合し、最終的な推論へと繋げる
ネットワークの深さは全体で 40 ~ 50 層ほどで、活性化関数として ReLU (Rectified Linear Unit) を採用することで、勾配消失を防ぎ、学習の効率化と精度の高度な両立を図りました。
課題・やりたいこと
新しい似合い度判定を開発するにあたり、解決すべき課題や実現したい目標は主に以下の通りです。
まず、サービス品質向上のための根幹として、より客観的な視点で「メガネが似合う」状態を定義することで、判定結果に対する納得性を高めることと、それに伴い、判定結果の解釈をお客様へ分かりやすくお伝えするための解説コメントを作成することを重要な要件の一つとしました。
さらに、単に「選択されたメガネ」の似合い度を判定する受動的なサービスに留まらず、お客様一人ひとりのお顔立ちに合わせて最適なメガネを能動的にレコメンドできる仕組みの実現にも取り組みます。
新しい似合い度判定のサービスユースケース
新しい似合い度判定が提供する、具体的なサービスユースケースについてご紹介します (2026 年 5 月時点で、最近オープンした JINS 新宿店、銀座店など一部の店舗でご利用いただけます)。
まず、本サービスは JINS の一部店舗に設置されているタブレット端末から、どなたでも気軽にご利用いただくことが可能です。実際のサービスの流れとしては、その場で「メガネをかけた自身の顔画像」を撮影します。そうすると、システム側で JINS 独自の「黄金比」(具体的には「フレームの縦幅」「フレームの横幅」「黒目の位置」の 3 点) を基準に解析が行われ、即座に「似合い度」が算出される仕組みとなっています。
さらに、本システムは JINS AI (オンライン上で入力されたお客様のメガネ購入に関する疑問やお悩みに対して店舗スタッフの接客のように、瞬時に回答や提案をする自社開発サービス) とも密接なシステム連携を行っており、JINS AI 側から提案されたフレーム画像をユーザーの顔写真に仮想試着させ、そのまま似合い度を判定するといった、高度なレコメンド体験を実現しています。
新しい似合い度判定の UI
システムアーキテクチャ
今回のシステムでは、 AWS が提供する様々な AI サービスを用いています。
- Amazon SageMaker AI : 各種オブジェクトの識別を行うために、オープンソースの機械学習ライブラリを用いて推論する処理を担当する。スマートフォン撮影において不可避である顔の角度や距離の不整合を吸収し、独自の「黄金比」と厳密な照合を可能とする水準までデータを正規化・整形する前処理を AWS Lambda と連携して行う。
- Amazon Bedrock : 基盤モデルは Claude 3 Haiku を使用し、Cross Region Inference でスムースな処理を行う。算出された幾何学的な分析結果に基づき、エンドユーザーの感性に響く「似合い度」の精緻な言語化、および説得力ある解説コメントを生成するようにシステムプロンプトを作成している。なお、Claude 3 Haiku は既にレガシーモデルのため、新しいモデルへの移行を検討している。
- Amazon Rekognition : IndexFaces を用いて画像内の「顔」を検出し、その特徴量を保存する (ローデータの保存はしない) 。この機能を用いて、別途ユーザー毎のサービスの利用頻度を定量的に計測することで、顧客体験の変遷を深く洞察する。
途中で利用を停止したサービスもありました。
- Amazon Comprehend : 当初、生成AIの出力するコメントを監視するガードレールとして利用していたが、システムプロンプトの厳密な定義により、Amazon Bedrock のみで JINS が求める高水準な品質を安定的に担保できることが実証された。その結果、ルールベースの検証のみとすることで、コメント生成におけるレスポンス速度の改善を実現した。基盤モデルに Claude 3 Haiku を採択しつつ、プロンプトエンジニアリングによって品質と速度を高度に両立させたことは、コンシューマー向けサービスとして極めて有益な技術的知見となった。
全体構成図
処理プロセスの説明
具体的な処理の流れについて説明します。本システムの処理プロセスは、大きく分けて次の 2 つのフェーズで構成されています。 具体的には、画像から特徴を抽出する「① 顔画像のオブジェクト判定処理」と、その解析結果をもとに最適な言葉を紡ぐ「② コメント生成処理」です。これら 2 つのプロセスをシームレスに連携させることで、お客様一人ひとりに合わせた似合い度判定を実施しています。
① 顔画像のオブジェクト判定処理
この処理では、入力された画像から顔領域とランドマーク (目・鼻・口の位置) を検出することから始まります。スマートフォンでの撮影は顔の向きや角度が一定ではないため、ここでは顔の傾きを正対化させる「ロール補正」を行うことが、後の「黄金比」との正確な比較において極めて重要となります。補正後の画像に対して再度詳細なランドマークや顔パーツ、さらにはフレームやレンズの矩形、眉毛の点などを精密に検出することで、最終的な似合い度の判定を行います 。
(図 : 似合い度判定処理)
② コメント生成処理
続くこの処理では、判定結果の数値データを元に、生成 AI がお客様一人ひとりに合わせた解説コメントを生成し、さらに表現の質を高めるための添削を行います。最終ステップとして、NG ワードの混入がないか、また感情表現が適切であるかといったチェックを多層的に施すことで、サービス品質を担保しながら、お客様の納得感を醸成する高品質なコメントを提供しています (2026 年 5 月時点では、UI 改善の為、コメントは一時的に非表示になっています)。
(図 : コメント生成処理)
実装上の課題と克服
開発の過程で行った技術検証では、いくつかの重要な課題が浮き彫りとなりました。具体的には、眼鏡と顔パーツの境界、あるいは眼鏡とレンズの境界における判定精度の不足であり、これらは主に顔ランドマークの検出精度に起因するものでした。これらの課題に対しては、フレームとレンズがそれぞれどこの範囲であるかのアノテーション付けを行なったデータセットを新たに教師データとして学習させたことで、実用レベルへの精度向上を実現しています。
また、アルゴリズムだけでなく、判定処理に使用するインプット画像そのものに起因する問題も確認されました。例えば、撮影時の顔の傾き (回転) によって、各パーツの幅の計測に微細なズレが生じてしまうといったケースです。これについては、あらかじめ回転角を正確に計測し、顔軸のズレを補正する処理を組み込むことで解決を図りました。具体的な実装としては、以下の def predict を定義し、画像の回転が必要かどうかを判定しています。
def predict を定義
def predict (
self,
image_rgb: NDArray_HxWx3,
face_bbox: BBox,
face_meas: FaceMeas,
file_saver: DevFileSaver,
) -> FaceRollPredictionResult:
self.logger.info ("顔を正対化する回転角度を予測し、回転可否を判定します。")
# 顔のランドマークから額と顎のポイントを取得
forehead = face_meas.forehead
chin = face_meas.chin
# 角度 (度数法) を計算
angle_deg = self._calc_angle_deg_to_vertical (forehead, chin)
# 顔の回転情報を描画した画像を保存
file_saver.draw_and_save_image_with_angle_deg (
image_rgb, face_bbox, forehead, chin, angle_deg
)
is_rotation_required = abs (angle_deg) >= ROTATE_THRESHOLD
if not is_rotation_required:
self.logger.info (
f"予測した顔の回転角度 {angle_deg:.2f}° の絶対値が閾値 {ROTATE_THRESHOLD}° 未満のため、ロール補正を実施しません。"
)
return FaceRollPredictionResult (
is_rotation_required=is_rotation_required,
angle_deg=angle_deg,
)
補足
顔に傾きがある状態では、本サービスの核となる「フレームの縦幅」「フレームの横幅」「黒目の位置」の判定結果に誤差が生じる可能性があるため、一定の傾きが検知された場合には必ず補正処理を挟むように設計しています。なお、補正の要否を判断する閾値 (ROTATE_THRESHOLD) は「2 度」と定義しており、これを超える傾きがある画像に対しては、自動的に正対化の処理が実行されます。
工夫した実装の紹介 (Amazon Rekognition)
リアル店舗でのサービス展開を行う企業ならではの要件として、「同じお客様が、一定期間内に何回サービスを利用されているか」というリピート状況を把握したいというニーズがあります。新しい似合い度判定では、このニーズに応えるために Amazon Rekognition の「顔コレクション」機能を活用しています。具体的には利用の都度、SearchFacesByImage で事前登録されているかを確認し、高い近似値としてヒットすれば同一人物として判定します。そうでなければ IndexFaces API を用いて顔の特徴量をコレクションに登録します。 (図 : 顔特徴量検索・登録処理)
Amazon Rekognitionに関連する実装例
顔特徴量の近似値検索の Python コードは以下の通りです。(一部抜粋)
# --------------------------------------------------------------
# コレクションから類似の顔画像を検索する
# --------------------------------------------------------------
try:
face_image_bytes = base64.b64decode (face_image_base64)
logger.info (
f"[{jins_trace_id}][{user_id}][{rekognition_collection_id}] コレクションから類似の顔画像を検索します。 閾値:{SIMILARITY_THRESHOLD}"
)
searchfaces_response = rekognition_client.search_faces_by_image (
CollectionId=rekognition_collection_id,
Image={"Bytes": face_image_bytes},
FaceMatchThreshold=SIMILARITY_THRESHOLD,
)
except Exception:
logger.exception (
f"[{jins_trace_id}][{user_id}][{rekognition_collection_id}] コレクションからの類似の顔画像の検索に失敗しました。"
)
return {
"status_code": 500,
"body": "HTTP 500 Internal Server Error",
}
# 類似顔画像の結果を取得
num_matches = len (searchfaces_response["FaceMatches"])
for index, face_match in enumerate (searchfaces_response["FaceMatches"]) :
similarity = face_match["Similarity"]
face_id = face_match["Face"]["FaceId"]
logger.info (
f"[{jins_trace_id}][{user_id}] 類似顔画像 {index + 1}: 類似度 {similarity}, FaceId: {face_id}"
)
if num_matches == 0:
logger.info (
f"[{jins_trace_id}][{user_id}][{rekognition_collection_id}] コレクションに類似の顔画像が見つかりませんでした。"
)
# --------------------------------------------------------------
# 顔画像をコレクションに登録する
# --------------------------------------------------------------
try:
logger.info (
f"[{jins_trace_id}][{user_id}][{rekognition_collection_id}] 顔画像をコレクションに登録し、顔情報を推定します。"
)
indexfaces_response = rekognition_client.index_faces (
CollectionId=rekognition_collection_id,
Image={"Bytes": face_image_bytes},
ExternalImageId=user_id,
MaxFaces=1,
QualityFilter="AUTO",
DetectionAttributes=["ALL"],
)
except Exception:
logger.exception (
f"[{jins_trace_id}][{user_id}][{rekognition_collection_id}] コレクションへの顔画像の登録に失敗しました。"
)
return {
"status_code": 500,
"body": "HTTP 500 Internal Server Error",
}
補足
Amazon Rekognition によって内部ベクトル化され、保存されている顔の特徴量データを用いた近似値検索、および属性推測の結果は、すべて Amazon S3 へ保存する設計としています。この検索プロセスでは、類似度の閾値を 99.5% 以上に設定し、過去のコレクションから合致するデータを抽出します。この「ヒットした件数」は、そのお客様が「過去に似合い度判定を利用した回数」と解釈することが可能です。以下は、特定の顔の特徴量に類似したデータが 2 件ヒットしていることを示す例です。
"FaceMatches": [
{
"Similarity": 100.0,
"Face": {
"FaceId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"BoundingBox": {
"Width": 0.34216898679733276,
"Height": 0.35217198729515076,
"Left": 0.348131000995636,
"Top": 0.18112799525260925
},
"ImageId": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
"ExternalImageId": "cccccccc-cccc-cccc-cccc-cccccccccccc",
"Confidence": 99.9990005493164,
"IndexFacesModelVersion": "7.0"
}
},
{
"Similarity": 100.0,
"Face": {
"FaceId": "dddddddd-dddd-dddd-dddd-dddddddddddd",
"BoundingBox": {
"Width": 0.34216898679733276,
"Height": 0.35217198729515076,
"Left": 0.348131000995636,
"Top": 0.18112799525260925
},
"ImageId": "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee",
"ExternalImageId": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"Confidence": 99.9990005493164,
"IndexFacesModelVersion": "7.0"
}
}
],
今後の課題と展望
今後のさらなる進化に向けて、私たちは LLMOps プロセスの構築に取り組み、サービス品質を継続的に維持・向上させていくことを目指しています。その具体的な手法として、モデルのパフォーマンスを客観的に評価するために、別の「LLM-as-a-judge」を活用した評価システムの導入を検討しています。(別の LLM-as-a-judge を使用してモデルのパフォーマンスを評価する)
Amazon Bedrock における LLM-as-a-judge の評価には、あらかじめ定義されたデフォルトの指標と、独自の要件に合わせて追加できるカスタム指標の 2 種類が存在します。現在、デフォルトで用意されている以下の指標を用い、自動評価の結果と人間の感覚がどの程度一致するかについて検証を進めている段階です。
- Following instructions : 応答がプロンプトによる指示をすべて尊重しているかを測定します。
- Readability : テキストで使用される用語や言語の複雑さを測定します。
- Harmfulness : 応答内において、憎しみや侮辱、暴力などの有害なコンテンツをどの程度回避できているかを測定します。
また、これらに加えてカスタム指標として「お客様に対して馴れ馴れしい表現になっていないか」といった、JINS らしい接客クオリティを正しく評価できるかどうかも併せて検証しています。
LLM-as-a-judge を活用した品質向上
さいごに
生成 AI の出力には本質的に不確実性が伴い、さらに Amazon Bedrock で利用可能な基盤モデルの種類やバージョンも絶えず変化し続けます。そのため、こうした技術的変化に伴うサービス品質のリスクをいかに評価し、品質を恒久的に担保し続けるかは、JINS にとって極めて重要な課題です。
かつての似合い度判定は、当時の機械学習分野で有用であった CNN を用いた先端的なサービスでしたが、判定の根拠を具体的に説明することが困難であるという課題を抱えていました。これからの似合い度判定は、似合い度に関するロジカルな定義を軸に据えつつ、最新の LLM 基盤モデルを積極的に採用することで、判定の納得性を高めます。お客様一人ひとりに寄り添った分かりやすいコメントを提供し、サービス全体のユーザー体験 (UX) をより強固なものへと進化させていきたいと思います。