拡張テキスト広告のCTRを予測するために、制作者やコンサルが考えた広告の重要な要素を特徴量に変形し、深層学習と組み合わせてみました。
はじめに
AIソリューション開発部所属の Melvin Charles DY です。「Melvin Charles」の全部が下の名前ですが、英文字やスペースを入れさせないシステムが多く「メルヴィン」(ある意味ニックネーム)だけを入力するハメになったりします。
さて、ちょっとしたアイスブレイクも済んだところで、この記事の概要に移ります。前に書いた記事でも書きましたが、NLP2022(言語処理学会第28回年次大会)にて、私の論文 「Predicting Click-through Rates of Text Search Ads Using Handcrafted Features」(ハンドクラフト特徴量を用いたテキスト検索連動型広告のCTR予測)のポスター発表をさせていただきました。
そのあとは、Machine Learning 15 Minutes! BroadcastにてZoom配信をさせていただきました。
ポスター発表は「1枚」、Machine Learning 15minutes! Broadcastのほうは「15分」という縛りでしたし、もっと自由に語りたいと思い今回ペンを手に取りました。そしてペンを置いてPCに向かいました。
この記事はプロジェクトの経緯と論文の解説がメインになりますが、ちょっとした裏話も挟んで、学会での発表とZoomでの発表にはなかった価値を作りたいと思います。そして、専門家ではなくても理解できる記事にするように頑張ります。
論文のあらすじ
弊社(DB)に蓄積しているGoogleの拡張テキスト広告の配信実績データと広告テキストを用いて、click-through rate (CTR)の予測を試みました。弊社の広告クリエイティブ制作とコンサルの方々が考えた広告の重要な要素に基づいて、ハンドクラフト特徴量を開発しました。実際に配信された見出しと説明文のデータから特徴量を抽出し、ニューラルネットワークに学習させてみました。比較の基準を設けるために、既存の手法もいくつか実行してみました。CTR予測のために広告のテキストをパラメータ化するのにハンドクラフト特徴量には十分な表現力がある、という結論に至りました。
プロジェクトの経緯、各手法の比喩表現を含めた解説、確信を持てない解釈などは論文に記載されておらず、この記事のための書き下ろしです。あらかじめご了承ください。
検索に連動する広告のこと
まずは、「検索連動型広告」について軽く説明しましょう。その名の通りGoogleやYahooなど検索エンジンで何かを検索したときに表示される広告です。ただ、これはページに静的に組み込まれているのではなく、検索したキーワードと連動して検索結果と一緒に表示されます。全ての検索結果には付いてきませんが、大抵は検索結果の上位ポジションに表示されます。
ちなみに、表示されるポジションも広告の成功率に大きく影響することから良いポジションほど競争率が高く、広告主や広告代理店の間のオークションで決まりますが、今回の話のスコープ外のため詳細は割愛します。気になる方は下記ページをご参照ください。
検索するときは何かに困っている場合が多いです。そのタイミングで問題の解決に繋がりそうな商品やサービスの広告を出せば、ユーザーに関心を持ってもらいやすくなります。ただし、問題を解決するサービスの広告であっても(本当に素晴らしい商品だとしても)その広告の文言に人の注目をひきつけて行動を起こさせる力がなければ、クリックや購入に繋がらず広告費用の無駄遣いになってしまいます。表示回数(英:impressions。用語:imp数)は大事ですが、クリックされる割合(英:click-through rate。用語:CTR)はそれより大事です。
何事も積み重ね
クリックを集めやすい広告を作るのには、やはり広告を制作している人の「センス」が問われます。対象に設定したキーワードなどに強く関連をもっていながら効果的な文章を書くのは、簡単に見えて実際はとても奥深い作業です。そして、属人化していて本当に有効なノウハウを伝達するのが難しい作業でもあります。エキスパートでも、パフォーマンスの良い広告を作れる確率は100%ではありませんし、具体的にどこが良いのかを説明しようとしても十分に出来ないこともあります。
その問題に応えるべく、広告のパフォーマンスに影響する要素の解析を目標とした「実績分析プロジェクト」が2年間ほど前に行われました。大きく分けて4つのステップがありました。はじめに、文言・内容・デザインを表現する「タグ」構成の作成が行われました。その次は実際のタグ付与でしたが、自動化ができる部分とできない部分で別々に対処しました。そのあとは統計解析を用いて要素(タグ)単体と要素の組み合わせがパフォーマンスへ与える影響を算出しました。最後のステップは、統計解析から得た知識を用いて今後の制作プロセスを改善することでした。
「実績分析プロジェクト」はいくつか部署を横断した、それなりに大きなプロジェクトでした。私はテキストに適用される「コピータグ」のチェックや設計段階に携わっていました。「コピータグ」の自動付与やレポートの編集も私の役割でした。自動付与に使ったスクリプトは、実は更に以前のプロジェクトのために開発したものを転用しました。もちろん全てそのままに使えたわけではありませんでした。コピータグのスキーマから正規表現のルールを自動的に生成(+手動の調整)するステップを挟む必要はありましたが、実際の検知と付与の部分はゼロから作る作業が省けました。
「実績分析プロジェクト」の後、サーチ広告(先述した「検索連動型広告」)のパフォーマンス予測に取り組むことになりました。
ただし目的は単なる「予測」ではありませんでした。広告につかえるテキスト自動生成のR&Dも行われていますが、それができるまでのエンドユーザーはやはり人間の制作者です。予測の精度はもちろん重要ですが、何をもってその予測結果に至ったのかが人間に解釈できる形に落とせなければ、役立てるポテンシャルは果たせないと思っていました。
その当時は深層学習はちょっとしか齧ったことはありませんでしたが、特徴量の選択と設計が重要だとなんとなくわかっていました。BERTやほかのTransformer系が成功するにつれて、「分散表現」という自然言語を密な連続値の行列に変換する手法が自然言語処理業界においては主流になりましたが、それを人間に解釈できる「制作へのヒント」に変換するのは難しそうだと思いました。
幸い、人間が理解できる(できそう)な広告の文章から特定な特徴を抽出方法はすでに手に入っていました。
前述の「実績分析プロジェクト」で最近まで使っていたコピータグのスキーマに基づいてハンドクラフト特徴量セットは作れるのではないか、と閃きました。
ハンドクラフト特徴量って何?
簡単に言うと、ハンドクラフト特徴量(英:handcrafted features、以下「HCF」)は開発者が選んで実装した特徴量のことです。自動的に学習された「learned features(以下「LF」)」と対照的に定義されたものです。
もちろん具体的な内容は異なりますが、HCFは基本的に何かの意味合いを持たせた、意図的に実装された特徴量のことを指します。ある意味LFはその逆で、入力を無差別にできるだけ細かく抽出された特徴量であり、その細かさゆえに一つの特徴量の意味合いがなくなります。LFの解釈に関連する研究もされていますが、基本的には単体のLFには意味を汲むことにはあまり意味がありません。
一方、HCFには意味合いを持たせることはできます。自然言語処理における例を紹介しましょう。
例文:ふわっとした肌触り、潤いの洗顔フォーム!今なら化粧水1本が無料に付きます。お買い求めは早めに!
もちろん、各単語を特徴量にすることは出来ますが、もっとハイレベルな束ね方もできます。例えば、「ふわっ」という擬態語は「シュワ」、「もちもち」、「ぷるぷる」などと括って「触感」の特徴量をデザインすることができます。もっと粒度の粗い「擬音語」や抽象的な「かわいい系単語」という特徴量も作れますが、粒度によって区別ができないケースがあり最終的にノイズになる可能性もあります。
逆に、同一の単語を区別したい場合も存在します。「無料」は「無料」でも、特典が付いてくるケースと年会費が不要なケースでは施策のために区別する必要がありました。特典が付いてくるケースは○(本|個|つ|回分)
が先に来る条件を定義したり、年会費のケースは年会費.{0,10}無料
のような正規表現で単語が少し離れていても検知できるようにしたり、工夫が利きます。分散表現のアルゴリズムによって、曖昧性を解消するために単語のコンテキストを考慮したりしますが、HCFだと明示的に設定できます。
しかし明示的に設定できる分、気を付けなければいけません。例えば0円
をそのまま正規表現パターンにすると「送料込み2000円」にも引っ掛かるので(?<![0-9])0円
のように「前には英数字がない0円」というルールを設定するなど、タグのスキーマから変換する際には注意して実装する必要があります。
もちろん良いことばかりではありません。事前に学習されたLFで構成されている汎用言語モデルを使えば、細かい手動調整などは不要で、早く実装できます。加えて、HCFのスキーマに問題空間を十分に表現できる網羅性がなければ、いくら学習させても精度は良くなりません。もう察している方もいるかと思いますが、HCFでできることには限界があります。
実のところ今回行ったHCFの実装は、広告の見出しと説明文それぞれに対する各特徴量の有無だけを表現する実装でした。例えば説明文に同じ特徴量に当たる文字列が数か所があっても、「あり」としか表現されません。順番などはほとんど考慮されておらず、『期間限定』のようなパワーワードが見出しの冒頭にきても最後にきても同じに扱われます。そのようなニュアンスを表現するためにいくつかのアイディアはありましたが、試す時間がなかったため棚上げしました。
オリジナル手法
HCFの説明から気づいた方もいるかもしれませんが、私は大量の正規表現を使って自動タグ付与装置を作りました。タグのスキーマに基づいて、付与されたタグにn-hot encodingを施し「タグベース特徴量」をニューラルネットワークに学習させてみました。
試行錯誤しながら実装したので、ハイパーパラメータチューニングの自動化は実装出来ませんでした。そのせいで結構時間をかけていましたが、深層学習に関する感覚が少し付いたかなと思います。結果的にReLU活性化関数とDropout層を挟んだ600ノードずつの5つの隠れ層のニューラルネットワークに落ち着きました。非線形活性化関数を挟んだ完全接続ニューラルネットワークはMultilayer Perceptron(略してMLP)と呼ばれていて、ニューラルネットワークのなかでは王道でシンプルな印象をもっています。
層の数とノード数は当然だが、違う活性化関数、目標値の対数変換、メタデータと特徴量データ別々の学習、色んなバリエーションを試してみました。精度には影響はなかったが、ついでにできたI/O部分の改善を紹介したいと思います。
データの量の問題で、全てを一度に読み込むことが出来なかったため、pandasのチャンク読み込み機能を使っていました。そこから、カラムの分割や対数変換などを挟んでpytorchのTensorに変換していました。ただ、それをエポックの度に行う必要はないのではないかと思いました。GPUに転送する直前にtorch.saveで保存し、次のエポックはtorch.loadで済ませる「tensor caching」を実装してみました。
コードは大幅に編集したわりには、そこまで軽くなったわけでもありませんでした。ただ、それはオリジナル手法の実験の時点でのことでした。
比較実験
今回の目標の一つは論文を出すことでした。もちろん「弊社ではこのようなR&Dをやっている」というアピールにもなりますが、自己投資の感覚で挑みました。
HCFの手間を省くために自然言語を使った応用全般に使える汎用言語モデルが開発された、と言っても過言ではないと思います。自分がやったことは傍流どころか主流に反して逆流のようなものなので、ちゃんとメリットを示さないと誰も認めません。なので、主流の手法からはじめ、比較の基準を見出すためにいくつかの実験を行いました。
LightGBM
まずは、LightGBMで精度の相場を探してみました。といいながら、他の実験で手がいっぱいでしたので、この実験は同僚の岩田大地さんに実装してもらいました。最終的に私のほうで修正もしましたが、渡されたコードのほぼそのまま使えました。(もちろん論文の謝辞にも感謝を述べました。)
ちなみに、今回お手伝いいただいた岩田さんは過去に「仮想通貨の価格予測コンペティションで優勝した話」という記事を書いています。もしよければこちらの記事もご一読ください。
LightGBMはニューラルネットワークを学習させる手法ではなく、入力の多岐にわたる事例から多数の決定木を生成して予測に影響しなさそうな決定木をそぎ落としていくイメージです。
Finetuned DistilBERT
ここ数年間の主流とも言われているのが汎用言語モデルのファインチューニングです。「汎用言語モデル」は、Wikipediaの記事などのような大量の入力から、多次元的に人が使う言語の「傾向」を吸収させられた、単語間の出現確率の集合体のようなものです。
ファインチューニングは、言語の「全体的な傾向」から、特定な分野・課題における傾向を際立たせるイメージです。その傾向は結局連続値で表現されているので、適切な関数で演算をすれば数値の出力はできます。ただし、その関数は複雑すぎて人手では定義できないので、試行錯誤的に計算してみて、出力した値と正解の差異に基づいて関数の変数を段々に調整していくプロセスです。
ただ、一つ一つの単語の文章中の位置別の傾向を表現するのにはあまりにも多い次元(変数)が必要なので計算は困難です。そのため、前述した分散表現が開発されました。各次元に多彩な情報を体現させることによって、全体的な次元数が計算可能な規模に抑えられました。それでも、この「計算可能な規模」が膨大でることは変わらず、実際にゼロから学習させられる企業は限られます。個人でやろうと思えば不可能ではないですが、伴うコストは普通の人の資産では破産する恐れのあるレベルなのでお勧めできません。そのような背景から、言語の全体を事前に学習した「汎用言語モデル」をベースに、細かいことの学習だけをすることを意味する「ファインチューニング」が主流になっています。
AI界隈ではBERT(Bidirectional Encoder Representations from Transformers)を聞いたことがない人は居ないでしょう。多くの「亜種」も開発されました。DistilBERTはその一つで、BERTの中の情報を蒸留(英:distill)して、余計な部分を無くすことによって精度を保ったままの軽量化されたバージョンです。
今回は、Hugging Faceを通じてDistilBERT-base-Japaneseを使いました。
DistilBERTはBERT系モデルの例に漏れず、入力はテキストです。広告の見出しと説明文はそのままには使えたので、一回はそれだけでファインチューニングをしました。
ただ、オリジナル手法の実験ではメタデータ(配信対象はPCかスマホか、どのブランドの広告だったのか、など)の影響は結構あったと確認できました。ここでメタデータも含めたかったです。メタデータはどうすればいいのかを悩んだのですが、メタデータの意味合いを示す列のヘッダーもテキストにくっつけてみました。パフォーマンスは、思っていたほどではありませんでしたが、少しは上昇したので良しとしました。(これも伏線です。)
前述したtensor cachingはオリジナル手法においてそこまでメリットを示さなかったものの、この実験をはじめDistilBERTを使った実験のすべてには有効な改善でした。メタデータを含めたファインチューニングの実験の1エポック目は50分かかりましたが、2エポック目以降は約32分ずつになり、所要時間の36%をカット出来ました!
アンサンブル
アンサンブル(英:ensemble)という単語は本来、同時に同じ曲を演奏する演奏者の集団を指す単語です。AIにおいては、「アンサンブル」といえば、別々に学習させたモデルを集めて同時に推論させて各パーツの結果を何らかの過程で一つの回答にするようなモデルを指します。最後の出力を決める方法は、平均をとったり多数決で選んだり、色々あります。
今回は、「オリジナル手法」のベストモデルとfinetuned DistilBERTのモデルからなるアンサンブルを構成し、両方の出力の平均をとってアンサンブルモデルの出力にしました。
前項で述べた通り、finetuned DistilBERTモデルは2パターンの学習を行いました。片方はメタデータを含めたもので、片方はメタデータなしの見出しと説明文だけでファインチューニングしたものでした。単体ではメタデータありのほうが若干良かったのですが、オリジナル手法とのアンサンブルを組ませたところ精度が大きく下がりました。
いまだに謎です……
Joint Learning
最後に、ジョイントラーニングを試してみました。これはXia氏等の論文「Click-Through Rate Prediction of Online Banners Featuring Multimodal Analysis」に記載された構成にインスパイアされました。
Multimodalと言えば同一の物や現象を表している複数の形式の情報を使うことを指しています。普通は一緒に表示される画像とテキストの組み合わせや、録音とその内容から起こした文章のペアなどです。
今回は同じテキストから抽出されたHCFとLFを使ってみようかと思いました。両方は同じものを形容しているが、片方は「エキスパートの目でみた箇条書き」のようなもので、片方は「日本語としての指紋」で、組み合わせることによって学習はより包括的に進むかもしれない、という気持ちで実装してみました。もちろん、メタデータも入れました。
HCF、メタデータ、LFという三つのmodeのデータを、1つのmodeずつを取り扱うサブネットワークで処理するようにしました。そして、その3つのサブネットワークの最後の層の各ノードの値を、もう一つのMLP機構に通して予測をさせてみました。学習はサブネットワークごとではなく、一遍に学習させました。
計算資源から見ると、これは一番重く、多彩なデータも扱っていたので期待していたのですが、そううまくは行きませんでした。
もうすこし時間があってこのあたりの調整と実験ができればより良い精度が出たかもしれませんが、この時点でもう論文を書き始めないとまずい時期だったので、断念しました。
余談:tensor cachingは極力しましょう
Tensor cachingにはじめて言及したときは「GPUに転送する直前」と書いたが、それはtensorの不変性を考慮したうえの判断でした。実験によって、入力のtensorが不変であるタイミングは違います。
簡単に言えば、tensor cachingはエポックを越しても変わらない入力値に適用できます。Pandasで分解して、様々な整形作業を経てtensorに変換した後にディスクの保存すれば、次のエポックには保存ステップするまでの処理は全部スキップできます! ですが、学習中のレイヤーの値やロス値を用いた調整、学習につれて変わっていく値をcacheするのはあまり意味がありません。
極端な話、ニューラルネットワーク中の値でも、学習していなければ同じ入力に対して決定論的に同じ出力になるはずなので、できるだけ前倒しすれば学習は軽くできます。
すこし前に便宜上「日本語としての指紋」と書いたものついて話しましょう。
BERTや他のBERT系モデルには[CLS] (classification, 分類)トークンがあり、その[CLS]トークンのポジションには文章の分類タスクにおける必要な特徴量の群(embedding)が収容されています。指紋と喩えましたが、イメージとしては「写真」というより「似顔絵」のようなものです。毛穴の一つ一つまで撮れているというより、文章の「顔」の特徴的なもの(たれ目具合、高い鼻、眉間のしわとか)だけを圧縮して表現しています。
[CLS] token embeddingは、厳密に言うとすべての隠れ層にあると思いますが、全ての層の「描写」を経たものは出力部分の直前のレイヤーにあります。なので、テキストを他のタスクに使えるBERT系分散表現に変換するのには、一回は推論させないといけません。
しかし、BERT系モデルは768個ノードずつを持っている12~24層で構成されているため、それなりに重くGPUのメモリーの使用量も多いです。ということは、BERT系モデルをGPUに載せていると、学習させたいニューラルネットワークに割り当てられるスペースも限られます。しかも、ディスクからの読み込みと整形が行えるのはCPU側のメモリーで、GPUメモリーへの移動は必然です。
BERT系モデルに占められるメモリーや計算コストは、エポック0の処理で対処しましょう。
実際の学習をする前にCLS token embeddingを含めた全ての不変データを学習に適したtensorに整形してcacheしました。そうすることによってBERT系モデルをGPUから削除できるため自分のニューラルネットワークをもっと大きくできる上、全体的な所要時間も短縮できて、win-win-winでした。
コードの編集はちょっと大変でしたし、CLS token embeddingをGPUからCPU側にコピーするステップは増えましたが、それは1回だけで済みました。1つのCLS token embeddingは768個のfloat値なのでディスク容量はそこまで使ったわけではありません。
気になる所要時間の(記録中の最大)短縮はなんと、エポック0を含めた1エポック目の94分から、cacheされたデータを読み込むの2エポック目以降は22分に縮めることができました。 所要時間を76%削減できた分、より多いエポックを学習することができた上に、GPUメモリーがパンパンのせいで小さくしていた自炊ニューラルネットワークも拡張できました!
結果と洞察
メトリクス
※全ての実験には、パーセンテージではなく0.0から1.0までの間の数値を使用しました。 ※学習用データと別に、メトリクスの算出だけのために取っておいたテストデータで検証しました。
タグベース特徴量を使わなかったFinetuned DistilBERT実験は、3つの指標において最低のパフォーマンスをしました。相関係数の最高値、そして最小値のRMSELossはアンサンブル実験において記録されました。ただし、最小値のMAELossを達成したのはオリジナル手法のモデルでした。
各モデルの動向をより直観的に把握するために、テストケースの何割が正確に予測できたかと何割が外れたのかも記録してました。
tol.
はtoleranceの略称です。Overshootは正解を0.05(5%)
以上に上回ったケースの割合で、Undershootは正解を0.05(5%)
以上に下回ったケースの割合です。Acc.は正解の±0.05(5%)
以内に予測出来た割合で、VAcc.はさらに±0.005(0.5%)
以内に当たったケースの割合です。Acc.の数値にはVAcc.が含有されています。
この分散図はテストケース全件(約14万件)で作りました。点が多すぎて少し分かりづらいですが、それでも傾向の違いは見えます。
オリジナル手法の図からは、他のモデルに比べて実際のCTRが高いケースを低く予測していることがわかります。しかしAccurate(Acc.)の割合は一番高かったです。
実はテストケースの90%以上のCTRは0.2以下で、CTRが0.5以上のケースは比較的に少ないのです。実際のCTRが0.2以下のケースに絞った、定数域の分散図も作ってみました。注意してほしいのは、Overshoot / undershoot / accurate 分類の閾値をより厳しくして0.05(5%)から0.02(2%)に変更しました。VAcc.の閾値は全体の分散図と同じです。
ただし、定数域の分散図に書いてある各グループの割合は全体のケースの数で割ったものです。例を挙げると、オリジナル手法の低領域分散図には Accurate (tol. 0.02 (2%)): 59.95%
と書いてありますが、これは正解が0.2以下のケースの中から59.95%が正解の±0.02以内に予測されたことを表しています。
ただし、VAcc.の基準は全体の分散図の時と同じです。オリジナル手法の場合、全体では23.23%で定数域では23.05%で、ほとんどのケースが定数域に集中していることは明らかだと思います。
定数域でLightGBMとオリジナル手法が良い勝負をしていましたが、定数域と全体でのパフォーマンスを両方加味して総合的に一番良かったのはオリジナル手法としています。
解釈
※このセクションには、憶測に近い話をさせていただきます。予めご了承ください。
話を少し巻き戻します。アンサンブルの項で述べたメタデータを含めたfine-tuned DistilBERTがアンサンブルの精度を下げてしまったことの原因ですが、可能性だけでありながらアイデアはあります。
メタデータを含めてfine-tuningした際、メタデータによる影響は発揮して学習されました。ですが、メタデータは広告の文章に比べて変動の幅が比較的小さいので、学習過程ではそのパターン性を重視しました。解釈すると、見出しと説明文の細かいニュアンスを引き換えに、ブランドを表しているアカウントIDのメタデータや配信環境に依存する傾向(例えばスマホだと短いコピーがいいとか)を取り入れすぎたのかもしれません。
また、メタデータを文章化してテキストにくっつけた際、広告の文章部分の先にくっつけました。DistilBERTにもアテンション機構があるので、もしかしたら先に来るものに余計にウェイトをかけてしまったかもしれません。
オリジナル手法のセクションで少し触れましたが、メタデータのみとHCFのみでMLPを学習させたことがあります。HCFだけの場合、相関係数は0.7未満で、最高記録だった0.7863にはそこまで劣っていませんでした。メタデータのみの場合は相関係数が0.5弱で、関連性はないといえないが決定的でもない結果でした。
メタデータとHCFをMLPに学習させた時はウエイトは適度に分散されたようでしたが、Transformer系のアテンション機構の副作用として入力の頭にあったメタデータを重視しました。しかも、メタデータ重視の傾向と広告の内容を重視した場合の傾向が真逆なケースもあったと見受けます。ブランド力に引っ張られてクリックされやすい「平凡」な文章もあれば、以外と大ヒットした事例もあり得ます。アンサンブルモデルは内部のモデルの出力の平均をとっていますが、逆方向の傾向によって不均等な変動が起きて正解からより離れたところに落ち着きます。
一方、オリジナル手法と広告内容だけでファインチューニングされたDistilBERTのアンサンブルは、各々単体の場合の精度を有意に上回りました。これは両方の良いところを活かせた結果に見えます。オリジナル手法モデルによって、重要な要素に寄って予測はおおむね決まりましたが、細かいニュアンスや書き方を加味できる(メタデータに影響されない)DistilBERTの結果に寄って調整され、結局正解に近づきました。
テストケースの結果でexploratory data analysisを行えばより確実なインサイトは見い出せると思いますが、他のタスクとの兼ね合いでこれも後回しにせざるを得ませんでした。
実用に向けて
CTRの予測はまだ会社の制作ワークフローに組み込まれていませんが、いずれはそうなるでしょう。そのために、先のニーズを見越して社内向けツールの開発も行いました。
ただし、ユーザーはまだいないので出来るだけ運用コストの低い実装にしたかったです。DistilBERTは普通のBERTより軽量ですがGPUなしでは推論の所要時間が長くなりすぎて、ユーザーに向いている画面のあるツールには向いていません。とは言えGPU付きのインスタンスをずっと立てているのはコスパが悪すぎる……と葛藤しながら、簡単なツールを作り始めました。
まずは、精度はともかく既存のモデルをベースに開発しました。運用コストほぼゼロを目指して、GCPのCloud Functionsでバックエンドを作って、フロントエンドはFirebaseでのサーバーレスappに決めました。その当時、Cloud FunctionsではGPUが使えなくて実行はCPUのみでした。それでもオリジナル手法モデルは数秒以内に予測の結果を返せたためUX的にセーフとしました。
DistilBERTを何かしらの形に必要とされるモデルができたら実装を替えようと思っていたのですが、精度面で総合的に良かったのはオリジナル手法のモデルでしたので、結局Cloud Functionの中のファイルを置き換えただけで済みました。
今のところツールの出力部分には予測CTRだけを表示していますが、ヒットしたコピータグの表示も実装する予定です。「AI」に対して「ブラックボックス」の印象を持っている方は少なくないですし、考え方のヒントが得られないLH手法ならなおさらです。ですが、今回のHCFは人が考えた特徴量のおかげで、人間が読めるラベルもついています。タグ付与ステップでのタグを予測CTRに添えてUIで表示すれば、オリジナル手法は何を見て計算しているのか少し理解を得て受け入れやすくなります。
ただ、出現したタグにはCTRを上げる影響と下げる影響のどちらがあったのか、そのような細かい説明はまだ出来ていません。ニューラルネットワークの各ノードを通して最終結果に対しての貢献を算出することは不可能ではないですが、その分計算コストがかかるためケースバイケースにもなりそうです。
ヒントでも加減は大事
完全接続構成の特徴として、一つの特徴量がその他の全部の特徴量と混ざりあっており高次相互作用のモデリングがされています。「コスト--OFF率--割り引き」のタグが付いたからCTRが+0.1とは保証できないうえ、「スペック--量--○グラム」と一緒に表示された場合は増減の幅も変わる可能性もあります。ニューラルネットワークは価値判断をせず一通り推論するので、高次元相互作用でもどうということありません。
一方、人間は高次元相互作用を意識をもって考察するのは苦手で、どこかで(一部を諦めて)簡略化しheuristicな考え方に切り替えます。「コスト」「スペック」「ベネフィット」から一個ずつのタグがついた3次元のケースの良し悪しはかろうじて予想できても、どういう数字を出せるかというのは答えられないでしょう。まして、「口コミ」「トラブル原因」「強調」など更に多くのタグが追加された相性表は想像もできないでしょう。
とはいえ人間(エキスパートであればなおさら)のheuristicは役立ちます。広告のテキストの自動生成はまだ十分な水準とは言えないほか、実世界の動きは大量な事後のデータを必要とするAIにとっては早すぎます。Heuristicな考え方による想像力と対応力を活かし続けたいです。
頭の中に多数の要素をモデリングすることはできないので、出現したタグの貢献度を付けて表示すれば他の特徴量セットの場合を考えず一見CTR貢献度が高いタグを中心に広告の制作作業は進むでしょう。それでパフォーマンスの広告で「成功」したとしても、最高の可能CTRが出なくてoptimalではないかもしれません。最悪、CTRを上げそうな特徴量ばっかりを狙って結局予測は期待に沿えない場合、ユーザーは頓挫するか、大量の実績データを学んだAIシステムが疑われてしまいます。どれもツールとして本末転倒です。
そもそもタグの組み合わせによって特徴量の貢献度は解釈不可能なほど変動するでしょうし、人の自由な発想を阻む極振り精神を煽ってしまう危険性もあるので、しばらくの間はHCFの貢献度のR&Dはお蔵入りと判断しました。
おわりに
複数の場面における精度を基準にすると、今回の勝者はオリジナル手法でした。個人的に読みが当たっていたことが嬉しかったです。同時に色んな手法の経験も積めました。
ですが、実装とメンテナンスのしやすさに重みを置けば、finetuned DistilBERTのような汎用言語モデルのファインチューニングをお勧めします。今回の結果は最弱でしたが、オンラインのリポジトリからすぐに入手でき、ハイパーパラメータを気にせず学習ができる上、そこそこの精度も出るのでスピード重視のプロジェクトにはうってつけです。しかも言語全体を網羅している(最新の造語・新語は別として)ので、捕えなかった単語がないと思えます。
前のプロジェクトで、コピータグのスキーマが制作されなかったら今回の手法は諦めたかもしれません。自分は自然言語処理系のエンジニアで、複数の業界における広告のトレンドとコツの知識は蓄えていません。
ただし、ハンドクラフト特徴量を使えば任意の要素の抽出や検証、または機械学習において狙った傾向を強調するのには捨てたものではありません。原始的に見えますが、様々な事例の「共通点」を定義できて、収束への導きとして役に立ちそうです。AIに抽象的な概念を学ばせているようにも見えます。ロマンに訴える解釈はともかく、CTR予測に限らず、テキストと何かしらの目標値の関連性を表現するのには(実装が大変ですが)有効な手段であることは証明できたと思います。
この記事は長くなりましたが、まだまだ試せてないアイディアや検証できていないところは残っています。語り切れてないトピックスもまだあります。ですが、そんなことも言っていられません。
このプロジェクトに使っていたデータは拡張テキスト広告(expanded text ads, 略して ETA)という広告形式の実績データでした。ですが、この記事の公開のタイミングのすぐ後(2022年6月30日)には、なんと、その形式の広告の新規作成は出来なくなります!
そうです。せっかく出来たのに使い道がほぼ無くなってしまいました。
ETAの次には、レスポンシブ検索広告(responsive search ads, 略してRSA)という形式が主流になります。ETAと違って、RSAの内容は動的に変わるほか、配信側による最適化(そとからは不透明で制御不可能)はより強くなり、実績データも少なく、課題のオンパレードです。
論文を発表した時点で次のプロジェクトは始まっていました。RSAに対しても人間性のあるハンドクラフト特徴量は通用するのか、試さなければわかりません。うまくいかなければ潔くやり方を切り替えますが、その時点まで汗をかいて作ったオリジナルな武器で、R&Dを精進します。
最後に、Opt Technologies ではエンジニアを募集中です。カジュアル面談も可能ですので、下記リンク先よりお気軽にご応募ください。