ロンドンのレンタル自転車のデータセットをクラスタ化するための K 平均法モデルを作成する


BigQuery ML は教師なし学習をサポートしています。データをクラスタにグループ化するために K 平均法アルゴリズムを適用することができます。教師あり機械学習が予測分析を目的としているのとは異なり、教師なし学習では記述分析が目的となります。データに基づいて意思決定を下せるように、データを理解することが重要になります。

このチュートリアルでは、BigQuery ML の K 平均法モデルを使用して、ロンドンのレンタル自転車の一般公開データセットからデータのクラスタを構築します。同データセットには、ロンドンの Santander Cycle Hire Scheme の 2011 年から現在までの利用者数が含まれています。また、開始時と停止時のタイムスタンプ、ステーション名、乗車時間も含まれます。

このチュートリアルのクエリでは、地理空間分析で使用できる地理関数を使用します。地理空間分析の詳細については、地理空間分析の概要をご覧ください。

目標

このチュートリアルの内容は、次のとおりです。

  • K 平均法クラスタリング モデルの作成。
  • BigQuery ML のクラスタの可視化に基づいたデータドリブンの意思決定。

料金

このチュートリアルでは、Google Cloud の課金対象となるコンポーネントを使用します。これには次のコンポーネントが含まれます。

  • BigQuery
  • BigQuery ML

BigQuery の費用については、BigQuery の料金ページをご覧ください。

BigQuery ML の費用については、BigQuery ML の料金をご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. 新しいプロジェクトでは、BigQuery が自動的に有効になります。既存のプロジェクトで BigQuery を有効にするには、

    Enable the BigQuery API.

    Enable the API

    にアクセスします。

はじめに

実際のデータには、データの自然な集まりやクラスタが含まれていることがあります。データドリブンな意思決定を行うには、これらのグループを記述的に識別するのが適切な場合があります。たとえば小売店であれば、購買習慣や場所が互いに似ている顧客の自然なグループを特定できます。このようなプロセスを「顧客セグメンテーション」と呼びます。

顧客セグメンテーションに使用するデータには、訪問した店舗、購入した商品、支払った金額などがあります。モデルを作成し、こうした顧客特性を反映するグループの特徴を把握することで、そのグループを構成するユーザーにアピールする商品を考案できるようになります。

また、購入されたさまざまな商品の中から商品グループを見つけることもできます。この場合、商品を購入したユーザー、購入した日時、購入した場所、その他の類似する特性に基づいてアイテムをクラスタ化します。モデルを作成して製品グループの特性を判別することで、クロスセルの改善方法など、情報に基づく決定を下せるようになります。

このチュートリアルでは、ロンドンのレンタル自転車のデータを自転車ステーションの属性に基づいてクラスタ化します。その際、BigQuery ML を使用して K 平均法モデルを作成します。

K 平均法モデルの作成は、次の手順で行われます。

  • ステップ 1: モデルを格納するためのデータセットを作成する。
    最初のステップとして、モデルを格納するデータセットを作成します。
  • ステップ 2: トレーニング データを確認する。
    次のステップでは、london_bicycles テーブルに対してクエリを実行し、クラスタリング モデルのトレーニングに使用するデータの確認を行います。K 平均法は教師なし学習にあたるため、モデルのトレーニングを行う際に、トレーニング データや評価用データにラベルの指定やデータの分割を行う必要はありません。
  • ステップ 3: K 平均法モデルを作成する。
    ステップ 3 では、K 平均法モデルを作成します。モデルを作成すると、クラスタリング フィールドは station_name になり、市内中心部から駅までの距離などのステーション属性に基づいてデータがクラスタリングされます。
  • ステップ 4: ML.PREDICT 関数を使用してステーションのクラスタを予測する。
    次に、ML.PREDICT 関数を使用して、特定のステーションのクラスタを予測します。名前に Kennington という文字列を含むすべてのステーションのクラスタを予測します。
  • ステップ 5: モデルを使用してデータドリブンの意思決定を行う。
    最後のステップは、モデルを使用してデータドリブンの意思決定を行うことです。たとえば、モデルの結果に基づいて、利用台数を増やすことでどのステーションにメリットが出るかがわかります。

ステップ 1: データセットを作成する

ML モデルを保存する BigQuery データセットを作成します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] ページに移動

  2. [エクスプローラ] ペインで、プロジェクト名をクリックします。

  3. 「アクションを表示」> [データセットを作成] をクリックします。

    データセットを作成する。

  4. [データセットを作成する] ページで、次の操作を行います。

    • [データセット ID] に「bqml_tutorial」と入力します。

    • [ロケーション タイプ] で、[マルチリージョン] を選択し、[EU(欧州連合の複数のリージョン)] を選択します。

      ロンドンのレンタル自転車の一般公開データセットは、EUマルチリージョンロケーションに格納されています。データセットも同じロケーションに存在する必要があります。

    • 残りのデフォルトの設定は変更せず、[データセットを作成] をクリックします。

      データセットの作成ページ。

ステップ 2: トレーニング データを確認する

次に、K 平均法モデルのトレーニングに使用するデータを調べます。このチュートリアルでは、以下の属性に基づいて自転車ステーションのクラスタリングを行います。

  • レンタル期間
  • 1 日あたりの利用数
  • 市中心部からの距離

SQL

次の GoogleSQL クエリは、K 平均法モデルのトレーニングに使用するデータを調べるために使用されます。

#standardSQL
WITH
hs AS (
SELECT
  h.start_station_name AS station_name,
  IF
  (EXTRACT(DAYOFWEEK
    FROM
      h.start_date) = 1
    OR EXTRACT(DAYOFWEEK
    FROM
      h.start_date) = 7,
    "weekend",
    "weekday") AS isweekday,
  h.duration,
  ST_DISTANCE(ST_GEOGPOINT(s.longitude,
      s.latitude),
    ST_GEOGPOINT(-0.1,
      51.5))/1000 AS distance_from_city_center
FROM
  `bigquery-public-data.london_bicycles.cycle_hire` AS h
JOIN
  `bigquery-public-data.london_bicycles.cycle_stations` AS s
ON
  h.start_station_id = s.id
WHERE
  h.start_date BETWEEN CAST('2015-01-01 00:00:00' AS TIMESTAMP)
  AND CAST('2016-01-01 00:00:00' AS TIMESTAMP) ),
stationstats AS (
SELECT
  station_name,
  isweekday,
  AVG(duration) AS duration,
  COUNT(duration) AS num_trips,
  MAX(distance_from_city_center) AS distance_from_city_center
FROM
  hs
GROUP BY
  station_name, isweekday )
SELECT
*
FROM
stationstats
ORDER BY
distance_from_city_center ASC

クエリの詳細

このクエリは、start_station_nameduration を含む自転車レンタルのデータを抽出し、distance-from-city-center を含むステーション情報に結合します。そして、平均乗車時間と利用数を含んだ stationstats でステーションの属性を計算します。この計算には、ステーション属性 distance_from_city_center も含まれます。

このクエリでは、WITH 句を使用してサブクエリを定義します。また、地理空間分析関数 ST_DISTANCEST_GEOGPOINT も使用します。これらの関数の詳細については、地理関数をご覧ください。地理空間分析の詳細については、地理空間分析の概要をご覧ください。

クエリを実行する

次のクエリはトレーニング データをコンパイルします。このチュートリアル後半の CREATE MODEL ステートメントでもこれが使用されます。

クエリを実行するには:

  1. [BigQuery] ページに移動します。

[BigQuery] に移動

  1. [エディタ] ペインで、次の SQL ステートメントを実行します。

    WITH
      hs AS (
      SELECT
        h.start_station_name AS station_name,
        IF
        (EXTRACT(DAYOFWEEK
          FROM
            h.start_date) = 1
          OR EXTRACT(DAYOFWEEK
          FROM
            h.start_date) = 7,
          "weekend",
          "weekday") AS isweekday,
        h.duration,
        ST_DISTANCE(ST_GEOGPOINT(s.longitude,
            s.latitude),
          ST_GEOGPOINT(-0.1,
            51.5))/1000 AS distance_from_city_center
      FROM
        `bigquery-public-data.london_bicycles.cycle_hire` AS h
      JOIN
        `bigquery-public-data.london_bicycles.cycle_stations` AS s
      ON
        h.start_station_id = s.id
      WHERE
        h.start_date BETWEEN CAST('2015-01-01 00:00:00' AS TIMESTAMP)
        AND CAST('2016-01-01 00:00:00' AS TIMESTAMP) ),
      stationstats AS (
      SELECT
        station_name,
        isweekday,
        AVG(duration) AS duration,
        COUNT(duration) AS num_trips,
        MAX(distance_from_city_center) AS distance_from_city_center
      FROM
        hs
      GROUP BY
        station_name, isweekday )
    SELECT
      *
    FROM
      stationstats
    ORDER BY
      distance_from_city_center ASC
  2. クエリが完了したら、クエリテキスト領域の下にある [結果] タブをクリックします。[結果] タブの列には、モデルのトレーニングに使用したクエリ station_namedurationnum_tripsdistance_from_city_center が表示されます。結果は次のようになります。

クエリ結果

BigQuery DataFrames

このサンプルを試す前に、BigQuery DataFrames を使用した BigQuery クイックスタートの手順に沿って BigQuery DataFrames を設定してください。詳細については、BigQuery DataFrames のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

import datetime

import pandas as pd

import bigframes
import bigframes.pandas as bpd

bigframes.options.bigquery.project = your_gcp_project_id
# Compute in the EU multi-region to query the London bicycles dataset.
bigframes.options.bigquery.location = "EU"

# Extract the information you'll need to train the k-means model in this
# tutorial. Use the read_gbq function to represent cycle hires
# data as a DataFrame.
h = bpd.read_gbq(
    "bigquery-public-data.london_bicycles.cycle_hire",
    col_order=["start_station_name", "start_station_id", "start_date", "duration"],
).rename(
    columns={
        "start_station_name": "station_name",
        "start_station_id": "station_id",
    }
)

s = bpd.read_gbq(
    # Use ST_GEOPOINT and ST_DISTANCE to analyze geographical
    # data. These functions determine spatial relationships between
    # geographical features.
    """
    SELECT
    id,
    ST_DISTANCE(
        ST_GEOGPOINT(s.longitude, s.latitude),
        ST_GEOGPOINT(-0.1, 51.5)
    ) / 1000 AS distance_from_city_center
    FROM
    `bigquery-public-data.london_bicycles.cycle_stations` s
    """
)

# Define Python datetime objects in the UTC timezone for range comparison,
# because BigQuery stores timestamp data in the UTC timezone.
sample_time = datetime.datetime(2015, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
sample_time2 = datetime.datetime(2016, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)

h = h.loc[(h["start_date"] >= sample_time) & (h["start_date"] <= sample_time2)]

# Replace each day-of-the-week number with the corresponding "weekday" or
# "weekend" label by using the Series.map method.
h = h.assign(
    isweekday=h.start_date.dt.dayofweek.map(
        {
            0: "weekday",
            1: "weekday",
            2: "weekday",
            3: "weekday",
            4: "weekday",
            5: "weekend",
            6: "weekend",
        }
    )
)

# Supplement each trip in "h" with the station distance information from
# "s" by merging the two DataFrames by station ID.
merged_df = h.merge(
    right=s,
    how="inner",
    left_on="station_id",
    right_on="id",
)

# Engineer features to cluster the stations. For each station, find the
# average trip duration, number of trips, and distance from city center.
stationstats = merged_df.groupby(["station_name", "isweekday"]).agg(
    {"duration": ["mean", "count"], "distance_from_city_center": "max"}
)
stationstats.columns = pd.Index(
    ["duration", "num_trips", "distance_from_city_center"]
)
stationstats = stationstats.sort_values(
    by="distance_from_city_center", ascending=True
).reset_index()

# Expected output results: >>> stationstats.head(3)
# station_name	isweekday duration  num_trips	distance_from_city_center
# Borough Road...	weekday	    1110	    5749	    0.12624
# Borough Road...	weekend	    2125	    1774	    0.12624
# Webber Street...	weekday	    795	        6517	    0.164021
#   3 rows × 5 columns

ステップ 3: K 平均法モデルを作成する

トレーニング データを確認したら、次のステップでは、そのデータを使用して K 平均法モデルを作成します。

SQL

CREATE MODEL ステートメントを model_type=kmeans オプション付きで使用することで、K 平均法モデルの作成とトレーニングが行えます。

クエリの詳細

CREATE MODEL ステートメントで、使用するクラスタの数(4)を指定します。station_name は特徴ではないので、SELECT ステートメントで EXCEPT 句を使って station_name 列を除外します。クエリによって station_name ごとに個別に行が作成されますが、SELECT ステートメントにより特徴だけが抽出されます。

num_clusters オプションを省略すると、トレーニング データの総行数に基づき適切なデフォルト値が BigQuery ML によって選択されます。あるいは、ハイパーパラメータを調整して適切な数値を見つけることもできます。適切なクラスタ数を決定するには、複数の num_clusters 値で CREATE MODEL クエリを実行して、誤差測定値を確認します。そして、誤差測定値が最小になるポイントを選択します。誤差測定値は、モデルを選択して [評価] タブをクリックすると取得できます。このタブには、Davies-Bouldin インデックスが表示されます。

トレーニング タブ

クエリを実行する

次のクエリでは、トレーニング データの確認で使用したクエリに CREATE MODEL ステートメントを追加し、さらにデータ内の id フィールドを削除します。

クエリを実行して K 平均法モデルを作成するには:

  1. [BigQuery] ページに移動します。

[BigQuery] に移動

  1. [エディタ] ペインで、次の SQL ステートメントを実行します。

    CREATE OR REPLACE MODEL `bqml_tutorial.london_station_clusters`
      OPTIONS(model_type='kmeans', num_clusters=4) AS
    WITH
      hs AS (
      SELECT
        h.start_station_name AS station_name,
      IF
        (EXTRACT(DAYOFWEEK
          FROM
            h.start_date) = 1
          OR EXTRACT(DAYOFWEEK
          FROM
            h.start_date) = 7,
          "weekend",
          "weekday") AS isweekday,
        h.duration,
        ST_DISTANCE(ST_GEOGPOINT(s.longitude,
            s.latitude),
          ST_GEOGPOINT(-0.1,
            51.5))/1000 AS distance_from_city_center
      FROM
        `bigquery-public-data.london_bicycles.cycle_hire` AS h
      JOIN
        `bigquery-public-data.london_bicycles.cycle_stations` AS s
      ON
        h.start_station_id = s.id
      WHERE
        h.start_date BETWEEN CAST('2015-01-01 00:00:00' AS TIMESTAMP)
        AND CAST('2016-01-01 00:00:00' AS TIMESTAMP) ),
      stationstats AS (
      SELECT
        station_name,
        isweekday,
        AVG(duration) AS duration,
        COUNT(duration) AS num_trips,
        MAX(distance_from_city_center) AS distance_from_city_center
      FROM
        hs
      GROUP BY
        station_name, isweekday)
    SELECT
      * EXCEPT(station_name, isweekday)
    FROM
      stationstats
     
  2. ナビゲーション パネルの [リソース] セクションでプロジェクト名を展開し、[bqml_tutorial] をクリックしてから [london_station_clusters] をクリックします。

  3. [スキーマ] タブをクリックします。モデルのスキーマには、BigQuery ML がクラスタリングを行う際に使用した 4 つのステーション属性が一覧表示されています。スキーマは次のように表示されます。

クラスタ スキーマ情報

  1. [評価] タブをクリックします。このタブには、K 平均法モデルによって識別されたクラスタが可視化されます。[数値特徴] には、セントロイドごとに最大 10 個の重要な特徴値が棒グラフで表示されます。可視化する特徴をプルダウン メニューから選択できます。

数値特徴のグラフ

BigQuery DataFrames

このサンプルを試す前に、BigQuery DataFrames を使用した BigQuery クイックスタートの手順に沿って BigQuery DataFrames を設定してください。詳細については、BigQuery DataFrames のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。


from bigframes.ml.cluster import KMeans

# To determine an optimal number of clusters, construct and fit several
# K-Means objects with different values of num_clusters, find the error
# measure, and pick the point at which the error measure is at its minimum
# value.
cluster_model = KMeans(n_clusters=4)
cluster_model.fit(stationstats)
cluster_model.to_gbq(
    your_model_id,  # For example: "bqml_tutorial.london_station_clusters"
    replace=True,
)

ステップ 4: ML.PREDICT 関数を使用してステーションのクラスタを予測する。

特定のステーションが属するクラスタを特定するには、ML.PREDICT SQL 関数または predict BigQuery DataFrames 関数を使用します。

SQL

クエリの詳細

このクエリは REGEXP_CONTAINS 関数を使用して、station_name 列に文字列「Kennington」を含むすべてのエントリを検索します。ML.PREDICT 関数は、これらの値を使用して、どのクラスタにステーションが含まれるかを予測します。

クエリを実行する

次のクエリは、名前に「Kennington」という文字列を含むすべてのステーションのクラスタを予測します。

ML.PREDICT クエリを実行するには:

  1. [BigQuery] ページに移動します。

[BigQuery] に移動

  1. [エディタ] ペインで、次の SQL ステートメントを実行します。

    WITH
      hs AS (
      SELECT
        h.start_station_name AS station_name,
        IF
        (EXTRACT(DAYOFWEEK
          FROM
            h.start_date) = 1
          OR EXTRACT(DAYOFWEEK
          FROM
            h.start_date) = 7,
          "weekend",
          "weekday") AS isweekday,
        h.duration,
        ST_DISTANCE(ST_GEOGPOINT(s.longitude,
            s.latitude),
          ST_GEOGPOINT(-0.1,
            51.5))/1000 AS distance_from_city_center
      FROM
        `bigquery-public-data.london_bicycles.cycle_hire` AS h
      JOIN
        `bigquery-public-data.london_bicycles.cycle_stations` AS s
      ON
        h.start_station_id = s.id
      WHERE
        h.start_date BETWEEN CAST('2015-01-01 00:00:00' AS TIMESTAMP)
        AND CAST('2016-01-01 00:00:00' AS TIMESTAMP) ),
      stationstats AS (
      SELECT
        station_name,
        isweekday,
        AVG(duration) AS duration,
        COUNT(duration) AS num_trips,
        MAX(distance_from_city_center) AS distance_from_city_center
      FROM
        hs
      GROUP BY
        station_name, isweekday )
    SELECT
      * EXCEPT(nearest_centroids_distance)
    FROM
      ML.PREDICT( MODEL `bqml_tutorial.london_station_clusters`,
        (
        SELECT
          *
        FROM
          stationstats
        WHERE
          REGEXP_CONTAINS(station_name, 'Kennington')))
  2. クエリが完了したら、クエリテキスト領域の下にある [結果] タブをクリックします。結果は次のようになります。

    ML.PREDICT の結果

BigQuery DataFrames

このサンプルを試す前に、BigQuery DataFrames を使用した BigQuery クイックスタートの手順に沿って BigQuery DataFrames を設定してください。詳細については、BigQuery DataFrames のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。


# Select model you'll use for predictions. `read_gbq_model` loads model
# data from BigQuery, but you could also use the `cluster_model` object
# from previous steps.
cluster_model = bpd.read_gbq_model(
    your_model_id,
    # For example: "bqml_tutorial.london_station_clusters",
)

# Use 'contains' function to filter by stations containing the string
# "Kennington".
stationstats = stationstats.loc[
    stationstats["station_name"].str.contains("Kennington")
]

result = cluster_model.predict(stationstats)

# Expected output results:   >>>results.peek(3)
# CENTROID...	NEAREST...	station_name  isweekday	 duration num_trips dist...
# 	1	[{'CENTROID_ID'...	Borough...	  weekday	  1110	    5749	0.13
# 	2	[{'CENTROID_ID'...	Borough...	  weekend	  2125      1774	0.13
# 	1	[{'CENTROID_ID'...	Webber...	  weekday	  795	    6517	0.16
#   3 rows × 7 columns

ステップ 5: モデルを使用してデータドリブンの意思決定を行う

評価結果により、さまざまなクラスタの状況を把握しやすくなります。次の例のセントロイド 3 は、市内中心部に近い混雑している都市ステーションを示しています。セントロイド 2 は、あまり混雑しておらずレンタル使用期間が長い、2 番目の都市ステーションを示しています。セントロイド 1 は、あまり混雑しておらず、レンタル期間が短い都市ステーションを示しています。セントロイド 4 は、移動がより長い郊外のステーションを示しています。

数値特徴のグラフ

以上のような結果に基づき、データを参考にして判断を行うことができます。次に例を示します。

  • 新しいタイプの鍵を試す必要があるとします。この実験の対象として、どのステーション クラスタを選択すればよいでしょうか。セントロイド 1、セントロイド 2、またはセントロイド 4 のステーションは最も混雑しているステーションではないので、論理的に言ってこれらを選択するのがよいでしょう。

  • 長距離用の自転車をいくつかのステーションに置くことを考えているとします。どのステーションが適しているでしょうか。セントロイド 4 は、市内中心部から離れた場所にあるステーションのグループで、最も長い利用になっています。したがって、長距離用の自転車を置くには最も適したステーションと思われます。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

  • 作成したプロジェクトを削除する。
  • または、プロジェクトを保存して、データセットを削除する。

データセットを削除する

プロジェクトを削除すると、プロジェクト内のデータセットとテーブルがすべて削除されます。プロジェクトを再利用する場合は、このチュートリアルで作成したデータセットを削除できます。

  1. 必要に応じて、Google Cloud コンソールで [BigQuery] ページを開きます。

    [BigQuery] ページに移動

  2. ナビゲーションで、作成した bqml_tutorial データセットをクリックします。

  3. ウィンドウの右側にある [データセットを削除] をクリックします。この操作を行うと、データセットとモデルが削除されます。

  4. [データセットの削除] ダイアログ ボックスでデータセットの名前(bqml_tutorial)を入力し、[削除] をクリックして確定します。

プロジェクトの削除

プロジェクトを削除するには:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

次のステップ