❄️

Snowflake Notebooksを使ってみた

2025/02/10に公開

皆様、こんにちは!
Septeni Japan 株式会社でエンジニアをしています、西垣と申します。
当社では、データウェアハウスとしてSnowflakeを利用しており、データ分析やレポーティングといった場面で積極的に活用しています。
そんなSnowflakeが突如としてNotebook機能を提供したとのことで(と言ってもリリースから半年経っておりますが💦)、これは試してみにゃいかん!!ということでその内容を本投稿でレポートさせていただきます。

Snowflake Notebooksとは?

公式ドキュメントでは以下のように説明されています。
https://docs.snowflake.com/en/user-guide/ui-snowsight/notebooks

  • Snowflake UI (Snowsight) 内で提供されている統合開発インターフェース
    • Python、SQL、Markdownなど複数のプログラミング言語に対応
    • Snowflakeデータを活用したデータ分析、機械学習モデルの開発などが実行可能

要は、Google ColaboratoryやJupyter Notebookのようなものですね。
では上記の開発環境との差分は?となるかと思いますので、そちらも簡単にまとめてみます。

  • Snowflakeへのネイティブな統合
    • DBに直接アクセスすることができるので、データの取得・操作がシームレスに行える
  • 管理とセキュリティ
    • データがSnowflake環境で完結するため、インフラのセットアップやメンテナンスが不要
    • Snowflakeのセキュリティポリシーやアクセス制御が適用されるため、安全性が高い
  • パフォーマンス
    • Snowflakeのクラウドインフラを利用した大量のデータ処理が高速かつスケーラブルに実行可能

従来のNotebookツールは拡張性が高い一方で、柔軟に使いこなすにはある程度の経験や慣れが必要になりますが、Snowflake Notebooksは操作性の敷居を下げつつも、十分なセキュリティやパフォーマンスを確保しています。
そのため、Snowflake環境でのデータ分析やデータサイエンスの作業を効率化し、管理負担を軽減するツールとしては非常に魅力を感じていただけると思います!

Snowflake Notebooksでデータ分析してみる

事前準備

まずはSnowflakeにデータセットを登録します。
下記のサイトから交通事故情報に関するデータセットを取得し、Snowflakeにアップロードしました。

https://www.kaggle.com/datasets/denkuznetz/traffic-accident-prediction?resource=download

利用規約

https://www.kaggle.com/terms

Notebookの新規作成

下記の手順でNotebookを新規作成します。

  1. Snowsightの左側メニューからCreate > Notebook > New Notebookを選択
  2. Notebook名、対象となるデータベース、スキーマを指定してCreateをクリック

作成が完了すると、以下のようにNotebook画面が表示されます。

ここまでで、データの準備とNotebookの作成に5分とかかっていません!
この調子でデータセットを可視化してみようと思います。

データの可視化 (Streamlit)

今回使用するデータセットにはカラムにnullが含まれている欠損データが存在するため、事前にデータの整形を行います。

-- 欠損データを排除したテーブルを作成
CREATE OR REPLACE TABLE CLEANED_TRAFFIC_ACCIDENT_PREDICTION AS
SELECT *
FROM TRAFFIC_ACCIDENT_PREDICTION
WHERE 
    WEATHER IS NOT NULL AND
    ROAD_TYPE IS NOT NULL AND
    TIME_OF_DAY IS NOT NULL AND
    TRAFFIC_DENSITY IS NOT NULL AND
    SPEED_LIMIT IS NOT NULL AND
    NUMBER_OF_VEHICLES IS NOT NULL AND
    DRIVER_ALCOHOL IS NOT NULL AND
    ACCIDENT_SEVERITY IS NOT NULL AND
    ROAD_CONDITION IS NOT NULL AND
    VEHICLE_TYPE IS NOT NULL AND
    DRIVER_AGE IS NOT NULL AND
    DRIVER_EXPERIENCE IS NOT NULL AND
    ROAD_LIGHT_CONDITION IS NOT NULL AND
    ACCIDENT IS NOT NULL
;

まずは簡単なデータ分析として、時間帯別の事故発生件数を集計し、Streamlitで可視化してみます。

-- 事故の発生件数を時間帯別に集計
SELECT TIME_OF_DAY, COUNT(*) AS ACCIDENT_COUNT
FROM CLEANED_TRAFFIC_ACCIDENT_PREDICTION
GROUP BY TIME_OF_DAY
ORDER BY ACCIDENT_COUNT DESC
;

import streamlit as st
import pandas as pd
import altair as alt
from snowflake.connector.pandas_tools import write_pandas

# セル間でのデータ参照
# クエリ結果をPandas DataFrameに変換
df = cell3.to_pandas()

# Streamlitで可視化
st.title('Traffic Accident Analysis')
st.write('Accident count by time of day')

chart = alt.Chart(df).mark_bar().encode(
    x='TIME_OF_DAY',
    y='ACCIDENT_COUNT'
)

st.altair_chart(chart, use_container_width=True)

データの可視化 (matplotlib)

次に天候、交通密度の2要素による事故発生件数を集計し、matplotlibで可視化してみます。

-- 天候、道路の種類による事故発生件数を集計
SELECT
  WEATHER,
  ROAD_TYPE,
  COUNT(*) AS ACCIDENT_COUNT
FROM
  CLEANED_TRAFFIC_ACCIDENT_PREDICTION
GROUP BY
  WEATHER,
  ROAD_TYPE
ORDER BY
  ACCIDENT_COUNT DESC
;

先程のStreamlitはSnowflake Notebooksに標準で組み込まれていましたが、今回は事前にパッケージをインストールする必要があります。
Notebook右上のPackagesからmatplotlibseabornをインストールします。

クエリ結果をもとに、事故発生件数の2次元ヒートマップを作成してみます。

import snowflake.connector
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# クエリ結果をPandas DataFrameに変換
df = cell5.to_pandas()

# ピボットテーブルを作成
pivot_table = df.pivot(index="WEATHER", columns="ROAD_TYPE", values="ACCIDENT_COUNT")

# ヒートマップの作成
plt.figure(figsize=(12, 8))
sns.heatmap(pivot_table, annot=True, fmt="d", cmap="YlGnBu")

# ラベルの設定
plt.xlabel('Road Type')
plt.ylabel('Weather')
plt.title('Heatmap of Accident Count by Weather and Road Type')

# グラフの表示
plt.show()

事故予測モデルの構築

最後に、Snowflake Notebooks上でデータの取得からモデルのトレーニングまでを一貫して行ってみました。
今回は事故予測用の学習データとして、ランダムフォレストモデルをトレーニングし、予測精度を評価します。

まずは学習用のデータをクエリで出力します。

SELECT
    WEATHER,
    ROAD_TYPE,
    TIME_OF_DAY,
    TRAFFIC_DENSITY,
    SPEED_LIMIT,
    NUMBER_OF_VEHICLES,
    DRIVER_ALCOHOL,
    ACCIDENT_SEVERITY,
    ROAD_CONDITION,
    VEHICLE_TYPE,
    DRIVER_AGE,
    DRIVER_EXPERIENCE,
    ROAD_LIGHT_CONDITION,
    ACCIDENT
FROM
    CLEANED_TRAFFIC_ACCIDENT_PREDICTION
;

次に、ランダムフォレストモデルをトレーニングし、作成したモデルとラベルエンコーダーを保存します。
sklearn-pandasjoblibも忘れないよう、インストールしておきます。

import snowflake.connector
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder
import joblib

# クエリ結果をPandas DataFrameに変換
df = cell7.to_pandas()

# カテゴリカルデータを数値にエンコード
label_encoders = {}
for column in df.select_dtypes(include=['object']).columns:
    le = LabelEncoder()
    df[column] = le.fit_transform(df[column])
    label_encoders[column] = le

# データの前処理
X = df.drop('ACCIDENT', axis=1)  # 特徴量
y = df['ACCIDENT']  # 目的変数

# 学習データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルのトレーニング
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# モデルの評価
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')

# モデルとラベルエンコーダーを保存
joblib.dump(model, 'random_forest_model.pkl')
joblib.dump(label_encoders, 'label_encoders.pkl')

ユーザーデータを作成し、モデルの評価結果を出力することで予測結果を確認することが出来ました!

import joblib
import pandas as pd

# 保存されたモデルとラベルエンコーダーを読み込む
model = joblib.load('random_forest_model.pkl')
label_encoders = joblib.load('label_encoders.pkl')

# 事故予測用のユーザーデータを作成
user_data = {
    'WEATHER': ['Clear'],
    'ROAD_TYPE': ['Highway'],
    'TIME_OF_DAY': ['Morning'],
    'TRAFFIC_DENSITY': [0],
    'SPEED_LIMIT': [80],
    'NUMBER_OF_VEHICLES': [12],
    'DRIVER_ALCOHOL': [0],
    'ACCIDENT_SEVERITY': ['Low'],
    'ROAD_CONDITION': ['Wet'],
    'VEHICLE_TYPE': ['Truck'],
    'DRIVER_AGE': [62],
    'DRIVER_EXPERIENCE': [30],
    'ROAD_LIGHT_CONDITION': ['Artificial Light']
}

# データフレームに変換
user_df = pd.DataFrame(user_data)

# カテゴリカルデータを数値にエンコード
for column in user_df.select_dtypes(include=['object']).columns:
    if column in label_encoders:
        le = label_encoders[column]
        user_df[column] = le.transform(user_df[column])
    else:
        raise KeyError(f"Column '{column}' not found in label encoders")

prediction = model.predict(user_df)
prediction_proba = model.predict_proba(user_df)

# 結果を表示
print(f"事故が発生する確率: {prediction_proba[0][1]:.2f}")
print("事故が発生する可能性が高いです" if prediction[0] == 1 else "事故が発生する可能性は低いです")

注意点 (セッションの終了)

SessionがActiveの状態だと、Notebookを終了してもウェアハウスが稼働してしまいますので、必ずEnd Sessionをクリックしてセッションを終了してください。

まとめ

簡単ではありますが、SnowFlake Notebookについての紹介とデータ分析のためにコードを動かしてみました。
データの取得と整形、そして機械学習モデルの作成までがSnowflakeで一貫しているため、作業効率が非常に良かったと感じています。
初心者の方でも操作しやすいので、興味のある方は下記のURLから無料のトライアルアカウントを作成してデータ分析を始めてみてはいかがでしょうか?
https://signup.snowflake.com/?_l=ja

他にもNotebookをGit管理できたり、スケジュールによるタスク定義を設定できるなどの便利な機能が既に実装されているようですので、これからも情報を追いかけていきたいと思います!

最後までお読みいただき、ありがとうございました🙇
質問やフィードバックなどございましたら、ぜひコメント欄でお知らせください。

Discussion