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

このチュートリアルでは、BigQuery ML の k 平均法モデルを使用して、データセット内のクラスタを識別する方法について説明します。

データをクラスタにグループ化する k 平均法アルゴリズムは、教師なし機械学習の一種です。教師あり機械学習が予測分析を目的としているのとは異なり、教師なし機械学習では記述分析が目的となります。教師なし機械学習は、データを理解してデータドリブンの意思決定を行うのに役立ちます。

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

このチュートリアルでは、ロンドンのレンタル自転車の一般公開データセットを使用します。また、開始時と停止時のタイムスタンプ、ステーション名、乗車時間も含まれます。

目標

このチュートリアルでは、次のタスクの手順について説明します。

  • モデルのトレーニングに使用されたデータを調べます。
  • k 平均法クラスタリング モデルの作成
  • BigQuery ML のクラスタの可視化を使用して、生成されたデータクラスタを解釈します。
  • k 平均法モデルで ML.PREDICT 関数を実行して、自転車レンタル ステーションのクラスタを予測します。

費用

このチュートリアルでは、課金対象となる以下の 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.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify 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.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

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

    Enable the BigQuery API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  7. 必要な権限

    • データセットを作成するには、bigquery.datasets.create IAM 権限が必要です。

    • モデルを作成するには、次の権限が必要です。

      • bigquery.jobs.create
      • bigquery.models.create
      • bigquery.models.getData
      • bigquery.models.updateData
    • 推論を実行するには、次の権限が必要です。

      • bigquery.models.getData
      • bigquery.jobs.create

    BigQuery における IAM ロールと権限の詳細については、IAM の概要をご覧ください。

データセットを作成する

k 平均法モデルを格納する BigQuery データセットを作成します。

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

    [BigQuery] ページに移動

  2. 左側のペインで、 [エクスプローラ] をクリックします。

    エクスプローラ ペインのボタンがハイライト表示されている。

    左側のペインが表示されていない場合は、 [左ペインを開く] をクリックしてペインを開きます。

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

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

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

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

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

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

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

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

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

トレーニング データを調べる

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

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

SQL

このクエリは、start_station_name 列と duration 列を含む自転車レンタルのデータを抽出し、このデータをステーション情報に結合します。これには、市の中心部から駅までの距離を含む計算列を作成することが含まれます。そして、平均乗車時間と利用数を含んだ stationstats 列でステーションの属性を計算します。この計算には、計算された distance_from_city_center 列も含まれます。

トレーニング データを調べる手順は次のとおりです。

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

    [BigQuery] に移動

  2. クエリエディタに次のクエリを貼り付け、[実行] をクリックします。

    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;

結果は次のようになります。

クエリ結果

BigQuery DataFrames

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

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

import datetime
import typing

import pandas as pd
from shapely.geometry import Point

import bigframes
import bigframes.bigquery as bbq
import bigframes.geopandas
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",
    }
)

# Use GeoSeries.from_xy and BigQuery.st_distance to analyze geographical
# data. These functions determine spatial relationships between
# geographical features.
cycle_stations = bpd.read_gbq("bigquery-public-data.london_bicycles.cycle_stations")
s = bpd.DataFrame(
    {
        "id": cycle_stations["id"],
        "xy": bigframes.geopandas.GeoSeries.from_xy(
            cycle_stations["longitude"], cycle_stations["latitude"]
        ),
    }
)
s_distance = bbq.st_distance(s["xy"], Point(-0.1, 51.5), use_spheroid=False) / 1000
s = bpd.DataFrame({"id": s["id"], "distance_from_city_center": s_distance})

# 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 = typing.cast(
    bpd.DataFrame,
    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

k 平均法モデルを作成する

ロンドンのレンタル自転車のトレーニング データを使用して k 平均法モデルを作成します。

SQL

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

k 平均法モデルを作成する手順は次のとおりです。

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

    [BigQuery] に移動

  2. クエリエディタに次のクエリを貼り付け、[実行] をクリックします。

    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