みてね×gihyo.jpスペシャル

写真⁠動画を自動分類し続ける「人物ごとのアルバム」機能の仕組み

株式会社MIXIで家族アルバム みてね⁠以下みてね)のData Engineeringグループ所属の浜田と申します。

2020年3月からプレミアム機能の1つとして提供している「人物ごとのアルバム」機能について、アーキテクチャ面や名寄せ処理、機械学習技術の活用の観点から自動分類の仕組みをご紹介し、直近に実施した改善事例を紹介します。

人物ごとのアルバムとは

「人物ごとのアルバム」は、みてねにアップロードされた写真や動画をプログラムで判別し、お子さまごとに自動的に分類する機能です。お子さま個人だけでなく、⁠子どもたち(兄弟や姉妹⁠⁠」や「家族みんな」といったまとまりで表示することもできます。また、月齢ごとに成長メモを残すこともでき、簡単に成長を振り返ることのできる機能となっています。

図1 人物ごとのアルバム機能紹介
図

自動分類フロー

さて、この「人物ごとのアルバム」機能をどのように実現しているか具体的に見ていきましょう。

自動分類フローは、以下の3つのステップから成ります。簡単に概要を説明します。

  • (1) 写真・動画解析パイプライン:ユーザが写真や動画をアップロードした直後に、機械学習モデルを用いた解析処理が順次実行され、結果がデータベースに保存されます。
  • (2) クラスタリングによる自動分類:解析された写真・動画が一定期間内に十分な件数まで溜まったとき、顔の特徴ベクトルを利用して顔同士をクラスタリングします。また、クラスタリングにより抽出された顔クラスタとみてねに登録している子どもを紐付けます。
  • (3) 既存クラスタとの照合による自動分類:1度でもクラスタリングが実施されていれば、(1) 写真・動画解析パイプラインの最後に、アップロードされた写真・動画の顔の特徴ベクトルと既存クラスタの特徴ベクトルを照合することで、ほぼリアルタイムな自動分類を実現しています。
図2 フローチャート
図

それでは、各項目ごとに中身を詳しく見ていきましょう。

(1) 写真⁠動画解析パイプライン

ユーザがみてねに写真や動画をアップロードすると、機械学習モデルを用いた解析器によって順次処理されます。まず、はじめに顔を検出します。後続のML解析器では顔検出された結果を用いて解析を行います。

また、動画の場合、指定秒数でスクリーンショットを切り出し、写真と同様の解析パイプラインで処理できるような工夫もしています。

  • 顔検出:写真・動画の中から顔を検出します。検出した顔は (xmin, ymin, xmax, ymax) の4点の座標(バウンディングボックス)として記録します。
  • 顔の傾き推定と補正:後続の解析器で顔検出結果を正しく利用するため、顔の傾きを推定し、補正します。
  • 顔の特徴抽出:顔検出された結果を用いて、顔の特徴ベクトルを抽出します。
  • 年齢・性別推定:顔検出された結果を用いて、年齢と性別を推定します。性別は0.0から1.0までのFloat値で表現します。

(2) クラスタリングによる自動分類

(2-1) クラスタリング対象の期間抽出

まず初めに、写真・動画の撮影日時を基準に、一定期間内に撮影された写真・動画を含む期間を抽出します。クラスタリング対象の期間抽出は以下のようなポイントを考慮しています。

  • 1ヵ月~2ヵ月程度の期間を1つのクラスタリング対象期間として抽出すること。
  • できる限り多くの写真・動画を含むちょうど良い期間を抽出すること。

とくに後者については、以下の事情を踏まえた期間抽出を行っています。

  • 期間が長すぎると、子どもの成長に伴う顔の変化が大きくなり、クラスタリングや名寄せ処理の精度が下がること。
  • 期間が短すぎると、写真・動画が少なくなり、クラスタリングの精度が下がること。
  • 写真・動画が多すぎると、クラスタリング実行時の処理時間が長くなること。
  • 家族の持つ写真・動画を漏れなく期間に含めたいこと。

この期間抽出はBigQueryを利用しており、1日1回動作します。条件を満たしたご家族分のみ期間抽出されます。

(2-2) クラスタリング処理

家族ごとに複数のクラスタリング期間が抽出されました。クラスタリング処理には連続性があり、直近のクラスタと今回クラスタを照合してクラスタ同士を紐付ける必要があるため、家族ごとにシーケンシャルなクラスタリング実行を行います。入力例は以下のようになります。

{
  "faces": [
    {
      "faceUuid": "face_uuid1",
    },
    {
      "faceUuid": "face_uuid2",
    },
    {
      "faceUuid": "face_uuid3",
    },
  ],
  "clusterUuids": [
      "prev_custer_uuid1", "prev_cluster_uuid2"
  ]
}
  • faces: クラスタリング対象の顔リスト
  • faceUuid: 顔UUID。顔の特徴ベクトルを参照する
  • clusterUuids: 直近のクラスタのリスト

顔の特徴ベクトルにクラスタリングアルゴリズムを適用して、実際のクラスタリングを行います。

出力例は以下のようになります。

{
  "clusters": [
    {
      "clusterUuid": "new_cluster_uuid1",
      "faces": [ "face_uuid1", "face_uuid3"],
      "averageAge": 1.234,
      "averageGender": 0.567
    },
  ],
  "clusterLinks": [
    ["prev_cluster_uuid1", "new_cluster_uuid1"],
  ]
}
  • clusters: 顔クラスタのリスト
  • clusterUuid: クラスタUUID
  • faces: クラスタに含まれる顔のリスト
  • averageAge: クラスタに含まれる顔の年齢推定結果の平均
  • averageGender: クラスタに含まれる顔の性別推定結果の平均
  • clusterLinks: クラスタ同士の紐付けリスト。直近のクラスタと今回クラスタのペア

(2-3) クラスタリング結果に対する名寄せ処理

クラスタリング結果から「人物ごとのアルバム」機能で提供するアルバムに写真や動画を振り分けます。初回のクラスタリングでは、顔クラスタと子どもの紐付けも同時に行います。

名称 説明
「子ども」アルバム 子どもが1人だけで写っている写真・動画
「子どもたち」アルバム 2人以上の子どもが写っている写真・動画
「みんな」アルバム 子どもが1人以上、子ども以外の人物※が1人以上写っている写真・動画

※子ども以外の人物とは、子どもと紐づかなかったすべての顔クラスタと定義しています。通常、ママやパパなど、よく登場する人物が当てはまります。

特徴量を抽出した顔同士をクラスタリングすることで、顔はいくつかのクラスタに分けられます。顔クラスタとみてねに登録したお子さまの情報を利用して紐付けています。

初回のクラスタリングと2回目以降のクラスタリングで処理が変わります。

ご家族にとって初めてのクラスタリングの場合、既存の顔クラスタが存在しないので、顔クラスタと子どもの紐付けを行う必要があります。これを名寄せ処理と呼んでいます。具体的には、下記のようなポイントを考慮しています。

  • クラスタに含む顔の多さ:みてねはお子さまの写真や動画をご家族で共有するアプリのため、顔の数が多ければ多いクラスタほどお子さまである確率が高い、という傾向があり、これを考慮しています。
  • みてねアプリに登録したお子さまの年齢と年齢推定結果の照合:子どもの年齢を昇順でソートしたものと、顔クラスタを年齢推定順でソートしたものを照合することで、子どもと顔クラスタを紐付けます。
  • 子どもが生まれる前の写真・動画:子どもに紐付けません。

2回目以降のクラスタリングでは、すでに顔クラスタと子どもが紐付いた状態が前提にあり、前回クラスタリング時に紐付けた顔クラスタが存在するので、前回の顔クラスタと今回新たにクラスタリングして作られた顔クラスタ同士を比較することで、顔クラスタ同士の紐付けを実現しています。

(3) 既存クラスタとの照合による自動分類

上記の(1)写真・動画の解析パイプラインの最後に、アップロードした写真や動画に写った顔の特徴量と既存の顔クラスタに含む顔の特徴量の平均を照合することで、顔がどのクラスタに所属すべきかを判定します。

通常、写真・動画がアップロードされてから数分~数十分の間に処理されます。

以上の通り、(1)(2)(3)により1ヵ月ごとのクラスタリングによる自動分類と写真や動画のアップロード直後のほぼリアルタイムな自動分類を実現しています。

課題

以上のようにして「人物ごとのアルバム」の自動分類を行っています。この自動分類システムは、多くのご家族に対して満足のいく分類精度を得られていますが、一部のご家族では以下のような問題が発生することがわかっています。

  • 兄弟が入れ替わってしまう
  • 子どもではない別の人物が紐付いてしまう
  • 顔クラスタに複数の人物が混ざってしまう
  • あるタイミングを境に写真・動画が人物ごとのアルバムに振り分けられなくなる
  • そもそも一切分類されない

「兄弟が入れ替わってしまう」課題については、アプリ機能としてきょうだい入れ替え機能を提供することで解消しています。

以下では直近に取り組んだ、クラスタリングの分類精度を高める施策についてご紹介します。

改善事例

前述の「(2) クラスタリングによる自動分類」に対し、下記の2つの改善を実施しました。

前回クラスタを参考情報として加える

従来、⁠(2-2) クラスタリング処理」で説明したクラスタリング処理は、⁠(2-1) クラスタリング対象の期間抽出」で抽出した期間ごとに独立して行っていました。つまり、1回のクラスタリングを行う期間は、前後の期間と重複せず、すべて独立にクラスタリングする設計でした。

ここで2回目以降のクラスタリングにおいて、前回のクラスタリング結果における顔クラスタから顔をサンプリングし、疑似ラベルとして今回のクラスタリングに初期値として活用することで、クラスタリング精度を改善することができました。

「(2-2) クラスタリング処理」の入力例は以下のように clusterUuid を新しく追加しています。

{
  "faces": [
    {
      "faceUuid": "face_uuid1",
      "clusterUuid": "prev_cluster_uuid1"
    },
    {
      "faceUuid": "face_uuid2",
      "clusterUuid": "prev_cluster_uuid2"
    },
    {
      "faceUuid": "face_uuid3",
      "clusterUuid": ""
    },
  ],
  "clusterUuids": [
    "prev_custer_uuid1", "prev_cluster_uuid2"
  ]
}
  • clusterUuid: 前回のクラスタリングで分類された顔のクラスタUUID

クラスタの壊れ検知⁠閾値調整によるリトライ

従来は、⁠(2-3) クラスタリング処理」においてクラスタ同士をまとめるかどうかの閾値を定数として持っていましたが、この閾値はご家族やクラスタリング期間によっては最適でない場合がありました。

ここで前述の「前回クラスタを参考情報として加える」工夫により、前回クラスタを疑似ラベルとして利用し、前回クラスタの分裂や混ざりを調べることで、クラスタの壊れ検知が可能となりました。実際にクラスタの壊れが検知された場合は、閾値を調整しながらリトライを繰り返すことで、より精度の高いクラスタリングを実現しています。

結果

以上、2つの施策により、目視による確認でもクラスタリング精度の向上が確認できました。また、定量的な指標としている紐付き率(※1)が15~20%改善することができました。

※1 紐付き率: 抽出された期間それぞれで顔クラスタと子どもがもれなく紐付けば100%になる。写真・動画不足により紐付かないケースも多い。とくに2人以上お子さまがいる家族は紐付き率が下がる。

図3 人物ごとのアルバムの紐付き家族率
図

この記事では、みてねData Engineeringグループにおける取り組みとして「人物ごとのアルバム」機能の紹介とクラスタリング精度の改善事例を紹介しました。

機械学習技術を用いた機能を提供し、運用し続けている方々など、どなたかの助けになれば幸いです。

おすすめ記事

記事・ニュース一覧