F@N Ad-Tech Blog

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

Domain Adaptation Neural Networkを使ったCTR予測

5日間のデータ分析のインターンに参加させていただいた田中です。普段はデータサイエンスをやっています。

内容

今回のインターンでは、Domain Adaptation Neural Networkを使ったCTR予測を行いました。

Domain Adaptation Neural Networkとは転移学習のひとつで、ラベルのあるデータとラベルのないデータを使って、ラベルのないデータに対しても予測できるように学習します。

通常のNeural Networkを使用したCTR予測では、インプレッションすることが出来たデータしか学習に使用できません。よって、インプレッションすることが出来なかったデータに対しては予測精度が著しく落ちることがあります。しかし、Domain Adaptation Neural Networkの場合、インプレッションすることが出来たデータとインプレッションすることが出来なかったデータを使うことで、すべてのデータについて高い精度で予測することが出来ます。

1日目

午前は、アドテクについて教えていただきました。

午後からは、論文をいくつか読んで、Domain Adaptation Neural Networkを構築しました。 Domain Adaptation Neural Networkの構築にはPytorchを使いました。

2日目

始めは、データの前処理とデータの読み込みを実装し、Domain Adaptation Neural Networkの学習をしました。

次に、評価関数の実装を行いました。使った評価関数は、Log Loss、Normalized Entropy、AUC、ECE(期待カリブレーション誤差)です。

CTR予測では、クリックされる確率を予測したいのであって、2クラス分類をしたいわけではありません。つまり、Log Lossなどの評価指標は不十分です。そこで、クリックされる確率を評価するのにより適切なECEという指標を用います。ECEの計算方法は、まずカリブレーションカーブを求めます。カリブレーションカーブとは、データをいくつかのグループにわけて, それぞれのグループ内での予測確率と, データの頻度が一致していることを評価します。そして、対角線とカリブレーションカーブの平均絶対誤差を計算することで求められます。この指標を使うことで、より良いCTR予測モデルを作ることが出来ます。

f:id:yuk_tanaka:20190809185539p:plain
カリブレーションカーブ

3日目

テストデータを使って、Domain Adaptation Neural Networkのテストを行いました。この時に、実装した評価関数を使って評価しました。

4日目

GPUインスタンスを借りて、Domain Adaptation Neural Networkの学習をしました。ここで、実際に運用するときのことを考慮した前処理に修正しました。

5日目

修正したデータと修正した前処理を使ってデータを加工し、Domain Adaptation Neural Networkの学習とテストと評価を行いました。また、一般的なNeural NetworkとDomain Adaptation Neural Networkの比較を行いました。

結果は以下の通りになります。3つの評価関数において、Domain Adaptationを使ったほうが良いという結果になりました。

Neural Network Domain Adaptation Neural Network
Log Loss 0.674 0.661
Normalized Entropy 0.998 0.970
AUC 0.685 0.664
ECE 0.089 0.086

参考文献

www.jstage.jst.go.jp

感想

ハイパーパラメータチューニングと検証ができなかったのが少し残念です。わからないところは非常にわかりやすく教えてもらえるのでよかったです。改善のためのアドバイスもしていただきました。5日間という短い期間でしたが、とても成長できて楽しかったです。

ミニDSPを作りました!

こんにちは!8月5日~8月9日の期間でインターンに参加させていただいた伊東です。
今回ファンコミュニケーションズさんの【ミニDSP構築】のインターンに参加してきました!

とても楽しく、学びのあった一週間だったので、この場を借りて振り返っていきたいと思います!

このインターンを知ったきっかけ

2019年6月20日に開催されたサポーターズさんのエンジニア向け1on1面談会でファンコミュニケーションズさんと出会ったことがきっかけでした。

面談を通じてアドテクノロジーや働き方など様々なお話を聞くことができました。そこでとてもアドテクノロジーに興味が湧いたので、インターンに申し込みました。

面接

面接はとても楽しい雰囲気でお話しすることができました。質問はプログラミング経験や、プログラミングへの思いなどを多く聞かれました。
(夜に面接して、次の日の昼に合格の連絡がきたのでとても驚きました笑)

インターン参加前

インターンの使用言語はPHPでした。今までC言語やRubyを使っていたのですが、PHPは全く触ったことがありませんでした、、、(面接でPHP未経験なことは伝えてました笑)

そこでインターン前から猛勉強を初めて、基本的な参考書を1冊終わらせました。このレベルで大丈夫か不安でしたが、メンターさんが優しく教えてくれたので、無事作り切ることができました!

1日目

午前中は入社手続きや、社内案内などをしてもらいました。とても広く綺麗なオフィスだったので感動しました。特に昇降机がとても気に入って、疲れた時など実際に立って開発をしていました。笑

f:id:n_ito:20190809145303j:plain

午後からは【ミニDSP構築】の課題に取り組みました。DSPとは「Demand-side Platform」の略で、広告を表示させる仕組みの一部分のようなものです。少し複雑な仕組みなので、興味のある人は調べてみてください!

午後は課題の説明、パソコンのセッティングを主にしました。会社から支給されるパソコンなので、初期設定や環境構築などが少し大変でした、、、

今回のインターンではあるリクエストを受け取り、最適な広告、値段を返すAPIを作ることが課題でした。この時点ではあまりAPIもわかってなかったので、とても不安でした、、、笑


2日目

2日目から本格的に開発に取り組みました。とにかく仕様書通りに構築していきました。わからないところはメンターの方がなんでも教えてくれたので、どんどん開発が進んでいきました。

仕様書を読むこと自体もとても勉強になりました。簡単な仕様書ではありましたが、実際にプログラマーの業務を体験できたような気がしました。

3日目

3日目の終盤ではかなり完成に近いものができました。1、2日目でかなりDSPの仕組みについても理解できてきたので、一人でもかなり開発することができました。

ローカル環境でAPIを叩いて、仕様書通りのレスポンスが返せた時はとても感動しました。APIは漠然としたイメージしか知らなかったのですが、実際に作ることで理解がかなり深まりました。

ちなみにお昼にはエンジニアのピザパーティがあって、休憩時間中にピザを食べてました。笑
ざっくばらんに社員の方と話せてとても楽しかったです!ピザを食べ過ぎて午後の開発は少し眠かったです、、、笑

4日目

4日目はこれまでに作ったのDSPを負荷テストしたり、AWSを使って仮想サーバ上に動かしたりしました。AWSを使ったことなくかなり苦戦しましが、ここでもメンターさんが丁寧に教えてくれたのでなんとか使うことができました。

実際に自分の作ったDSPが返した広告がブラウザに表示された時はとても感動しました!AWSではメンターさんや他のインターン生と表示させる広告のオークションなどを行いました。

この日の夜は日本酒会という集まりに参加させていただきました!各自でお酒を持ち寄り、社員の方やインターン生みんなで飲んでいました。ただの会社の飲み会ですね、、、笑

5日目

午前中は退社手続きや細かい修正などをしました。書類を書いている時は少し寂しかったです、、、

午後からはインターン全体フィードバックや応用の課題に取り組みました。応用課題は難しくて、完成させることができませんでした、、、笑
応用課題は中途半端に終わってしまったので、家で完成させたいと思います。

全体の感想

とにかく5日間楽しく、学びのあるインターンでした!社員の方が楽しそうに働いているので、緊張することなくインターンの期間をを過ごすことができました。

会社の雰囲気を知れたこともとても良かったです。5日間エンジニアの方達と同じ空間にいたので、実際に働いている姿を見ることができました。一緒にいるからこそわかる自由な風土や、文化を知れてとても良かったです。

またわからないことがあってもメンターの方に聞ける環境だったので学べること多く、成長することができました!実際のDSPを作った時に出てくる課題など、様々な実践的なことも学べたのもとても良かったです。

5日間ありがとうございました!

RedisサーバをDockerで置き換えるインフラインターン

8月5日〜9日の5日間、ファンコミュニケーションズでインフラコースのインターンシップに参加させていただきました。

タイトル通り、稼働しているRedisサーバの内一台をDockerコンテナ内で動かすことに取り組みました。
その後、logやDBサーバの冗長化構成の調査と落とした時の動作確認、復旧手順の作成と実行を行いました。
詳しい日程と取り組んだ内容、得られた知見と感想について以下にまとめます。

日程

テーマ 課題
1 オリエンテーション・環境準備 社用PCをカスタマイズする
踏み台サーバにsshできるようにする
個人用インスタンスにsshできるようにする
個人用インスタンスでdockerを利用できるようにする
個人用インスタンスを、カスタマイズする
開発 CentOS 7ベースのDockerコンテナを起動する
ゴールを定める プロダクトは今、どう動いているかを理解する
2 リリース後に、どうなっているべきかを考える
考えた内容をメンターに説明する
考えた内容をGitHubのIssueに投稿する
DockerコンテナでRedisを起動する
Redisのセットアップ
PR作成
テスト項目を考える
テストコードを書く
3 リリース リリース時に、想定されるリスクを考える
リスクへの対応方法を考える
リリース後の確認項目を考える
考えた内容をメンターに説明する
考えた内容を作業PRにまとめ、レビュー依頼を出す
リリースする
まとめ ブログ記事の執筆など
4 リリース結果の報告会

​ 本番サーバの構築が終了したので、その後、本番サーバを停止する課題に取り組みました。 以下、課題の詳細になります。 ​

テーマ 課題
4 調査 sslサーバ3台以上にログインし、実際にどんな構成になっているか確認する
サーバにどんなリクエストがきているか調べる
リクエストはどう処理されているか調べる
処理中に登場するrsyslogへの出力箇所を見つける
rsyslogdのconfファイルを確認する
rsyslogdの転送先のサーバを調べる
各サーバが、何のログを最終的にどこに出力しているのかを調べる
各サーバが、どう冗長化されているか調べる
構成図を描き、メンターにレビューしてもらう
構成図を描き、インフラ/開発エンジニアにレビューしてもらう
障害試験 どのサーバ・どのプロセスを停止するか決める
停止したときに、何が起こるか想像する
想像したとおりになったか、確認方法を考える
想像したとおりにならなかった場合の対処方法を考える
障害試験の作業PRを出す
停止してみる
想像したとおりになったか、確認する
5 まとめ ブログ記事の執筆など
障害試験結果の報告会
スキップしたOptionalの課題をすすめる

※考える系の課題でも、はじめは必ずメンターとの対話形式ですすめる時間を確保する

対話しながら進めることができたので、とっかかりが掴みやすくスムーズに進めることができました。

やった事

既存構成の把握

nendのクリック処理を行っている部分をとっかかりに、オンプレミスにあるサーバの構成を把握し、構成図に起こしました。

f:id:t_murata:20190809120404j:plain
nend - クリック処理の既存構成図

MySQL部分のMasterとSlaveの関係はもっと複雑ですが、ソースから読み取れた分だけ記載しています。一部の詳しい構成は4日目にメンターさんから説明を受けました。

Redisコンテナの作成

稼働中のRedisバージョンに合わせてインストール。
設定ファイルもビルド時にコピーする。

FROM centos:centos7

RUN <Redisのビルドとインストール>

COPY conf.d  /path/to/redis/etc/
RUN mkdir /path/to/redis/data
EXPOSE<Redisのポート>

CMD ["/path/to/redis.conf"]
ENTRYPOINT  ["/path/to/redis-server"]

Docker(Redis)デプロイ

上記のDockerfileを元にデプロイ。

Rsyslogサーバ(AWS)を落としてみる

AWS上のlogサーバの内、一台を落とす。
影響の確認と落とした際の他サーバの動作を予想し、復旧時の動作確認方法をまとめる。
レビューを貰ったのち、実行する。

MySQLサーバ(Slave)を落としてみる&復旧する

AWS上のMySQLスレーブの内、一台を落とす。
落とすまでの手順とDBが壊れた際の復旧処理をまとめる。
レビューを貰ったのち、実行する。

日別のタスクとメモ

1日目

 - 開発環境にDockerを導入

 - 構成の大枠をメンターから教えてもらう
 - それを元に踏み台サーバからWebサーバにアクセス
 - httpd.conf等を見ながら構成を想像する
 - ps auxでどんなプロセスが動いているか確認
 - Rsyslogとzabbixのプロセスを発見したので、各設定ファイルを見てサーバのIPを特定
 - Rsyslogのロギング方法を確認

 - WebのLVSサーバを見に行く
 - keepalivedの設定が想像通りになっていることを確認

 - PHPのclick処理部分を読み始める
 - Define多すぎてよくわからなくなる
 - redis_manager.phpなどredisに関わる部分の処理を読む
 - どのサーバがどの設定ファイルを読んでいるかを把握する
 - clickがどのDBサーバを使っているかを大体把握する

2日目

 - 1日目に把握した構成を雑にまとめる
 - レビューをもらう

 - Redisスレーブのconfを確認してコピー
 - 開発環境のDockerにRedisコンテナを作る
 - Dockerfile記入
 - WARNINGが出る為、docker runのオプションとOS設定を変更
 - そのままのconfを適用すると動かなくなったので、ログを見ながらconf内容を修正

 - redis-cliを使ったテストをシェルスクリプトにまとめる

 - Dockerfileのissueを作成

3日目

 - Redis Dockerfileのレビューを受けて修正する
 - リリースの為の手順とPRを発行する
 - リリース手順のレビューを受ける
 - リリース手順を修正する

 - リリース!
 - 元に戻す

 - インターン中のまとめ

4日目

 - conversionのRsyslogと冗長化の調査
 - どのサーバ、どのプロセスを停止するか決める
 - 停止したときに、何が起こるかを考える
 - 障害試験の作業PRを出す

 - 実行!

 - インフラチームに成果発表

 - DB(Slave)を落としてみる
 - AWS CLIの書き方を調べる
 - DB落とす→復旧までの手順をまとめてPRを出す

5日目

 - DB落としてみて復旧作業。
 - インターンの振り返り

分かった事

一つのシステムの一部分のインフラだけでも、想像以上にサーバが多い。
影響を受けるサーバや本番への適用手順などを整理して、まとめる→レビューすることで抜け漏れやミスを防げ、新たな問題も見つけ出せる。
Warningは読み飛ばさない。結構重要な設定ミスだったりする。
Dockerやインフラを触る上で、Linuxや主要なミドルウェアの知識は必須。
知識があったら設定項目や構成をもっと素早く洗い出せたと思う。
ミーティングに参加していても、分からない用語が多数出てきたので出来る範囲で触ってみたいと思う。
シェルスクリプトとviが出来ると捗りそう。

この仕事楽しい!

長期間働けるならやってみたいこと

Docker上で動くRedisを増やして、最終的にはすべてのRedisサーバをDocker上で動かす。 デプロイからテストまでを自動化し、テストに失敗したらロールバックする構成を組みたい。Ansibleに組み込んでみたい。

既存のインフラを監視して問題点を把握できるようにしたい。
問題点を分析した上で、適切な対策ができるようになりたい。
システムの要件に応じた適切な技術の選定とインフラの0からの構築をしてみたい。
Kubernetesをオンプレミス環境で使ってみたい。

インターンの感想

本番環境にリリースするまでの流れを短い間に経験出来て、とても面白かったです。
システム構成を読み解くこと、その一部を変更することでどのような影響を及ぼすかを考えること、テストやリリースの流れと問題点を洗い出すことなど、それぞれのフェーズで考え、試行錯誤することが多く、楽しく過ごせました。
メンターや社員さんとの距離感もよく、悩んでも分からない部分に関しては質問がしやすかったので、スムーズに進めることが出来ました。

5日間、ありがとうございました!

CTR予測と精度向上をやってみた

初めまして、8月5日より5日間インターンでお世話になっている安村です。
今回、業務で蓄積された実データに触れてみたい!アドテク業界を知りたい!という思いでインターンに参加させていただきました。

1日目

午前は入社手続きや事業内容についてのお話や、社内案内などがありました。
午後からはインターンでの目標を設定し、本格的に業務が始まりました。
初めに頂いた入門資料をもとに、データベースからのデータの取得からロジスティック回帰を用いたCTR予測までの一連の流れを学びました。
この時、業務で蓄積された実データを扱えることにワクワクしつつ、1億行もあるデータに圧倒されていました。。。

2日目

学習データの傾向を掴むためにデータの可視化などをしていました。
ある特徴量において出現頻度に偏りがあることを発見し、説明変数が無駄に多くなっているのでは?などと精度向上のアイデアを考えていました。

3日目

説明変数が多くなっている問題があったため、ロジスティック回帰の代わりにLasso回帰を用いて学習を行ってみました。
学習データは5週間前から1週間前のデータ、テストデータは直近の1週間のデータを使用しています。また、データは不均衡データ(ほとんどクリックされない)であるので、学習データはダウンサンプリングしています。
下の表はテストデータにおけるロジスティック回帰とLasso回帰の評価指標を比較したものとなっています。

AUC LogLoss NE ECE
ロジスティック回帰 0.6862465 0.0285730 0.9784192 0.1156183
Lasso回帰 0.6375969 0.0290539 0.9948855 0.1114336

ECE(期待カリブレーション誤差)とは、予測確率と実際のクリック確率の誤差を間接的に表したものとなります。CTR予測では、クリックの有無の予測よりクリック確率が重要視されています。
実験結果より、AUC・LogLoss・NEの誤差が増加したもののECEが小さくなっていることより、CTR予測の精度が向上していることがわかります。

また、お昼にはピザランチがあり、エンジニアの方々とキャリアなどのお話が聞けて、非常に有意義な時間となりました。

4日目

他のモデルでも試してみようと新たにSGDにて学習を行いました。

AUC LogLoss NE ECE
ロジスティック回帰 0.6862465 0.0285730 0.9784192 0.1156183
Lasso回帰 0.6375969 0.0290539 0.9948855 0.1114336
SGD 0.6377311 0.0290611 0.9951336 0.1097917

Lasso回帰より精度が向上しました!

また、学習させている間にもデータの分析をしており、下図のように曜日によって学習データとテストデータのクリック数の分布に偏りがあることを見つけました。
テストデータの木曜日に急激にクリック数が増加していことがわかります。この日は8月1日で学生が休みに入ったため分布に偏りが出たのかもしれないなどと色々と考えていました。

f:id:r_yasumura:20190809184119p:plainf:id:r_yasumura:20190809184057p:plain

5日目

最終日の午前は、曜日によるクリック数の分布の違いについての検証を行いました。
新たに6月のデータを取ってきてSGDで学習させた結果が以下の表のようになります。

AUC LogLoss NE ECE
SGD (学習期間 : 7月) 0.6377311 0.0290611 0.9951336 0.1097917
SGD (学習期間 : 6月) 0.6375969 0.0290539 0.9948855 0.1004191

ECEの精度が向上していることがわかります。このことから、学習期間とテスト期間の特徴量の分布の違いが精度の悪化に影響していたと考えられます。

午後は、カリブレーションの改善方法であるProbability calibrationについて調べていました。
下記はその簡単なまとめとなります。

カリブレーションの改善について

Probability calibrationには主に二つの手法があります。

  • Platt Calibration
  • Isotonic Regression

ここでは、Isotonic Regressionによるカリブレーションの改善について説明します。

Isotonic Regression

Isotonic Regression(単調回帰)とは、あるデータに対して非減少関数を適合させるモデルのことです。
入力値f_iから予測値y_iを推定する式は以下のようになっています。
f:id:r_yasumura:20190809190113p:plain
ここで、mは単調増加関数です。
Isotonic Regressionの学習では、データに適合する単調増加関数mを求めることとなっています。

f:id:r_yasumura:20190809190256p:plain
[引用] : 1.15. Isotonic regression, https://scikit-learn.org/stable/modules/isotonic.html>

カリブレーションプロット

CTR予測では、クリックの有無(0/1, 目的変数)があるものの、クリック確率(真の予測値)は未知となっています。そこで、カリブレーションの評価方法としてカリブレーションプロットを用います。
カリブレーションプロットは、あるモデルからの出力結果を複数のグループにまとめ、グループ内での予測確率の平均と実際のラベル比率をプロットしたものです。対角線に近いほどカリブレーションが達成されていることを示しています。
また、カリブレーションの改善では予測結果を対角線に近づけるための処理を行います。

f:id:r_yasumura:20190809190939p:plain

Isotonic Regressionによるカリブレーションの改善

Isotonic Regressionによるカリブレーションの改善では、上記のグラフにおける予測確率の平均値を入力値f_iとし、実際のデータのラベル比率を出力値y_iするようなモデルの学習を行います。
これによって、あるモデルから出力された予測確率をIsotonic Regressionによって実際のデータのラベル比率に近づけることが可能となります。

参考文献

[1] Alexandru Niculescu-Mizil, Rich Caruana, "Predicting Good Probabilities With Supervised Learning", Appearing in Proceedings of the 22nd International Conference on Machine Learning, Bonn, Germany, 2005.

おわりに

今回が初めてのインターンで色々と不安を感じていましたが、メンターの片桐さんや内田さん・長田さんのおかげで楽しいインターンとなりました。本当にありがとうございました!
また、データ分析をしていく上でもっと技術があればもっと面白いんだろうなと思うことが多々あり、今後より勉強していきたいと思いました。

1週間お世話になりました!

新規サービスインターンに参加しました!

5日間新規サービスインターンに参加させて頂いた高橋です。
インターンでは、Nuxt.jsを使用して開発を行いました。

スケジュール

1日目 インターンの手続きと新規サービスの説明

午前中はインターンの手続きと説明を受けました。
午後からは新規サービスの説明を受け、何の技術で開発を行うのかを検討しました。
私は、普段からNuxt.jsを使用する機会が多く、また、配属された先でもNuxt.jsでよく開発しているとのことだったので、Nuxt.jsで開発することになりました。
支給されたPCの環境を整え、Nuxt.jsの環境をGitHubのリポジトリにあげました。

2 ~ 4日目 新規サービスの開発

2日目から新規サービスの画面の作成が始まりました。
午前中は必要なライブラリなどを調べました。
2日目から毎日12時から朝会(昼会ではない)を行いました。朝会では今日やることだったり、UIや機能面での疑問点などを出し合ったりしました。発言もしやすく、チーム一体となってサービスを作っていくことを体感しました。
午後からは画面の作成を開始しました。
認証にはFirebaseを使用しました。Firebaseを使用したことがほとんどなかったのでidTokenを取得するのに時間がかかりました。また、GAEにデプロイもしました。

3日目はFirebaseから取得したidTokenをvuex-persistedstateを使用してログインの永続化を行いました。Local Storageは使用したことはありますが、Cookieを使用したことがほとんどなかったので色々と調べながら開発を行いました。また、トップ画面も作成しました。

4日目はmiddlewareを使用しログイン画面へリダイレクトさせるように実装しました。middlewareもほとんど使用したことがなかったので、Nuxt.jsのライフサイクルや、どういう処理を行うのかを調べながら開発を行いました。
また、詳細画面も作成しました。詳細画面ではリロードをするとデータが消えてしまうため、nuxtServerInitを使用し、リロード時にAPIを叩くようにしました。

5日目 退社手続きとフィードバックとデプロイ

5日目の午前中に退社手続きをしました。もうインターンが終わってしまうのかという寂しさを感じました。
午後からはnuxtServerInitの修正をし、次にマイリストを作成しました。最終日は手続きなどで時間があまりなかったですが、トップ画面と詳細画面で使用したコンポーネントを使用したのでなんとかマイリストを作成することができました。
メンターの方からフィードバックを受けました。貴重な意見が聞けたので、今後に活かしていきたいです。
最後に自分の作成したものをGAEにデプロイし、インターン終了です。

感想

今までNuxt.jsで開発を行っていましたが、認証周りはあまりやってこなかったので技術力が上がった気がします。また、FirebaseやGAEなども触ったことがほとんどなかったので、いい経験になりました。
昼食時は、色々な部署の方と話す機会を設けて頂き、貴重な話を聞けたこともよかったです。
新規サービスのインターンは私が初めてだったことを知り、驚きました。
実際の業務を通して、やりがいを感じました。仕事の楽しさが少しわかった気がします。

1週間あっという間でしたが、内容の濃いインターンになりました。