tjtjtjのメモ

自分のためのメモです

BigQuery ML 予測モデルによるタクシー運賃の予測(日本語)

機械学習している感はないが、なんとか雰囲気は分かるようになってきた。

ながれ

  • ニューヨーク市のタクシーデータの探索
    • 質問: 2015 年のイエロー タクシーの毎月の賃走回数は?
    • 質問: 2015 年のイエロー タクシーの平均速度は?
  • モデル作成
    • (モデル・学習の)目的を特定する
    • 特徴を選択し、トレーニング データセットを作成する
    • モデルを格納する BigQuery データセットを作成する
    • BQML モデルタイプを選択し、オプションを指定する
      • モデル作成
  • 分類モデルの性能を評価する
    • 性能の基準を選択する
  • タクシー運賃を予測する
  • モデルの性能を向上させる
    • BigQuery の地理空間機能を活用して、ML モデルの精度を高める方法
  • 詳細情報
  • 探索できるその他のデータセット
    • シカゴのタクシー運賃を予測する場合

今回のデータ

ニューヨーク市が提供する一般公開データセットだそうです。

質問: 2015 年のイエロー タクシーの毎月の賃走回数は?

月別ピックアップ回数を求めている

#standardSQL
SELECT
  TIMESTAMP_TRUNC(pickup_datetime, -- ピックアップ日時 -> ピックアップ月
    MONTH) month,
  COUNT(*) trips                   -- 件数
FROM
  `bigquery-public-data.new_york.tlc_yellow_trips_2015`
GROUP BY
  1
ORDER BY
  1

質問: 2015 年のイエロー タクシーの平均速度は?

時刻別の平均速度を求めている

#standardSQL
SELECT
  EXTRACT(HOUR
  FROM
    pickup_datetime) hour,
  ROUND(AVG(trip_distance / TIMESTAMP_DIFF(dropoff_datetime,
        pickup_datetime,
        SECOND))*3600, 1) speed
FROM
  `bigquery-public-data.new_york.tlc_yellow_trips_2015`
WHERE
  trip_distance > 0
  AND fare_amount/trip_distance BETWEEN 2
  AND 10
  AND dropoff_datetime > pickup_datetime
GROUP BY
  1
ORDER BY
  1

目的を特定する

機械学習モデルを BigQuery 内に作成し、過去の賃走データセットに基づいてニューヨーク市のタクシー運賃を予測します。 乗車前に運賃を予測できれば、乗客とタクシー会社の双方が、より効率的に乗車・配車の計画を立てられるようになります。

特徴を選択し、トレーニング データセットを作成する

フィールド一覧を確認しろ、と言っているがリンク先を確認できないので雰囲気で。

ニューヨーク市のイエロー タクシーのデータセットは市が提供する一般公開データセットで、BigQuery に読み込まれ、自由に探索できるようになっています。 フィールドの全一覧をこちらで確認してから、データセットをプレビューして、機械学習モデルが過去のタクシー賃走と運賃の関係を理解するのに役立つ特徴を見つけます。

特徴

  • 通行料の金額
  • 運賃の金額
  • 時間帯
  • 乗車場所
  • 降車場所
  • 乗客人数
#standardSQL
WITH params AS (
    SELECT
    1 AS TRAIN,
    2 AS EVAL
    ),

  daynames AS
    (SELECT ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'] AS daysofweek),

  taxitrips AS (
  SELECT
    (tolls_amount + fare_amount) AS total_fare, -- 通行料の金額(通行料+運賃 チップは入れない)
    daysofweek[ORDINAL(EXTRACT(DAYOFWEEK FROM pickup_datetime))] AS dayofweek, -- 曜日
    EXTRACT(HOUR FROM pickup_datetime) AS hourofday, -- 時間帯
    pickup_longitude AS pickuplon, -- 乗車場所
    pickup_latitude AS pickuplat,
    dropoff_longitude AS dropofflon, -- 降車場所
    dropoff_latitude AS dropofflat,
    passenger_count AS passengers -- 乗客人数
  FROM
    `nyc-tlc.yellow.trips`, daynames, params
  WHERE
    trip_distance > 0 AND fare_amount > 0  -- 距離, 運賃 がゼロは除く
    AND MOD(ABS(FARM_FINGERPRINT(CAST(pickup_datetime AS STRING))),1000) = params.TRAIN -- データの 1/1000 のみを抽出(TRAINはトレーニング対象か)
  )

  SELECT *
  FROM taxitrips

チップは入れないって、チップまで記録されているのか、このデータには。チップも課税対象なんだからそらそうか。

モデル作成

前クエリの #standardSQL を置き換える。

CREATE or REPLACE MODEL taxi.taxifare_model
OPTIONS
  (model_type='linear_reg', labels=['total_fare']) AS

WITH params AS (
    SELECT
    1 AS TRAIN,
    2 AS EVAL
    ),

  daynames AS
    (SELECT ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'] AS daysofweek),

  taxitrips AS (
  SELECT
    (tolls_amount + fare_amount) AS total_fare,
    daysofweek[ORDINAL(EXTRACT(DAYOFWEEK FROM pickup_datetime))] AS dayofweek,
    EXTRACT(HOUR FROM pickup_datetime) AS hourofday,
    pickup_longitude AS pickuplon,
    pickup_latitude AS pickuplat,
    dropoff_longitude AS dropofflon,
    dropoff_latitude AS dropofflat,
    passenger_count AS passengers
  FROM
    `nyc-tlc.yellow.trips`, daynames, params
  WHERE
    trip_distance > 0 AND fare_amount > 0
    AND MOD(ABS(FARM_FINGERPRINT(CAST(pickup_datetime AS STRING))),1000) = params.TRAIN
  )

  SELECT *
  FROM taxitrips

分類モデルの性能を評価する

線形回帰モデルには、二乗平均平方根誤差(RMSE)などの損失指標を使用します。RMSE が下がるまでトレーニングを続け、モデルを改善していきます。

#standardSQL
SELECT
  SQRT(mean_squared_error) AS rmse --- 二乗平均平方根誤差
FROM
  ML.EVALUATE(MODEL taxi.taxifare_model,  -- ML.EVALUATEは 評価
  (

  WITH params AS (
    SELECT
    1 AS TRAIN,
    2 AS EVAL
    ),

  daynames AS
    (SELECT ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'] AS daysofweek),

  taxitrips AS (
  SELECT
    (tolls_amount + fare_amount) AS total_fare,
    daysofweek[ORDINAL(EXTRACT(DAYOFWEEK FROM pickup_datetime))] AS dayofweek,
    EXTRACT(HOUR FROM pickup_datetime) AS hourofday,
    pickup_longitude AS pickuplon,
    pickup_latitude AS pickuplat,
    dropoff_longitude AS dropofflon,
    dropoff_latitude AS dropofflat,
    passenger_count AS passengers
  FROM
    `nyc-tlc.yellow.trips`, daynames, params
  WHERE
    trip_distance > 0 AND fare_amount > 0
    AND MOD(ABS(FARM_FINGERPRINT(CAST(pickup_datetime AS STRING))),1000) = params.EVAL  --- 評価対象を抽出
  )

  SELECT *
  FROM taxitrips

  ))

結果は 9.4。これを下げる方法を模索するのが「モデルの改善」なのだろう。

行  rmse
1   9.47663701977026

タクシー運賃を予測する

#standardSQL
SELECT
*
FROM
  ml.PREDICT(MODEL `taxi.taxifare_model`,  -- 予測
   (

 WITH params AS (
    SELECT
    1 AS TRAIN,
    2 AS EVAL
    ),

  daynames AS
    (SELECT ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'] AS daysofweek),

  taxitrips AS (
  SELECT
    (tolls_amount + fare_amount) AS total_fare,
    daysofweek[ORDINAL(EXTRACT(DAYOFWEEK FROM pickup_datetime))] AS dayofweek,
    EXTRACT(HOUR FROM pickup_datetime) AS hourofday,
    pickup_longitude AS pickuplon,
    pickup_latitude AS pickuplat,
    dropoff_longitude AS dropofflon,
    dropoff_latitude AS dropofflat,
    passenger_count AS passengers
  FROM
    `nyc-tlc.yellow.trips`, daynames, params
  WHERE
    trip_distance > 0 AND fare_amount > 0
    AND MOD(ABS(FARM_FINGERPRINT(CAST(pickup_datetime AS STRING))),1000) = params.EVAL
  )

  SELECT *
  FROM taxitrips

));

モデルの性能を向上させる

BigQuery の地理空間機能を活用して、ML モデルの精度を高める方法

このブログを見よとのこと。

towardsdatascience.com