Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

What is spray?

What is spray

spray | Introduction » What is spray? はてなブックマーク - spray | Introduction » What is spray?

adtech × scala勉強会でsprayの事例が幾つかあったので軽く触ってみることにしました。上のWhat-is-sprayで紹介されている内容をここでも簡単に記述しておくと以下のような感じです。2014.12.23日現在、最新のVersionは1.3.2のようです。尚、本記事の実験環境はCentOS Linux release 7.0.1406 (Core)で動かしています。

  • Akka上で動く、HTTP/RESTをサポートしたクライント/サーバーサイドのライブラリ。
  • JVMのlayerを触りたい場合もレガシーなJavaの実装が必要なくscalaAPIの記述で事が足りる。
  • sprayはフレームワークというよりはライブラリ志向で作られている(哲学的に)。
  • 完全非同期、Non-Blocking。
  • ActorとFutureベース。
  • ハイパフォーマンス、軽量、テスト可能。
  • twirlというtemplate engineもある。
  • 中心となるspray-io、インメモリのキャッシュであるspray-caching、spray-io上でClient/Serverとして動くspray-can、Servlet上で動かすためのspray-servletなどのモジュールが用意されている。

Getting Start

Hello world

Getting Started with sbt — Installing sbt on Linux はてなブックマーク - Getting Started with sbt — Installing sbt on Linux
まずはscalaのbuild toolをinstall、次にsprayを動かしてみます。プロジェクト名はhello-worldとします。以下の実行によりHTMLを吐き出すところまでは出来ました。spray-templateはspray-can上でspray-routingを実行するためのtemplateなようです。

$ wget https://dl.bintray.com/sbt/rpm/sbt-0.13.7.rpm
$ sudo yum localinstall sbt-0.13.7.rpm -y
$ git clone git://github.com/spray/spray-template.git hello-world
$ cd hello-world
$ sbt
> test
> re-start
$ curl "http://127.0.0.1:8080/"

<html>
   <body>
      <h1>Say hello to <i>spray-routing</i> on <i>spray-can</i>!</h1>
   </body>
</html> 
Source Code

以下のパスに設定ファイルおよび起動、実行されているプログラムが記載されています。

hello-world/src/main/resources/application.conf
hello-world/src/main/scala/com/example/Boot.scala
hello-world/src/main/scala/com/example/MyServer.scala

実行したいPathinfoを切り替えたい場合はMyServer.scalaの中のMyServiceに記載されているpathのパラメータを変更します。

// this trait defines our service behavior independently from the service actor
trait MyService extends HttpService {

  val myRoute =
    path("hello") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete {
            <html>
              <body>
                <h1>Say hello to <i>spray-routing</i> on <i>spray-can</i>!</h1>
              </body>
            </html>
          }
        }
      }
    }
}

re-start後に再度curlします。helloのパスが有効化されました。

$ curl "http://127.0.0.1:8080/"
The requested resource could not be found.
$ curl "http://127.0.0.1:8080/hello"

<html>
   <body>
      <h1>Say hello to <i>spray-routing</i> on <i>spray-can</i>!</h1>
   </body>
</html>

以下のように記述するとpathの条件分岐が可能です。

val myRoute =
    path("hello") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete {
            <html>
              <body>
                <h1>Say hello to <i>spray-routing</i> on <i>spray-can</i>!</h1>
              </body>
            </html>
          }
        }
      }
    } ~
    path("world") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete {
            <html>
              <body>
                 <h1>Say world to <i>spray-routing</i> on <i>spray-can</i>!</h1>
              </body>
            </html>
          }
        }
      }
    }

上記はvalおよびpathの定義で分岐させましたが、traitの分岐も可能です。こうするとCodeの可読性が良くなる気がします。

class MyServiceActor
  extends Actor
  with ServiceHello
  with ServiceWorld {

  def actorRefFactory = context

  def receive = runRoute(helloRoute ~ worldRoute)
}


trait ServiceHello extends HttpService {

  val helloRoute =
    path("hello") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete {
            <html>
              <body>
                <h1>Say hello to <i>spray-routing</i> on <i>spray-can</i>!</h1>
              </body>
            </html>
          }
        }
      }
    }
}

trait ServiceWorld extends HttpService {

  val worldRoute =
    path("world") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete {
            <html>
              <body>
                <h1>Say world to <i>spray-routing</i> on <i>spray-can</i>!</h1>
              </body>
            </html>
          }
        }
      }
    }
}
twirl

spray/twirl はてなブックマーク - spray/twirl
TwirlというTemplateEngineを導入してみます。まずはtwirlをproject/plugin.sbt、build.sbtに以下の内容を追加します。各行の追加は空行が必要なので気をつけてください。

# project/plugin.sbt
addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.2")

resolvers += "spray repo" at "http://repo.spray.io"

addSbtPlugin("io.spray" % "sbt-twirl" % "0.7.0")

# build.sbt
Twirl.settings

次にtemplateを追加します。main直下にtwirlディレクトリを作成し、index.scala.htmlなどを配置します。index.scala.htmlの内容を以下のものとします。templateの記述方法はplayframeworkと同等になります。最後にMyServer.scalaで変数のpに値を渡してあげると、埋め込んで出力してくれます。

// MyServer.scala
trait MyService extends HttpService {

  val myRoute =
    path("") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete (
            html.index.render("twirl").body
          )
        }
      }
    }
}

// index.scala.html
@(p: String)

<!DOCTYPE html>
<html>
<body>
  <p>Hello-World @p</p>
</body>
</html>
curl "http://127.0.0.1:8080/"

<!DOCTYPE html>
<html>
<body>
  <p>Hello-World twirl</p>
</body>
</html>

MysqlとのConnection

Slick OR Mapper

sprayからmysqlに接続するためにSlickというOR Mapperを利用します。まずはmysqlとの接続driverとslickをbuild.sbtに加えます。Slickは使用するVersionによって記述が大きく異なるので注意が必要です。この記事では2.1.0を利用しています。Slick - Scala Language Integrated Connection Kit — Slick 2.1.0 documentation はてなブックマーク - Slick - Scala Language Integrated Connection Kit — Slick 2.1.0 documentation

$ diff -u build.sbt build.sbt.bak
--- build.sbt	2014-12-23 13:45:33.476276736 +0900
+++ build.sbt.bak	2014-12-23 13:39:23.122278989 +0900
@@ -16,8 +16,6 @@
     "com.typesafe.akka"   %%  "akka-actor"    % akkaV,
     "com.typesafe.akka"   %%  "akka-testkit"  % akkaV   % "test",
     "org.specs2"          %%  "specs2-core"   % "2.3.11" % "test",
-    "mysql" % "mysql-connector-java" % "5.1.25",
-    "com.typesafe.slick" %% "slick" % "2.1.0"
   )
 }

あまり良く無い例ですが、http://127.0.0.1:8080にアクセスしたタイミングでMyServiceから直接Mysqlに接続してTableの作成、データのInsertを行います。理想としてはDBSchemaClass、Connectionを別途定義することだと思うので、気になった人は自由に書き変えてください。

trait MyService extends HttpService {
  class Customers(tag: Tag) extends Table[(Int, String, String)](tag, "customers") {
    def id = column[Int]("id", O.PrimaryKey)
    def name = column[String]("name")
    def email = column[String]("email")
    def * = (id, name, email)
  }
  val customers = TableQuery[Customers]
  Database.forURL("jdbc:mysql://localhost/test?user=root&password=",
    driver = "com.mysql.jdbc.Driver") withSession {
    implicit session =>
      try {
        (customers.ddl).drop
      } catch {
        case e:Exception => println("table not found")
      }
      (customers.ddl).create
      customers ++= Seq(
        (1, "foo", "foo@com"),
        (2, "bar", "bar@com")
      )
  }

  val myRoute =
    path("") {
      get {
        respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here
          complete {
            <html>
              <body>
                Create/InsertDB is Completed
              </body>
            </html>
          }
        }
      }
    }
}
$ curl "http://127.0.0.1:8080/"
<html>
  <body>
     Create/InsertDB is Completed
  </body>
</html>

mysql> select * from customers;
+----+------+---------+
| id | name | email   |
+----+------+---------+
|  1 | foo  | foo@com |
|  2 | bar  | bar@com |
+----+------+---------+
2 rows in set (0.00 sec)

DMP vs DSP : CookieとDataのSync

Syncの流れ

f:id:yutakikuchi:20141119011539p:plain

How does cookie sync work between DMP and DSP? - Quora

上のQuoraにデータ分析した結果を売ってお金にしたいDMP分析された結果を広告配信のターゲティング精度に還元してお金にしたいDSPとの間でCookieの同期とデータ分析結果の受け渡しについて良いまとめがあったので要約したいと思います。上の内容に書いてない事で僕が知識として持っていることも加えておきます。

Cookie Sync
  • 特定のWebサイトはサイト分析やより精度の高い広告配信のためにDMPのJavaScriptタグを設置する。
  • 設置されたDMPのJavaScriptタグはDMP側での分析サーバに送られるリクエスト以外にDSPドメインのpixelタグが含まれている。
  • DMP/DSPの両方にRequest処理が走り、そのResponseを受け取るのでCookieがDMP/DSPそれぞれで発行される。通常のCookieの場合はブラウザを識別できる一意のIDが付与されている。(※以下の説明ではCookie = ブラウザ識別のための一意のIDと置き換えて考えて良い。)
  • DMPおよびDSPCookieがそれぞれ異なるが同一のブラウザだと認識する必要があるので、Cookie対応表を作成し少なくともDMP/DSPのどちらか一方で保持する必要がある。
  • CookieRFCの規格により特定ドメイン内でのみ有効なので、HttpHeaderのリクエストでCookieを別ドメインに直接渡すことはできない。
  • DSPのpixelが呼ばれるときにDMPのCookieをRequestパラメータとして渡せば、DSPDSPCookieとパラメータからDMPのCookieの両方が取得できるので、DSP側ではそれの対応表が作成することができる。もし対応表をDMP側で対応表を持つ場合はDSPCookieをパラメータとしてDMP側のサーバにRedirectする。
  • もし対応表を作成するタイミングでDSPCookieがまだ無ければ新規発行し、HttpResponseとして返す。
  • 処理の流れのイメージは上図参照。
Data Sync
  • CookieのSyncはOnlineで行うのが一般的。DMPの分析データはOnlineのリアルタイムで行うと処理コストが大きいので、Offlineのバッチ処理で行う。
  • DMPはDMPのCookieに紐づく各種Webサイトから収集した行動履歴によりAudienceの分析を行い、結果をDSP側にバッチ処理で転送する。
  • DSP側は対応表からDSPCookieに紐づくデータに変換してAudienceの分析データを利用する。

機械学習のOverfitting対策

Overfitting対策

How can I avoid overfitting? - Quora はてなブックマーク - How can I avoid overfitting? - Quora

機械学習で偏った学習データに適合したモデルを評価データに対して利用した場合、精度が悪い結果が得られることがあります。単純にモデルにInputする訓練データが少なかったり、局所領域に存在するデータ扱っていたり、モデルの自由度が高く複雑である事など幾つか原因が考えられ、上のQuoraで解決策について意見が書かれています。ここでは結論として書かれた内容について簡単に紹介します。

K-Fold Cross Validation

単純な解決方法としては学習時に偏ったデータに適合しすぎないように学習データをK個のまとまりに分割して、K-1個のデータを用いて学習、残りの1個を用いて評価する作業を組みわせパターン全てで行うというK-Fold Cross Validationという手法が用いられます。こうすることによってデータの偏りは防ぐことができますし、モデルの汎化性能(評価データへの適用能力)を正しく評価することも可能であり、複数のモデルからより秀でたモデルを選択する手段としても有効かと思います。

Regularization

Regularizationは過学習を抑止するためのペナルティ項で、モデルのパラメータがより複雑になればなるほど値を大きくする仕組みです。 代表的な例としてL1,L2,L1L2正則化といったものがあり、それぞれ精度やメモリの消費、スパース具合が異なります。よく目にする報告としてはL1がL2よりも計算量が少なく済む(精度が低く、スパースになりがちであるため)があります。Support Vector Machineの一つのツールであるliblinearを例にとると、学習コマンドであるtrainで学習データを指定すると同時に正則化パラメータを設定することが可能です。
Support Vector Machineは特徴ベクトルの「マージン最大化」により分類を行う手法ですが、綺麗にデータを分類できない場合にマージンの具合を決めるための定数Cというものを指定したりします。Cを大きくすると誤りを許さないハードマージン、Cを小さくするとソフトマージンで多少の誤差は許容とするという働きになります。正確にはRegularizationとは異なりますが、役割は似ているところがあります。

Recsys2014の発表から現在のRecommend Systemの問題点を読み取る

集合知プログラミング

集合知プログラミング

Recsys 2014 Tutorial - The Recommender Problem Revisited

Recsys 2014 Tutorial - The Recommender Problem Revisited はてなブックマーク - Recsys 2014 Tutorial - The Recommender Problem Revisited
仕事でRecommenderに関わっているのでRecsys2014の最初の発表を読んで現在の問題点を再確認したいという気持ちで、内容を起こしてみます。途中に出てくる数式の理解および書き写しが大変なので、概要だけ書きます。また意味を理解するためには「機械学習の手法」と「Recommend」に対する知識をそれなりに必要とされます。

The Recommender Problem

  • Recommendは古くから"過去の行動履歴"、"他のUserとの関係性"、"アイテムの類似度"、"Context"に基づいてどのようにUserがアイテムを好むかを自動的に予測する便利な関数を作る事である。
  • RecommendationはDataを基に前処理、モデルの学習、テストおよびValidation評価をする一般的なデータマイニング問題としてみなすことが可能。
  • 機械学習以外の側面として、UserInterface、Systemの要件定義、セレンディピティ多様性、気づき、説明などの要素がある。
  • セレンディピティは直接求められていないものを探す。Userが既に知っているアイテムを紹介してはいけず、Userを興味に近しい領域に拡張させる
  • 様々なカテゴリジャンルのアイテムを表示する事が多様性と気づきである(意訳)
Collaborative Filterling (CF) Traditional Methods
  • 協調フィルタリングには似ているUserベースでの予測をするものと(Personalized)、全てのUserの平均でのやり方がある(Not Personalized)。
  • 手頃な手法でRecommendを作ることは簡単だが精度を改善することは難しい。手頃な手法と精度の間にはビジネス価値に大きな差がある。
  • User-Baseの協調フィルタリングはターゲットしたいアクティブUserを見つけて、近似関数によりUserを識別し、似ているUserが好むアイテムを見つけて、予測をして、TopNのアイテムをRecommendする。
  • Item-Baseの協調フィルタリングはターゲットしたいUserが持っているアイテムを探し、他のUserが過去に持っているアイテムのみを使ってどれほど似ているかを計算し、最も似ているk個を選択しRecommendする。
  • ほとんどの場合良い結果が期待される。次のことにできれば挑戦したい。user/itemの相互作用は1%以下なのでDataがsparseになる。NNはUserとアイテムの両面での数を多く必要とする。
Model-Based Collaborative Filterling
  • Memory-Basedの手法は予測のために全てのUser-Itemののデータベースを利用する。またNNのような統計学技術を必要とする。
  • Model-Basedの手法は最初にUserのModelを作成する。例えばBayesian Network、Clustering、Rule-base approace、Classification、Regression、LDA等。
  • Netfilix PrizeでのModel-Basedから学んだことはとても高い精度であり、改善の精度が10%あったこと。
  • 2007年のPrizeではTop2のアルゴリズムがSVD(RMSE:0.8914)、RBM(RMSE:0.8990)であった。Lnear BlendはRMSE:0.88であった。※ SVD(Singular Value Decomposition)、RBM(Restricted Boltzmann Machine)
  • 使用中のModelもSVD++とRBMの両方を使用したアンサンブル学習である。期待される改善にエンジニアリングの努力の価値はないので、他の問題に焦点を当てている。
Clustering
  • UserのClusterを行い、それぞれのClusterに対して物理参照を計算する。UserはClusterのレベルに応じたrecommendationを受け取る。
  • LSH(locality-sensitive Hashing)は高次元の似ているアイテムをグルーピングするHashing関数。主なアプリケーションはNN(Nearest-neighbors)
  • その他の興味深いClustering手法、k-means、affinity propagation、spectral clustering、LDA、Non-parametric Bayesian Clustering。
Association Rules & Classifiers
  • 過去の購入記録は関連するアイテムとして解釈される。Recommendされる内容は自信をもって薦めることができる最小のものに限られる。実装と実行を早くしたい。
  • Classifiersは正例、負例を使ってモデルを作成する。アイテムの特徴ベクトル、顧客の趣味嗜好、アイテム間の関係がinputに用いられる。例としてLogistic Regression、Bayesian Networks、SVM、決定木等。
  • Classifiersは協調フィルタリング、コンテンツベースフィルタリングの両方で使われる。良い点は応用が効き、他の手法と連結して精度改善することが可能。悪い点は関連する訓練データが必要、オーバーフィットするので正則化が必要。
Limitaion of Collaborative Filtering
  • Cold Start : 十分な他のUserが既にシステムの中に存在し、新しいアイテムも必要とする。
  • Popularity Bias : ユニークな興味に対してrecommendするのが難しい。人気商品が推薦される傾向にあり、Tailに存在するアイテムが出なくなる。
Content-Based Recommendation(CB)
  • WebPageやネットニュースの記述などのText-Basedの商品、記述されたアイテムの特徴(keyword等)によってrecommendする方法などがある。
  • User Modelは似ている方法で構成される。User ModelはNeural NetworkやNaive Bayesなどの技術に基づいて分類される。
Pros/Cons CB Approach
  • CBの良い点 : 他のUserデータを必要としない、Cold-StartやSparsityの問題が無い、ユニークな趣味嗜好のUserに対してアプローチや不人気商品に対してアプローチできる、コンテンツの特徴をリストすることで説明を強化できる。
  • CBの悪い点 : コンテンツが測定可能な特徴としてencodingされなければならない、Userはコンテンツの特徴の学習可能な機能として表現される、serendipityの改良は難しい、簡単にオーバーフィットする。
Hybrid Approaches Hybridzation Methods
  • Hybridさせた方が精度が良さそう(意訳)
  • weighted、Switching、Mixed、Feature Combination、Cascade、Feature augmentation、Meta-levelなどの複合手法がある。(詳細は省略)
Ranking
  • Recommendationはソートされたアイテムリストとして表現されている。RecommendationはRanking問題として理解されなければならない。人気は明白なベースラインである。いろいろな特徴が加えることが可能。
  • RMSEは使用できない。
  • 例として2つの特徴(人気と予測Rate)を利用した線形モデルをRankingとするものがある。
Learning to rank
  • 機械学習の問題 : ゴールは訓練データからRanking Modelを構築すること。
  • 訓練データは完全な順序もしくは2値判断(関連する、しない)である可能性がある。
  • Rankの結果は数学的なスコアによって削減されたアイテムの順序である。
  • Rankingを学習することはPersonalizationの重要な要素となる。
  • classification問題の一般的なものとして扱うことができる。
  • metricsを利用したrankingの測定の質として、Normalized Discounted Cumulative Gain、Mean Reciprocal Rank(MRR)、Fraction of Concordant Pairs(FCP)などがある。
  • これらの測定に対して直接機械が学習したモデルを最適化させることは難しいが、最近の研究されたモデルは直接最適化させている。
  • アプローチとしてPointwise,Pairwiseがある。
  • Pointwise : 個人に関連するかどうかを定義した損失関数を最小化する、回帰や分類に基づいたRanking Score、通常の回帰/Logistic回帰/SVM/GBDTなどがある。
  • Pairwise : pair-wiseの選択に基づいた損失関数、Goalはランキング内の転置数を最小化する、Ranking問題は2値分類問題に変換される、RankSVM/RankBoost/RankNet/Frank
  • その他にListwiseという手法がある。(詳細は省略)
Similarity as Recommendation
  • Graph-Based Similarityの例としてSimRankというものがある。
  • Similarityは異なる次元を参照することが可能。metadataやタグの類似、再生行動履歴の類似、評価履歴の類似等
  • それらをアンサンブルで結合する。重み付けは既存のレスポンスにより回帰から学習される。もしくはMABが調査/開発する。
Deep Learning for Recommendation
  • SpotifyはRecurrent Networkを利用してる

Recurrent Neural Networks for Collaborative Filtering | Erik Bernhardsson

  • その他のDeep LearningによるContents-BaseのRecommendationは以下のURLから確認することができる。


Recommending music on Spotify with deep learning – Sander Dieleman

  • 少しのCF情報が適用な時にColdStartな新しいタイトルのアプリケーション。
  • audio信号を入力としたmel-spectrogramを利用する。
  • 40の見えない要素を予測するためにdeep neural networkを学習する。
  • Networkの構成は4つの畳み込みlayerをつくる。(意味が良くわかりませんでした)
Social and Trust-based Recommenders
  • 近接するSocialのuserに人気なアイテムを推薦する。近接するSocail = 信頼である。
  • AlgorithmとしてAdvogato/Appleseed/MoleTrust/TidalTrustなどがある。
  • 他のSocialの利用として友人関係は異なる手法のCFに与えることができる。user-userの類似度をSocial networkの情報に置き換えるとか、Social Connectionを機械学習のオブジェクト的な正則化としての関数で使う等。
  • Userを個人属性によってカテゴリ化、Demographicのクラスに基づいた推薦をすることが目的。
  • Demographicのグループはmarketing reserchからできる。Demographicの技術は人と人の関連性を形成する。
Page Optimization
  • Pageの構成を考える。Userがより良く見る部分に良いコンテンツを配置したい。
  • 正確度と多様性、新しい発見と継続、深さとカバー率、新鮮さと安定性、推薦とタスクなどの比較がある。
  • コンテンツを一緒に配置するためには異なる要素の結合が必要。Navigational / Attention Model、Personalized Relevance Model、Diversity Model
Tensor Factorization & Factorization Machines
  • N-Dimensional Model(User,Item,Time等)
  • FM(Factorization Machines)
MAB Explore/Exploit
  • Personalization Algorithmの手法を構築するときに重要な問題の一つはトレードオフをどのように扱うか。
  • Exploitation : Userの今の状況を知っていることでのマネタイズ。Exploration : Userについてもっと知る機会として相互作用を利用する事。
  • このようなトレードオフに対応するために通知され最適な戦略を必要とする。Solution : 手頃な候補のセットを選択し、それらの情報を集めるために十分である事をuserに見せる。
  • Multi-Armed Bandits 可能な戦略や候補をあたえられた時、ポテンシャルを最大限に良くするarmを選択する。(この辺はBanditsアルゴリズムを勉強しないとよく分からない)
  • 基本的なstrategyはE - Greedyであり、Recommender Systemに適用するためにはarmを選択することは、アイテムの選択とアルゴリズムの選択を意味する。
  • よりよいstrategyは平均だけでは無く、分散も考慮している。Upper Confidence Bound, Thompson Sampling

Criteoが発表したCross Device Advertisingのreportを読む

アドテクノロジー プロフェッショナル養成読本 ~デジタルマーケティング時代の広告効果を最適化! (Software Design plus)

アドテクノロジー プロフェッショナル養成読本 ~デジタルマーケティング時代の広告効果を最適化! (Software Design plus)

Cross Device Advertising

Cross-device advertising: How to navigate mobile marketing's next big opportunity | Criteo はてなブックマーク - Cross-device advertising: How to navigate mobile marketing's next big opportunity | Criteo
リターゲティング広告の分野で最強と言われているCriteoが2014年の9月に書いているCross Device Advertisingのreportについてまとめを書いておきます。そもそもCross Deviceって何よっ思った方の為にも簡単に説明を書いておきますが、個人が複数のデバイスを利用してインターネットをしているとタッチポイントが分散してしまうので、個人の興味を解析してAdを配信したいサービスにとっては断片的な行動ログをそれぞれの端末から得るより、複数のデバイスを利用している人を1個人として特定できたらいいよねって話です。現状の識別情報については1ブラウザの特定はCookie、1端末の特定はIDFA、1ユーザーの特定はUserIDで行われているのが一般的で、これらは纏めた管理ではなく基本的に独立して扱っています。UserIDを使うと特定サービス内において複数デバイスを紐付ける事も可能なんですが、UserID自体が各メディアサービス(FacebookIDやTwitterID等)の識別子であるため、メディ側での利用に限定される事とAd配信サービス側は直接知る事ができないので扱いづらいとされています。


複数デバイスの解決をテクノロジーを使って推し進める上での気をつけなければいけない点は"インターネットユーザーの不快"と"個人情報保護"とされています。個人情報についてはどこまでなら許容可能という線引きを国が握ってしまっているのでそこは法律に従うしか無い状況です。数年前から個人情報を一切利用せずにCookieの代替IDを生成する41st Parameter社のADTruthやtactadsというSolutionにも注目が集まって来ていますが、今のところ精度はまだまだという感じのようです。
AdTruthとは? | AdTruth はてなブックマーク - AdTruthとは? | AdTruth
Cross-device advertising solutions はてなブックマーク - Cross-device advertising solutions

Criteo Report / Technology and Tracking : Volume vs. Accuracy

結局最後まで読んでみて目新しい話はあまりありませんでしたが、User識別の精度が低いと広告費用や機会損失をしているというメッセージが良く伝わってきました。 簡単にまとめるとCross Deviceによる広告配信はまだまだこれからということだと思います。 一部ですが重要だと思った事を意訳メモします。

  • スマートフォンタブレット、ラップトップのようなモバイルデイバスを40億人が利用する時代である。
  • Cross Deviceの広告配信による収益は素晴らしい物になるはずだが、市場関係者はCross Device識別は技術的に難しいものになると考えている。なぜならばプラットフォームをまたいで分析する事が現状はできないから。
  • 60%の人が複数のプラットフォームを利用している。それはdesktopを使っているアカウントに比べ凄く多くなっている。またTVを見ながらタブレットを使うようなケースも珍しい事ではない。
  • インターネットユーザーは流動的にデバイスを使い分けるのでますます難しい問題になるが、ちゃんと識別して広告を配信しないと無駄な費用を使ってしまう。間違って識別してしまうと複数人のように扱ってしまう。
  • インターネットユーザーは昼にPCで探して、更にスマートフォンでも探して、最終的には翌日にお家のPCで買うようなケースがあるから、市場関係者はこういった問題を解決するために複数のデバイス分析をちゃんと行い、いつどこでどれだけ商品が購入されるかを予測しないといけない。
  • モバイル広告をうまく展開できない3つの障壁として、ユーザー属性が取得できない、デバイスを跨ぐ消費者をうまく識別できない、サービスの最適化やパフォーマンスが低いのでコンバージョンが低いことが挙げられる。
  • 2016年には年には消費者がモバイルを使う率が44.3%に上がる見込み。
  • 1日における時間の使い方もTV,雑誌,ラジオよりモバイルデバイスを使う時間が長くなっている。
  • Cross Device広告は正確な方法と暗示的な方法の2つが用いられている。正確な手法としてはDeviceを跨いでもUniqが保証される情報を利用しており、昔からある方法としてはクレジットカード番号や会員カード、E-mailや電話番号、住所等がある。しかしこれらは全て消費者やプラットフォームに展開する事が出来ない。暗示的な方法としては消費者を推定する事もあるが、精度が低い事とプライバシーの危険性が大きくなってしまう事が懸念。
  • 正確な方法を利用する場合はopt-outやプライバシーをサポートする必要があるし、ユーザー数を増やす事と個人情報に気をつけなければいけない。
  • 暗示的な方法で機械学習モデルを利用してデバイスの特徴から二つのデバイスや同じユーザーから利用されている事を計算する事が出来るが、当然別々の2人を認識してしまう事もある。精度が40〜75%のように異なるとパフォーマンスとROIの低下に繋がる。正確な方法と同様にopt-out機能も準備しないといけない。
  • Single Sign Onも正確な方法の一つの例であるがDevice間を跨いだLoginというのは全ての消費者が行ってはくれないので難しい。
  • 一人の消費者がLoginしたときデバイスの移行と興味の移り変わりを認識する事が可能であるし、全ての端末でLoginしてくれると最善なカスタマージャーニーを提供することが出来る。
  • Hotels.comの例だと25%はモバイルデバイスからbookmarkされており、その内の60%は現在もしくは翌日の宿泊先である。これを利用すればもっと良い広告ターゲティングが利用できるだろう。
  • 暗示的なCross Deviceの認識方法にはいくつか問題がある。最大の欠点は全てのプラットフォームとデバイス間で継続して利用可能な識別子が無い事。そして識別子を得る事が出来るのは家庭内という状況下では可能だが、誰が特定の広告を見ているかという点迄掘り下げる事が出来ない。
  • 暗示的な方法の例として、同じIPで利用されるipadを1個人として識別する事もあるが、複数人の家族で利用している場合は正しく無いとされる。しかしながら個人の識別子を利用して言う場合に限り個人として特定をする事は可能。
  • 本来ターゲティングしたいUserでは無い人に広告を配信してしまうと多大なる機会損失となる。
  • 様々なメディアや広告配信やテクノロジー会社がCross Deviceの識別をする事に一生懸命になっており、全てのプライバシーのルールや制約をより正確で包含できるような仕組みを作っている。しかしこれは簡単な事ではない。
  • Cross Deviceで一人を特定する事を本格的に行うにはまだ多くの準備が必要。多くの人が考えている混乱を排除しなければならない。
  • 急速なタッチポイントの増加で広告は更に費用が掛かるものになってしまっている。精度が低い事は広告費用を無駄にしてしまっている。
  • 消費者がクレジットカードのような長期に渡って購買で利用する識別子だったり、Mailをどのデバイスで読んでいるかなどの正しい情報を集める事はとても重要。
  • 良いSolutionを提供してくれるPartnerを見つける事も重要。様々な企業が今Cross-Deviceの分析手法を確立している最中であるが、あと半年から1年以内に幾つかの企業がsolutionを発表する事が期待されている。
  • データの取得とopt-outの方法はクリアでなければならない。
  • Online広告からアプリへのWebインタフェースも自然な物でないといけない。デザインが重要。
  • より正確な時間に正しい広告を正しいUserに届ける事はConversionを改良する。

検索Crawlerを作る

Solr in Action

Solr in Action

Nutch + Solr + Hbase + Zookeeper

Nutchで特定のWebPageをCrawlingしてSolrのIndexを作ろうとした時にかなり嵌ってしまったので作業のメモを記録しておきます。(※タイトルに語弊があるようですが、検索Crawler自体を作るという話ではありません。)特にNuth/Hbase間のVersion依存があるので、installしてみたけど動かなかったという人の参考になればと思います。Webを色々と探してみるとNutch2.2.1Hbase0.90.Xを組み合わせると良いようです。僕が試してみた環境は以下のものです。因にZookeeperは個別にinstallする必要は無いようです、Hbaseを起動するとZookeeperも実行されます。

  • OS : CentOS 6.4
  • Java : 1.7.0_51
  • Nutch : 2.2.1
  • Solr : 4.7.0
  • Hbase : 0.90.6
  • Zookeeper : 3.4.6

またNutchのTutorialに関しても注意が必要です。Webで紹介されているものは1.X系のものが多く、Crawlingのコマンドも掲載されているものをそのまま実行するとdeprecatedされていて動かなかったりします。NutchのVersionを確認して必要なTutorialを参照するようにしましょう。 特に一番したのリンクのCommandLineOptionsに記載されているVersion毎の×印を参考にすると良いでしょう。

続きを読む

Android Studioを入れてFacebookSDKのLogin機能を使うまでの作業記録

Android Studioの導入以降

柄にも無くAndroid Appliの開発に手を染め始めた@yutakikuchi_です。
Android Appliの開発をする為にはEclipseAndroid Studioを導入すると良いようです。ぐぐってみると断然Eclipseのドキュメントが多いようですが、EclipseはGradleというAndroid Appliをビルドするツールが導入しづらいとの事で、僕はAndroid Studioを選びました。Android Studioの導入はdotinstallに詳しく載っているので、僕と同じ初学者の方は一度参考にする事をお勧めします。Androidアプリ開発入門 (全12回) - プログラミングならドットインストール はてなブックマーク - Androidアプリ開発入門 (全12回) - プログラミングならドットインストールまたschooでも同じような講義が公開されていますがGradleに対する説明がある冒頭だけ見れば良いと思います。その他はdotinstallでOK。Android StudioではじめるAndroidアプリケーション実践入門 - 無料動画学習|schoo(スクー) はてなブックマーク - Android StudioではじめるAndroidアプリケーション実践入門 - 無料動画学習|schoo(スクー)


dotinstallで無料会員で視聴できるのはMyActivity.Java、activity_my.xmlを編集してボタンを押下した時に画面に表示する文言を変更するという所までです。アプリの細かい開発の動画もあるようなんですが有料会員でないと利用できません... Oh...。Javaビジネスロジック書いて取得したデータをViewに反映したいという欲求を満たす為に今日は自分で試してみた事を記録しておきます。

続きを読む