見出し画像

広告セグメントをfastTextとMagnitudeを使ってマッピングする

電通デジタルでデータサイエンティストを務めている荒川です。広告領域を中心にデータ系のプロジェクトを統括しています。

本記事ではfastTextMagnitudeを用いて、複数の広告プラットフォームで提供されるセグメントをマッピングする手法を紹介します。

広告セグメントをマッピングしたい

デジタル上で広告配信をする際の特徴として、ターゲットに応じて細かくセグメンテーションできる点は、異論の余地がないでしょう。最も基本的なターゲティング手法のひとつとして、広告プラットフォームが提供するセグメントを用いることがあります。

例えば「カメラ好き」がターゲットだった場合、各プラットフォームが提供している「カメラ関心層」といったセグメントを配信対象にセットすることで、狙いたいターゲットに絞った広告配信が可能になります。

電通デジタルでは、プランナーの業務効率化/品質向上のために、想定ターゲットを入力すると最適なセグメントを広告プラットフォーム横断でレコメンドするツールを開発・運用しています。ツールのイメージは下記の通りです。

画像1

どうやってマッピングするか?

この開発にあたり、いくつかの課題がありました。

・ターゲットを示す文字列を含むセグメントに加え、意味的に近いセグメントもレコメンドしたい
例:「カメラ好き」をターゲットとする際に、「一眼レフ」「写真」もレコメンド対象に含みたい

これだけであれば、word2vecなど学習済みの単語の分散表現を用い、単語間の類似度を測れば解決します。

- 環境:python 3.6.9, gensim 3.7.1
- word2vecモデル:Wikipedia全文(20191201)からmecab-ipadic-NEologdを用いて形態素解析したデータから学習

# coding: utf-8
import gensim
model_w2v = gensim.models.KeyedVectors.load_word2vec_format('word2vec.vec')
model_w2v.most_similar('カメラ')
[('ビデオカメラ', 0.7933143377304077),
('デジタルカメラ', 0.7386393547058105),
('ポラロイドカメラ', 0.7071923017501831),
('ステレオカメラ', 0.6923556923866272),
('銀塩カメラ', 0.6911982297897339),
('フィルムカメラ', 0.6904247403144836),
('トイカメラ', 0.690095067024231),
('ビューカメラ', 0.6850080490112305),
('一眼レフカメラ', 0.6825188398361206),
('オートフォーカス', 0.6822280883789062)]
model_w2v.similarity('カメラ', '写真')
0.6078799
model_w2v.similarity('カメラ', 'カメ')
0.30326644

問題は以下の点です。

・プラットフォームごとに、頻繁にセグメント一覧はアップデートされる
例:「カメラ」に関するセグメントとして、「装着型カメラ、ウェアラブルカメラ」といったカテゴリが追加される

・プラットフォームごとに、表記のクセがある
例:「カメラ、ビデオ」や「カメラ レンズ」「家電/カメラ」など読点やスペース、スラッシュが含まれる

当然、コーパスの更新や一定の前処理は実施しますが、どうしても未知語(Out of Vocabulary、以下OOV)が発生してしまいます。実際に、あるプラットフォームの1000近いセグメントで検証したところ、単純なword2vecを使って類似度を計算すると、前処理をした上でもOOVが2割近く発生してしまいました。

加えて、業務上、新商品や新カテゴリ立上げ時のマーケティングを支援することも多く、OOVを扱う頻度は他の業種に比べても高いことが想定できます。

例えば、近年流行りの「ウェアラブルカメラ」を見てみましょう。Wikipediaから学習したword2vecだとOOV扱いになってしまいます。

model_w2v.most_similar('ウェアラブルカメラ')
KeyError: "word 'ウェアラブルカメラ' not in vocabulary"

fastTextの活用

そこでOOVに対応できる手法として、fastTextの活用を検討しました。fastTextはFacebook社が開発した自然言語処理用のライブラリで、サブワードの組み合わせでOOV問題に対応できるのが特徴です。

例えば、word2vecでは「カメラ」「デジタルカメラ」「ウェアラブルカメラ」は文字列が異なるので別の単語として処理されていましたが、fastTextでは単語の構成要素の一部(=サブワード)を切り出して学習しています。結果として、例えば「コンタクトレンズ型カメラ」のような学習されづらい単語に対しても、類似度を測定することができます。

先ほどword2vecでは未知語扱いされてしまった「ウェアラブルカメラ」の類義語を計算すると以下のようになります。

- fastTextモデル:Wikipedia全文(20191201)をmecab-ipadic-NEologdを用いて形態素解析したデータから学習

$ git clone https://github.com/facebookresearch/fastText.git
$ cd fastText
$ sudo pip install .
import fasttext
model_ft = fasttext.load_model('fasttext.bin')
model_ft.get_nearest_neighbors('ウェアラブルカメラ')
[(0.7659165263175964, 'ウエアラブルカメラ'),
(0.7492480874061584, 'ウェラブルカメラ'),
(0.6163538694381714, 'GoPro'),
(0.6079729795455933, 'ウェアブルカメラ'),
(0.581913411617279, 'YoCam'),
(0.557768702507019, 'Gopro'),
(0.5546076893806458, 'GOPRO'),
(0.5467113256454468, 'ビデオカメラ'),
(0.5453832745552063, 'SJCAM'),
(0.5403473973274231, 'GoPRO')]

「ウェアラブルカメラ」の別表記や、同カテゴリの商品を類義語として抽出できていることが分かります。

非常に簡単なステップですが、利用に際してはいくつかの留意点があるので、それらをまとめておきます。

・2019年6月25日に投稿されたfastTextの公式ブログで、公式と非公式で分かれていたパッケージが統一されました。fastTextとfasttextの2種類がありますが、Pythonを利用する場合はすべて小文字のfasttextになっています。

・今回のように類義語判定に用いたget_nearest_neighborメソッドは、PyPIバージョンでは対応しておらずpipが使えないことが開発者から言及されています。GitHubの公式リポジトリから最新版をクローンすることが望ましいです。

ただしfastTextも万能ではなく、単語によっては適切に類義語を算出できないことがあります。

model_ft.get_nearest_neighbors('装着型カメラ')
[(0.4935285151004791, 'チョームトーン'),
(0.43158572912216187, 'バーンケーン'),
(0.42488616704940796, 'タンジョウ'),
(0.41781604290008545, 'フーニャン'),
(0.4117698669433594, 'バーンカピ'),
(0.40833190083503723, 'チャウタン'),
(0.39589110016822815, 'サートーン'),
(0.3956961929798126, 'トクマク'),
(0.39493605494499207, 'タンビン'),
(0.39311349391937256, 'スランゴール')]

なぜかタイの地名が出てきてしまいました。

Magnitudeの活用

そこでOOV対策に特徴を持つPythonパッケージMagnitudeを活用しました。MagnitudeのOOV対策の特徴は元の論文によれば下記の通りです。

1. 似た文字列のOOV同士(例:uberxとuberxl)には、完全なランダムでなく、少しだけ似たランダムベクトルを付与する
2. OOVのランダムベクトルと類義語のトップ3の平均を、30:70の重みで足す
3. 接頭辞や接尾辞に引っ張られすぎないようにする(例:uberificationは、verificationでなくuberと近くなってほしい)
4. 3文字以上連続する文字は2文字に縮小する(例:hiiiiiiiiはhiiとみなす)

考え方としてはfastTextに近いですが、既存のいかなる分散表現にも適用可能で、いわば分散表現のアンサンブル学習を簡易に行うことができます。

このMagnitudeを学習済みのfastTextモデルに適用し、実際に先ほどの「装着型カメラ」の類義語を算出してみます。

#Magnitude化したfastTextの読み込み
from pymagnitude import *
model_ft_mg = Magnitude('fasttext.magnitude', normalized=False, ngram_oov=True, case_insensitive=True)
model_ft_mg.most_similar('装着型カメラ')
[('胃カメラ', 0.7659754753112793),
('カメラ', 0.7594144344329834),
('デジタルカメラ', 0.661688506603241),
('ステレオカメラ', 0.6485621929168701),
('レンジファインダーカメラ', 0.6423608660697937),
('銀塩カメラ', 0.6411576271057129),
('ビューファインダー', 0.6378160119056702),
('ハイスピードカメラ', 0.6345838308334351),
('装着型', 0.6306685209274292),
('レンジファインダー', 0.6301928758621216)]

カメラに近い単語が出るようになりましたが、「胃カメラ」など一般的な「ウェアラブルカメラ」とは想定シーンが異なるものも含まれてしまいます。

model_ft_mg.get_nearest_neighbors('ウェアラブルカメラ')
[('ウェアラブルコンピュータ', 0.8619465827941895),
('ウェアラブル', 0.8566116690635681),
('ウェブカメラ', 0.7005716562271118),
('ネットワークカメラ', 0.6830942630767822),
('ヘッドマウントディスプレイ', 0.6802486181259155),
('ハンドヘルドコンピュータ', 0.6611820459365845),
('Web会議', 0.6538692712783813),
('ポータブルコンピュータ', 0.6488516330718994),
('ユビキタスコンピューティング', 0.6477289199829102),
('デジタルメディアプレーヤー', 0.643582284450531)]

「ウェアラブルカメラ」は逆に、「ウェアラブル」に引っ張られ、カテゴリや商品名が表示できなくなっています。このように、どちらの手法も一長一短があるので、後は運用上望ましい手法がどちらか評価する必要があります。

理想的には、仮にすべてのセグメントに対して人手で類似度のラベリングができれば、単語類似度タスクに落とし込めるので、スピアマン順位相関係数で評価できます。しかし、膨大なセグメントに対してラベリングしていくのは、非常に骨が折れる作業です。実務的には類似度の上位2~3セグメントが問題なくレコメンドできればよいと判断し、

・カタカナ語を中心に上位セグメントを目視で確認しファインチューニング
・類似度の適当な閾値を定める

といった形で対応することにしました。結果として、fastText単独で利用するより、MagnitudeのOOV対応を加味した方が望ましいと判断し、実運用に載せています。

今後の展望

fastTextについては、Probabilistic FastText for Multi-Sense Word Embeddingsとして、fastTextにGaussian Mixtureを組み合わせたモデルも提案されています。

また、ここまでお読みいただいた方からは、他のOOV手法、例えばGoogleが発表したBERTは使わないのか、という意見が出るかもしれません。

開発時においては公開されているBERTの日本語学習済みモデルも多くなく手軽に検証しにくかったことと、文書でなく単語の類似度判定なので、fastText+Magnitudeでも問題ないと判断し運用に載せました。

現在、これらのモデルでも同様のタスクで試しており、従来モデルよりも運用しやすく高い精度を出せれば、導入していく予定です。

参考文献

[1]https://fasttext.cc/
[2]https://arxiv.org/pdf/1607.04606.pdf
[3]https://fasttext.cc/blog/2019/06/25/blog-post.html
[4]https://github.com/facebookresearch/fastText/issues/905
[5]https://github.com/plasticityai/magnitude
[6]https://arxiv.org/pdf/1810.11190.pdf
[7]https://yag-ays.github.io/project/out-of-vocab-magnitude/
[8]https://arxiv.org/pdf/1806.02901.pdf

みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!