F@N Ad-Tech Blog

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

ファンコミュニケーションズのインターンに参加しました!

はじめまして!京都で技術補佐員をやっている林と申します(秋から院生になります笑)。
今回は、9月9日~13日の1週間で、ファンコミュニケーションズで「広告配信システム(DSP)の構築」というインターンに参加させていただきました。このブログでは、インターンの参加までの流れから、インターンの内容や感想について書いていこうと思います。

インターン参加まで

この会社を知るきっかけにもなったのがサポーターズという会社が行なっている1 on 1 面談イベントでした。1番最初に面談をしてもらえたことがかなり記憶に残っています。このサポーターズでのイベントをきっかけに「そもそもアドテクって何?」「広告配信の裏側を知りたい!」と思い、このインターンに応募しました。オンライン面接での選考が行われました。
一度インターン参加確定になったのですが、私的な諸々の都合で日程をずらしていただき、9月9日から無事に参加させていただけることになりました。

前日から東京で宿泊していました。インターン中の宿泊先は外苑前という駅にあるホテル(神宮球場の目の前)だったのですが、そこが大変綺麗だったので、前日から一人でテンションが上がっていました笑。

インターンの内容

インターンの内容は、PHPを使ってminiDSPを構築する、という内容でした。最初は、「DSP???」という感じでしたが、初日に広告配信の仕組みを解説してもらい大枠を理解することが出来ました。気になる方は、「DSP SSP」とかでググると良い記事が沢山出ると思います。

具体的には、 SSPからのリクエスト(「Aというメディアが広告欲しがってるよ」、SSP)に対し、そのメディアの広告枠を買う金額を予測し(ここは対象外、ML)、最適な広告を決定して返す(「私たちはこの広告をこの値段で出すのが良いと思います」、DSP)という処理を実装しました。

初日

深夜に台風が関東を直撃した日だったので、会社には出社出来た数人しかいませんでした(運良く地下鉄は動いてた)。午前中は、書類の手続きと社内見学、SSP・DSPの説明、PCのセットアップ等がありました。
ランチは、入社して数年目の若手社員の方々と食べました。
午後は、メンターの人とオンラインで挨拶をした後(電車が動かなかったらしい)、仕様の説明や技術選定、開発のスケジュール等を話し合い、実際に開発に取り組んでいきました。

言語はPHPだったので素のPHPでも良いかなと思ったのですが、とりあえずAPIを光速で作りたいなと思ったので、自分が慣れているLaravelというフレームワークを使用しました。

その他、選定したものは以下になります。

  • PHP (Laravel, Lumen, Slim4)
  • Mysql 8
  • Redis × 2
  • Nginx
  • Fluentd

これらを全てDockerにのせ、Docker-Composeで立ち上げられるようにしました。
その後、今回のAPI作成で関わるモデルのDB設計をして、実際にAPI作成の途中までを行いました。

Docker化には以下の参考サイトが非常に役立ちました!
qiita.com

2日目

2日目はひたすらAPIを作っていきました。リクエスト毎にMysqlに接続するのは無駄な処理なので、Predisを使ってRedisにキャッシュさせるようにしました。

また、DSPサーバーからMLサーバーへリクエストをする必要があるので、Guzzleを使用してリクエストを送るようにしました。しかしながら、MLサーバーを立ててないことに気づいたので、Slim4という軽量のフレームワークを使って簡易的に立てました。(Laravelばっかりでもね・・・)

メディアタイプや金額でフィルタリングをする必要があるのですが、それはLaravelで使われているCollectionクラスで実装しました。

インターンの課題に含まれていた、イベントに対してログを出すという仕様も実装しました。(Laravelは便利!)

結果として、2日目で仕様に書かれていたAPIやログは一応全て実装できました!!

3日目

コントローラーに処理を殴り書きしていたので、関数に切り出す作業を行いました。

また、運用を考え、1つのRedisで書き込みと読み込みを行うのは負荷が高くなるので、書き込み用のRedisと読み込み用のRedisに分けることにしました。(世に言うmaster-slave構成です)

3日目のお昼は社内で食事をしましたが、昼以降はとあるイベントのため帰宅となりました。

(3日目の午後は、私は渋谷に行ってカラオケと本屋で楽しんでました笑)

4日目

4日目は、Redisのmaster-slave構成を終わらせ、AWS上でメンターに用意してもらったSSPとの連携を行いました。

その後に、速度計測をすると想定よりも遅かったので、速度改善にシフトしていきました。
具体的に行ったことは、不要な処理を削除し出来るだけデータ操作回数を減らしたのと、Slim4をLumenというフレームワークに変えたことです。

これとは別に、ログをFluentdで集約するように設定しました。

最終日

仕様を満たしていない箇所があったので(ログにmsecを残す部分)、そこを修正しました。AWS上で動いているかを最終確認し、発表のためのスライドを作成していました。

発表には多くの社員さんが来ていただき、無事に終えることが出来ました。

その後は、このブログ記事を書いて終わりです・・・。(あっという間でした)

感想

広告全体の仕組みやその裏側の仕組み等、アドテクの基礎が理解出来るようになったと思います。実際の技術や仕組み等も見ることができ、自分でもminiDSPを作ることが出来たのは大きな収穫だったなと思います。また、インターンを通して、自分が慣れている技術(Laravel)だけでなく、慣れていない部分(Docker, Redis, Lumen)にも触れられたので大変良かったです。

会社自体で言うと、とてもフレキシブルな会社だなと思いました。リモートで作業している社員さんが多いだけでなく、出勤・退勤時間も裁量労働制なのでかなり自由です。自分に合った働き方が出来る会社で素晴らしいなと思いました。

メンターさんについてですが、かなり優しく接して頂いたという印象です。技術的なことからサービス的なことまで、色んな質問に答えていただき非常に勉強になりました。

まとめ

インターンに行くことで会社の中の雰囲気を感じ取ることが出来て非常に良かったと思います。
また、アドテク自体への興味もかなり深まったので、個人的には最高に良かったインターンだと思いました。

短い間でしたが、インターンに受け入れていただき、また多くのサポートをしていただき、本当にありがとうございました!

ネット広告CTR予測業務体験記

データ分析コースのインターンシップに参加させていただいた大庭です。 今回はデータサイエンティストとしての働き方を間近で体感するためにインターンに応募しネット広告のCTR予測について5日間取り組みました。

CTR予測とは

ネット広告が表示される流れとして、ユーザがサイトに訪問したときに広告リクエストがアドネットワークに送信されます。 そのリクエストに含まれる情報により、広告主側が入札金額を決定し、その入札に勝った広告主の広告がサイトに表示されます。

このとき、広告主側は当然クリックの確率が高いユーザへ広告を流したいので、リクエストに含まれる情報から広告が表示されたときのクリックの確率を予測するというのがCTR予測です。

CTR予測の流れ

  1. DBからデータを取得する
  2. データを特徴量に変換する
  3. 特徴量をモデルに入力し、学習させる
  4. 評価

本記事では2~4について言及していきます。

2. データを特徴量に変換する

DBから取得したデータを予測に役立ちそうな形式(特徴量)に変換します。 例えば、DBにtimeと呼ばれる広告が表示された時刻を記録したデータがある場合、hourのような時間帯の情報に変換したり、土日か平日かなどに変換するといったことが挙げられます。

今回私は、

  • 広告の表示時間から時間帯を抽出
  • 広告開始から何日経っているか
  • wifiの有無
  • 貰った処理例から変数を減らす

などを検討しました。

3. 特徴量をモデルに入力し、学習させる

2で変換した特徴量を機械学習のモデルに入力、学習させます。

モデルには

  • 主成分分析
  • ロジスティック回帰

を用いました。 カテゴリカルな変数が多く入力次元数が数千となったため、主成分分析で次元圧縮を行い、ロジスティック回帰に入力しました。

  • 学習データ: 2019年8月の連続する平日3日間
  • テストデータ: 学習データの次の日(平日)

しかし、実データが膨大かつ不均衡 (クリック率がとても低い) なので処理の負荷を考えて 、学習データに関しては負例を一定割合取り除き (ダウンサンプリング) 、テストデータに関しては正例・負例を問わず一定数割合取り除き (ランダムサンプリング) ました。

ちなみに、今回はテストデータ (1日分のデータ) は5%を残すランダムサンプリングをしたのですが、それでも膨大なデータが残っていました。

また、ハイパーパラメータの探索にOptunaを用いました。

4.評価

CTR予測ではクリックされる確率を予測したいのですが、データに存在するのはクリックされているかの 0/1 データしかないので、適切な評価指標を定めにくいという問題があります。 そこで、予測確率と正解ラベルのないクリック確率の近さを測るキャリブレーション精度により評価します。(こちらの記事をご参照ください。)

結果

期待キャリブレーション誤差
最初に貰った処理例の結果 0.00033
改良した処理の結果 0.00022

f:id:fan_t_oba:20190906172241p:plain
最初に貰った処理例の結果

f:id:fan_t_oba:20190906172311p:plain
改良した処理の結果

期待キャリブレーション誤差の結果、私が改良した処理の結果の方が誤差が小さいですが、キャリブレーションカーブを見ると対角線から離れたグループがより見受けられる結果となりました。 深くは検証していませんが、貰った処理例で使われている変数を減らしたのと、主成分分析が結果に出たかなと思っています。

今回はここで時間切れでしたが今後の展望として、 ロジスティック回帰以外のモデルの検証 特徴量の検討 を行いたいです。

本番サーバを止めてみたよ。

参加した経緯

某マッチングイベントで仲良くなり、5日間のインフラ系インターンに参加させていただいた。

私は誰なのか

飛田一貴(通称: かずきち)です。
大阪の専門学生で、しがないWebエンジニアをやっています。
インフラは素人に毛が生えた程度にしか分かりません。

なぜインフラ系のインターンを選んだのか

今まではWebを中心にやってきましたが、自分のスキルの幅を広げたかったからです。

何をやったのか

端的に言うと、本番環境で動いているサーバを止めてみました。
それに至るまでにサーバの構成や役割、ユーザからのリクエストがどう流れているか等を調べ、最終的に「止めても問題ない」と判断できたサーバを止めました。

技術的な話

インフラの細かい構成の話とかをすると怒られそうな気がするので、代わりに技術調査メモをいい感じにまとめてここに貼り付けておこうかなあと思います。

sysctl

sysctlはLinuxカーネルのパラメータを確認したり変更したりできるコマンド。
カーネルの再構築が不要で、コマンドで動的に動作を変更できる。

systemctl

sysctlと似ているが別物。
systemctlsystemdを操作するコマンド。
サービスのステータスを確認したり、設定したりできる。
CentOS 6まではserviceというinitをいじくるコマンドが用意されていたが、CentOS 7からはsystemdが採用されたためsystemctlを使うようになった。
systemctl <operation> <unit_name> の形式で操作できる。

journalctl

systemdの動作している環境では、標準のログ(≒ジャーナル)収集・格納サービスとしてjournaldが用意されている。
journaldの操作は journalctl コマンドで行う。
よく使うオプションとして、ジャーナルを流し続ける -f や指定したサービスのジャーナルに絞る -u <unit_name> がある。

rsyslog

rsyslogsyslogというログを転送するための仕組みに信頼性(reliability)が担保されたもの。
TCPで転送できるようになったらしい。

LVS

LVSLinux Virtual Serverの略。
レイヤ4で動作するロードバランサ。
正確には、Linuxカーネルに組み込まれているIPVS(IP Virtual Service)というロードバランサの実装を用いて作ったクラスタのことを指している。
LVSの設定や操作には、 ipvsadm か、それをさらにラップした keepalived を使用する。

ipvsadm

あんまりよく分かっていない。
ipvsadm -Ln というコマンドでリアルサーバのweightとかアクティブなコネクション数、インアクティブなコネクション数を確認できた。
このコマンドでリアルサーバの生死を簡易的に判別できる。

keepalivedの設定

ここの設定を一番読んだ気がする。

リアルサーバ

リアルサーバとは、仮想サーバに関連付けられた実際のサーバのこと。

ウェイト

重み(weight)はヘルスチェックが成功/失敗する度にプライオリティをどれだけ上げるかとかそういう設定っぽい。
weight というパラメータに対して設定する。

ヘルスチェック

リアルサーバが生存しているかを確認するリクエスト。
delay_loop というパラメータに対してヘルスチェックを送信する間隔を設定する。

ヘルスチェックでどんなリクエストを送信するかを設定することができる。
例えば以下のように記述すると、 /foo.html に対してGETリクエストを送信し、HTTPステータスが200かどうかを確認する。

HTTP_GET {
  url {
    path /foo.html
    status_code 200
  }
}
タイムアウト時間

connect-timeout というパラメータに対して設定する。
ここで設定された秒数の間、ヘルスチェックが失敗するとリアルサーバがダウンしたと判断する。

再試行間隔

リアルサーバがダウンしている場合のヘルスチェックを再試行する間隔。
delay_before_retry というパラメータに対して設定する。

ヘルスチェック失敗時

ヘルスチェックに失敗した場合にweightを0にする設定として、 inhibit_on_failure という設定がある。

スケジューリングアルゴリズム

どのようにロードバランシングするかの種類(スケジューリングアルゴリズム)の設定。
lvs_sched というパラメータに対して設定できる。

スケジューリングアルゴリズム 説明
rr ラウンドロビン(round-robin)アルゴリズム。リアルサーバを設定順に選択する。全てのサーバに均等にトラフィックが分散される。
wrr weight round-robin。rrにweightによる重み付けを加味したもの。
lc least connection。コネクション数が一番少ないサーバを選択する。
wlc weight least connection。lcにweightによる重み付けを加味したもの。(コネクション数 + 1) / weight という計算式によってサーバが選択される。

SSL化していると、暗号化/復号化にそれなりの処理が必要なため、複雑なスケジューリングアルゴリズムを選択するとリクエストを処理しきれなくなることがあるらしい。
ちなみにスケジューリングアルゴリズムは他にも色々あった。

ステート

state というパラメータに設定する。
MASTER とか BACKUP がある。

転送方式

lvs_method というパラメータに設定する。
nat はNATで、LVSでアドレス変換をして返す方式。
dr はダイレクトルーティングで、LVSを介さずに直接クライアントへ返す。
ダイレクトルーティンではLVSの負荷が軽減されるというメリットがある。

感想

いつもと違う技術領域に触れることができたため、新鮮で刺激的でした。
また、現場で働いているインフラエンジニアの方から適切なアドバイスを貰うことができるため、効率的に学ぶことができました。
フロントエンド、バックエンド、インフラ、ネットワークと様々な技術領域やレイヤを扱うことのできるつよつよエンジニアを目指していきたい。

インターン:実業務体験編

 9/2~9/6インターンに参加させて頂いたYです。本名を言うのが恥ずかしいので、MIB風の名前でお許しください。

 最近は歴史ものにハマっていて、今回のブログは宮本武蔵が書いていた五輪書のような構成で書かせていただきたいと思います。

地の巻:参加するまでの経緯

 まずは簡単な自己紹介をさせていただきたいと思います。私は現在情報理工学を勉強している大学院1年生です。本当は意識高い学生みたいな感じで書きたかったのですが、正直に話すと、今年の4月に入ってから

=============================================
なんとなくそろそろ就活を動きださないマズイなと思い始める
          ↓
なんとなくCodesprintというエンジニア就活向けのサイトを知る
          ↓
なんとなく逆求人イベントに応募してみる
          ↓
なんとなくファンコミュニケーションズさんに声を掛けていただく
          ↓
なんとなくwebサービス開発に興味があって参加してみた
=============================================

という全く参考にならない意識低い学生でした。でも元々物作りや新しい技術を勉強することが好きで、せっかくこのような勉強させていただく機会があるから、参加しないと絶対後悔すると思い、お話しを頂いたとき、即参加すると決めました。

水の巻:一週間の流れ

 今回私が参加したのは実業務体験コースで、社員さんが普段実際にやられている仕事を一緒にやるという感じでした。事務作業を含むこの一週間の大体のスケジュールは以下のようになります。

  • 月曜日:入社手続き 社内見学 開発環境の設定
  • 火曜日:タスク①の開発作業
  • 水曜日:タスク①のリリース作業
  • 木曜日:タスク②の開発作業
  • 金曜日:退社手続き ブログ作業 一週間の成果発表

 最も仕事密度が高いのは火水木の三日間でした。長いように思われますが、新鮮な体験ばかりで、三日間合わせた体感時間は6時間半くらいで、本当にあっという間って感じでした。ちなみに、ブログを書いている金曜日11時20分現在では、午後の成果発表の準備は13%くらいしかできていません。ちゃんと発表できるか正直凄く不安です。

火の巻:主にやったこと

 今回はファンコミュニケーションズさんのサービスであるnendに関する開発業務を二つやらせていただきました。実際に書いていたコードや詳しい開発画面をお見せできないので、雰囲気で感んじていただければと思います。

①情報を削除する際に警告を出す

 お客さんが間違って必要となる情報を削除してしまって復元してほしいという報告を受け、このような依頼がきました。具体的には、削除ボタンを押したあとに、「本当に削除して宜しいでしょうか」みたいな警告を出すという仕組みを作る仕事でした。使い慣れていない開発環境やプログラミング言語もあったのですが、無事に期間中にリリースができて凄く達成感を感じました。

②検索機能に新たな検索項目を追加する

 文面通りに検索機能の項目一覧に新たな検索項目を追加する仕事でした。最初はそれほど難しい内容ではないと思っていたのですが、途中に開発要求の仕様変更があったり、変更したコードが別のところにも使われていることが判明し、やり直すことになってしまったり、思っていた以上に時間がかかってしまい、苦労しました。でも、これもエンジニアの醍醐味だと思うので、結構楽しんで作業をしました。残念ながらインターン最終日の金曜日は基本リリース禁止なので、インターン期間中にリリースすることができず、ちょっとした心残りです。

(追記)※ 上記の機能、無事にリリースできてました!

風の巻:感じた雰囲気

 今回のインターンに参加する前は、IT会社の社員さんはTシャツジーパンで、パソコン画面とにらめっこしながらキーボードをガチャガチャするという勝手なイメージを持っていました。実際にファンコミュニケーションズさんで一週間働いてみたら、「あっ、思ってた通りなんだ。本当にそうなんだ」と、イメージが覆されませんでした。でも、これはだらしないとかチャラチャラしているとかの悪い意味ではなく、嫌な緊張感がないリラックスしている状態で仕事できる環境が整えられているという意味です。
 また、モブプロという開発チームの皆さんが一緒にプログラミングをする会にも参加させていただきました。より良いサービスを提供できるように、皆さんが意見を出しあいながら、共にさらなる高みを目指して頑張っている感じは個人的に凄く好きです。内容は難しく、正直全てを理解することができませんでしたが、社会人の仕事スタイルも含め、勉強になったことがたくさんありました。

空の巻:感想&今後について

 私はエンジニア就職希望なので、今回のインターンを通して、エンジニアが普段どのような感じで仕事をしているのかをかなりイメージを掴みました。まだまだかじった程度に過ぎないですが、PHPやDockerなど、新しい技術も勉強できて、本当に大変有意義な一週間でした。一方、メンターさんがいないと、とても一人でできるとは思えない仕事なので、自分の実力不足を痛感しました。
 これから本格的に就活が始まると思うので、今回の経験を糧にして就活頑張っていきたいと思います。短い間ですが、本当にお世話になりました。ありがとうございました。
 

インターンでCTR予測をしました

初めまして、9月2日から9月6日の5日間、ファンコミュニケーションズのインターンでお世話になった高専生4年の天野まゆです。今回はデータ分析ということでCTR予測というものに取り組みました。

CTR予測とは

CTR(Click Through Rate)はクリック率といい、動画や画像などの広告が表示された回数に対してどのくらいクリックされたかを割合で表します。
また、CTR予測を行うことによってユーザーのニーズがわかり効率的に広告を表示させることができます。

学習、テストデータの用意

CTR予測を行うために、必要なデータを用意します。しかし、そのままデータを出してしまうと不均衡データであったり、膨大な量のデータになってしまうのでハンドリングが大変になります。なので、今回は以下に示す2つの方法を使って学習、テストデータの用意をしました。

ランダムダウンサンプリング

データの中から等しく抽出(無作為抽出)し削除すること

ダウンサンプリング

不均衡なデータで偏った方のデータ削除すること

モデルの作成

テストデータが用意できたところでモデルを作成していきます。今回はscikit-learnというPythonの機械学習ライブラリを使ってモデルの作成を行いました。
まず、scikit-learnで学習するために先ほど作成したデータを数値化する必要があります。そのためにone-hot変換をしました。
one-hot変換が終わったところでモデルの作成に取り掛かります。今回は、ロジスティック回帰を使った予測モデルをインスタンス化し、fit関数で学習を行いました。

モデルの評価

今回のモデルの評価方法には、AUCとROC曲線を使いました。

ROC曲線

横軸をFalse Positive Rate(正解が負であるものを間違えて予測する割合)、縦軸をTrue Positive Rate(正解が正であるものを正しく予測した時の割合)とした時にできる曲線のこと。

AUC

ROC曲線下の面積。1に近くなればその予測モデルの精度は良く、0.5に近くなればランダムに予測して当たっていることになるので予測モデルの精度は悪いことがわかります。

これらを使って出た結果が以下のグラフのようになります。

f:id:fan_m_amano:20190905174348p:plain
ROC 曲線とAUC結果

※ グラフ内に書いてあるareaがAUCの値です。


AUCが1に近ければ近いほど精度が良いのですが、どこかで間違えてしまったのか非常に精度が悪い結果になってしまいました。

感想

データ分析は学校の授業でデータの取得から正規化、簡単な解析をやっていたのですが、生の膨大な量のデータを目の当たりにして最後までできるか不安でした。ですが、メンターの方がわからないことなど丁寧に教えてくださった甲斐もありなんとかモデルの評価までたどり着くことができました。今回は初めてのインターンということでとても緊張していましたが、食事会を開いてくださったり、社内も非常に過ごしやすく楽しい5日間を過ごせました。短い期間でしたがありがとうございました。