Slide 1

Slide 1 text

データに関する堅牢性と可読性を向上させる pydanticとpanderaの活用方法の提案 (PyCon JP 2022) 桂川大輝

Slide 2

Slide 2 text

自己紹介 ● 名前:桂川 大輝(GitHub:daikikatsuragawa[1]) ● Pythonの使用用途:開発、分析、研究 2 [1] daikikatsuragawa (Daiki Katsuragawa)(https://github.com/daikikatsuragawa)

Slide 3

Slide 3 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 3

Slide 4

Slide 4 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 4

Slide 5

Slide 5 text

Pythonによる開発とデータ ● 多くの開発におけるデータ ○ データの管理 ○ データの処理 ● Pythonによる開発におけるデータ ○ データ分析 ○ 機械学習(データからルールやパターンを発見) 5 Pythonによる開発ではデータの扱いの幅が広い

Slide 6

Slide 6 text

機械学習を使った処理の例 1. データ収集 ○ ドメインに基づくデータを収集 2. 前処理 ○ 収集したデータを任意の処理に基づき学習用に変換 3. 学習 ○ 前処理済みデータを学習(モデルの作成) 4. 予測 ○ 学習済みモデルにより予測 6

Slide 7

Slide 7 text

機械学習を使った処理の例〜データに関する問題〜 1. データ収集 ○ ドメインに基づくデータを収集 2. 前処理 ○ 収集したデータを任意の処理に基づき学習用に変換 3. 学習 ○ 前処理済みデータを学習(モデルの作成) 4. 予測 ○ 学習済みモデルにより予測 7 様々な理由により 期待しないデータを 収集してしまう可能性 (例:年齢が-1)

Slide 8

Slide 8 text

機械学習を使った処理の例〜データに関する問題〜 1. データ収集 ○ ドメインに基づくデータを収集 2. 前処理 ○ 収集したデータを任意の処理に基づき学習用に変換 3. 学習 ○ 前処理済みデータを学習(モデルの作成) 4. 予測 ○ 学習済みモデルにより予測 8 防ぐことができれば問題ないが、 防げなかった場合… 後の処理に影響し、本来もたらす 価値を見出せない (場合によっては不利益も…)

Slide 9

Slide 9 text

機械学習を使った処理の例〜データに関する問題〜 1. データ収集 ○ ドメインに基づくデータを収集 2. 前処理 ○ 収集したデータを任意の処理に基づき学習用に変換 3. 学習 ○ 前処理済みデータを学習(モデルの作成) 4. 予測 ○ 学習済みモデルにより予測 9 期待しない前処理を 実施してしまう可能性 (例:重要な指標の計算の誤り)

Slide 10

Slide 10 text

機械学習を使った処理の例〜データに関する問題〜 1. データ収集 ○ ドメインに基づくデータを収集 2. 前処理 ○ 収集したデータを任意の処理に基づき学習用に変換 3. 学習 ○ 前処理済みデータを学習(モデルの作成) 4. 予測 ○ 学習済みモデルにより予測 10 防ぐことができれば問題ないが、 防げなかった場合… 後の処理に影響し、本来もたらす 価値を見出せない (場合によっては不利益も…)

Slide 11

Slide 11 text

機械学習を使った処理の例〜データに関する問題〜 1. データ収集 ○ ドメインに基づくデータを収集 2. 前処理 ○ 収集したデータを任意の処理に基づき学習用に変換 3. 学習 ○ 前処理済みデータを学習(モデルの作成) 4. 予測 ○ 学習済みモデルにより予測 11 問題:すべてのデータが期待する内容・状態とは限らない

Slide 12

Slide 12 text

データに関する理想と現実 12 理想 すべてのデータが期待する内容・状態 現実 期待しない内容・状態のデータが存在

Slide 13

Slide 13 text

データに関する理想と現実と問題 13 理想 すべてのデータが期待する内容・状態 現実 期待しない内容・状態のデータが存在 問題 (ギャップ) すべてのデータが期待する内容・状態とは限らない

Slide 14

Slide 14 text

データに関する問題 14 解消したい 問題 すべてのデータが期待する内容・状態とは限らない ● データに関する堅牢性が低い ● データに関する可読性が低い

Slide 15

Slide 15 text

データに関する堅牢性が低い ● 期待しないデータ(型)の格納を許すコード ● 期待しないデータ(値)の格納を許すコード 15 probability = 0.5 # float型の0~1の値を期待(OK) probability = 50 # float型の0~100の値を期待(NG) number = 1 # int型の値を期待(OK) number = "文字列" # int型の値を期待(NG) 堅牢性の向上が必要(データのバリデーションの実装など)

Slide 16

Slide 16 text

データに関する可読性が低い ● コードからデータの仕様の理解が困難 ● ● 構造を表現するデータやデータフレームの仕様の理解はより困難 16 可読性の向上が必要(データの仕様の理解を可能にするコードなど) probability # float型の0~1の値を期待?/int型の0~100の値を期待? df # データフレーム?/列数は?/各列の期待する型は?/各列の期待する値は?

Slide 17

Slide 17 text

データに関する問題と課題 17 解消したい 問題 すべてのデータが期待する内容・状態とは限らない ● データに関する堅牢性が低い ● データに関する可読性が低い 解決したい 課題 データに関する堅牢性と可読性の向上 データに関する堅牢性と可読性の向上が必要

Slide 18

Slide 18 text

データに関する課題と打ち手 18 解決したい 課題 データに関する堅牢性と可読性の向上 打ち手 仕組みの導入(例:ライブラリ) データに関する堅牢性と可読性の向上のためのライブラリの導入を検討

Slide 19

Slide 19 text

データに関する堅牢性と可読性を向上させるための提案 ● 構造で表現されるデータのスキーマをpydanticで定義 ○ pydantic(ライブラリ): スキーマの定義に基づき構造で表現されるデータをバリデーション ● データフレームのスキーマをpanderaで定義 ○ pandera(ライブラリ): スキーマの定義に基づきデータフレームをバリデーション ● pydanticとpanderaを併用 19 本発表はpydanticとpanderaの活用方法の提案

Slide 20

Slide 20 text

データに関する堅牢性と可読性を向上させるための提案 ● 構造で表現されるデータのスキーマをpydanticで定義 ○ pydantic(ライブラリ): スキーマの定義に基づき構造で表現されるデータをバリデーション ● データフレームのスキーマをpanderaで定義 ○ pandera(ライブラリ): スキーマの定義に基づきデータフレームをバリデーション ● pydanticとpanderaを併用 20 前提知識としてpydanticとpanderaの理解に必要な型ヒントを説明

Slide 21

Slide 21 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 21

Slide 22

Slide 22 text

型ヒントとは? ● 型ヒント(Type Hints[2]) ○ 「変数」、「関数の引数」や「関数の戻り値」の定義に 型のヒントを付与するという記法 ● 型ヒントの振る舞い ○ 実行時に型のチェックはしない(誤りが存在しても動作) ○ ツール(例:mypy[3])と組み合わせて静的チェックを実現 22 [2] PEP 484 – Type Hints | peps.Python.org(https://peps.Python.org/pep-0484/) [3] mypy - Optional Static Typing for Python(http://www.mypy-lang.org/) コードの可読性の向上 ツールと組み合わせることで堅牢性の向上 name: str = "パイソン 太郎"

Slide 23

Slide 23 text

型ヒントの記述方法① ● 変数:直後に「:」と型を記述 ● 関数の引数:各引数の直後に「:」と型を記述 ● 関数の戻り値:「:」の直前に「->」と型を記述 23 name: str = "パイソン 太郎" def divide(numerator: int, denominator: int) -> float: return numerator / denominator

Slide 24

Slide 24 text

型ヒントの記述方法② ● 辞書型(Dict)、リスト型(List)などの要素の型の指定 ● 複数の型(Union)の指定 24 from typing import Dict user_and_age: Dict[str, int] = {'パイソン 太郎': 20} from typing import Union str_or_int: Union[str, int] = 0 # or パイソン 太郎"

Slide 25

Slide 25 text

型ヒントの記述方法③ ● 必須ではない(Optional)という指定 ● 任意である(Any)という指定 25 from typing import Optional optional_int: Optional[int] = None # or 0 from typing import Any any: Any = 0 # or "パイソン 太郎", {"パイソン 太郎": 20} ...

Slide 26

Slide 26 text

型ヒントの記述方法④ ● 存在しない(None)という指定 26 from typing import Any def return_none(input: Any) -> None: pass

Slide 27

Slide 27 text

型ヒントの記述方法⑤ ● 自作のクラスを指定 27 class SampleClass: pass sample_class: SampleClass = SampleClass() def return_input(sample_class: SampleClass) -> SampleClass: return sample_class

Slide 28

Slide 28 text

型ヒント〜まとめ〜 ● 型ヒント(Type Hints) ○ 「変数」、「関数の引数」や「関数の戻り値」の定義に 型のヒントを付与するという記法 ● 型ヒントの振る舞い ○ 実行時に型のチェックはしない(誤りが存在しても動作) ○ ツール(例:mypy)と組み合わせて静的チェックを実現 28 可読性と堅牢性の向上に期待

Slide 29

Slide 29 text

型ヒント〜まとめ〜 ● 型ヒント(Type Hints) ○ 「変数」、「関数の引数」や「関数の戻り値」の定義に 型のヒントを付与するという記法 ● 型ヒントの振る舞い ○ 実行時に型のチェックはしない(誤りが存在しても動作) ○ ツール(例:mypy)と組み合わせて静的チェックを実現 29 型ヒントに基づいて可読性と堅牢性を向上させる pydanticとpanderaを説明

Slide 30

Slide 30 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 30

Slide 31

Slide 31 text

複数の部品によって構成されるシステムを開発していますか? ● 多くのシステムは複数の部品によって構成 ○ 部品:モジュール・クラス・メソッド・外部のAPIなど ● 各部品が役割と責任を持ち連携 ○ 各部品の入出力を把握しておけばシステムの全ての把握は不要 ○ 入出力:int、str、JSON(構造) 31 部品Y 部品Z JSON JSON

Slide 32

Slide 32 text

堅牢性が低い:期待しないデータを格納してしまう ● 期待しないデータのやり取りが発生 32 対応しないと… 部品Y 部品Z JSON 人に関するデータを 格納したJSONを 渡します。 {name: ”パイソン 太郎” , age: -1} ドメイン的に ありえないデータが来た

Slide 33

Slide 33 text

可読性が低い:コードからデータの仕様を読み取れない ● 仕様がわからないデータの扱いが困難 ● 期待しないデータか否かの判断が困難 33 ???のデータを 格納したJSONを 渡します。 (期待しないデータであ ることに気がつかない) 部品Y 部品Z JSON {???: ???, ???:???, …} 何が格納されている?

Slide 34

Slide 34 text

構造で表現されるデータのスキーマをpydanticで定義 ● pydantic[4] ○ 定義したスキーマに基づき構造で表現されるデータを バリデーションするライブラリ ○ 辞書型・JSONとのシリアライズ/デシリアライズも可能(入出力に有用) ○ GitHubのスター:11.3k[5](2022/10/15時点) ○ ライセンス:MIT License[6] 34 [4] pydantic(https://pydantic-docs.helpmanual.io/) [5] pydantic/pydantic: Data parsing and validation using Python type hints(https://github.com/pydantic/pydantic) [6] pydantic/LICENSE at master · samuelcolvin/pydantic(https://github.com/samuelcolvin/pydantic/blob/master/LICENSE) pip install pydantic

Slide 35

Slide 35 text

データに関する堅牢性と可読性を向上させるpydantic ● 堅牢性の向上 ○ スキーマの定義に基づくデータのみが存在(バリデーション) ● 可読性の向上 ○ スキーマの定義によるデータの仕様の把握が可能 35

Slide 36

Slide 36 text

pydanticの利用例〜スキーマの定義とバリデーション〜 36 from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) external_data = { 'name': 'パイソン 太郎', 'age': 20 } user = User.parse_obj(external_data) 型、有効範囲の定義 デシリアライズ データの仕様の 読み取りが可能 (例:ageは20以上) 定義を満たす インスタンスの生成

Slide 37

Slide 37 text

pydanticの利用例〜スキーマの定義とバリデーション(エラー)〜 37 from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) external_data = { 'name': 'パイソン 太郎', 'age': 19 } user = User.parse_obj(external_data) 有効範囲外の値 ValidationError

Slide 38

Slide 38 text

pydanticの利用例〜バリデーション(エラー)〜 38 --------------------------------------------------------------------------- ValidationError Traceback (most recent call last) (省略) ValidationError: 1 validation error for User age ensure this value is greater than or equal to 20 (type=value_error.number.not_ge; limit_value=20) エラーの詳細を確認可能 (例:ageの20以上という定義を満たしていない)

Slide 39

Slide 39 text

pydanticの利用例〜定義したスキーマを引数とする関数〜 39 from pydantic import validate_arguments @validate_arguments def input_user(user : User) -> None: pass external_data = { 'name': 'パイソン 太郎', 'age': 20 } input_user(external_data) 引数のバリデーションを 実行するデコレーター pydanticで定義した クラスも引数として指定

Slide 40

Slide 40 text

pydanticの利用例〜定義したスキーマを引数とする関数(エラー)〜 40 from pydantic import validate_arguments @validate_arguments def input_user(user : User) -> None: pass external_data = { 'name': 'パイソン 太郎', 'age': 19 } input_user(external_data) 有効範囲外の値 ValidationError

Slide 41

Slide 41 text

pydanticの利用例〜定義したスキーマを返り値とする関数〜 41 def output_user() -> User: external_data = { 'name': 'パイソン 太郎', 'age': 20 } return User.parse_obj(external_data) output_user()

Slide 42

Slide 42 text

pydanticの利用例〜定義したスキーマを返り値とする関数(エラー)〜 42 def output_user() -> User: external_data = { 'name': 'パイソン 太郎', 'age': 19 } return User.parse_obj(external_data) output_user() 有効範囲外の値 ValidationError

Slide 43

Slide 43 text

pydanticの利用例〜より詳細なスキーマの定義〜 43 from pydantic import BaseModel, Field, validator import unicodedata class User(BaseModel): id: int name: str # 半角空白を含む(※前後以外) age: int = Field(ge=20) @validator("name") def check_contain_space(cls, v): if " " not in v.strip(): # 前後の半角空白を無視 raise ValueError("ensure this value contains spaces") return v.strip() # 前後の半角空白を削除 デコレーターによる詳細なスキーマの定義 (例:半角空白を含むか否かを判定)

Slide 44

Slide 44 text

スキーマの定義に基づくデータのみが存在(バリデーション) 44 部品Y 部品Z JSON pydanticによる堅牢性の向上 スキーマを定義した データのみを出力 (バリデーション) スキーマを定義した データのみを入力 (バリデーション) スキーマを定義した データのみが存在

Slide 45

Slide 45 text

スキーマの定義によるデータの仕様の把握が可能 45 from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) 型、有効範囲の定義 データの仕様の 読み取りが可能 (例:ageは20以上) pydanticによる可読性の向上

Slide 46

Slide 46 text

構造で表現されるデータのスキーマをpydanticで定義〜まとめ〜 ● 複数の部品によって構成されるシステムの開発 ○ 各部品(モジュール・クラス・メソッドなど)が役割と責任を持ち連携 ○ 堅牢性が低い:期待しないデータを格納してしまう ○ 可読性が低い:コードからデータの仕様を読み取れない ● pydantic ○ 定義したスキーマに基づき構造で表現されるデータを バリデーションするライブラリ ○ 堅牢性の向上:スキーマの定義に基づくデータのみが存在(バリデーション) ○ 可読性の向上:スキーマの定義によるデータの仕様の把握が可能 46 pydanticによるデータに関する堅牢性と可読性の向上

Slide 47

Slide 47 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 47

Slide 48

Slide 48 text

データフレームを使っていますか? ● データフレーム(pandas.DataFrame[7]) ○ 表型式のデータの取り込み、加工、集計、分析に利用(例:機械学習) ○ 例:アヤメ(iris)の特徴と種類(scikit-learn[8]より) 48 [7] pandas - Python Data Analysis Library (https://pandas.pydata.org/) [8] scikit-learn: machine learning in Python — scikit-learn 1.1.1 documentation (https://scikit-learn.org/stable/) sepal_length sepal_width petal_length petal_width target 0 5.1 3.5 1.4 0.2 0 1 4.9 3.0 1.4 0.2 0 2 4.7 3.2 1.3 0.2 0 3 4.6 3.1 1.5 0.2 0 4 5.0 3.6 1.4 0.2 0

Slide 49

Slide 49 text

堅牢性が低い:期待しないデータを格納してしまう 49 sepal_length sepal_width petal_length petal_width target 146 6.3 2.5 5.00 1.9 2 147 6.5 3.0 5.20 2.0 2 148 6.2 3.4 5.40 2.3 2 149 5.9 3.0 5.10 1.8 2 150 ◯△□ 3.0 4.35 1.3 3 数値を期待しているが… 文字列が格納されている 0/1/2を期待しているが… 3が格納されている

Slide 50

Slide 50 text

可読性が低い:コードからデータの仕様を読み取れない 50 import pandas as pd from sklearn.datasets import load_iris data = load_iris() iris = pd.DataFrame(data.data, columns=data.feature_names) iris["target"] = data.target iris.head() irisにはどんなデータが 格納されている?

Slide 51

Slide 51 text

データフレームのスキーマをpanderaで定義 ● pandera[9] ○ 定義したスキーマに基づきデータフレームをバリデーションするライブラリ ○ GitHubのスター:1.7k[10](2022/10/15時点) ○ ライセンス:MIT License[11] 51 [9] pandera (https://pandera.readthedocs.io/en/stable/) [10] unionai-oss/pandera: A light-weight, flexible, and expressive statistical data testing library (https://github.com/unionai-oss/pandera) [11] pandera/LICENSE.txt at master · unionai-oss/pandera (https://github.com/unionai-oss/pandera/blob/master/LICENSE.txt) pip install pandera

Slide 52

Slide 52 text

データに関する堅牢性と可読性を向上させるpandera ● 堅牢性の向上 ○ スキーマの定義に基づくデータのみが存在(バリデーション) ● 可読性の向上 ○ スキーマの定義によるデータの仕様の把握が可能 ※2種存在する記述方法より“SchemaModel”を説明 52

Slide 53

Slide 53 text

panderaの利用例〜アヤメ(iris)のデータセットの準備〜 53 import pandas as pd from sklearn.datasets import load_iris data = load_iris() iris = pd.DataFrame(data.data, columns=data.feature_names) iris["target"] = data.target

Slide 54

Slide 54 text

panderaの利用例〜アヤメ(iris)のデータセットの準備〜 54 iris = iris.rename( columns={ "sepal length (cm)": "sepal_length", "sepal width (cm)": "sepal_width", "petal length (cm)": "petal_length", "petal width (cm)": "petal_width", } ) 説明を簡単に するために改名

Slide 55

Slide 55 text

panderaの利用例〜データセットの確認①〜 55 iris.head() 0/1/2(カテゴリ) 現実的な数値 sepal_length sepal_width petal_length petal_width target 0 5.1 3.5 1.4 0.2 0 1 4.9 3.0 1.4 0.2 0 2 4.7 3.2 1.3 0.2 0 3 4.6 3.1 1.5 0.2 0 4 5.0 3.6 1.4 0.2 0

Slide 56

Slide 56 text

panderaの利用例〜データセットの確認②〜 56 iris.describe() sepal_length sepal_width petal_length petal_width target count 150.000000 150.000000 150.000000 150.000000 150.000000 mean 5.843333 3.057333 3.758000 1.199333 1.000000 std 0828066 0.435866 1.765298 0.762238 0.819232 min 4.300000 2.000000 1.000000 0.100000 0.000000 25% 5.100000 2.800000 1.600000 0.300000 0.000000 50% 5.800000 3.000000 4.350000 1.300000 1.000000 75% 6.400000 3.300000 5.100000 1.800000 2.000000 max 7.900000 4.400000 6.900000 2.500000 2.000000

Slide 57

Slide 57 text

panderaの利用例〜スキーマの定義〜 57 import pandera as pa from pandera.typing import Series class IrisSchema(pa.SchemaModel): sepal_length: Series[float] = pa.Field(gt=0, le=8) sepal_width: Series[float] = pa.Field(gt=0, le=5) petal_length: Series[float] = pa.Field(gt=0, le=7) petal_width: Series[float] = pa.Field(gt=0, le=3) target: Series[int] = pa.Field(isin=[0, 1, 2]) 0/1/2(カテゴリ) 現実的な数値

Slide 58

Slide 58 text

panderaの利用例〜バリデーション〜 58 iris = IrisSchema.validate(iris) iris.head() sepal_length sepal_width petal_length petal_width target 0 5.1 3.5 1.4 0.2 0 1 4.9 3.0 1.4 0.2 0 2 4.7 3.2 1.3 0.2 0 3 4.6 3.1 1.5 0.2 0 4 5.0 3.6 1.4 0.2 0

Slide 59

Slide 59 text

panderaの利用例〜期待しないレコードの追加〜 59 invalid_record = { "sepal_length": 5.8, "sepal_width": 3.0, "petal_length": 4.35, "petal_width": 1.3, "target": 3, # invalid value } invalid_iris = iris.append(invalid_record, ignore_index=True) invalid_iris["target"] = invalid_iris["target"].astype(int)

Slide 60

Slide 60 text

panderaの利用例〜期待しないレコードの確認〜 60 invalid_iris.tail() sepal_length sepal_width petal_length petal_width target 146 6.3 2.5 5.00 1.9 2 147 6.5 3.0 5.20 2.0 2 148 6.2 3.4 5.40 2.3 2 149 5.9 3.0 5.10 1.8 2 150 5.8 3.0 4.35 1.3 3

Slide 61

Slide 61 text

panderaの利用例〜バリデーション(エラー)〜 61 invalid_iris = IrisSchema.validate(invalid_iris) --------------------------------------------------------------------------- SchemaError Traceback (most recent call last) (省略) SchemaError: failed element-wise validator 0: failure cases: index failure_case 0 150 3 indexが150のレコードでエラー SchemaError

Slide 62

Slide 62 text

スキーマの定義に基づくデータのみが存在(バリデーション) 62 panderaによる堅牢性の向上 sepal_length sepal_width petal_length petal_width target 146 6.3 2.5 5.00 1.9 2 147 6.5 3.0 5.20 2.0 2 148 6.2 3.4 5.40 2.3 2 149 5.9 3.0 5.10 1.8 2 150 ◯△□ 3.0 4.35 1.3 3 SchemaError

Slide 63

Slide 63 text

スキーマの定義によるデータの仕様の把握が可能 63 import pandera as pa from pandera.typing import Series class IrisSchema(pa.SchemaModel): sepal_length: Series[float] = pa.Field(gt=0, le=8) sepal_width: Series[float] = pa.Field(gt=0, le=5) petal_length: Series[float] = pa.Field(gt=0, le=7) petal_width: Series[float] = pa.Field(gt=0, le=3) target: Series[int] = pa.Field(isin=[0, 1, 2]) 0/1/2(カテゴリ) 現実的な数値 panderaによる可読性の向上

Slide 64

Slide 64 text

データフレームのスキーマをpanderaで定義〜まとめ〜 ● データフレーム(pandas.DataFrame) ○ 表形式のデータの取り込み、加工、集計、分析に利用(機械学習などで活用) ○ 堅牢性が低い:期待しないデータを格納してしまう ○ 可読性が低い:コードからデータの仕様を読み取れない ● pandera ○ 定義したスキーマに基づきデータフレームをバリデーションするライブラリ ○ 堅牢性の向上:スキーマの定義に基づくデータのみが存在(バリデーション) ○ 可読性の向上:スキーマの定義によるデータの仕様の把握が可能 64 panderaによるデータに関する堅牢性と可読性の向上

Slide 65

Slide 65 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 65

Slide 66

Slide 66 text

pydanticとpanderaを併用 ● 類似した記述方法 ● 組み合わせた利用 66

Slide 67

Slide 67 text

pydanticとpandera(SchemaModel)の類似した記述方法 67 # pydantic # Userのスキーマ from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) # pandera # Userをレコードとするデータフレームのスキーマ import pandera as pa from pandera.typing import Series class UserSchema(pa.SchemaModel): name: Series[str] age: Series[int] = pa.Field(ge=20)

Slide 68

Slide 68 text

pydanticとpandera(SchemaModel)の類似した記述方法(差分) 68 # pydantic # Userのスキーマ from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) # pandera # Userをレコードとするデータフレームのスキーマ import pandera as pa from pandera.typing import Series class UserSchema(pa.SchemaModel): name: Series[str] age: Series[int] = pa.Field(ge=20) pydanticを理解していれば pandera(SchemaModel)の理解は容易 pandera(SchemaModel)を理解していれば pydanticの理解は容易

Slide 69

Slide 69 text

pydanticとpandera(SchemaModel)の類似した記述方法(差分) 69 # pydantic # Userのスキーマ from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) # pandera # Userをレコードとするデータフレームのスキーマ import pandera as pa from pandera.typing import Series class UserSchema(pa.SchemaModel): name: Series[str] age: Series[int] = pa.Field(ge=20) pydanticと併用するpanderaの利用方法は“SchemaModel”

Slide 70

Slide 70 text

pydanticとpanderaを組み合わせた利用 70 import pandera as pa from pandera.engines.pandas_engine import pydanticModel # pandera 0.10.0~ from pandera.typing import Series from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(ge=20) class UserSchema(pa.SchemaModel): class Config: dtype = pydanticModel(User) coerce = True Userスキーマ(pydanticにより定義)に従う レコードの集合となるデータフレームの スキーマ(panderaにより定義)

Slide 71

Slide 71 text

pydanticとpanderaを併用〜まとめ〜 ● 類似した記述方法 ○ 記述方法は対応しており差分は少ない ○ 一方に慣れていれば他方の導入も容易 ○ pydanticと併用するpanderaの利用方法は“SchemaModel” ● 組み合わせた利用 ○ スキーマ(pydanticにより定義)に従うレコードの集合となる データフレームのスキーマ(panderaにより定義)の実現 71 両方を活用できる場合にpydanticとpanderaを併用

Slide 72

Slide 72 text

データに関する堅牢性と可読性を向上させるための3つの提案 ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 72 3つの提案をpydanticとpanderaの導入の意思決定の参考に!

Slide 73

Slide 73 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 73

Slide 74

Slide 74 text

pydanticとpanderaの導入に伴い発生するリスク ● 導入に伴い発生するリスクが存在 ○ 導入した後に発生する不具合 ○ 開発プロセスにおけるコスト ● リスクの把握や検証をした上での意思決定が大事 74 pydanticとpanderaの導入前にリスクの把握や検証が必要

Slide 75

Slide 75 text

pydanticとpanderaの導入前に把握・検証しておくべきリスクの例 ● 学習コスト ○ 開発者の学習コストが確保できるか? ● 処理時間 ○ バリデーションによって増加される処理時間は許容範囲に収まるか? ○ 成果物がもたらす価値にも影響する可能性 ● ライブラリの容量 ○ 実行環境においてインストールするライブラリの容量が確保できるか? 75 pydanticとpanderaがもたらす価値とリスクを比較して意思決定

Slide 76

Slide 76 text

目次 ● 背景:データに関する問題 ● 前提知識:型ヒント ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 ● 付録:pydanticとpanderaの導入前に把握・検証しておくべきリスク ● まとめ 76

Slide 77

Slide 77 text

まとめ ● データに関する問題(解消したい問題) ○ すべてのデータが期待する内容・状態とは限らない ● 解決したい課題 ○ データに関する堅牢性と可読性の向上 ● 提案①:構造で表現されるデータのスキーマをpydanticで定義 ● 提案②:データフレームのスキーマをpanderaで定義 ● 提案③:pydanticとpanderaを併用 77