オルトプラスエンジニアの日常をお伝えします!

Weka+JAVAのあるデータ分析実践例

※この記事は「AltPlus Advent Calendar 2016」の17日目の記事ですよ。

ご挨拶

皆さんこんにちは。こちらはブログを書くのが苦手な id:Sherphie です。

今度話したいのは、あるゲームプロジェクトである時期のあるイベントで経験したとある事例です。

具体的なデータは禁則事項ですので開示できないですが、流れのみ話します。

どうぞお楽しみに。

背景

ミッション概要:

最近のイベントから離脱したユーザーの離脱原因が分からない...

サブアカウントも結構活躍していて、手動検出のコストが高い...

何ができるのか?

戦場環境:

  • アカウント数:数百万レベル
  • イベント参加者数:禁則事項
  • 手動検出したサブアカウントサンプル:数個レベル

基本装備品:

  • i5-3740 cpu + 8G ram 普通なデスクトップパソコン1台
  • JDK 1.7/1.8 環境 JAVA base ですから
  • JAVA IDE: Eclipse Mars 他のIDEでも全く問題なし
  • Weka 3.7.14 / 3.8 歴史が長いの有名な機械学習+データマイニングのプラットフォーム

ミッション報酬:

  • バフ:自己満足

では、ミッションスタート!

状況分析

  • ユーザーのイベント参加状況は既に分かったので、教師信号を作って、決定木分析で分析しよう。
  • 大量のサブアカの持ち主は大抵は同じ習慣でサブアカを管理していて、クラスタリングで相似性が高いアカウント検出しよう。

操作の流れ

1. データファイルの読み込み~

固有フォーマットのARFF或いはCSVファイルなど、DBと直接接続も可能ですよ。

f:id:Sherphie:20161216210942j:plain

2. 次元圧縮 (日本語訳名かっこいい感じ!

分析処理の作業量を減らすために、高次元のデータを情報が出来る限り損失が出ないように低次元のデータに変換します~

f:id:Sherphie:20161216211157j:plain

3. アルゴリズム選択、パラメーター選択、解析スタート!

  • J48(C4.5)アルゴリズムによる決定木分析

f:id:Sherphie:20161216213022j:plain

  • EMアルゴリズムによるクラスタリング

[f:id:Sherphie:20161216213035j:plain

(以上は教科書の内容でそのままコピペでいいです。本説明の削除も忘れないように。)

4. 結果の評価と可視化

  • データ量によって、10秒或いは10時間後、終了~

  • 生成されたモデルの正解率、結構高いですね~

f:id:Sherphie:20161216220109j:plain

  • 生成されたルールモデル。禁則事項が多すぎるので、もう意味が分からない...。けどそれはもう過学習の防止または禁則事項を減らせるために、2%の正解率を犠牲させて枝刈り処理済みました結果です...

f:id:Sherphie:20161216221419j:plain

  • クラスタリングの結果です。各クラスタは色付きで分別されて、黒いクラスターはサブアカ所在のクラスタです。ちなみに条件付きで選出されたインスタンス数(簡単的に言うと調査範囲内のアカウント数)は約70万個ぐらいです。

f:id:Sherphie:20161216220128j:plain

5. もう終わりよ~(え?上記の結果の意義と使い方も分からない?)

  • 決定木構造から生成されたモデルは今後他のユーザーの離脱可能性判断の根拠として使えます。

    • 例:レベル189以下、イベント参加率64%、SRカード持ち数5以内、最後ログイン記録は5日前のユーザー → 今後離脱の可能性は93%です(モデルの正解率)。

   

  • クラスタリングの結果の使え方は、とりあえずサブアカ所在のクラスタ内の他のアカウントも同じサブアカの嫌疑が高いので、そのまま同じポリシーで処置すればいいです。

    • 同じクラスタにあるというのは、その表現されたパターンはかなり相似性が高いですから。

6. JAVAとの連携 

  • 1997年ぐらいからWekaは既にJAVAベースになりましたので、現在Weka内の全ての機能は、JAVAで簡単に使用可能です。

  • 先ほどの決定木分析をJAVAで実行出来るコードはどれぐらいだろう?サンプルコードは下記の様子です。

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

import weka.classifiers.Evaluation;

import weka.classifiers.trees.J48;
import weka.classifiers.Classifier;

import weka.core.Instances;
import weka.core.converters.ArffLoader;

public class J48Test {  
    public static void main(String[] args) throws Exception {  
        //----------------必要なデータの読み込む---------------
        Classifier classifierJ48 = new J48();
        ArffLoader rawatf = new ArffLoader();
        
        //まずは訓練用データ読み込む
        File dataLoader = new File("*** .arff file path ***"); 
        rawatf.setFile(dataLoader);
        Instances instancesTrainJ48 = rawatf.getDataSet();
        
        //次は検証用データの読み込む
        dataLoader = new File("*** .arff file path ***");  
        rawatf.setFile(dataLoader);
        Instances instancesTestJ48 = rawatf.getDataSet();
        
        //-----------------基本パラメーター設定------------------
        //ターゲット属性行位置設定(最初の1行目の番号は0)
        instancesTrainJ48.setClassIndex(0);

      //instancesTestJ48.numAttributes()使ったら属性数を返すことは可能


        //~~~~~~~~~~~~~~~~~~~訓練スタート~~~~~~~~~~~
        classifierJ48.buildClassifier(instancesTrainJ48); 
        
        //-------------------訓練結果の評価----------------
        Evaluation evaluation = new Evaluation(instancesTrainJ48);
        evaluation.evaluateModel(classifierJ48, instancesTrainJ48);
        
        System.out.println(evaluation.toMatrixString());
      }  
}

はい~ミッション完了!(冗談じゃない!何の栄養もないだろう!)

申し訳ないです。以下正文。

  • 結構失礼な話し方で書きまし申し訳ございません。ここまで我慢した読者に心より感謝申し上げます。

  • 練習データではないですので、結構隠す必要があるものが多いので、更に分かり難くなりました。申し訳ございません。

  • 実際のデータ分析過程中、各ゲームデータに対する理解、その理解の結果を活かして必要な情報を洗い出すこと、またはこの情報を活用することが重要です

  • ご覧通り、上記のデータ分析過程中、実際の操作は本当に僅かな何ステップです。

  • 実際の時間コストから見ると、6割の時間は前処理(生データの洗い出し)、3割の時間はアルゴリズムの選択およびパラメータの最適化、残ったのは上記の部分です。

  • 開発工数=お金です。もしデータ分析のツールまで作らなければならないなら、時間コストはもったいないです。

  • 積極的にWeka、Azure、Tensorflowなどのようなプラットフォームを応用すれば、仕事の効率はだんだん高くなれるはずです。

最後、Wekaの開発者たちに感謝します。