FANCOMI Ad-Tech Blog

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

大学生3人組でインターンに参加させていただきました

2018/3/19~2018/3/23まで2018/3/21の春分の日を除いての4日間インターンに参加させていただきました。
メンバーはfopen(@fopen_s) , Kanon(@kanon_k4) , itosato(@it0sat0) の三人です。

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

参加者全員が立命館大学の新2回生であり、立命館大学で2017/11/25日に開催された通称「あいちゃれ」(正式名称:立命館大学 全国高校・大学ソフトウェア創作コンテスト(ICT Challenge+R))にてファンコミュニケーションズの方々より、アイデア部門で賞をいただきました。その際に「好きなものを好きなように作るインターンがある」ということを教えていただき、『自分が作りたいものを開発してよく、その上実践経験のあるプロのエンジニアさんに質問できるとか行くしかねぇなこれ!』と、思い参加させていただきました。

4日間でしたこと

今回は、「あいちゃれ」で提案した農家さんと学生さんをマッチングするサービス「CCCS~City & County side Connecting Service~」を実際に開発することにしました。

1日目

会社に到着すると用意された机に案内されました.荷物をおいて少し休憩するとミーティングルームに案内され、会社の大まかなルールと入社に必要な書類を渡されました。
インターンを行うにあたっての書類が新入社員とほぼ同等数書く必要があったため、午前中は社内ルールの説明やオフィスの案内、書類にサインする時間になりました。4日間という短い期間にも関わらず、しっかりと社内案内や書類。緊急時の対応等を用意していただいており大変好感がもてました。書類を書き上げると歓迎会でお昼を食べに行きましょうと声をかけていただき、一緒に昼食を食べました。
午後からはエンジニアの方を交えて現在考えている大まかなサービスシステムや使用技術について共有を行いました。その後メンバーでミーティング。実装する機能の洗い出しや全員のイメージを擦りあわせてから、最後にもう一度エンジニアの方を交えてシステムの概要を報告して、更なるアドバイスをいただきました。そこからは個人作業に入り、それぞれが担当する部分の大まかな開発の進め方や詳細部分の決定作業を行い、初日は終了!

2日目

fopen・バックエンド(Flask + db管理)
Kanon・jQueryでフロントとバックエンドを結合
itosato・(html + css + js)でフロント
という役割分担初日に決まったので朝から開発をはじめました。
フロント・バックエンドは順調に開発が進んだものの、jQueryからAPIサーバーにPOSTするとOPTIONSというメソッドを使用していてPOSTできない問題が発生し、半日溶かしてしまいました。
エンジニアの方も経験があったらしく、アドバイスをもらうことで何とか解決し一安心。
現在のWebブラウザでは、あるWebサイトが持つ情報が別の悪意あるWebサイトに悪用されるのを防ぐために備わっている防御機構(CORS)が原因でした。

3日目

フロント・バックエンドは開発スピードが早くはなかったが何とか滞ることなく、じわじわと進捗を生み続けることが出来ていました。
しかし、またしてもjQueryとFlask間でエラーが発生。
どうしてもFlask側から投げたCookieをjQueryで保持することができない問題が発生しました。
二日目の件についてはバックエンド側の対処で解決したため、レスポンスヘッダーにいろいろ設定してみたり、リクエストを変えてみたりしましたが、どうしても上手く行かずこれも半日程度溶かしてしまうことに。
エンジニアさんと議論した結果、決め手となる情報源を見つけることはできませんでしたが、どうやらhttp通信とajaxでは若干レイヤーが違うようなのでうまくいかなかった様子。試行錯誤することで上手くcookieを利用する手法があるかも知れないというところまでたどり着きましたが、進捗状況的に考える時間は無かったためレスポンスヘッダーにトークンをのせて返すことになりました。おそらくセキュリティ的によろしくないので真似する際は自己責任でよろしくお願いします。

4日目

インターン最終日だというのにFlaskとjQueryの進捗が芳しくなかったため、それぞれ気合を入れなおしたり、残り数時間じゃ実装できないと嘆いたりとバタバタしながらの作業。
結果的に動作させたい9割ぐらいの実装は完成しましたが、jQueryでリクエストを飛ばす際のエラーに時間が裂かれすぎてjQueryの実装をギリギリ間に合わせることが出来ませんでした。
バックエンドのセキュリティ対策も全くと言ってもいいほど出来ず……DBは生で叩いているのにエスケープが全くされていないため、SQLインジェクションやXSSもやり放題となっている現状のままではとても公開できそうにはありません。
後1日あればなんとか形になったと思いつつも、4日間という短い期間に目や肩や腰が痛くなったものの、プロの方々の手厚いサポートを受けながら真剣に開発が出来たということを今の時期から経験できたことは、とても大きな糧となりました!

社内の雰囲気

社内の雰囲気は、参加初日の月曜日こそ皆さんが疲れていたようでとても大きな声で話せる雰囲気ではなかったですが、火曜からはエンジニアさんがふざけあったり昼ご飯の時間にボードゲームで遊んだり、エンジニアの皆さんが笑顔で仕事をしており、とても良い職場だと感じました。

メンバーそれぞれの感想

fopen

社内は綺麗で働いている社員さん達も挨拶をすると必ず返してくれるため、とてもよい環境でした。
言語化できていない質問にも的確にアドバイスをしていただき、短い間でしたが技術的なサポートだけでなくイベントの開催や食事会を開いてくださったのですぐに緊張がとけて、会社になじむことができました。
とても成長できた4日間だったと感じています。様々なサポートありがとうございました。

Kanon

私はインターンに参加すること自体初めてだったので、色々と緊張もしていたりしましたが、最後は非常に楽しむことができてよかったです。
開発環境に関しては、もっと静かな部屋でキーボードのタイプ音だけが鳴り響くような場所を想像していたりしましたが、
社員のみなさんが色々会話していたり笑っていたりして、とても楽しい環境でした。
今回開発していた、Webアプリケーション自体はとても「よくできた」ものではなかったのですが、エラーが出たら質問できたり、構成について相談できたり、あたたかい場所でした。
ランチなどで他のインターン生の方との交流もすることができ、4日間とも非常に多くの知見を得られるインターンでした。
短い期間でしたが、ありがとうございました。

itosato

今回のような、がっつりサービスを開発するというインターンは初めてで、さらにフロント開発も本格的なものは今回が初めてだったのでいろいろと心配な部分が多かったのですが、サービス概要を詰めていくところからプロの方々のサポートを受けることができたので、自信をもって開発を進めることが出来ました!
初日からエンジニアの方も含めたランチや懇親会など、開発の部分以外もとても充実しており、エラーや不具合で苦しんだ部分もありましたが、とても素晴らしい経験をさせていただきました。4日間という短い間でしたが、本当にお世話になりました。ありがとうございました!

まとめ

・各々の技術アップにつながった
・個人で学ぶことが難しいDB設計などが学べた
・Web系は難しい……
・会社の雰囲気が伝わった

最後に

4日間という短い期間でしたが、入社から退社までのフォロー、技術的なアドバイス、歓迎会などのイベント開催など大変お世話になりました。とても楽しく勉強させていただきました。本当にありがとうございました!

インターンで圏論に目覚めた学生の話

3月19日から1週間お世話になっているy_koizumiです。
2月頭からインターンを転々としており
これが5社目で春休み最後のインターンとなりました。

普段は学生団体でチーム開発をしています。
技術領域としてはゲーム・Android/iOS・サーバといろいろ経験してきました。

インターンのブログを書くとのことで1週間で思ったことを
他のインターンなどの比較を踏まえながらツラツラと書いていきます!

やったこと

今回のインターンではviidleの機能開発をScalaでやらせてもらいました。
「viidleのアクション(View)を別アプリケーションで実行する」機能の一部を開発しました。

実際に担当したのは「Pub/SubのMessageをSubscribeしてHTTPリクエストを送る」というものです。

参加の経緯

他のインターン生と同じくサポーターズで面談したことがきっかけで
インターンに参加させていただくことになりました。

他の会社のインターンにも結構入っていたので
何か得るものがあるかな〜というラフな気持ちできていました

インターンの目的

・Scala触ってる会社を色々みてみたいと思ったから
・Scalaでの関数型プログラミング能力を向上させたかったから
・ScalaとかDDDやっている人たちとの人脈作り
この時点では圏論なんてことは頭の中にありませんでした(笑)

4日間の日程

・1日目:AkkaStreamsとGCPを使ってサンプルを動かす
・2日目:AkkaStreamsを本格的に使ってみる
・3日目:並列化によるパフォーマンスの向上、DDDについて雑談
・4日目:圏論について学習、ブログを書く、Rustについて雑談

1日目

業務内容

午前中は入社手続きをやりました。
他の会社よりも約2割り増しの記入量だったと思います ^^;

午後からは1週間でやることの説明と実装に取り掛かりました。
初めてAkkaを使うのでわからないことが多かったですが
石川さんに色々教えてもらって実装していきました。

余談

戦術的DDDを取り入れている最中とのことで、これからメンバーに浸透させていくのは大変だろうなぁと勝手に思っていました。
DDDを取り入れるのはどの会社でも苦戦しているようだったので
何かチームとして勉強していく方法はないものか自分でも探してみようと思います(笑)

2日目

業務内容

2日目はAkkaStreamsを使ってロジックの実装を行いました。
基本のSource、Flow、Sinkを理解して
BroadCastやZipなど色々な実装方法を試していました。

ドキュメントが英語なので少し苦戦しましたが
石川さんに助けてもらいながらロジックを実装することができました。

感じた事

石川さんが英語の文献をさらっと投げてきていたので
やっぱり英語の文献を積極的に活用しなきゃダメだなー感じました。

3日目

業務内容

パフォーマンス改善と認証情報の外部ファイル切り出しに取り組みました。
AkkaStreamsの仕様を理解するのが苦しかったので
石川さんに英語の記事を紹介してもらって頑張りました。

2日目で処理フローを分けていたのですが
これでは実装できなかったので処理フローを1本化して実装し直しました。

パフォーマンスの詳しい値を検証することはできませんでしたが
非同期で実行するため処理が詰まることは無さそうです。

圏論に興味を持ち始めた

機能開発がある程度落ち着いたら、関数型や圏論について色々お話しさせていただきました。
Scalaの基本的な操作はある程度できるようになっていたので
これからはモナドとかを学習していこうかなと考えるようになりました。

学生のためのインターンイベントに参加した

業務後にインターン生の成果発表イベント?なるものに参加しました。
イベントでは元営業の方とお話することができて新鮮でした。一人が数十社の企業を相手にすると聞いて面白そうな世界だなと感じました。

思い返すと、どこの会社に行っても人事、エンジニア、役員としか話していなかったので
営業の方と話すのは初めてだったかもしれません。

4日目

業務内容

3日目終了の時点でタスクは一区切りついたのでブログを書いていました。
ブログを書くこと自体は初めてで、ただ感じたことを書いたんですが大丈夫なんですかね ^^;

圏論について

石川さんや酒井さんから圏論についての話を聞いていると面白そうだなと思ったので、
午前中は関数型プログラミングと圏論についてひたすら情報を集めていました。

友達に数学科の人がいたので圏論について聞いてみると
「かなり抽象的だから数学をある程度やってから嗜むもの」
と言っていたのでかなり難しい概念なんだと再認識しました。
職業エンジニアの場合ライブラリの使い方を理解できていれば十分なのかな〜とも思ったりしました。

圏論を適用した高度なライブラリが開発され続けており、関数型プログラミング言語をやっていく上では重要な概念なので、これから1年かけて勉強していこうと思います。

まとめ

・技術的な気づきを多く得ることができたと思います。
・会社の雰囲気については、落ち着いてるな〜という印象を受けました。
・関数型の理解を深めるためのキッカケとなったのでよかった。
・ピザを沢山食べる事が出来た
・圏論頑張る。

1週間ありがとうございました!

ランチに誘ってくれた社員の皆さんありがとうございました!
石川さんと酒井さんとは技術的なお話をする機会が多かったのでとても助かりました!
内田さんにも手続き周りでサポートして下さりありがとうございました!

複数の機械学習モデルでCTR予測をしてみた。

こんにちは、弊社で2ヶ月間インターンとして働いているr_konumaです。
この記事では、2ヶ月間のインターンでやったことをまとめようと思います。

モデルを変えると精度は大きく変化するのか?

現状、弊社でCTR予測に使われている機械学習モデルがあるのですが、
他のモデルを使うことで精度が大きく変化するのかを検証しました。

2ヶ月間でやったこと

1. 大規模なデータベースへのアクセス

まず、CTR予測をするためのデータの取得します。
Treasure Dataにjupyter notebookから接続し、データをローカルの環境に引っ張ってきます。

ここで、初めてHive, Prestoに触れました。
(それぞれの言語に特徴があるので、処理したいクエリーに合わせて使い分ける必要がありました。)

CTR予測をするに当たって、クリックされたデータとクリックされなかったデータの割合には偏りがあったので、
そのまま訓練データとして扱うのには適していませんでした。

そこで、クリックされなかったデータをダウンサンプリングし、
訓練データとしました。

2. データ整形

引っ張ってきたままのデータでは学習することができないので、次にデータの整形をします。
ここは地道な作業になるので、もくもくとデータを綺麗にします。
具体的には、ダミー変数に置換したり、正規化を行ったりしました。

この段階では、データを綺麗にしつつ、
・どういうデータがあるのか
・あるデータはどういう形式で格納されているのか
・変数の値はどのようなものか, etc....
を見てたりしました。

3. データ中身を眺めてみる

せっかくデータを綺麗にしたので、少し中身を見てみました。
pythonのライブラリにはpandasがあるので、データを可視化が簡単にできました。
具体的には、デバイス比と報酬型広告かどうかの比率をみました。
f:id:fan_r_konuma:20180323162038p:plain:w400
デバイスはiPhoneが一番多く、また報酬型広告の方が多いことがわかりました。

さらに中身をみてみます。(ダウンサンプリングしているので現実の値とは異なります。)
f:id:fan_r_konuma:20180323120426p:plain:w400
クリック数が一番多いのはiPhoneですが、割合をみると全体的に大きな差があるようには感じられませんでした。
f:id:fan_r_konuma:20180323162252p:plain:w300
報酬型かどうかについては、報酬型である方がそうでない場合に比べて2倍違いました。
ただし、今回はダウンサンプリングをしているので実際は正確に2倍違う訳ではなく、
ここからわかることは、報酬型の方がクリックされる可能性があるということくらいです。

4. 複数のモデル作成と評価

評価方法には、ROC曲線とAUC値を用いました。
それぞれのモデルのROC曲線が違う色で示されており、右下にAUC値がまとめられています。
f:id:fan_r_konuma:20180323161109p:plain
ROC曲線を見てみるとわかるかと思うのですが、どれもさほど大きな変化はありませんでした。
しかし、下表のように、学習にかかる時間はロジスティック回帰が一番短かったので、今回試したモデルの中では、ロジスティック回帰が一番性能の良いモデルという結果となりました。

学習モデル 学習時間
ロジスティック回帰 58.0907 [sec]
LinearRegression 280.7520 [sec]
SGDRegressor 64.0105 [sec]
Ridge Regression 89.7170 [sec]
RandomForestRegressor 504.0530 [sec]

まとめ

  • 今回試したモデルの中ではロジスティック回帰が一番パフォーマンスのよいモデルである。
  • 機械学習モデルを変えるだけでは、精度に大きな影響はない。
  • 学習をさせる前に、モデルに対する特徴を理解して適切なモデルをいくつかに絞った方がよい。

機械学習モデルに関する理解をした上でライブラリを使わなければせっかくオープンにされている複雑なプログラムも有効に活用できない、というのが今回CTR予測をしてみた感想です。

ScalaのSくらいしか知らなかったモバイルアプリエンジニアですが、はじめてサーバーをつくりました

こんにちは、はじめましての方々ははじめまして。
3月5日〜3月9日まで1週間のインターンという形でお世話になりました。とやまです。

タイトルにもある通り今まで僕はAndroidのアプリ開発を中心に行ってきたいわゆるモバイルアプリエンジニアですが、Scalaへの興味とバックエンドエンジニアリングというまだ見ぬ領域について知りたくて今回のインターンに参加させていただきました。

その参加レポートを書かせていただきます。

1週間でやったこと

Play frameworkとFinagle(Finch)を使ったSSPの構築

1日目

 1日目はアドテク業界とアドテクサーバーの仕組みについて少し教えていただいた上で1週間のテーマを選定、その後ドワンゴ様が提供しているScala新卒研修テキストを頼りにScalaをおさらいしました。
聞いたところ、社内にはDSPに携わる方々は多い中、SSPに携わっている方は少ないこともあって、SSPを異なるフレームワークやライブラリを使ってベンチマークをする人がいなかったとのことです。
Scalaもあまり知らない上、アドテクについても全く知らなかったけど、せっかくインターンに参加するならわずかでも会社の役に立ちたいと思ってこのテーマをやらせていただきました。ちなみに、今回のSSPとDSPの実装仕様は以下のissueにあります。

github.com

2日目

 2日目は早速Play frameworkを使ってSSPを作ることからはじめました。
半日使ってそれっぽいものを作っていた感じはしていたのですが、僕が半日かけて作っていたものはHTTPサーバーではなく、ソケットサーバーだったことを1日のほぼ終わりどきに気づいて頑張って作り直しました。
最初は「やらかした」と思っていましたが、今となってはそれぞれの仕組みついて両方理解することができたので逆によかったなと感じます。

3日目

 3日目は、前日のPlayサーバー開発の続き、超簡易型DSPの開発を行いました。淡々とPlayとScalaを知るだけでなく、Scalaらしい関数型としての書き方も教えていただきました。特にfor式とyieldを使ったfor内包式のすばらしさにはとても感動しました。なるほど、mapやflatMapはこうやって実現できているのかと。改めてScalaの素晴らしさを思い知らされた1日でした。

4日目

 4日目はPlayサーバーのベンチマークテストとFinagleサーバーの開発を行いました。ベンチマークの結果についてはこの後書きます。
Finagleはそのまま使うのではなく、基本的にそのラッパライブラリを使うものだと聞いたのでFinchを使って実装を行いました。
はじめFinchを触って感じたことは、Playよりも応用がきいたライブラリなのか色々コードの自由度が高いなと感じました。JsonのパースもPlayの時のような最初からパーサーが付属されている感じではなく、circeなどのパーサーライブラリを使わなければならないことも自由度が高いと感じる部分でもありました。関数型に実装を近づけるならFinchだとということがよく分かりました。

5日目

 5日目はFinagleサーバーの実装をギリギリまでしました。本当はこのブログも最終日に書かなければいけなかったのですが、僕のムチャブリで後日提出する形にさせてもらいました。ありがとうございます。
褒められるほど綺麗なコードとまではいきませんでしたが、動くものが完成してベンチマークも行いました。最後はキリの良いところで終わることができたので良かったです。

1週間の成果

今回作成した2つのサーバーは僕のGithubにあげました。以下になります。

github.com

github.com

Finagleサーバーのベンチマークは後日酒井さんがプルリクエストを送っていただきました。

$ h2load -p http/1.1 -H Content-Type:application/json -d sample.json -c 100 -n 1000 http://localhost:9000/v1/ad
starting benchmark...
spawning thread #0: 100 total client(s). 1000 total requests
Application protocol: http/1.1
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 4.75s, 210.64 req/s, 30.79KB/s
requests: 1000 total, 1000 started, 1000 done, 859 succeeded, 141 failed, 0 errored, 0 timeout
status codes: 859 2xx, 0 3xx, 141 4xx, 0 5xx
traffic: 146.17KB (149681) total, 81.94KB (83911) headers (space savings 0.00%), 29.36KB (30065) data
                     min         max         mean         sd        +/- sd
time for request:    15.70ms       2.38s    363.72ms    654.46ms    89.90%
time for connect:      546us      4.49ms      2.50ms      1.02ms    60.00%
time to 1st byte:      2.25s       3.13s       2.43s    144.92ms    72.00%
req/s           :       2.11        3.10        2.75        0.14    88.00%

また、Playサーバーのベンチマークです。

$ h2load -p http/1.1 -H Content-Type:application/json -d sample.json -c 100 -n 1000 http://localhost:9000/
starting benchmark...
spawning thread #0: 100 total client(s). 1000 total requests
Application protocol: http/1.1
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 1.84s, 542.53 req/s, 203.50KB/s
requests: 1000 total, 1000 started, 1000 done, 1000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 2 2xx, 998 3xx, 0 4xx, 0 5xx
traffic: 375.09KB (384096) total, 302.77KB (310038) headers (space savings 0.00%), 88B (88) data
                     min         max         mean         sd        +/- sd
time for request:     5.19ms    615.94ms    172.32ms    110.00ms    78.40%
time for connect:      364us      6.84ms      3.37ms      1.91ms    57.00%
time to 1st byte:   128.61ms    146.79ms    137.70ms     12.86ms   100.00%
req/s           :       5.43        6.84        5.81        0.38    83.00%

確実な結果ではありませんが、Finagleで実装したサーバーの方が早そうです。

最後に

1週間と短い間でしたが、メンターとしてテーマやScalaについて真摯に教えてくださった酒井さん、他社員のみなさんありがとうございました。
初めてのScala、初めてのサーバーサイドでかなり苦労しましたが、多くのことを学ぶことができました。
また、アドテク業界の奥の深さについても知ることができて、この業界の興味がとても湧きました。
今後は自分でもっとScalaやデファクトスタンダードであるCatsについて勉強してしていくことで関数型についての学習を深めていきたいと思います。

アドテクサービスのデータで時系列解析した話

初めまして、3/5から1週間インターンとしてお世話になりましたt_nakashimaです。
普段は大阪で音声信号処理や機械学習のお勉強をしたりgolangを書くバイトしたりトランペットを演奏したりしています。

  • インターンに参加した理由
  • 何をしたのか
    • データ分析・機械学習の基礎
    • 広告SDKの組込み
    • 実際のデータを用いた時系列解析
      • 自己相関
      • 偏自己相関
      • SARIMAモデル
    • 参考文献
  • 感想
    • 楽しかったところ
    • 苦労したところ
  • 謝辞
続きを読む