「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

25
ビビビビビビビビビビビ ビビビビビビビビビビ ビビビ #7 25 PAGES Shintaro Nomura R 2016.05.13 @ Akiba Code

Transcript of 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

Page 1: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

「ビジネス活用事例で学ぶ データサイエンス入門」輪読会 #7

25 PAGES

Shintaro Nomura

R で 学 ぶ

2016.05.13 @ Akiba Code

Page 2: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

使用テキストとソースコードの場所 2

「ビジネス活用事例で学ぶ データサイエンス入門」http://amzn.to/1Y73Y52( kindle 版あり)

使用データおよびソースコードの DLSBクリエイティブサイトhttp://www.sbcr.jp/support/11915.html

Page 3: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

データ分析の模範フロー(復習)

現状とあるべき姿

問題発見

データ収集と加工

データ分析

アクション

3

ギャップから問題の構造を把握

Page 4: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

データ分析を活用した機能の実装

今回の分析ストーリー

目的 チーム内で同時間帯にゲームを遊んでいる人が多くなるようにプレイヤーにチーム編成をさせたい

分析アプローチ 過去のサービス利用状況から、ユーザごとに翌日サービスを利用する時間帯の予測を行う

アクション 分析結果をもとに、同じ時間帯にアクセスするであろうユーザ同士でチームを作らせる

4安定期に入った自社開発ゲームあるある

PDCA 回したくなりがちPlan( 企画 )→Do( 実施 )→Check( 検証 )→Action( 改善 )

新企画:チーム編成のサジェスト機能

Page 5: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

中間データ読み込み用の関数の作成 5readActionHourly <- function(app.name, date.from, date.to) {date.from <- as.Date(date.from)date.to <- as.Date(date.to)ldply(foreach(day = seq.Date(date.from, date.to, by = "day"),combine = rbind) %do%{f <- sprintf("sample-data/section10/action_hourly/%s/%s/action_hourly.tsv“, app.name, day)read.csv(f, header = T, stringsAsFactors = F, sep = "\t")})}あくまでデータの読み込みを統一的に処理するための関数を作成しているだけ。

・ readActionHourly は処理方法を指定する関数 (function) となっている・ as.Date は()内のデータ型式を日付型データに変換するコマンド・ foreachとldplyを使ってforループの記述から脱却しよう - kensuke-miの日記

Page 6: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

sprintf 関数と「 function 」

sprintf(" まず %s, その次に %s", " 最初の文字列 ", " 次の文字列 ")[1] " まず 最初の文字列 , その次に 次の文字列 "

6

hello <- function(name){ + print(sprintf("Hello %s", name)) + } hello(“ ジャニーさん” ) # 定義した関数で出力

[1] "Hello ジャニーさん "

詳しくは・「みんなのR データ分析と統計解析の新しい教科書」第8章・ RPubs - R の文字列結合が面倒くさいので色々考えてみた

Page 7: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

実際に実行してみた方が理解が早い

action.hourly <- readActionHourly("game-01", "2013-08-01", "2013-08-08")head(action.hourly)function により定義した readActionHourly 関数を使用し、 app.name, date.from, date.to を指定した上で、「 sample-data/section10/action_hourly/%s/%s/action_hourly.tsv 」を読み込んでみた結果

そもそもの「 sample-data/section10/action_hourly/ 」以下の構造

7

Page 8: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

時間帯が列になるように整形

dates <- unique(action.hourly$log_date)train.list <- lapply(1:(length(dates) - 1), function(i) {day <- dates[i]x <- action.hourly[action.hourly$log_date == day, ]df <- dcast(x, user_id ~ log_hour, value.var = "count",function(x) {ifelse(sum(x) >= 7, 1, 0)})names(df) <- c("user_id", paste0("p", i, "_", 0:23))df})head(train.list[[1]])過去の下処理の集大成みたいなコードが続きますが、いくつかは #5 資料を参照くださいhttp://www.slideshare.net/ShintaroNomura/5-59987223applyファミリー | apply,sapply,lapplyの使い方とその例

length(XXX): XXX の中にある要素の個数dates[k]: 「 dates 」のk番目の要素を取り出すx <- action.hourly[action.hourly$log_date == day, ]:

8print(dates)[1] "2013-08-01" "2013-08-02" "2013-08-03" "2013-08-04" "2013-08-05" "2013-08-06" "2013-08-07" "2013-08-08"

Page 9: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

R における for ループ

for(i in 1:10){print(i)}出力結果:

[1] 1 [1] 2 [1] 3 [1] 4 [1] 5 [1] 6 [1] 7 [1] 8 [1] 9 [1] 10

9

Page 10: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

同じ曜日の別の日のデータと結合

# 説明(変数)用のデータを作成train.data <- train.list[[1]]for (i in 2:length(train.list)) {df <- train.list[[i]]   # train.list[2] ~ train.list[7] を df に格納→新 train.data にマージtrain.data <- merge(train.data, df, by = "user_id", all.x = T)train.data[is.na(train.data)] <- 0 }names(train.data)

# 答えとなるデータを作成ans0 <- action.hourly[action.hourly$log_date == dates[length(dates)], ]# 時間帯が列になるように整形ans <- dcast(ans0, user_id ~ log_hour, value.var = "count", function(x) {ifelse(sum(x) >= 7, 1, 0)})names(ans) <- c("user_id", paste0("a_", 0:23)) # 説明用のデータとくっつけるtrain.data <- merge(train.data, ans, by = "user_id", all.x = T)train.data[is.na(train.data)] <- 0names(train.data)

10

この場合、「 2013-08-08 」になる

Page 11: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

最終 train.datahead(train.data)・ train.data と ans がマージされた最終 train.data

※ 画像はテキスト p.244 より

11

Page 12: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

今回の分析アプローチ(おさらい)

今回の分析ストーリー

目的チーム内で同時間帯にゲームを遊んでいる人が多くなるようにプレイヤーにチーム編成をさせたい

分析アプローチ

過去のサービス利用状況から、ユーザごとに翌日サービスを利用する時間帯の予測を行う

アクション分析結果をもとに、同じ時間帯にアクセスするであろうユーザ同士でチームを作らせる

12

予測モデル構築 → 検証 → 予測モデルを分析アルゴリズムに実装

Page 13: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

予測モデルの構築

予測モデルの構築がそもそも可能か?

扱うデータに「規則性」「まとまり」が存在しないならば

モデル構築は厳しい

ノイズの除去

ビジネスデータにはノイズが多く、モデリングに悪影響を

及ぼす可能性も

利用ツールの選定

構築モデルにどのツールを用いるべきか予想がつかない場

合は、なるべく多くのツールで実際に検証

13

Page 14: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

分類モデルの性能比較 ( 利用ツールの選定 )

複数のツール同士の性能を比較する方法は、

分析者が構築したいモデルへのニーズ(正

解率が高い方が良いとか、不正解を極力減

らしたいとか etc… )によって、用いる指

標が異なる

今回は指標に F1-measure (値)を使用し

ている

14

Page 15: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

F1-measure (値)

Recall = 正解率 ( TP+TN / 全体 )Precision = 適合率 ( TP / 陽性判定全

体)

逆相関になりやすいので調和平均をとる

15

正解は「1」 正解は「0」

予測が「1」 TP (真陽性) FP (偽陽性)

予測が「0」 FN (偽陰性) TN (真陰性)

Page 16: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

F値基準によるノイズの除去

F1値を使用して分類モデルにおけるノイ

ズの閾値を決定(直近3日間 PV≧7だと

翌日訪問/同 PV<7だと来ないモデル)

これにより、同 PV が7未満の箇所をノ

イズと決定し、そのデータを0に換える

16

Page 17: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

決定木

第9章(今回はスルー)では、決定木を

用いた分析が行われた (p.215)

17

Page 18: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

決定木:分類と回帰

分類ルールを木構造で表したもの

目的変数がカテゴリデータなどの場合は「分

類木」、連続値などの量的データの場合は

「回帰木」と呼ばれる

参考:決定木 – 分類木 | トライフィールズ

⇨ひとまず R で動かして見てみましょう

ソースコード

18

Page 19: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

「タイタニック」データと決定木

タイタニック号事故で生死を分けた要因

を属性情報から分類(「分類木」)

19

Page 20: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

ランダムフォレスト

集団(アンサンブル)学習のひとつ

ランダムに抽出した決定木を複数つくり、

その中から精度の高いモデルを1つ作成

する手法

今回のコードでは、” e1071” というパッ

ケージが必要になるかも

20

Page 21: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

randomForest とクロスバリデーション

# 学習のカスタマイズfit.control <- trainControl(method = "LGOCV", p = 0.75, number = 30)リサンプリング方法: Leave-Group-Out クロスバリデーションp: LGO クロスバリデーションにて学習 (訓練 ) に用いるデータの割合number :指定したリサンプリング方法において学習を繰り返す回数

21

Wikipedia: クロスバリデーション

交差検証(英 : Cross-validation )とは、統計学において標本データを分割し、その一部をまず解析して、残る部分でその解析のテストを行い、解析自身の妥当性の検証・確認に当てる手法を指す。

データの解析(および導出された推定・統計的予測)がどれだけ本当に母集団に対処できるかを良い近似で検証・確認するための手法である。

最初に解析するデータを「訓練事例集合( training set )」などと呼び、他のデータを「テスト事例集合( testing set 、テストデータ)」などと呼ぶ。

Page 22: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

randomForest による学習コード

# ランダムフォレストによる学習rf.fit.list <- lapply(0:23, function(h) {df <- train.data[, c(paste0("p", 1:7, "_", h), paste0("a_", h))]df1 <- df[df[, ncol(df)] == 1, ]df0.orig <- df[df[, ncol(df)] == 0, ]df0 <- df0.orig[sample(1:nrow(df0.orig), nrow(df1)), ]df <- rbind(df1, df0)fit <- train(x=df[, -ncol(df)], y=df[, ncol(df)],method = "rf", preProcess = c("center", "scale"),trControl = fit.control)fit})ncol(XXX) : XXX の行数(n×m次元である XXXベクトルにおけるn)nrow(XXX) : XXX の列数(n×m次元である XXXベクトルにおけるm)

train() : 予測モデルのフィッティングを行う関数( {caret} が必要)  method :予測方法の指定( rf = ランダムフォレスト)  trControl : training データをどうやって選ぶか( fit.control にて指定済み)

22

Page 23: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

構築された最終モデルによる予測精度

# 作成したモデルの予測値と実際の値との比較結果の表示for (i in 0:23) {result.rf <- predict(rf.fit.list[[(i + 1)]]$finalModel, train.data)result.rf.pred <- ifelse(result.rf >= 0.5, 1, 0)print(confusionMatrix(result.rf.pred, train.data[, paste0("a_",i)]))}Confusion Matrix and Statistics  ( i = 0 のとき;結果はモデル計算の都度変わる)

Accuracy : 0.815 ←( 389 + 47 ) / ( 389 + 20 + 79 + 47 ) 95% CI : (0.7794, 0.847) No Information Rate : 0.8748 P-Value [Acc > NIR] : 1 … (こうした結果が各時間帯ごとに出力される:最終的に 26×24 行出力)

23

Prediction\Reference 正解は「1」 正解は「0」

予測が「1」 389 20予測が「0」 79 47

Page 24: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

アクション( 10.5 )

テキストでは、構築された予測モデルの精度に問

題がないとの判断から、それにより各ユーザごと

に「翌日どの時間帯にどの程度の確率でゲームを

利用するか」を出力するアルゴリズムを実装

その出力データに基づき、各ユーザが入るチーム

探しの際に、翌日そのユーザが来た際にアクティ

ブユーザー率が高くなる確率が高いチームを推薦

する機能を導入することにした

24

Page 25: 「ビジネス活用事例で学ぶ データサイエンス入門」輪読会#7資料

長期間おつかれさまでした

Q. 今後、当グループで学習したいこと (n=11; 最終回の参加希望者・回答者 )

以下の書籍をクリックすると Amazon に飛びます。

25

1 2 3

11 9 7