PythonとBigQueryで鬼速!相関分析

販売数予測において、販売数に影響を与える変数(要因)とは何か。

例えば、商品の価格、季節、天気、気温、販促CM、店舗の立地、棚割、競合他社の販売状況などが考えられます。これらの変数のことを、特徴量(説明変数)といいます。

予測では、過去データを学習してモデルを作り、モデルに未来の特徴量を与えて予測値を算出します。その際、どの変数を重視するかがわかれば、より正確な予測値を導くことができます。

簡単そうですが、実際には「気温」ひとつとっても、最低気温、最高気温、平均気温、過去3日間の移動平均気温、平年値との差、前日との気温差など、いくらでも考えられます。どれを学習データとして使うのが最適か、人間が判断するのは難しいです。

そこで、予測を始める前に、それぞれの特徴量と目的変数との相関関係を調べる必要があります。

今回は、Python と BigQuery を使い、あらゆるお客様のあらゆるデータで使いまわせる相関分析ツールを自作したのでその紹介です。

なお、気温などの外部データは弊社のソトミルからご提供しております。お気軽にお問い合わせください。

全体の流れは黄→緑→青なのですが、今回紹介しているのは緑の部分です。

お客様によってデータセットもデータもテーブルもカラム名も違うので、それを変数としてセットできるように作ったのがポイントです。赤字で [カスタム系操作] と書いてある箱です。

セットされた変数は、以下のように配列型でBigQueryに格納されます。

まだ notebook 上で動かしてるだけなので私が手動で書き換えているのですが、ゆくゆくはアプリ化して画面作って公開したいなと思ってます。

BigQuery はデータセットの結合や、実行結果の保管場所です。ロード速くてほぼ無料で使えるし、Looker(旧データポータル)でダッシュボードにしたり、Vertex で AutoML の予測に使ったりと使い勝手がとても良いです。

こんな感じでクエリを埋め込んで使ってます。データセットの結合などは、Python で1レコードずつ処理するよりも BigQuery 上で実行した方がめちゃくちゃ速いし可読性も良いです。

分析エンジンでは、どの変数を使って、どの単位で集計する時が最も相関が高い(=予測しやすい)のか、を調べることができます。

具体例を紹介します。

以下は、ソトミルの外部データ(気温)とお客様の出荷データを結合し、あらゆる集計単位でのすべての組み合わせで相関係数を調べたものです。目的変数も、「数」が良いのか「率」が良いのかなど不明だったので、6パターン調べました。

集計単位はWHEN(時間)、WHERE(地理)、WHAT(商品ごと、ブランドごと、等)の3つに分類します。WHATについては、商品が最も小さな単位で191、ブランド別では74、メーカー別なら15のデータが含まれている、という意味です。WHENは、出荷データが 3 年分だったので年ごとなら3つ(2020年、2021年、2022年)、四半期ごとなら 各年1Q〜4Q あるので 4 つです。

<実行した結果>

実行すると、以下のようなテーブルが出力されます。1行ごとに、目的変数、気温データ、集計単位とその値の時の相関係数がわかります。

下のキャプチャでは 1,924,004 件の相関係数とその組み合わせが出力されました。

200万件近い組み合わせで、人間が相関係数を手動で調べるのは不可能ですが、このツールがあれば、あらゆるお客様のあらゆるデータで、最も予測に適したデータの集計単位や組み合わせを、知見のない人でも見つけることができます。

この相関係数はどうやって出しているかというと、例えば1行目の「2020年、03860センターの、生茶」の出荷データ256件について、目的変数「日別返り発注率(5日間移動平均)」と気温データ「平均気温」の相関係数を計算しています。

最後に、Looker でダッシュボードにします。

ここでは、WHEN、WHERE、WHATの項目名のみ(値を除外)に集約して相関係数の平均を確認します。

結果、外部データとして使う気温は「最低気温」、目的変数は「日別発注数(5日間移動平均)」、集計単位は「週別」「センター別」「ブランド別」の時、最も相関係数が高いことがわかりました。

ソトミルは、気象、イベント、SNS、政府統計情報などの汎用データ提供サービスです。

個別、および、ご希望の組み合わせや粒度で統合したデータセットとしてご提供します。予測や分析の精緻化に向け、ダッシュボード化や社内データとの組み合わせも承ります。
提供形式:データ(CSV、API)、PDFレポート、ダッシュボード他

もしこの記事を読んでご興味持っていただけましたら、お気軽にお問い合わせください。