Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

広告配信現場で使うSpark機械学習

8,858 views

Published on

Using Apache Spark Machine Learning by advertising.

Published in: Engineering
  • Be the first to comment

広告配信現場で使うSpark機械学習

  1. 1. 広告配信現場で使う Spark機械学習 株式会社サイバーエージェント 井上ゆり
  2. 2. 自己紹介> 井上 ゆり 株式会社サイバーエージェント アドテク本部 AMoAd所属 twitter: @iyunoriue GitHub: x1- HP: バツイチとインケンのエンジニアブログ http://x1.inkenkun.com/ 2
  3. 3. 本日は広告屋らしく、 Apache Sparkを使った CTR(=Click Through Rate)推定 をご紹介させて頂きます。 3
  4. 4. 2014年、Criteo社が Hashing Trickとロジスティック回帰 を使ったCTR推定を発表しました。 この論文→http://people.csail.mit.edu/romer/papers/TISTRespPredAds.pdf ! ! 今回はこの手法を使います。 4
  5. 5. CTR推定の流れ Pipeline 5 読み込み & パース 特徴ベクトル に変換 学習 検証 CSVファイル Hashing Trick Logistic Regression spark-csv Cross Validator SQL/DataFrame Apache Spark 1 2 3 4
  6. 6. 使うもの ★ Apache Spark • SparkSQL & DataFrame ・・・データ操作/加工 • Spark MLlib • Pipeline ・・・ワークフロー • HashingTrick ・・・特徴のベクトル化、次元削減 • LogisticRegression ・・・ロジスティック回帰 • CrossValidator ・・・最適モデルの選択 ★ databricks/spark-csv ・・・CSVパーサ 6
  7. 7. 推定に使うデータ KaggleのCTR推定コンテストで使われた テストデータを使います。 https://www.kaggle.com/c/avazu-ctr-prediction/data ! 7
  8. 8. データ構造 8 • id: ad identifier • click: 0/1 for non-click/click • hour: YYMMDDHH • C1 -- anonymized categorical variable • banner_pos • site_id • site_domain • site_category • app_id • app_domain • app_category • device_id • device_ip • device_model • device_type • device_conn_type • C14-C21 -- anonymized categorical variables
  9. 9. PipelineSQL/DataFrame Apache Spark 9 読み込み & パース 特徴ベクトル に変換 学習 検証 CSVファイル Hashing Trick Logistic Regression spark-csv Cross Validator 3 4 CSVの読み込み&パース 21
  10. 10. ! databricks/spark-csvを使ってCSVを読み込みます。 これを使うと、ヘッダーとカラム名が対応した DataFrameを作ることができます。 こんなかんじ。 10 id click hour C1 banner_pos app_id site_id ... 1 0 2015080106 abc 9 9 5 ... 2 0 2015080106 def 5 10 10 ... 3 1 2015080107 ghi 1 2 2 ... 4 0 2015080107 jkl 0 5 6 ... CSVの読み込み&パース
  11. 11. 11 val rawCsv = sqlContext.read .format( "com.databricks.spark.csv" ) .option( "header", "true" ) .load( "/var/kaggle-data/train*.gz" ) ソースコードはこんなかんじです。 ※scalaを使っています CSVの読み込み&パース
  12. 12. PipelineSQL/DataFrame Apache Spark 12 読み込み & パース 特徴ベクトル に変換 学習 検証 CSVファイル Hashing Trick Logistic Regression spark-csv Cross Validator 3 4 特徴ベクトルに変換 1 2
  13. 13. ! DataFrameに読み込んだCSVは、Hashing Trickにかけ ロジスティック回帰モデルで訓練するために少し加工 します。 クリックされたかどうかを目的変数(=label)とし、 その他の項目を説明変数(=特徴)とします。 13 特徴ベクトルに変換 id click hour C1 banner_pos app_id site_id ... 1 0 2015080106 abc 9 9 5 ... 2 0 2015080106 def 5 10 10 ... 3 1 2015080107 ghi 1 2 2 ... 4 0 2015080107 jkl 0 5 6 ... 目的変数 説明変数
  14. 14. この数値も文字列も含む特徴から Hashing Trickを使って 特徴ベクトルをつくりたいのですが・・・ 14 特徴ベクトルに変換
  15. 15. ! Hashing Trickを行う際に、このままのデータだと 少し困ったことになります。 ! 例えば site_id=10, app_id=10, banner_pos=9, .. というレコードの特徴は下記のようになるので (10, 10, 9, ..) ! site_idを表す10とapp_idを表す10の 区別がなくなってしまいます。 15 特徴ベクトルに変換
  16. 16. ! そこで site_id=10 → site_id:10 app_id=10 → app_id:10 のように 項目名を値に付与することで特徴として区別します。 ! (10, 10, 9, ..) ↓ (site_id:10, app_id:10, banner_pos:..) 16 特徴ベクトルに変換
  17. 17. 17 日付は、時刻部分だけを特徴として使いたいので時刻 を取り出すUDFも作成します。 val f = udf { (v:String, prefix:String ) => s"$prefix:$v" } ! UDF(=UserDefinedFunction)を作成して DataFrameを加工します。 ! 項目名と値を結合するUDFはこんなかんじです。 val hour = udf { (v:String ) => v slice( 6, 8 ) } 特徴ベクトルに変換
  18. 18. 18 val data = rawCsv.select( $"id", $"click".cast( DoubleType ).as( "label" ), array( f( hour( $"hour" ), lit( "hour" ), f( $"C1", lit( "C1" ), f( $"banner_pos", lit( "banner_pos" ), f( $"site_id", lit( "site_id" ), f( $"site_domain", lit( "site_domain" ), f( $"site_category", lit( "site_category" ), : f( $"C21", lit( "C21" ) ) ).as( "text" ) ) ! 先ほどのUDFを使ってDataFrameを加工し、訓練データ を準備します。 特徴ベクトルに変換
  19. 19. PipelineSQL/DataFrame Apache Spark 19 読み込み & パース 特徴ベクトル に変換 学習 検証 CSVファイル Hashing Trick Logistic Regression spark-csv Cross Validator 4 学習 1 2 3
  20. 20. ! 訓練データの準備ができたので Pipelineを使って HashingTrickによる特徴のベクトル化 〜ロジスティック回帰による確率推定 のフローを組み立てます。 20 学習
  21. 21. ! 今回使う • Hashing Trick • LogisticRegression をPipelineStageとしてPipelineに渡します。 21 val hashingTF = new HashingTF() .setNumFeatures( 1000 ) .setInputCol( "text" ) .setOutputCol( "features" ) ! val lr = new LogisticRegression() .setMaxIter( 10 ) .setRegParam( 0.1 ) ! val pipeline = new Pipeline().setStages( Array( hashingTF, lr ) ) 学習
  22. 22. PipelineStage ! 後は先ほど準備した訓練データをPipelineに fitさせるだけです。 22 val model = pipeline.fit( train ) PipelineはHashing Trickとロジスティック回帰を 順次実行します。 Pipeline Hashing Trick Logistic Regression DataFrame (site_id:10, app_id: 10,..), (.. 学習
  23. 23. ! 学習済みのモデルにテストデータを渡すと probability(確率)がベクトルで出てきます。 probabilityベクトルのインデックス1番目が clickされる確率を表します。 23 model.transform( test ).select( $"label", $"prediction", v0( $"probability" ).as( "probability0" ), v1( $"probability" ).as( "probability1" ) ).take(10).foreach ( predictPrint ) label:0.0, predict:0.0, v(0):0.8720480148381256, v(1):0.1279519851618744 label:1.0, predict:0.0, v(0):0.7926627870942957, v(1):0.2073372129057043 label:1.0, predict:1.0, v(0):0.4711335790138061, v(1):0.5288664209861939 label:1.0, predict:1.0, v(0):0.4756467107691264, v(1):0.5243532892308737 : ↑probability(1)>0.5の場合に1.0と推定されているのがわかります。 学習 CTR
  24. 24. PipelineSQL/DataFrame Apache Spark 24 読み込み & パース 特徴ベクトル に変換 学習 検証 CSVファイル Hashing Trick Logistic Regression spark-csv Cross Validator 検証 1 2 3 4
  25. 25. ! Spark MLlibには、交差検証を使って モデルに最適なパラメータを選択するための 仕組みがあります。 最後にこれを使って パラメータのチューニングを行います。 25 検証
  26. 26. 先ほどのPipelineをCrossValidatorに渡して CrossValidatorモデルを作成します。 26 val crossval = new CrossValidator() .setEstimator( pipeline ) .setEvaluator( new RegressionEvaluator ) 検証
  27. 27. 検証したいパラメータ・グリッドを作成します。 27 val paramGrid = new ParamGridBuilder() .addGrid( hashingTF.numFeatures, Array(10, 1000) ) .addGrid( lr.regParam, Array(0.1, 0.001) ) .addGrid( lr.maxIter, Array(10, 100) ).build() ↑この例では2×2×2=8回の試行が行われて 最適パラメータが決定します。 ※つまり結構な時間がかかります。 検証
  28. 28. 先ほど作成したパラメータ・グリッドと fold数(訓練データ対テストデータの分割数)を渡して 訓練を開始します。 28 crossval.setEstimatorParamMaps( paramGrid ) crossval.setNumFolds( 3 ) ! val cvModel = crossval.fit( train ) 検証
  29. 29. 訓練が完了したら最適モデルを取り出して 最適パラメータを確認することができます。 29 val parent = cvModel.bestModel.parent.asInstanceOf[Pipeline] val bestHT = parent.getStages(0).asInstanceOf[HashingTF] val bestLR = parent.getStages(1).asInstanceOf[LogisticRegression] ! println(s"numFeatures: ${bestHT.getNumFeatures}") println(s"regParam: ${bestLR.getRegParam}") println(s"maxIter: ${bestLR.getMaxIter}") numFeatures: 1000 regParam: 0.001 maxIter: 100 このモデルを使って推定もできます。 →動的なパラメータ・チューニングが可能! 検証
  30. 30. ソースコードは下記に公開しています。 https://github.com/x1-/spark-example/blob/master/src/main/ scala/com/inkenkun/x1/spark/examples/ml/HashingTrickLR.scala 30
  31. 31. ご清聴ありがとうございました。

×