Tradeoff AnalyticsでAMIMOTOマネージドの最適プランを調べてみる
Tradeoff Analyticsについて Tradeoff Analyticsについては下の記事で紹介書いてるので、参考にしてください。 https://wp-kyoto.cdn.rabify.me/try-to-r […]
目次
Tradeoff Analyticsについて
Tradeoff Analyticsについては下の記事で紹介書いてるので、参考にしてください。
https://wp-kyoto.cdn.rabify.me/try-to-run-tradeoff-analytics/
どうせなら身近なものでテストしてみたいなと思ったので、ウチのサービスを題材にしてみました。
やってみたいこと
「価格・PV・WordPressインストール数とDBタイプの4種類から、希望条件に近いプランのリスト」を出すということを試してみます。
リクエストJSONを作る
最終的には1つのJSONにまとめますが、とりあえずパーツごとに作ります。
プロダクトリストを作る
まずは候補リストから。
候補はoptions
の中にリストとしてまとめていきます。
データソース
データはプラン一覧から拾ってきます。
https://ja.amimoto-ami.com/plans/hosting/single-instance-plan/
https://ja.amimoto-ami.com/plans/hosting/multi-instances-plan/
JSON
values
の中に、価格・PV・DBタイプ・WordPressインストール数を入れてます。
"options": [ { "key": "1", "name": "t2.micro", "values": { "price": 3000, "pv": 100000, "db": "EC2", "wp": 3 } },{ "key": "2", "name": "t2.small", "values": { "price": 6000, "pv": 300000, "db": "EC2", "wp": 3 } },{ "key": "3", "name": "t2.medium", "values": { "price": 15000, "pv": 500000, "db": "EC2", "wp": 3 } },{ "key": "4", "name": "c4.large", "values": { "price": 20000, "pv": 1000000, "db": "EC2", "wp": 5 } },{ "key": "5", "name": "c4.8large", "values": { "price": 350000, "pv": 20000000, "db": "EC2", "wp": 5 } },{ "key": "6", "name": "w-Small", "values": { "price": 80000, "pv": 3000000, "db": "RDS-Single", "wp": 5 } },{ "key": "7", "name": "w-Large", "values": { "price": 120000, "pv": 6000000, "db": "RDS-Single", "wp": 5 } },{ "key": "8", "name": "w-XLarge", "values": { "price": 160000, "pv": 10000000, "db": "RDS-Single", "wp": 10 } },{ "key": "9", "name": "w-2XLarge", "values": { "price": 320000, "pv": 20000000, "db": "RDS-Single", "wp": 10 } },{ "key": "10", "name": "HA-Small", "values": { "price": 120000, "pv": 3000000, "db": "RDS-Multi", "wp": 5 } },{ "key": "11", "name": "HA-Large", "values": { "price": 180000, "pv": 6000000, "db": "RDS-Multi", "wp": 5 } },{ "key": "12", "name": "HA-XLarge", "values": { "price": 200000, "pv": 10000000, "db": "RDS-Multi", "wp": 10 } },{ "key": "13", "name": "HA-2XLarge", "values": { "price": 460000, "pv": 20000000, "db": "RDS-Multi", "wp": 10 } } ]
検索条件を入れる
columns
キーの中に検索候補を入れていきます。
"columns": [ { "key": "price", "type": "numeric", "goal": "min", "is_objective": true, "full_name": "Price", "range": { "low": 0, "high": 300000 }, "format": "currency: 'JPY¥' : 2" },{ "key": "pv", "type": "numeric", "goal": "max", "is_objective": true, "full_name": "Monthly Pageview", "range": { "low": 10000000, "high": 20000000 }, "format": "number:2" },{ "key": "db", "type": "categorical", "goal": "min", "is_objective": true, "full_name": "Database Type", "range": [ "EC2", "RDS-Single", "RDS-Multi" ], "preference": [ "EC2", "RDS-Single", "RDS-Multi" ] },{ "key": "wp", "type": "numeric", "goal": "max", "is_objective": true, "full_name": "WordPress installation ", "range": { "low": 1, "high": 10 } } ]
検索条件を表にまとめるとこうなります。
項目名 | 範囲 |
---|---|
価格 | 0~300,000円 |
PV | 10,000,000~20,000,000 PV |
DBタイプ | EC2内DB > RDS1台 > RDSマルチAZ |
WPインストール数 | 1 ~ 10 |
categoricalの分類方法
preference
の配列順序でレコメンド度合いを取ります。
goal
をmaxにした場合は配列の後ろの方にあるものを優先、minにした場合は前にあるものを優先します。
JSONにまとめる
最後にsubject
にタイトルを付けて、JSONにまとめます。
まとめたものが以下の通り。
{ "subject": "amimoto", "columns": [ { "key": "price", "type": "numeric", "goal": "min", "is_objective": true, "full_name": "Price", "range": { "low": 0, "high": 300000 }, "format": "currency: 'JPY¥' : 2" },{ "key": "pv", "type": "numeric", "goal": "max", "is_objective": true, "full_name": "Monthly Pageview", "range": { "low": 10000000, "high": 20000000 }, "format": "number:2" },{ "key": "db", "type": "categorical", "goal": "min", "is_objective": true, "full_name": "Database Type", "range": [ "EC2", "RDS-Single", "RDS-Multi" ], "preference": [ "EC2", "RDS-Single", "RDS-Multi" ] },{ "key": "wp", "type": "numeric", "goal": "max", "is_objective": true, "full_name": "WordPress installation ", "range": { "low": 1, "high": 10 } } ], "options": [ { "key": "1", "name": "t2.micro", "values": { "price": 3000, "pv": 100000, "db": "EC2", "wp": 3 } },{ "key": "2", "name": "t2.small", "values": { "price": 6000, "pv": 300000, "db": "EC2", "wp": 3 } },{ "key": "3", "name": "t2.medium", "values": { "price": 15000, "pv": 500000, "db": "EC2", "wp": 3 } },{ "key": "4", "name": "c4.large", "values": { "price": 20000, "pv": 1000000, "db": "EC2", "wp": 5 } },{ "key": "5", "name": "c4.8large", "values": { "price": 350000, "pv": 20000000, "db": "EC2", "wp": 5 } },{ "key": "6", "name": "w-Small", "values": { "price": 80000, "pv": 3000000, "db": "RDS-Single", "wp": 5 } },{ "key": "7", "name": "w-Large", "values": { "price": 120000, "pv": 6000000, "db": "RDS-Single", "wp": 5 } },{ "key": "8", "name": "w-XLarge", "values": { "price": 160000, "pv": 10000000, "db": "RDS-Single", "wp": 10 } },{ "key": "9", "name": "w-2XLarge", "values": { "price": 320000, "pv": 20000000, "db": "RDS-Single", "wp": 10 } },{ "key": "10", "name": "HA-Small", "values": { "price": 120000, "pv": 3000000, "db": "RDS-Multi", "wp": 5 } },{ "key": "11", "name": "HA-Large", "values": { "price": 180000, "pv": 6000000, "db": "RDS-Multi", "wp": 5 } },{ "key": "12", "name": "HA-XLarge", "values": { "price": 200000, "pv": 10000000, "db": "RDS-Multi", "wp": 10 } },{ "key": "13", "name": "HA-2XLarge", "values": { "price": 460000, "pv": 20000000, "db": "RDS-Multi", "wp": 10 } } ] }
あとはこれをPOST
でwatson APIにぶん投げます。
Tradeoff Analytics APIで分析する
検索パラメータができたので、あとはAPIを使って解析します。
$ curl -X POST --user YOUR_USERNAME:YOUR_PASSWORD \ --header "Content-Type: application/json" \ --data @problem.json \ "https://gateway.watsonplatform.net/tradeoff-analytics/api/v1/dilemmas?generate_visualization=false"
戻り値を確認する
リクエストパラメータなども含まれた状態で返ってくるので、jqで見たい部分だけ抜き出します。
$ curl -X POST --user YOUR_USERNAME:YOUR_PASSWORD \ --header "Content-Type: application/json" \ --data @problem.json \ "https://gateway.watsonplatform.net/tradeoff-analytics/api/v1/dilemmas?generate_visualization=false" \ | jq ".resolution" { "solutions": [ { "solution_ref": "1", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"1\" has a value in column \"pv\" which is:\"100000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "100000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "2", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"2\" has a value in column \"pv\" which is:\"300000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "300000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "3", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"3\" has a value in column \"pv\" which is:\"500000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "500000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "4", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"4\" has a value in column \"pv\" which is:\"1000000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "1000000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "5", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"5\" has a value in column \"price\" which is:\"350000\" while the column range\" is: [0.0,300000.0]", "error_code": "RANGE_MISMATCH", "tokens": [ "price", "350000", "[0.0,300000.0]" ] } }, { "solution_ref": "6", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"6\" has a value in column \"pv\" which is:\"3000000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "3000000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "7", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"7\" has a value in column \"pv\" which is:\"6000000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "6000000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "8", "status": "FRONT" }, { "solution_ref": "9", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"9\" has a value in column \"price\" which is:\"320000\" while the column range\" is: [0.0,300000.0]", "error_code": "RANGE_MISMATCH", "tokens": [ "price", "320000", "[0.0,300000.0]" ] } }, { "solution_ref": "10", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"10\" has a value in column \"pv\" which is:\"3000000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "3000000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "11", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"11\" has a value in column \"pv\" which is:\"6000000\" while the column range\" is: [1.0E7,2.0E7]", "error_code": "RANGE_MISMATCH", "tokens": [ "pv", "6000000", "[1.0E7,2.0E7]" ] } }, { "solution_ref": "12", "status": "EXCLUDED" }, { "solution_ref": "13", "status": "INCOMPLETE", "status_cause": { "message": "A column of a option is out of range. Option \"13\" has a value in column \"price\" which is:\"460000\" while the column range\" is: [0.0,300000.0]", "error_code": "RANGE_MISMATCH", "tokens": [ "price", "460000", "[0.0,300000.0]" ] } } ] }
solutions.status
を確認していくと、solutions.solution_ref
が8のオブジェクトのみFRONT
で、それ以外はINCOMPLETE
やEXCLUDED
になっています。
INCOMPLETE
はrangeの範囲外の値が設定されているもの、EXCLUDED
はTradeoff Analyticsが最適解で無いと判断したもので、FRONT
となっているものがTradeoff Analyticsからレコメンドされるアイテムです。
ということで今回はsolutions.solution_ref
が8のプランが希望する条件に一致する様子です。
solutions.solution_ref
はoptions.key
の値と同じなので、options.key
が8のアイテムを見てみましょう。
{ "key": "8", "name": "w-XLarge", "values": { "price": 160000, "pv": 10000000, "db": "RDS-Single", "wp": 10 } }
と、いうことで
項目名 | 範囲 |
---|---|
価格 | 0~300,000円 |
PV | 10,000,000~20,000,000 PV |
DBタイプ | EC2内DB > RDS1台 > RDSマルチAZ |
WPインストール数 | 1 ~ 10 |
の条件に一致するプランは「w-XLarge」だということになりました。
"solution_ref": "12"
がEXCLUDED
になっていますが、これはDBタイプが「RDS-Multi」と一番低い優先順位になっているためだと思われます。
{ "key": "12", "name": "HA-XLarge", "values": { "price": 200000, "pv": 10000000, "db": "RDS-Multi", "wp": 10 } }
options
のkey: db
のgoal
をminではなくmaxに変更すると、このHA-XLargeプランもFRONT
となります。
まとめ
「複数の条件から最適なプランを探す」というのはシステム化するのが手間な印象がありましたが、Tradeoff Analyticsを使うことでJSONさえ作ればかなり簡単に作れることがわかりました。
あとはJSON生成の自動化やプランレコメンド調査用のUIを作るところのノウハウなどが集まるようになれば、もっと便利になるかなと思います。