Amazon API Gateway + Lambda + Amazon Machine Learning で会員の購買予測が出来るWordPressプラグインを作る

# 概要
Amazon API Gateway + Lambda + Amazon Machine Learningでユーザの購買(契約)予測が出来るWordPressプラグインを作ってみました。

Amazon Machine Learningでデータを機械学習させ、結果をAPI GatewayからWordPressへ返却、ユーザの購買(契約)予測を管理画面のユーザ一覧に表示させるまでを実施します。

この人のデータからは購入（契約）できそうだなとか、そうではなさそうだなというのを管理画面から可視化する仕組みです。

# Amazon Machine Learningにてモデルを作る
![スクリーンショット 2015-07-20 22.48.15.png](https://qiita-image-store.s3.amazonaws.com/0/65478/29171434-617c-5214-fd01-246bea56489a.png)

[Amazon Machine Learningのサンプルをちょっとチューニングしてみる](http://qiita.com/tominaga443/items/7c91ab873b2578445614)を参考にさせてもらいました。
こちらと全く同様のチューニングを行い、**契約してくれそうな顧客**を予測します。

>サンプルデータはカリフォルニア大学アーバイン校が公開しているデータセットで、ポルトガルの金融機関の定期預金キャンペーンに関するデータです。データの内容は年齢や職業などの顧客情報、キャンペーンを案内した時期、消費者物価指数などの経済情報で、予測したいこと（target）は「顧客が定期預金を契約するかどうか」です。チュートリアルでは、定期預金を契約した顧客を1(positive)、契約しなかった顧客を0(negative)として、binary classificationを使って判定を行います。

Amazon Machine Learningではチュートリアル用のサンプルデータが用意されています。今回は機械学習用のデータとして、そのサンプルデータを使用します。

また、real time predictions(API経由でユーザごとの予測を返却してくれる機能)を有効化して、各会員の購買予測を返せるようにします。

補足：このデータを使用するということは、ポルトガルの金融機関のシステムでのみの使用が前提となります。実際にサイトに適用するは会員データを解析してサイトにあったモデルを作ってやる必要があります。

# Lambdaファンクション
```js
var aws = require('aws-sdk');
var machinelearning = new aws.MachineLearning();
var params = {
  MLModelId: '<Machine LearningのモデルID>'
};

exports.handler = function(event, context) {
  machinelearning.getMLModel(params, function(err, data) {
    if (err) {
      console.log(err, err.stack);
    } else {
      var params = {
        MLModelId: '<Machine LearningのモデルID>',
        PredictEndpoint: data.EndpointInfo.EndpointUrl,
        Record: {
          age: event.age,
          job: event.job,
          marital: event.marital,
          education: event.education,
          default: event.default,
          housing: event.housing,
          loan: event.loan,
          contact: event.contact,
          month: event.month,
          day_of_week: event.day_of_week,
          duration: event.duration,
          campaign: event.campaign,
          pdays: event.pdays,
          previous: event.previous,
          poutcome: event.poutcome,
          emp_var_rate: event.emp_var_rate,
          cons_price_idx: event.cons_price_idx,
          cons_conf_idx: event.cons_conf_idx,
          euribor3m: event.euribor3m,
          nr_employed: event.nr_employed,
        }
      };
      machinelearning.predict(params, function(err, data) {
        if (err) console.log(err, err.stack);
        else     context.succeed(data);
      });
    }
  });
};
```
こういった形で、予測を返してもらうために必要なパラメータをMachine Learningへ送信します。

# API Gateway
上記で作ったLambdaファンクションをweb上で使えるようにAPI GatewayでAPI化します。

![スクリーンショット 2015-07-20 22.58.29.png](https://qiita-image-store.s3.amazonaws.com/0/65478/ba6a05c0-6d02-074c-4caa-043387ea5bda.png)

query stringで予測用のパラメータをAPIに渡すと契約してくれそうな顧客かそうでないかを返してくれます。
```
Request: /?age=22&job=technician&marital=married...
```

以下が結果です。predictedLabelが1であれば、契約してくれそうな顧客。0であれば契約してくれなそうな顧客となります。

``` json
{
  "Prediction": {
    "details": {
      "Algorithm": "SGD",
      "PredictiveModelType": "BINARY"
    },
    "predictedLabel": "1",
    "predictedScores": {
      "1": 0.3982754647731781
    }
  }
}
```

# WordPressプラグイン化
API Gatewayで作った購買予測APIをWordPressに組み込みましょう

### API Gatewayへのデータのリクエスト
```php
$response = wp_remote_get('<API Gatewayへのエンドポイント>?age='.<AGE>.'&job='.<job>.・・・・<other parameter>);
if( !is_wp_error( $response ) && $response["response"]["code"] === 200 ) {
    $response_body = json_decode($response["body"]);
    update_user_meta( $user_id, 'Predict', $response_body );
} else {
    // Handle error here.
}
```
wp_remote_系の関数で会員登録などのタイミングでwp_usermetaに購買予測APIの結果を入れます。

### ユーザ一覧へ購買予想を出力
```php
class WP_Machine_Learning_Sample {
	private static $instance;
	private function __construct() {}
	
	public static function get_instance() {
		if( !isset( self::$instance ) ) {
			$c = __CLASS__;
			self::$instance = new $c();
		}
		return self::$instance;
	}
	
	public function init() {
		add_filter( 'manage_users_columns', array( $this, 'manage_users_columns' ) );
		add_filter( 'manage_users_custom_column', array( $this, 'manage_users_custom_column' ), 10, 3 );
	}
	
	public function manage_users_custom_column( $val, $column_name, $user_id ) {
 		$predict = get_user_meta( $user_id, 'predict', true );
		
		if ( empty($predict) ) {
			return;
		}

	 	$predict = json_decode($predict);	

		switch ($column_name) {
			case 'kobaiyosoku' :
				if ( $predict->Prediction->predictedLabel === '1') {
					return '契約してくれそう';
				} else {
					return '契約してくれなさそう';
				}
				
				break;
			case 'kobaiscore' :
				$label = $predict->Prediction->predictedLabel;
				return $predict->Prediction->predictedScores->{$label};
				break;
			default:
		}
			
		return $val;
	}
	
	public function manage_users_columns( $column ) {
		$column['kobaiyosoku'] = '購買予測';
		$column['kobaiscore'] = 'スコア';
		return $column;
	}
}
$wpmls_instance = WP_Machine_Learning_Sample::get_instance();
$wpmls_instance->init();
```

![ユーザー ‹ テスト — WordPress.png](https://qiita-image-store.s3.amazonaws.com/0/65478/04fe27ec-c010-8417-16af-5dc92c8f44c9.png)
こんな感じで購買予測がユーザ一覧画面に表示されます。

# まとめ
会員サイトをWordPressで作るときはこんな感じでスコア順にソートさせるなどして、購買意欲の高いユーザ、特定のアプローチがとれたり出来そうです。
また、メディアなどでは、キュレーション系のアプリに掲載される傾向を機械学習させて、記事を作った時にキュレーションアプリに載る載らないの判定させるとか面白いかも。

機械学習自体はユーザ予測のためのモデルを作るまでがなかなか難しい部分は有りますが、API GatewayやAmazon Machine Learningが出てきたことでより身近にこういったサービスが作れるのは楽しいですね！