rails A/B testingby split gemRyuma Tsukano
A/B testingとは●   WebサイトでUIのパターンを複数準備●   同時期にユーザー毎にパターンを切替え●   コンバーション率を計測●   より効果的な物を選択
典型的なA/B testingのイメージUser毎にRandomに2つのUIを切り分け         30%      60%         がclick   がclick  LOSE                     WIN! =>...
やや強引に言葉を整理広義な意味のA/B testing = split test                                               ※人によって定義違うが  ○ A/B test (marketing/...
なぜA/B testing?● 静的なWebサイトだけの話?● ECサイト/ソシャゲー等Design重視site向け?● Designの微かな差の反応を確認したいだけ?● Designer/UX系の人たちの話で、開発には関  係無い?=> 開発...
現場で● 1)機能単位の効果を知りたい。 ○ 機能改修したが、本当に改善? ○ PV/UU見れば反応分かる。   ■ 但し、これらは沢山の要因で動く。● 2)数値の正しい目安を知りたい。 ○ Click数等で機能単位で数値取れるが、時系列の異な...
そこでA/B testing1)UI/Page単位でテストする事で ○ 機能毎の効果が明確になる2)同じタイミング同士の結果を比較する事で ○ より正しい数値比較が可能になる
A / Btestingの最大のメリット(画面変化を伴う )機能改修毎に、明確な成績が付く事
A / B testing導入すると…● 実は、***機能改修は何も改善してなかった● 実は、コンバーション変化無かった。=>等々、諸々のエグい事実が丸裸に!(なるかも)
A / B testingの方法外部サイト● google / adobe / sitecatalyst / optimizely等=>多くが、静的ページのためのもの作り● JSでtrack埋め込み● URLを切り替えて集計● JSで要素毎に表...
外部サイトからのA / B testing●   コンバーションのタイミングに限界●   A / B の切り替えが煩雑●   JSで勝手にhtmlすり替わる?物もある●   サーバーsideの手から離れるので扱いにくい●   そもそも決定打が無...
ruby gemのA/B testing● A/Bingo : rails2時代のstandard?  ○ 公式でrails3無い?非公式forkあるが、動作謎● vanity : rails2/3切替り時のstandard?  ○ 何故か最近...
splithttps://github.com/andrew/split1. 簡潔な記述        ■ 簡潔にA/B testingを記述できて気持ち良い!2. pattern管理        ■ sessionでpatternを管理して...
1)簡潔な記述A/B testing    ab_test(テスト名, 旧パターン, 新パターン)コンバーション  finished(テスト名)これだけ。
scaffold apples#app/views/apples/index.html.erb<% ab_test("link-abtest", "NEWNEW!", "新規に作成!") do|link_label| %>  <%= link_...
ブラウザある人には「NEWNEW!」ある人には「新規に作成!」
こんな書き方も出来る#app/views/apples/index.html.erb<% ab_test("link-abtest", "A", "B") do |pattern| %> <% if pattern == "A" %>  ・・・...
ちなみに開発時は?パラメータでパターンを指定できる● ?テスト名=パターン名=>これで強制的にパターンを表示させて確認
ab_testの記述設定ファイルにも書ける# cofig/initializer/split.rbSplit.configure do |config| config.experiments = {   "ex1" => { :alternat...
補足ab_test   ○   パターンは幾つでも追加可能   ○   controller/viewどこでも書ける   ○   hashで重み付け可能(新パターンを5%のuserに等)   ○   今後、メトリクス追加できるらしい(今は無理)...
2)patternの管理sessionにpatternが入ってる(設定でcookie可) "split"=>{"hoge:2"=>"ptnB",           "hoge:2:finished"=>true}2つの情報● テスト名:ver...
パターン "split"=>{"hoge:2"=>"ptnB",           "hoge:2:finished"=>true}テスト名:version=>表示パターンを記録 ○ versionはdataを(サーバー側)Resetすると繰...
Clickの記録  "split"=>{"hoge:2"=>"ptnB",            "hoge:2:finished"=>true}finished=>true  ○ ゴール(finished)にたどり着いたらつくFlag  ○ ...
2つのReset● クライアント側のReset ○ 方法:finished (reset => true)   ■ ※defaultなのでreset指定しないとreset => trueになってる ○ 変わる事:sessionのクリア。違うパタ...
はまる所開発時、reset/versionでハマる。 1.   testX:1でptnAを表示 2.   表示内容修正 3.   サーバ側Resetして再開(testX:2) 4.   split testのsessionとしてカウントされず。...
3) Redis普段使ってるRDBとは別にRedisで管理           conversion数/         普段のデータ   パターン/完了flag           session数                      ...
Redis とはKVS(in memory/後でdiskにも書込)  ○ read/writeいずれもnosqlでTOPクラスのspeed  ○ データ構造がprogramming言語ちっく  ○ 設定/install が簡易事例  ○ git...
Redis install / 設定まで(mac)install   ○ $ brew install redis実行   ○ $ redis-serverおしまい。
SplitのRedisデータ構造hogeテストでptnA/ptnBを試した場合 1.   split:experiment_start_times =>test開始時刻 2.   split:experiments =>test名 3.   s...
splitのRedisデータ上の注意以下のデータは辿れない(記録してない) ○ 1countの時系列データ(いつ押した?) ○ 1countのUser情報(誰が押したか?)splitに無い欲しい情報があれば、別の仕組みを用意する必要ある
Q&AQ:Redis落ちたら? ● Split側でcatchする仕組み有り。   ○ config.db_failover_on_db_error = proc{|error| ... } ● その結果、アプリはエラーにならない。   ○ lo...
4)dashboardhttps://localhost:3000/split に、皆で見れるdashboardgem split , :require => split/dashboard#config/routes.rbmount Spli...
dashboardの意味列の説明 ○   ALTERNATIVE NAME : 選択肢名 ○   PARTICIPANTS : セッションの数 ○   NON-FINISHED : まだゴール到達してない数 ○   COMPLETED : ゴー...
ラベルの意味 ● control : 比較元 ● CONVERSION RATEの+50:0% : 比較元   に対して何%改善したか?の割合
そもそもの数値の話Q : なんか異常にcompletedが少ない気が?   ○ Reset次第で数値の意味合いが違うのでご注意を● finished(reset => false) :   ○ 1userが複数click => complete...
TipsUse thisは使わなくてもいいかも...  ○ 結果がredis見ないと分からず保守しづらい  ○ ab_testのコードがソース中に沢山あると、内容が掴み    辛くなりそう。  ○ 突然、Redisデータ無くなったら...恐ろし...
5)bandit algorithm実験と利益を最大限にするための戦略● Aに価値がある時はなるべくAを表示● Bに価値がある時はなるべくBを表示現状のdataから学習して、出現割合に融通を利かせる
splitでの実装設定ファイルでabtest記述。# cofig/initializer/split.rbSplit.configure do |config| config.experiments = {   "ex" => { :alter...
やってみた。AとBの2patternで、ひたすらBだけ押しまくる  回数   1    2    3    4    5    6    7    8    9    10  表示   A    B    B    A    A    A   ...
何が嬉しいのか?● A/B testing実験期間中も利益を最大化  ○ win/loseがある程度分かっているなら、その割合に応じ    てwinnerをいっぱい出した方が得。● continuous experiments出来る  ○ 要す...
まとめA/B testing  ○ 機能毎の成績表。  ○ 見てはいけないものが丸裸に!(なるかも)Split  ○     記述が死ぬ程簡単  ○     sessionでばっちり管理  ○     Redisで楽チン。構造もsimple  ...
おしまい
Upcoming SlideShare
Loading in...5
×

Rails A/B testing by split gem

3,045

Published on

A/B testing of ruby on rails by split gem.

Published in: Technology

Transcript of "Rails A/B testing by split gem"

  1. 1. rails A/B testingby split gemRyuma Tsukano
  2. 2. A/B testingとは● WebサイトでUIのパターンを複数準備● 同時期にユーザー毎にパターンを切替え● コンバーション率を計測● より効果的な物を選択
  3. 3. 典型的なA/B testingのイメージUser毎にRandomに2つのUIを切り分け 30% 60% がclick がclick LOSE WIN! => 採用
  4. 4. やや強引に言葉を整理広義な意味のA/B testing = split test ※人によって定義違うが ○ A/B test (marketing/lean startup etc) ■ 特定のUIを切替 ※今日話すsplitが ■ 直列にBefore/Afterを比較 どちらかというと こっち ○ split test(design/UXがどちらかというとこっち) ■ (主に)Pageレベルの切り分け ■ 並列に複数のpatternと比較 ○ 多変量テスト ■ 要素組み合わせ ■ 複数patternを比較 http://www.massivesplash.com/Blog/Entry/is-there-a-difference-between-split-test-and-ab-test
  5. 5. なぜA/B testing?● 静的なWebサイトだけの話?● ECサイト/ソシャゲー等Design重視site向け?● Designの微かな差の反応を確認したいだけ?● Designer/UX系の人たちの話で、開発には関 係無い?=> 開発現場の話を。
  6. 6. 現場で● 1)機能単位の効果を知りたい。 ○ 機能改修したが、本当に改善? ○ PV/UU見れば反応分かる。 ■ 但し、これらは沢山の要因で動く。● 2)数値の正しい目安を知りたい。 ○ Click数等で機能単位で数値取れるが、時系列の異なる 比較になる。 ○ 時系列の違う数値の比較は意味があるのか? ■ ex.先月のclick数30万=>今月のclick数50万 ■ 実は機能改修以外の他の要因で数値が上がってる だけだったりして...
  7. 7. そこでA/B testing1)UI/Page単位でテストする事で ○ 機能毎の効果が明確になる2)同じタイミング同士の結果を比較する事で ○ より正しい数値比較が可能になる
  8. 8. A / Btestingの最大のメリット(画面変化を伴う )機能改修毎に、明確な成績が付く事
  9. 9. A / B testing導入すると…● 実は、***機能改修は何も改善してなかった● 実は、コンバーション変化無かった。=>等々、諸々のエグい事実が丸裸に!(なるかも)
  10. 10. A / B testingの方法外部サイト● google / adobe / sitecatalyst / optimizely等=>多くが、静的ページのためのもの作り● JSでtrack埋め込み● URLを切り替えて集計● JSで要素毎に表示切替等
  11. 11. 外部サイトからのA / B testing● コンバーションのタイミングに限界● A / B の切り替えが煩雑● JSで勝手にhtmlすり替わる?物もある● サーバーsideの手から離れるので扱いにくい● そもそも決定打が無い?● 綺麗なグラフ有り難いが、殆ど有料=> そこで、ruby gemでA/B testing
  12. 12. ruby gemのA/B testing● A/Bingo : rails2時代のstandard? ○ 公式でrails3無い?非公式forkあるが、動作謎● vanity : rails2/3切替り時のstandard? ○ 何故か最近のrails3で動かず、ググると同じerrorで困っ てる人いて、解決策無かった ○ そもそも、レポジトリ1年位更新されてない?● split : rails3で動く。開発は進行中。=>という事で、split
  13. 13. splithttps://github.com/andrew/split1. 簡潔な記述 ■ 簡潔にA/B testingを記述できて気持ち良い!2. pattern管理 ■ sessionでpatternを管理してて頼れる!3. Redis ■ Redisに結果を保存してて、とても今時!4. dashboard ■ dashboardで非開発者と情報共有出来る!5. bandit algorithm ■ bandit algorithmで実験の幅が広がる!
  14. 14. 1)簡潔な記述A/B testing ab_test(テスト名, 旧パターン, 新パターン)コンバーション finished(テスト名)これだけ。
  15. 15. scaffold apples#app/views/apples/index.html.erb<% ab_test("link-abtest", "NEWNEW!", "新規に作成!") do|link_label| %> <%= link_to link_label, new_apple_path %><% end %>#app/controllers/apples_controlldef new finished("link-abtest") ・・・
  16. 16. ブラウザある人には「NEWNEW!」ある人には「新規に作成!」
  17. 17. こんな書き方も出来る#app/views/apples/index.html.erb<% ab_test("link-abtest", "A", "B") do |pattern| %> <% if pattern == "A" %>  ・・・ <% elsif pattern == "B" %>  ・・・ <% end %><% end %>=>柔軟に切り分けれる。
  18. 18. ちなみに開発時は?パラメータでパターンを指定できる● ?テスト名=パターン名=>これで強制的にパターンを表示させて確認
  19. 19. ab_testの記述設定ファイルにも書ける# cofig/initializer/split.rbSplit.configure do |config| config.experiments = { "ex1" => { :alternatives => ["a", "b"], :resettable => false}, "ex2" => { :alternatives => ["X", "Y"]} }end● 書けるoptionが増える(後述)● 複数のA/Btestingやる時に混乱無さそう。
  20. 20. 補足ab_test ○ パターンは幾つでも追加可能 ○ controller/viewどこでも書ける ○ hashで重み付け可能(新パターンを5%のuserに等) ○ 今後、メトリクス追加できるらしい(今は無理)finished ○ controller/viewどこでも書ける(今後jsも) ○ Client側のreset書き分けれる(reset => true/false) ■ コロコロUI変わると不自然なので、基本はresetせず 同パターンを表示すべき ■ 広告等はresetしてもいいかも。CaseByCase ○ 今後、finishedも複数分けれるらしい(今は無理)
  21. 21. 2)patternの管理sessionにpatternが入ってる(設定でcookie可) "split"=>{"hoge:2"=>"ptnB", "hoge:2:finished"=>true}2つの情報● テスト名:version=>パターン● finished=>true
  22. 22. パターン "split"=>{"hoge:2"=>"ptnB", "hoge:2:finished"=>true}テスト名:version=>表示パターンを記録 ○ versionはdataを(サーバー側)Resetすると繰上がる ○ 1度表示したらクライアント側のResetしない限り、同じ物 を表示し続ける(しっかりしてる) ○ Resetについては、後述
  23. 23. Clickの記録 "split"=>{"hoge:2"=>"ptnB", "hoge:2:finished"=>true}finished=>true ○ ゴール(finished)にたどり着いたらつくFlag ○ 既にカウントしたら2回以上カウントしない(これもクライア ント側のResetしない限り)
  24. 24. 2つのReset● クライアント側のReset ○ 方法:finished (reset => true) ■ ※defaultなのでreset指定しないとreset => trueになってる ○ 変わる事:sessionのクリア。違うパターンが表示される 可能性有り。再度ゴールすると1count。● サーバー側のReset ○ 方法:Dashboard(後述)からReset ○ 変わる事:testのversion繰り上げまだ、開発中でごちゃごちゃしてる。
  25. 25. はまる所開発時、reset/versionでハマる。 1. testX:1でptnAを表示 2. 表示内容修正 3. サーバ側Resetして再開(testX:2) 4. split testのsessionとしてカウントされず。ptnAのまま固 定。あれ?動いてない?=>SessionClearで解決。 ○ v1でptnAを表示したのでclient側resetしないと、v2でも ptnAを表示し続ける=>Resetの扱いはご注意を
  26. 26. 3) Redis普段使ってるRDBとは別にRedisで管理 conversion数/ 普段のデータ パターン/完了flag session数 Session/cookie Redis RDBMS (設定次第) Server (app/ web)=>RDBへの影響を心配しなくて済む
  27. 27. Redis とはKVS(in memory/後でdiskにも書込) ○ read/writeいずれもnosqlでTOPクラスのspeed ○ データ構造がprogramming言語ちっく ○ 設定/install が簡易事例 ○ github/instagram/Flickr/ニコ生/ソシャゲーetc... ○ 丁度、web+db press vol.73(2013/3)でも特集
  28. 28. Redis install / 設定まで(mac)install ○ $ brew install redis実行 ○ $ redis-serverおしまい。
  29. 29. SplitのRedisデータ構造hogeテストでptnA/ptnBを試した場合 1. split:experiment_start_times =>test開始時刻 2. split:experiments =>test名 3. split:hoge =>"ptnA","ptnB" 4. split:hoge:ptnA => 全session数/conversion数 5. split:hoge:ptnB => 同じ。それぞれの値を保持。–>シンプル。自分でも管理画面やグラフ画面作れそう。
  30. 30. splitのRedisデータ上の注意以下のデータは辿れない(記録してない) ○ 1countの時系列データ(いつ押した?) ○ 1countのUser情報(誰が押したか?)splitに無い欲しい情報があれば、別の仕組みを用意する必要ある
  31. 31. Q&AQ:Redis落ちたら? ● Split側でcatchする仕組み有り。 ○ config.db_failover_on_db_error = proc{|error| ... } ● その結果、アプリはエラーにならない。 ○ logはくだけ。 ○ ちなみに、その際は一番目のpatternを表示Q:冗長化は? ○ Redisの設定fileにslaveOf書くだけでReplication ○ 本家が自動failoverの管理サーバ開発中 ■ redis sentinel
  32. 32. 4)dashboardhttps://localhost:3000/split に、皆で見れるdashboardgem split , :require => split/dashboard#config/routes.rbmount Split::Dashboard, :at => split
  33. 33. dashboardの意味列の説明 ○ ALTERNATIVE NAME : 選択肢名 ○ PARTICIPANTS : セッションの数 ○ NON-FINISHED : まだゴール到達してない数 ○ COMPLETED : ゴール到達数 ○ CONVERSION RATE : コンバーション率 ○ CONFIDENCE : コンバーション率の信頼性 ○ FINISH : Use thisを押すと、同pattern固定信頼性が95%を上回ったらほぼ確定。
  34. 34. ラベルの意味 ● control : 比較元 ● CONVERSION RATEの+50:0% : 比較元 に対して何%改善したか?の割合
  35. 35. そもそもの数値の話Q : なんか異常にcompletedが少ない気が? ○ Reset次第で数値の意味合いが違うのでご注意を● finished(reset => false) : ○ 1userが複数click => completedは1 ○ completed≒セッション数● finished(reset => true) ○ 1userが複数click => completedは複数回 ○ completed≒click数
  36. 36. TipsUse thisは使わなくてもいいかも... ○ 結果がredis見ないと分からず保守しづらい ○ ab_testのコードがソース中に沢山あると、内容が掴み 辛くなりそう。 ○ 突然、Redisデータ無くなったら...恐ろしい事に..=>結果が明らかな時に 一時的にUse thisしておいて、 すぐab_testのソースを消した方がいいかも
  37. 37. 5)bandit algorithm実験と利益を最大限にするための戦略● Aに価値がある時はなるべくAを表示● Bに価値がある時はなるべくBを表示現状のdataから学習して、出現割合に融通を利かせる
  38. 38. splitでの実装設定ファイルでabtest記述。# cofig/initializer/split.rbSplit.configure do |config| config.experiments = { "ex" => { :alternatives => ["X", "Y"], :algorithm => Split::Algorithms::Whiplash} }endこれだけ。
  39. 39. やってみた。AとBの2patternで、ひたすらBだけ押しまくる 回数 1 2 3 4 5 6 7 8 9 10 表示 A B B A A A A B A B 回数 11 12 13 14 15 16 17 18 19 20 表示 A B B A A B B A B A 回数 21 22 23 24 25 26 27 28 29 30 表示 B A B B A B B B B B 回数 31 32 33 34 35 36 37 38 39 40 表示 B A B B B B A A B B=>後半、Bが主流に!(もっと回数多いと分かり易いかも )
  40. 40. 何が嬉しいのか?● A/B testing実験期間中も利益を最大化 ○ win/loseがある程度分かっているなら、その割合に応じ てwinnerをいっぱい出した方が得。● continuous experiments出来る ○ 要するに、A/B testingで放置 ○ ex. ハローウィンはオレンジと黒、クリスマスは赤白が好 まれる ○ ex. 12,1月は忘年会/新年会探す社会人、3,4月は引越 しする大学生と、利用する層がコロコロ変わる ○ 季節要因で結果がコロコロ変わってもカバー可能
  41. 41. まとめA/B testing ○ 機能毎の成績表。 ○ 見てはいけないものが丸裸に!(なるかも)Split ○ 記述が死ぬ程簡単 ○ sessionでばっちり管理 ○ Redisで楽チン。構造もsimple ○ dashboardで非開発者と情報共有出来る ○ bandit algorithmで色々応用出来そう
  42. 42. おしまい
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×