F@N Ad-Tech Blog

株式会社ファンコミュニケーションズ nend・nex8のエンジニア・技術ブログ

アドテクの会社でCTR予測をしてみた。

はじめまして!5日間インターンとして参加させて頂いた中島です。
データ分析のインターンは初めてだったのですが、簡単に紹介させて頂きます。
今回はCTR予測を行いました。

CTR予測

CTRとは「ユーザに広告を表示しクリックされる確率」を言います。
広告配信の最適化は、限られた広告予算の中でクリック率を最大化することであり、そのためにはCTRを正しく予測することが不可欠です。
この5日間で、より精度の高いCTR予測をするモデルの設計に取り組みました。

5日間の流れ

1日目 事務処理と大規模データベースへのアクセス

午前には事務手続きをし、その後アドテクについて教えて頂きました。

本格的に業務が始まったのは午後から。
まず、CTR予測をするためのデータの取得をします。Treasure Dataに接続し、SQLを用いて必要なデータを取り出しました。ここで、はじめてPrestoに触れました。

なんとなくSQLが書けるようになったら、今度はjupyter notebookから接続し、データをローカルの環境に引っ張ってきます。

広告のリクエスト数が1億以上あったため、
データをうまくサンプリングしないとカーネルが落ちて大変でした。

引っ張ってきたデータを眺めながら、広告のクリックされる確率の低さ(0.5%くらい?)に驚きつつ1日目を終えました。

2日目 データ整形とネガティブダウンサンプリング

この日は昨日とってきたデータの整形とネガティブダウンサンプリングを行いました。
ネガティブダウンサンプリングとは、意図的に負データを減らすことで、正データとの比を揃えることです。
今回のCTR予測ではクリックされない広告のリクエストを100分の1程度に減らしました。

その後欠損データの修正などデータハンドリングを行い、ロジスティック回帰を用いて学習しました。

モデルの評価に使うのはAUC, LogLoss, NEの3つ

AUC Area under the curve 予測した際のROC曲線の下側部分の割合。大きいほどよい。
LogLoss Logarithmic Loss 予測値と正解との距離を対数とった値。小さいほどよい。
NE Normalized Entropy モデルにより予測されたLogLossを、平均から予測されたCTRのLogLossで割った値。1より高いと平均から予測した方がまし。

それぞれの違いは今回メンターについてくださったsakaiさんの記事を参考にしてください。

tech-blog.fancs.com

3日目 特徴量の追加とグリッドサーチ

2日までは限られた特徴量のみを使っていたのですが、3日目から特徴量を増やしました。

そしてグリッドサーチを用いてロジスティック回帰モデルのパラメタチューニングを行いました。

が、大して成果が出ることはなくこの日は悲しみの帰宅。

4日目 他の学習モデルを試す

3日目まででロジスティック回帰に限界が見えてきた(個人的な特徴量エンジニアリング力不足)ので、他の手法を試してみることにしました。
今回試したのがLightGBMです。
Welcome to LightGBM’s documentation! — LightGBM documentation

LightGBMはXGBoostなどと同じ勾配ブースティングの一つです。
XGBoostと同程度の性能でありながら、より高速で機械学習コンペなどでもよく目にすることから使ってみました。

ワンホットエンコーディングなど色々勝手にやってくれるのでとても楽(特徴量エンジニアリングとは、、)

5日目 特徴量選択とパラメータチューニング

昨日試したLightGBMのモデルのスコアを上げるため、もう一度使用する特徴量を見直すことにしました。
LightGBMには訓練データのそれぞれの特徴量の重要度を測るメソッドがあるので、それを用いて特徴量の選別を行いました。

f:id:fan_k_nakashima:20180831182033p:plain
特徴量名は伏せてますが、こんな感じで可視化できます。

その後特徴量を選択し、簡単なパラメタチューニングを行った最終的な結果がこちら

f:id:fan_k_nakashima:20180831182110p:plain

訓練データ:2018年7月1日~31日のログ
テストデータ:2018年8月1日~7日のログ

学習モデル AUC LogLoss NE
XGBoost 0.71 0.0326 0.9557
LightGBM 0.74 0.0320 0.9391

同時に試したXGBoostのスコアも載せてあります。
スタッキングなどをすればもっと上がったんでしょうが、5日間ということもあってここでタイムアップ。
NEが0.9391なので平均から予測するよりは良いモデルになってくれました。

まとめと感想

  • LightGBMを用いてそこそこ精度の高いモデルができた
  • ビックデータのハンドリングはサンプリングが大事

まともにデータ分析を行ったのは初めてでしたが、メンターのsakaiさんが丁寧に教えてくださったおかげで全体の流れがみえました。
レベルに合わせて教えて頂けるので、聞きたいことを聞きつつ伸び伸びやらせて頂きました。
生データを使ってデータ解析をしたい人、自分のペースに合わせて進めたい人にはとても良いインターンなのではないかと思います!
5日間お世話になりました!

SSP構築インターンに参加してきた

初めまして、森です。
8月20日~24日の5日間、SSP構築インターンに参加させて頂きました。
一緒に参加した倉林くんは日記形式のブログでした。
インターンの詳細なレポートにつきましてはそちらを参照して頂けると幸いです。
tech-blog.fancs.com

私はこのインターンに参加しようか考えている人に向けて書きたいと思います。

はじめに、結論から申しますと

めっちゃオススメのインターンです!!

サーバサイドの開発やアドテク業界に興味のある方は、是非参加を検討してほしいと思いました。

内容も勿論ですが、交通費や宿泊費についても殆ど全て支給して頂けるので、私のように遠方の学生でも安心です。
どうやら、私は特別選考枠に合格したようです。

内容

SSP (Supply-Side Platform) を少し簡単な仕様にしたMini-SSPの開発インターンです。
Mini-SSPをざっくりと説明すると、『広告のリクエストを受けて、DSPに広告の入札リクエストを投げて、最も入札金額の高い広告をレスポンスとして返すサーバサイドのプログラム』です。
開発したMini-SSPは最終的には、用意して頂いたSDK(広告をリクエストする部分)、DSPでテストします。

開発言語はかなり柔軟に対応して頂けるようでした。
今回私は、オススメして頂いたこともありScalaを選択しました。なおScalaは未経験の模様。かなり難しくて苦労しました

日程は5日間。
初日は入社書類の記入や社内案内、SSPに関するイントロダクションが主でした。残った時間で開発をしますが、開発環境は殆どまっさらな状態から始まるため、実際には開発環境を整えるところから始まります。
2日目~4日目はすべて開発に時間を使うことができました。
5日目は本番環境でテストをする日……

だったのですが、私は3日目の夜に食べたご飯があたったのか、胃腸炎になりダウン。
後になって分かったのですが、4日目の実習中に見舞われていた関節痛は、寝違えたのではなく胃腸炎の炎症に由来するもの?だったそうです。まさに馬鹿は風邪をひかない
インターン中はとても充実していて楽しかった分、悔いを残しての幕引きとなってしまいました。二度と炙りサーモンは食べない。

オフィス

オフィスは東京都渋谷区の青山ファーストビル4F。
通りに面していて、駅からも遠くない、コンビニや食事処が近くにある好立地でした。
とても綺麗なオフィスで、コーヒーやお茶などが飲み放題、オフィス中央には社員の人が補充した軽食などが置かれていました。
お茶の飲み放題がとても良かったので、作業に疲れたら気分転換にお茶を汲みに行っていました。

オフィスの机は自動昇降機能付きの机で、高さを調整する機能付きでした。
オフィス内にはこの机を高くして立って業務に取り組んでいる方もおられました。

ファンコミュニケーションズさんの社員の皆さん

社員の皆さんはとても気さくで優しい方ばかりでした。
Scalaらしいコードの書き方についてアドバイスを頂いたり、親身になって一緒にデバッグして頂いたりと、お世話になりっぱなしでした。

まとめ

  • 学生に合わせた柔軟な実習
  • かなりガッツリ開発を体験
  • 社員さんが優しい

いいところばっかりの紹介になってしまいましたが、本当にいいところばっかりのインターンシップでした。

いろいろ助けて頂いてようやく完成させることができたMini-SSPをテストすることができなかったのは悔やまれますが、とても充実した4日間でした。
知らないことづくめでしたが、様々な新しいことに挑戦することができ、とてもいい刺激になりました。
これを読んでいる貴方の参加する一助となれば幸いです。

謝辞

実習中は色々と教えていただきました。
とても良い経験になり、沢山の刺激を受けることができました。
この場をお借りしてお礼を申し上げたいと思います。
ありがとうございました。

また、最終日には関係者の方々に多大なご心配とご迷惑をおかけしてしまいました。
今ではすっかり元気になりました。
まだまだ残暑の厳しい季節ですので、ご自愛ください。
生ものには要注意です。

1週間のデータ分析インターンを終えて

こんにちは.
F@Nさんの1週間インターンに参加した にしかわです.
インターンで行ったこと、感じたことを書こうと思います.

インターンに参加した理由

・就活イベントでお話させて頂いた時に社員の方が自社のシステムについて楽しそうに話していたので、自分もこんなエンジニアになりたいと思ったから.
・興味のある分野のインターンだったから.

何をしたのか

CTR予測をしました.
アドテクノロジーについて無知だったため、メンターの方にシステムについて丁寧に教えて頂きました.

SQLにつまずく

社内でのデータベースから特徴量を抽出する際に、SQLを使用しました.
アプリを作る際にちょこっと使ったぐらいのスキルだったので、1日目はほぼSQLにつまずきタスクが進みませんでした.

特徴量のエンコードにつまずく

性別・IDなどはone hotする必要があるので、LabelBinarizerというsklearnのメソッドを使いました.
なぜかエンコードできず、ほぼ1日悩んでいました.
原因がデータがfloat型だったことだと気づいた時は、発狂しそうでした.

ロジスティック回帰を使い、CTR予測

sklearnのLogisticRegressionを使用しました.
精度確認するため、ROC曲線、AUC値、Logarithmic Loss、Normalized Entropyという指標を使いました.
詳しいことはこちらを見てください.
https://tech-blog.fancs.com/entry/ctr-prediction-model-evaluation

カーネルとpcが落ちる

初日はjupyter notebookのカーネルが落ちるたびに驚いていましたが、1週間で普通のことだと悟りました.
しかし、pcが落ちるのは絶望ですね...
ダウンサンプリング大事

k-meansで新しい特徴量を作ってみる

特徴量の種類が少ないことが問題ということなので、既存の特徴量を用いて新しい特徴量の作成に挑みました.
サイトIDを使い、クラスタリングを行ってラベルを抽出しました.
以下が結果です.
campaign_id,frequencyを適用
AUC = 0.6726877465581093
Logarithmic Loss = 1.4451557532902062
Normalized Entropy = 2.700788250592528

campaign_id,frequency + 作成した特徴量
AUC = 0.6678840993331718
Logarithmic Loss = 1.366609496859506
Normalized Entropy = 2.6290588331512277

ちょっとよくなってる!

作成した特徴量の傾向を眺める

f:id:fan_a_nishikawa:20180831181154p:plain
gender 1は男性、2は女性を表しています.
クラス1は男性が多くて、2は女性が多いことがわかります.
サイトIDから性別をちょっとだけ予想できることを発見しました.

まとめ

とても良い環境でインターンをさせてもらえた

わからないことだらけでどうなることやらと思っていましたが、メンターの方が丁寧に教えてくださったので、なんとかタスクを進めることができました.
もくもくと作業したい時はほっといてくれるので、自分にとってとても作業しやすい環境でした.
あと、隣の席のインターン生がとても優秀だったので、色々教えてもらいました.←良い刺激になりました!

つまずくことが多かったですが、その分技術力を身につけることが出来ました!
メンターのt_sakaiさん、y_kawasakiさん、面倒を見てくださったa_uchidaさん、ランチに連れて行ってくださった社員さん、本当にありがとうございました.

自作アプリで広告配信

はじめまして、株式会社ファンコミュニケーションズで8月20日~24日の5日間インターン生としてお世話になりました大山です。
私は広告配信用モジュールnendSDKチームで自作アプリへのSDK導入を行ったので、その振り返りをしようと思います。

やったこと

1日目

まずは入社書類を記入し & アドネットワークの仕組みについて簡単に教えていただきました。
その後、今回のインターン課題を設定。私は最近趣味でAndroidアプリ開発を行なっており、ちょうどJavaからKotlinへと移行したところだったので、「Kotlinで開発がしたい!」と申し出ました。
最終的に自分のインターン課題は、現在開発中の自作Androidアプリを完成させ、nendSDKを利用してアプリ内で広告配信をするということに決定。
開発中のAndroidアプリというのは、自分がKotlinの練習も兼ねて作り始めた目覚ましアプリで、ざっくりとした仕様は以下の通り。

  1. 起きたい時間を入力し、アラームセット
  2. 時間になるとアラームが鳴り出し、同時に玉転がしゲームスタート
  3. 端末を傾け、玉を穴に落とさずゴールまで運ぶことでアラーム停止
    (神経を集中させるミニゲームで目を冴えさせて二度寝防止)

インターン開始時点でゲーム部分はほぼ完成していたので、今回は主に目覚ましアプリとしての部分を実装していくということに。
他には、広告の表示タイミングや広告形式の決定、Androidアプリの開発環境構築などを行って初日は終了。

2日目

ゲーム部分の微調整を行なった後、アラーム設定画面の作成開始。
アラームをセットした時間が来たら、当然他のアプリを起動していたり端末がスリープ状態であってもアラームが鳴ってくれないといけません。そこで、アプリがバックグラウンドにいる際に、設定時刻が訪れたという端末からの通知を受け取るレシーバー等も作成。
あまり使い慣れてはいないKotlinでの開発でしたが適宜ググりつつ大きな問題もなく進行。というか諸々Javaで書くよりシンプルになっててKotlin万歳!

3日目

 アラーム起動時の音楽再生処理も実装しアプリの主要機能は完成。
いよいよ広告表示機能の実装に移りました。
アプリやWebサイトで広告配信をするといった経験はゼロだったので、ここの作業が一番苦労するだろうと予測していました。
スケジュールとしては3日目をほぼ全部費やすつもりでいました。

 

結果としては、10分足らずでサンプル広告の表示に成功

f:id:fan_k_oyama:20180824181828p:plain

わかりやすい公式ドキュメントも用意されており、作業も単純でした。
特にバナー広告なんてレイアウトファイルやらに数行ちょちょっと足してあげるだけで作業が終了し、なんというか拍子抜け...。
広告表示が予想外に早く終わったので、その後はアラームのキャンセル機能追加だったりゲーム部分のステージ追加だったりといった細かい所を詰めていく段階に入りました。

4日目

 とりあえずアプリは仮完成。ということでSDK開発チームの方々にレビューしていただくことになりました。
しかし、コード共有のためにGitHubのリポジトリにプッシュしようとしているときに問題発生。(正確には初日の段階でローカルリポジトリに問題が発生していた)
強引に歴史改変を繰り返しながらなんとかコードレビューをしていただける所まで持って行けたのですが、この一連のGit作業にこの日の大半を費やすこととなり、Git力不足を痛感しました。精進します。

5日目

最終日ということでレビューしていただいた点を時間の許す限り修正。
加えて退社手続き書類を書いて、このブログを書いて、インターンは無事終了!

感想

nendSDKを使った広告表示は思いのほか簡単で、東京メトロの乗り換えは思いのほか大変でした。

インターンへの参加は今回が初めてだったんですが、オフィスは綺麗で作業環境は自宅より快適で全く不自由なく開発できました。
自分の書いたコードをレビューしてもらう機会は普段なかなか無いのでドキドキでしたがいい経験になりました。
また、お昼にはランチにも連れて行ってもらったりと社員の方々には大変お世話になりました。ありがとうございました!

1週間のSSP構築インターン by Scala を終えて

どうも、僕です。
え?知らない?それはそう。はじめまして倉林です。
5日間のScalaを使ってのSSP構築インターンということで色々やってきましたが、技術の突っ込んだことを書くとどうせ間違ったこと書きそうで怖いのでやったことを日記みたいな感じにまとめたいと思います。

この5日間でやったこと

1日目

Scalaはほんの少しだけ触ったことがあるくらいで、書き方に困ったら関数型ガン無視の脳筋コードを書くレベルです。
サーバーに関してもいじったことはないので、仕様書を渡されてまず何をするかを考えました。
「とりあえず、サーバーに必要なものを打ち込んでいくべ」的なノリで必要なもののインストール作業から入りました。(のちにこれが裏目にでる・・・)

今回、使ったのは
scala : 2.12.2
Play Framework : 2.6.18
です。

2日目

この日でSDK -> SSP -> DSPの流れを想定したリクエスト、レスポンスの受け渡しの大枠ができた感じです。
ただ、Scalaの非同期処理についてまったく理解ができていなかったので電車と自宅で頑張ってました。なお結局理解ができなかった模様。
この日はそこまで進捗という進捗を出すことができなかった。

3日目

この日は非同期処理で苦戦してました。
Future[List[Future[Hoge]]]みたいなネストした型をどう処理するかとかで悩んでたのですが、色々な方にフォローを受けながらなんとか解決をして仕様を完全に満たしてないですがローカル環境でリクエスト、レスポンスのできるSSPを作れました。
ひとまず安心して、整理のためにPlayで自動生成される使わないファイル群を削除したら。。。

Unexpected exception
ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, Configuration error: Configuration error[Cannot load class filters.ExampleFilter]

ふぁーーーー!!!消したファイル別に使ってないやんけ!!!!って心で叫んでました。

まぁ、conf/application.confファイルのExample.Filterをenabledにしたら直ったんですけどね。
どうでもいいところで時間を取られた。。。
でもこういったエラーにはこう対処するって知識はめっちゃ大事だと思うので逆に今回で知れてよかったと思うことにしました。
つーか、Play2.6のリファレンスくそやんな。

4日目

寝坊しました。
この日は一番Scalaを書いた日です。
正直、Play使ってると便利すぎて毎回決まり切ったコードしか書かないような感じになってしまうのですが(個人の感想)受け取ったレスポンスに対する処理とかは紛れもなくScalaでした。
Optionをどう使ったらよいか、いかにScalaらしく書くかなどを考えさせられる1日でした。
普段はJavaを書いているのですが、Scalaに触れてみるとこんな書き方ができるのか、イミュータブルになるとどんな利点があるのかなどを調べたりして他の言語とはまた違った興味深さや面白さがありました。

5日目

実際に本番環境に移してテストをする日です。
ここまでは思ったよりも順調(そんなことはない。)だったのですが、いざ本番のサーバーに移して実行するとまぁ動かないこと。
サーバーにインストールしたsbtのバージョンが悪かった、そもそもコードの書き方が悪かった(ブロッキング、ノンブロッキングをここで知った)etc...があり、なかなかうまく動かず、社員の方につきっきりになってもらい最終的にしっかりと動くものが作れました!!!
ただ、動くものは作れたがここからどうパフォーマンスをあげていくのかなどのことを考えたら「ここからがめっちゃ楽しいじゃん!」という気持ちになりました、いつもは単に動くコードを書くということだけを考えていて、どういう処理にしたらより高速になる、どういう非同期処理にしたら効率よくリクエストが捌けるなどは考えたこともなかったのでとても新鮮で面白いと感じました。

最後の方はこの記事を書くのだったりでバタバタしてしっかりしたSSPのテスト結果とかは用意できなかったです。ごめんなさい。
あ、ブランチでよいのならGithubのURLをあげておきます。
github.com

これ書いているときはまだ最新版をpushしていない罠
まだ自分なりに書き直したりしたいのでこれで許してください。

感想

5日間という短い時間でしたが、内容の濃く、楽しいインターンにすることができたと思います。
普段耳にするけど実際に触れたことのないアドテクについて触れられてとてもよかったです。
社員の方々も色々教えていただき本当にありがとうございました!!!
ここで学んだことをこのインターンで終わりにしないで、自分なりに復習して他でも活かせるように今後も努力していきたいと思います!
本当にありがとうございました!