天池初体験——新人実戦の[オフライン]

9649 ワード

 
  
注意,本篇博文代码存在一些问题,请查看修改版的博文,地址为:
    :http://www.wyblog.cn/2016/11/05/%e5%a4%a9%e6%b1%a0%e5%88%9d%e4%bd%93%e9%aa%8c-%e6%96%b0%e4%ba%ba%e5%ae%9e%e6%88%98%e8%b5%9b%e4%b9%8b%e7%a6%bb%e7%ba%bf%e8%b5%9b/
  • は冒頭に書かれています.本編の博文の適用対象は、天池試合にどうやって手をつけるか分からない仲間です.本稿では,データを最も簡単に整理し,特徴を抽出し,モデルを構築したり,人工規則を用いて予測したりして,データを選択して提出し,結果を得る方法を最初から記録する.したがって,本論文では,特徴の選択抽出とモデルがどのように構築されるかに注目する必要はない.最後に、本人が使用しているツールはSparkであり、非常に便利であり、spark-sqlツールを含み、データベースのデフォルトではderbyが使用されている.また、Sparkにはmllibライブラリが含まれており、機械学習に関する作業を非常に便利に行うことができ、オフライン試合は完全にSparkで完成できると言える.

  • 試合問題の説明
    公式の説明は以下の通りで、ここでは簡単な説明だけを行います.
    https://tianchi.shuju.aliyun.com/getStart/introduction.htm?spm=5176.100068.5678.1.VEirgR&raceId=231522
    2つのテーブルが表示されます.第1のテーブルUIは、ユーザが今月中に商品集合体上での行動データであり、第2のテーブルPは商品集合情報である.試合問題によると、採点データは12月19日にユーザーが商品のサブセットの商品購入情報を予測した.ここでは、いくつかの簡単なルールを提供します.
  • は、Pテーブルの商品情報に基づいてUIテーブルをフィルタリングし、Pテーブルを含む商品のインタラクティブな記録のみを残すことができる.このルールの背後にある原理は,ユーザが異なるカテゴリの商品やサービスに対して購入する戦略が異なるため,Pテーブルに含まれるカテゴリのデータだけを考慮して学習することである.
  • は実際の状況を簡略化し、ここでは先日のユーザー商品の相互作用状況を予測することによってのみ予測する.すなわち,19日の購入状況を予測するために,17,18日のユーザインタラクションで予測した.予測を行うためには、モデルを学ぶ必要があります.したがって,16,17番のユーザインタラクティブデータと18番のユーザの購入データに基づいてこのモデルを学習することができ,本稿では決定ツリーモデルを簡単に選択する.
  • UIテーブルにはブラウズ、コレクション、カートの追加、購入の4つのデータしか含まれていないため、意思決定ツリーの構築には十分ではないに違いないので、ユーザーへの採点(例えば、ある商品のブラウズに1回2点、コレクションに3点など)、ブラウズが総インタラクティブ回数に占める割合を計算するなど、特徴を拡張する方法を考えなければなりません.ここはただ私が勝手に挙げた特徴で、具体的には自分で脳の穴を開けて考えなければなりません.
  • 重要な問題があります.私たちが抽出したトレーニングセットのデータの中で、18日に購入しない項目のデータ量は18日に購入した項目のデータ量よりずっと多く、つまり正負のサンプルの割合が大きすぎます.これはモデル学習にとって災難的であり,学習したモデルは全く使えない.そのため、18日に購入したすべての訓練セットを選択し、同じ数または少ない数の負のサンプルを新しい訓練セットとして選択し、新しい訓練セットを利用して意思決定ツリーモデルを学ぶ必要があります.そうすれば、効果が得られます.

  • データの準備
    Sparkクラスタに関連する場合、オペレーションファイルはHDFSにデフォルト設定されます.まず2つのソースデータをHDFSにアップロードし、Sparkで読み取り、テーブルに登録します.ここではpysparkインタラクティブ環境を使っています.
    
    #  CSV  ,    ,   derby     
    df=spark.read.csv("tianchi_fresh_comp_train_user.csv",header=True)
    df2=spark.read.csv("tianchi_fresh_comp_train_item.csv",header=True)
    df.createOrReplaceTempView("user")
    df2.createOrReplaceTempView("item")
    
    #SQL  :  P   UI ,     user_item 
    spark.sql("CREATE TABLE user_item AS \
    SELECT t.* FROM user AS t \
    JOIN item AS b \
    ON t.item_id=b.item_id \
    AND t.item_category=b.item_category")
    
    次に、16、17番のユーザーのインタラクションを統計し、ユーザーが18番で購入行為を行ったかどうかを識別する必要があります.
    
    spark.sql("CREATE TABLE day1617_18_detail AS \
    SELECT user_id,item_id, \
    CASE WHEN substr(time,1,10)='2014-12-16' OR substr(time,1,10)='2014-12-17' AND behavior_type=1 THEN 1 ELSE 0 END AS Is_2day_view, \
    CASE WHEN substr(time,1,10)='2014-12-16' OR substr(time,1,10)='2014-12-17' AND behavior_type=2 THEN 1 ELSE 0 END AS Is_2day_favor, \
    CASE WHEN substr(time,1,10)='2014-12-16' OR substr(time,1,10)='2014-12-17' AND behavior_type=3 THEN 1 ELSE 0 END AS Is_2day_tocar, \
    CASE WHEN substr(time,1,10)='2014-12-16' OR substr(time,1,10)='2014-12-17' AND behavior_type=4 THEN 1 ELSE 0 END AS Is_2day_buy, \
    CASE WHEN substr(time,1,10)='2014-12-18' AND behavior_type=4 THEN 1 ELSE 0 END AS Is_buy \
    FROM user_item ")
    
    また、17、18番のユーザーのインタラクティブな動作を統計する必要があります.
    
    spark.sql("CREATE TABLE day1718_19_detail AS \
    SELECT DISTINCT user_id,item_id, \
    CASE WHEN substr(time,1,10)='2014-12-17' OR substr(time,1,10)='2014-12-18' AND behavior_type=1 THEN 1 ELSE 0 END AS Is_2day_view, \
    CASE WHEN substr(time,1,10)='2014-12-17' OR substr(time,1,10)='2014-12-18' AND behavior_type=2 THEN 1 ELSE 0 END AS Is_2day_favor, \
    CASE WHEN substr(time,1,10)='2014-12-17' OR substr(time,1,10)='2014-12-18' AND behavior_type=3 THEN 1 ELSE 0 END AS Is_2day_tocar, \
    CASE WHEN substr(time,1,10)='2014-12-17' OR substr(time,1,10)='2014-12-18' AND behavior_type=4 THEN 1 ELSE 0 END AS Is_2day_buy \
    FROM user_item")
    
    上記の2つのテーブルに基づいて、対応する日付の様々なインタラクション動作の合計数を統計します.
    
    spark.sql("CREATE TABLE day1617_18_train_data AS \
    SELECT * FROM (SELECT user_id,item_id, \
    SUM(CASE WHEN Is_2day_view=1 THEN 1 ELSE 0 END) AS 2day_view, \
    SUM(CASE WHEN Is_2day_favor=1 THEN 1 ELSE 0 END) AS 2day_favor,\
    SUM(CASE WHEN Is_2day_tocar=1 THEN 1 ELSE 0 END) AS 2day_tocar,\
    SUM(CASE WHEN Is_2day_buy=1 THEN 1 ELSE 0 END) AS 2day_buy,\
    SUM(CASE WHEN Is_buy=1 THEN 1 ELSE 0 END) AS DAY18_buy \
    FROM day1617_18_detail \
    GROUP BY user_id,item_id) \
    WHERE 2day_view>0 OR 2day_favor>0 OR 2day_tocar>0 OR 2day_buy>0")
    
    spark.sql("CREATE TABLE day1718_19_predict_data AS \
    SELECT * FROM (SELECT user_id,item_id, \
    SUM(CASE WHEN Is_2day_view=1 THEN 1 ELSE 0 END) AS 2day_view, \
    SUM(CASE WHEN Is_2day_favor=1 THEN 1 ELSE 0 END) AS 2day_favor,\
    SUM(CASE WHEN Is_2day_tocar=1 THEN 1 ELSE 0 END) AS 2day_tocar,\
    SUM(CASE WHEN Is_2day_buy=1 THEN 1 ELSE 0 END) AS 2day_buy \
    FROM day1718_19_detail \
    GROUP BY user_id,item_id) \
    WHERE 2day_view>0 OR 2day_favor>0 OR 2day_tocar>0 OR 2day_buy>0")
    
    最後に、すべての正のサンプルと、同じ数の負のサンプルを抽出し、最終的なトレーニングセットテーブルtrain_を構成する必要があります.datatable.
    フィーチャー抽出およびモデル生成
    ここでは、自身の特徴が少なすぎるため、特徴拡張が必要です.以下のコードでは、いくつかの特徴を勝手に拡張しました.
    #    ,spark        ,              ,          features,         label,       。
    from pyspark.ml.linalg import Vectors
    from pyspark.ml.feature import VectorAssembler
    
    assembler=VectorAssembler(inputCols=["t1","t2","t3","t4","t5","t6","t7","t8","t9","t10"],outputCol="features")
    
    dataset_train=spark.sql("SELECT user_id,item_id,2day_view,2day_favor,2day_tocar,2day_buy, \
    CASE WHEN day18_buy>0 THEN 1 ELSE 0 END as label,\
    2day_view*2 AS t1 , 2day_favor*3 AS t2 , 2day_tocar*4 AS t3 , 2day_buy*1 AS t4 ,\
    2day_view*1+2day_favor*2+2day_tocar*3-2day_buy*1 AS t5,\
    (2day_view+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t6,\
    (2day_favor+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t7,\
    (2day_tocar+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t8,\
    (2day_buy+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t9,\
    (2day_favor+1)*(2day_tocar+1)-2day_buy*2 AS t10 \
    FROM train_datatable WHERE 2day_buy<20")
    
    output_train = assembler.transform(dataset_train)
    train_data=output_train.select("label","features")
    
    訓練データセットがあれば,次はSparkのMLlibでモデルを構築し,モデルを訓練する.spark mllibの使用方法は本明細書で議論する範囲外である.TreeModelを訓練したとします
    
    from pyspark.ml import Pipeline
    from pyspark.ml.classification import DecisionTreeClassifier
    from pyspark.ml.feature import StringIndexer, VectorIndexer
    from pyspark.ml.evaluation import MulticlassClassificationEvaluator
    
    labelIndexer = StringIndexer(inputCol="label", outputCol="indexedLabel").fit(train_data)
    featureIndexer =VectorIndexer(inputCol="features", outputCol="indexedFeatures", maxCategories=4).fit(train_data)
    (trainingData, testData) = data.randomSplit([0.7, 0.3])  #                    
    dt = DecisionTreeClassifier(labelCol="indexedLabel", featuresCol="indexedFeatures")
    pipeline = Pipeline(stages=[labelIndexer, featureIndexer, dt])
    TreeModel = pipeline.fit(trainingData)
    predictions = model.transform(testData) #           
    
    #                ,     0.22  
    evaluator = MulticlassClassificationEvaluator(
        labelCol="indexedLabel", predictionCol="prediction", metricName="accuracy")
    accuracy = evaluator.evaluate(predictions)
    print("Test Error = %g " % (1.0 - accuracy))
    
    #                 
    model=TreeModel.stages[2]
    print(model.toDeBugString)
    
    予測セットの生成と予測
    まず17,18番の統計データテーブルから予測セットを構築し,予測セットも特徴ベクトルを生成することに注意する.
    
    from pyspark.ml.linalg import Vectors
    from pyspark.ml.feature import VectorAssembler
    assembler=VectorAssembler(inputCols=["t1","t2","t3","t4","t5","t6","t7","t8","t9","t10"],outputCol="features")
    
    dataset_predict=spark.sql("SELECT user_id,item_id,2day_buy, \
    2day_view*2 AS t1 , 2day_favor*3 AS t2 , 2day_tocar*4 AS t3 , 2day_buy*1 AS t4 ,\
    2day_view*1+2day_favor*2+2day_tocar*3-2day_buy*1 AS t5,\
    (2day_view+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t6,\
    (2day_favor+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t7,\
    (2day_tocar+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t8,\
    (2day_buy+1)/(2day_view+2day_favor+2day_tocar+2day_buy+1) AS t9,\
    (2day_favor+1)*(2day_tocar+1)-2day_buy*2 AS t10 \
    FROM day1718_19_predict_data WHERE 2day_buy<5")
    
    output_predict = assembler.transform(dataset_predict)
    predict_data=output_predict.select("user_id","item_id","2day_buy","features")
    
    最後に、モデルを適用してデータを予測し、結果をファイルに書き、最後に提出することができます.
    
    prediction=model.transform(predict_data)
    result=prediction.select("user_id","item_id","2day_buy","prediction")
    result.createOrReplaceTempView("result")
    outdata=spark.sql("SELECT user_id,item_id FROM result WHERE prediction>0 AND 2day_buy=0") #   17/18             
    outdata.write.csv("outfile.csv")
    
    最終的には、時間F 1の採点精度2016-11-04 12:47:00|6.36805181%|0.044161668が200点以上を占め、初めて出場したシロには達成感があった.
    結び目
    本文は主にゼロから試合を始める方法を詳しく紹介した.特徴抽出,モデル構築などについては,さらに深く学習する必要がある.みんながすべて良い成绩があることを望みます!
    原文を参照:http://www.wyblog.cn/2016/11/05/%e5%a4%a9%e6%b1%a0%e5%88%9d%e4%bd%93%e9%aa%8c-%e6%96%b0%e4%ba%ba%e5%ae%9e%e6%88%98%e8%b5%9b%e4%b9%8b%e7%a6%bb%e7%ba%bf%e8%b5%9b/