ページの先頭です。
サイト内の現在位置を表示しています。
ここから本文です。

Step3:機械学習を用いた顧客セグメンテーションのハンズオン

 (目安:60分程度)

1.概要

Step2の結果から、最近購入し、かつ最近Webも閲覧している顧客群が存在していることがわかりました。これが、現在の売上を支えつつ、今後も売上が見込める優良顧客のセグメントであるといえそうです。
では、今後の売上向上につながる潜在的な優良顧客「予備群」は、どうやれば見分けられるでしょうか?

Step2の分析を振り返ってみると、顧客のセグメントは以下の観点(分析軸)で分類できそうです。

  • 最近購入しているか
  • 最近Webを閲覧しているか

 

このときの組み合わせは以下の4つとなります。
  1. 最近購入した - 最近Webを閲覧した
  2. 最近購入した - 最近Webを閲覧していない
  3. 最近購入していない - 最近Webを閲覧した
  4. 最近購入していない - 最近Webを閲覧していない

 

潜在顧客へのアプローチとしては、最近購入はしていないものの商品やキャンペーンに興味をもっていそうな「3. 最近購入していない - 最近Webを閲覧した」の顧客にアプローチするのが最も効率が良さそうです。


そこで、3.の顧客の洗い出しを行うことを分析方針のひとつにしてみます。
また上記2つのパラメータだけでなく購買回数についても合わせて分析してみましょう。いろいろな軸でデータを分析することで新たな知見が得られる可能性が高まります。

Step3ではStep2で作成した構造化/非構造化データの組み合わせをもとに、機械学習を利用したデータ分析を体験していただきます。

具体的な進め方としては、顧客データとWebアクセスログを利用した機械学習(クラスタリング)の分析モデルを作成し、顧客のセグメンテーションを実施します。

機械学習を行うためには Spark というコンポーネントを利用します。
Spark はいくつかの言語でプログラムを記述することができますが、今回は Python から Spark の機能を利用する PySpark でプログラムを作成します。

Step3のシステム概要図


Step3は以下の手順で実施し、通常 60分程度で完了できます。

  • データの取り込み・・・・・Step2で作成したHive ビューからデータを取得します
  • 非分析モデルの作成・・・機械学習に利用するデータ(特微量)を決定し、クラスタリングの代表的なアルゴリズムk-meansを用いて分析モデルを作成します。
  • 分析モデルの適用・・・作成した分析モデルを利用し顧客のセグメンテーションを行います。
  • 可視化・・・セグメンテーション結果を可視化します。

2.事前準備

チュートリアルStep2を完了してください。
Step3では Step2で作成したビューを使用します。

機械学習の実行に必要なライブラリを以下の手順に従ってインストールしてください。
既にインストール済みの場合は「Zeppelin Noteの作成」に進んでください。
Webブラウザで以下のIPアドレスにアクセスし、WebConsoleからSandboxにログインします。

IPアドレス http://<SandboxインストールサーバのIPアドレス (SSH)>:4200
Username root
Password 設定されたパスワード(*)
(*) 初回ログイン時は「hadoop」となっています。

下記のコマンドを実行し、ライブラリをインストールします。
※ライブラリをインストールするために、Sandbox内からインターネットへのアクセスが必要です。

# yum install python-devel python-pip gcc
# pip install pandas==0.23.3
# pip install matplotlib==2.2.2

Zeppelin Noteの作成

Step3で利用する Zeppelin Noteを作成してください。
Webブラウザで以下の URL にアクセスし、Zeppelinにログインします。

IPアドレス http://<SandboxインストールサーバのIPアドレス(SSH)>:9995

Noteの新規作成を行います。
トップページから「Create new note」をクリックします。

Note Nameに任意の名前を入力し、「Default Interpreter」を「spark2」と設定してノートを作成します。

上記の画像の通りの名前を入力すれば「tutorial_step3」というZeppelin Noteが作成できます。

3.操作手順

a. データの取り込み

Step2 と同様に、Zeppelin の Paragraph にプログラムを書いて実行していきますが、Step3 では Sparkの機械学習ライブラリ SparkML を使うため、Spark を Python のコードで扱うことができる PySpark を利用します。


まずは、Step2 までで作成したデータを Hive のビューから PySparkで扱えるデータ型として読み出します。そのために Zeppelin の paragraph に書いて実行するコードは以下のようなものです。
コード番号:3-1

%pyspark
 
from pyspark import SparkContext
from pyspark.sql import SparkSession, SQLContext
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.clustering import KMeans
 
SparkContext.setSystemProperty("hive.metastore.uris", "thrift://sandbox-hdp.hortonworks.com:9083")
 
sparkSession = (SparkSession
                .builder
                .appName('sandbox-test')
                .enableHiveSupport()
                .getOrCreate())
 
df = sparkSession.sql('SELECT frequency,recency,webrecency FROM customer_table_joined')
df.show()

このコードが何をやっているのかを以下に説明します。

Zeppelin上でPysparkを実行するため、先頭行に「%pyspark」と記述します。

 %pyspark

機械学習の実行に必要なモジュールをインポートします。

from pyspark import SparkContext
from pyspark.sql import SparkSession, SQLContext
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.clustering import KMeans

接続するHiveのMetastoreを指定します。

 SparkContext.setSystemProperty("hive.metastore.uris", "thrift://sandbox-hdp.hortonworks.com:9083")

SparkSQLを使用するため、SparkSessionのインスタンスを生成します。

sparkSession = (SparkSession
                .builder
                .appName('sandbox-test')
                .enableHiveSupport()
                .getOrCreate())

SparkSQLを使用して、Step2にて作成したビュー(customer_table_joined)から DataFrame 形式でデータを取得します。
取得するカラムは「frequency(購買回数)」、「recency(最終購買日)」、「webrecency(最終Webアクセス日)」の三つです。

 df = sparkSession.sql('SELECT frequency,recency,webrecency FROM customer_table_joined')

取得した DataFrame の内容を表示する場合は以下を実行します。

 df.show()

プログラムが下記のようになっていることを確認し、赤枠で囲ったアイコンをクリックしてプログラムを実行します。
(初回の実行では数分程度時間がかかることがあります。)

実行すると、下記のようにDataFrameの内容が表示されます。
作成した Hive ビューから、指定したデータを取得できたことがわかります。

b. 分析モデルの作成

次は、いよいよ機械学習ライブラリを使ってデータのクラスタリングを行い、「最近購入しているか」「最近Webを閲覧しているか」という分析軸に沿って顧客を分類します。

DataFrame から特徴量を取り出してSparkMLが扱えるベクトル形式に変換し、機械学習アルゴリズムk-meansを適用してクラスタリングします。

そのために Zeppelin の paragraph に書いて実行するコードは以下のようなものです。
コード番号:3-2

%pyspark
 
vec = VectorAssembler(inputCols=["frequency","recency","webrecency"], outputCol="features")
 
df01 = vec.transform(df)
df01.show()

DataFrameとして取得した、「frequency(購買回数)」、「recency(最終購買日)」、「webrecency(最終Webアクセス日)」を、この後でk-meansで扱う特徴量として利用します。

PySpark の機械学習で利用する特微量はあらかじめベクトル形式に変換する必要があるため、ここではVectorAssembler でそれらのベクトル化を行っています。

プログラムが下記のようになっていることを確認し、赤枠で囲ったアイコンをクリックしてプログラムを実行します。

実行すると、「features」というカラム名でベクトル化された値が追加されていることがわかります。

次に、「frequency(購買回数)」、「recency(最終購買日)」、「webrecency(最終Webアクセス日)」を特徴量として k-means アルゴリズムを実行し、クラスタリングの分析モデルを作成します。

そのために Zeppelin の paragraph に書いて実行するコードは以下のようなものです。
コード番号:3-3

%pyspark
 
kmeans = KMeans(k=4, seed=1)
model = kmeans.fit(df01.select('features'))
 
centers = model.clusterCenters()
print(centers) 

「KMeans」の引数kはクラスタ数を表し、seedは乱数シードを表しています。
それらのパラメータによって決まるk-meansのアルゴリズムを、前の paragraph で得られたベクトル形式の特徴量「features」に適用する(fit()メソッド)ことにより、今回作成する顧客セグメンテーションのモデル「model」を得ます。
このモデルの変数の名前は、「model」の代わりに好きな名前を入れることも可能です(「segmentation」など)。

作成したk-means分析モデル(クラスタリング)の各クラスタの重心は、clusterCenters() メソッドによりベクトル形式で取得できますので、それを 「centers」という変数に格納して表示しています。

プログラムが下記のようになっていることを確認し、赤枠で囲ったアイコンをクリックしてプログラムを実行します。(数分程度時間がかかることがあります。)

実行すると、4つのクラスタの重心が得られていることがわかります。
重心はそれぞれベクトル形式で出力されます。

これで「model」という名前の顧客セグメンテーションモデルと、重心「centers」が得られました。

c. 分析モデルの適用

作成した分析モデル「model」をベクトル化する前の顧客データに適用し、顧客のセグメンテーションを行い、その結果のカラムを加えたデータを表示します。
コード番号:3-4

%pyspark
 
transformed = model.transform(df01)
transformed.show()

プログラムが下記のようになっていることを確認し、下記の赤枠で囲ったアイコンをクリックしてプログラムを実行します。

実行すると、下記のように表示されます。
分析モデルを適用した顧客のセグメンテーション結果が「prediction」という名前のカラムに格納されています。
それぞれの顧客は0~3いずれかのグループに分類されていることがわかります。

ここまでのデータ取得・分析モデル作成・適用のプログラムをまとめて記述すると以下のようになります。
このように、Zeppelin では Paragraph ごとに分割してプログラムを記述し、インタラクティブにプログラムを実行することができます。先に実行した Paragraph と次の Paragraph を続けて、一つのプログラムとして実行することもできます。

コード番号:3-5

%pyspark
from pyspark import SparkContext
from pyspark.sql import SparkSession, SQLContext
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.clustering import KMeans
 
SparkContext.setSystemProperty("hive.metastore.uris", "thrift://sandbox-hdp.hortonworks.com:9083")
 
sparkSession = (SparkSession
                .builder
                .appName('sandbox-test')
                .enableHiveSupport()
                .getOrCreate())
  
df = sparkSession.sql('SELECT frequency,recency,webrecency FROM customer_table_joined')
 
vec = VectorAssembler(inputCols=["frequency","recency","webrecency"], outputCol="features")
df01 = vec.transform(df)
 
kmeans = KMeans(k=4, seed=1)
model = kmeans.fit(df01.select('features'))
transformed = model.transform(df01)
transformed.show()

d. 可視化

上記で実施した顧客セグメンテーション結果の可視化を行います。

結果の可視化には Python の機械学習で一般的に利用される matplotlib を用いて、分析結果を可視化します。
以下の流れで、分析結果の可視化を行います。

  • データ形式の変換・・・matplotlibで可視化するために Spark の DataFrame 形式を Pandas の DataFrame 形式に変換します
  • 結果の可視化・・・matplotlibを用いて顧客の分布とセグメンテーション結果を表示します

「分析モデルの作成・適用」にて記載したプログラムの続きとして、以下のコードを実行します。
コード番号:3-6

%pyspark
 
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('ggplot')
 
centers01 = pd.DataFrame(centers)
centers01.columns = ['frequency','recency','webrecency']
  
txp = transformed.toPandas()
 
plt.figure(figsize=(20, 15), dpi=50)
 
colors = ["red", "blue", "green", "orange"]
 
for i in txp["prediction"].unique():
    df02 = txp.query("prediction == %d" % i)
    plt.scatter(df02.recency, df02.webrecency, s=30, c=colors[i])
 
plt.scatter(centers01.recency, centers01.webrecency, s=300, c="black", edgecolors='black')
 
plt.xlabel("Recency (days)")
plt.ylabel("Web Access Recency (days)")
 
plt.show()

以下に、このコードの内容を説明します。

データ形式の変換

分析結果を可視化するため、matplotlibとPandas のモジュールを追加でインポートします。

import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('ggplot') 

matplotlibで描画するために、クラスタの重心と顧客セグメンテーション結果のデータを PandasのDataFrame 形式に変換します。
また、わかりやすさのため、重心のカラムに名前を設定しておきます。

centers01 = pd.DataFrame(centers)
centers01.columns = ['frequency','recency','webrecency']
 
txp = transformed.toPandas() 


結果の可視化

matplotlibを使用して、顧客セグメンテーション結果を散布図で表示します。

まず、出力されるグラフのサイズを設定します。

plt.figure(figsize=(20, 15), dpi=50)

各クラスタの要素をプロットする際に使用する色を設定します。

colors = ["red", "blue", "green", "orange"]
 

顧客セグメンテーション結果をプロットします。
今回はx軸を「recency(最終購買日)」、y軸を「webrecency(最終Webアクセス日)」としてプロットします。

for i in txp["prediction"].unique():
    df02 = txp.query("prediction == %d" % i)
    plt.scatter(df02.recency, df02.webrecency, s=30, c=colors[i])

同様に、各クラスタの重心のプロットを行います。

plt.scatter(centers01.recency, centers01.webrecency, s=300, c="black", edgecolors='black')

x軸とy軸の軸タイトルを設定します。

plt.xlabel("Recency (days)")
plt.ylabel("Web Access Recency (days)")
 

グラフを出力します。

plt.show()

プログラムが下記のようになっていることを確認し、下記の赤枠で囲ったアイコンをクリックしてプログラムを実行します。

実行すると、下記のように分析結果が散布図で表示されます。
赤・青・緑・黄はそれぞれの顧客グループ(クラスタ)で、黒い丸は各クラスタの重心を表しています。

この顧客の分布図から、顧客データとWebアクセスログを利用した分析で顧客を以下の4つのグループに分類できたことがわかります。

また、この結果を元にキャンペーン等のマーケティング施策を実施するといった活用方法が考えられます。

  1. 青:最近商品を購入し、Webにもアクセスしている優良顧客
  2. 黄:最近商品を購入しているが、Webにはアクセスしていない安定顧客
  3. 緑:最近商品を購入していないが、Webにはアクセスしている見込み顧客
  4. →Webにはアクセスしており商品への興味は持っていると考えられるため、クーポン送付などのキャンペーンを実施するといった施策が考えられます。(狙い通りの潜在顧客が洗い出されました。)
  5. 赤:最近商品を購入していないし、Webにもアクセスしていない離反顧客


ここで、比較のために、新しいデータであるWebアクセスログの情報を使わず、従来型のRDB顧客データだけから得られた「最終購買日」と「購買頻度」を縦横の軸にとって顧客分布をグラフ化してみましょう。
コード番号:3-7

%pyspark
 
plt.figure(figsize=(20, 15), dpi=50)
colors = ["red", "blue", "green", "orange"]
 
 
for i in txp["prediction"].unique():
    df02 = txp.query("prediction == %d" % i)
    plt.scatter(df02.recency, df02.frequency, s=30, c=colors[i])
 
plt.scatter(centers01.recency, centers01.frequency, s=300, c="black", edgecolors='black')
 
plt.xlabel("Recency (days)")
plt.ylabel("frequency (number of times)")
plt.show()

上記 2 (黄)と 3(緑) の顧客グループが混ざってしまっています。Webアクセスログからの情報を組み合わせない、従来の顧客データのみを利用した分析では、青、黄、緑、赤のグループが区別できない、つまり、顧客のセグメントが発見できないということがわかります。

このように、従来から利用している顧客データに、Webアクセスログのような新しい形式のデータを加えることで、従来は見えなかった新しい軸での分析が可能となり、マーケティングや新しいビジネスの開拓に活用することができます。

最後に、プログラムをまとめて記述すると以下のようになります。
コード番号:3-8

%pyspark
from pyspark import SparkContext
from pyspark.sql import SparkSession, SQLContext
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.clustering import KMeans
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('ggplot')
 
SparkContext.setSystemProperty("hive.metastore.uris", "thrift://sandbox-hdp.hortonworks.com:9083")
 
sparkSession = (SparkSession
                .builder
                .appName('sandbox-test')
                .enableHiveSupport()
                .getOrCreate())
  
df = sparkSession.sql('SELECT frequency,recency,webrecency FROM customer_table_joined')
 
vec = VectorAssembler(inputCols=["frequency","recency","webrecency"], outputCol="features")
df01 = vec.transform(df)
 
kmeans = KMeans(k=4, seed=1)
model = kmeans.fit(df01.select('features'))
transformed = model.transform(df01)
centers = model.clusterCenters()
 
centers01 = pd.DataFrame(centers)
centers01.columns = ['frequency','recency','webrecency']
txp = transformed.toPandas()
 
plt.figure(figsize=(20, 15), dpi=50)
colors = ["red", "blue", "green", "orange"]
for i in txp["prediction"].unique():
    df02 = txp.query("prediction == %d" % i)
    plt.scatter(df02.recency, df02.webrecency, s=30, c=colors[i])
 
plt.scatter(centers01.recency, centers01.webrecency, s=300, c="black", edgecolors='black')
 
plt.xlabel("Recency (days)")
plt.ylabel("Web Access Recency (days)")
 
plt.show()

Step3は以上となります。

これでチュートリアルは完了です。お疲れ様でした。

  • 本資料中に記載される商品名、OSS名、会社名、ロゴ、トレードマークはそれぞれ各社、各団体の商標または登録商標です。

ページの先頭へ戻る