More Related Content Similar to Machine learning CI/CD with OSS (20) More from yusuke shibui (20) Machine learning CI/CD with OSS2. 自己紹介
shibui yusuke
● 自動運転スタートアップのティアフォー所属
● バックエンドエンジニア &
インフラエンジニア &
データエンジニア &
雑用
● Github: @shibuiwilliam
● Qiita: @cvusk
● FB: yusuke.shibui
● 最近やってること: IstioとGoとARとデータ分析
cat : 0.55
dog: 0.45
human : 0.70
gorilla : 0.30
物体検知
20. 取得したデータが正しい
● Data validation
○ データの形式が正しい
■ データ型が正しい: intになる値にfloatやstrが含まれていない
■ データの範囲が正しい:身長データに 3cmや300cmのようなありえない値が含まれていない
○ データの分布が正しい
■ 単位が正しい:cmで登録している身長データに mやmmによる身長が含まれていない
■ 分布が偏っていない:平均 170cm, 中央値169cmのデータを分割した結果、平均、中央値が乖離して
いない
21. 取得したデータが正しい
import pandas
import pandera
schema = pa.DataFrameSchema({
"gender": pa.Column(str,
checks=pa.Check(lambda x: x in _genders ,
element_wise=True, error=f"gender must be {_genders}"),
),
"height_cm": pa.Column(float,
checks=[
pa.Check(lambda x: 130 <= x <= 210 ,
element_wise=True, error=f"height must be between [130, 210]",
),
pa.Hypothesis.two_sample_ttest(
sample1="male", sample2="female", groupby="gender",
relationship="greater_than", alpha=0.01, equal_var=True,
),
],
),
})
df = pd.DataFrame(data = {"gender": genders, "height_cm": heights})
df = schema(df)
● PythonのPandasとPanderaによるdata
validation。
● カラムごとにdata schemaを定義し、
チェックを挟むことで取得したデータの
正しさを検証する。
● Hypothesis testingを活用することで複数
カラム間の妥当性をテストすることが
可能。
22. 取得したデータが正しい
import pytest
import math
import collections
import numpy as np
# 学習ラベルとテストラベルの偏りをテスト
def test_labels_distribution(y_train, y_test):
tr_counter = collections.Counter(y_train)
te_counter = collections.Counter(y_test)
for (trk, trv), (tek, tev) in zip(tr_counter.items(), te_counter.items()):
assert math.isclose(trv, tev, rel_tol=0.01, abs_tol=0.0)
# 画像データの色の偏りをテスト
def kl_divergence(a: np.ndarray, b: np.ndarray, bins=10, epsilon=0.00001):
a_hist, _ = np.histogram(a, bins=bins)
b_hist, _ = np.histogram(b, bins=bins)
a_hist = (a_hist+epsilon) / np.sum(a_hist)
b_hist = (b_hist+epsilon) / np.sum(b_hist)
return np.sum([ai * np.log(ai / bi) for ai, bi in zip(a_hist, b_hist)])
def test_image_bias(train_image: np.ndarray, test_image: np.ndarray):
assert kl_divergence(train_image, test_image) < 0.1
● 学習時のデータの偏りをテストする
● 学習データとテストデータで傾向が異なる状態
を防ぐ目的
● 研究開発時にはTensorBoardやKnow Your
Dataが便利
https://knowyourdata.withgoogle.com/
● CI/CDや学習の自動化を進める際は、
Data Validation同様にデータの異常を検知
するためのユニットテストを書く
24. # 少量データで学習が動く&進むことをテスト
@pytest.mark.parametrize(
(“model”, "train_path", “test_path” “epochs”),
[(model, “/tmp/small_train/”, “/tmp/small_test/”, 10)],
)
def test_train(
model: nn.Module,
train_path: str,
test_path: str,
epochs: int,
):
trainloader = make_dataloader(train_path)
testloader = make_dataloader(test_path)
init_accuracy = evaluate(model, testloader)
losses = train(model, epochs, trainloader)
assert losses[0] > losses[-1]
trained_accuracy = evaluate(model, testdata)
assert init_accuracy < trained_accuracy
機械学習開発のテスト
def make_dataloader(data_path: str) -> DataLoader:
return dataloader(data_path)
def train(
model: nn.Module,
epochs: int,
trainloader: DataLoader,
) -> List[float]:
losses = []
for epoch in range(epochs):
average_loss = train_once(model, trainloader)
losses.append(average_loss)
model.save()
return losses
def evaluate(
model_path: str,
testloader: DataLoader,
) -> List[float]:
predictor = Model(model_path)
evaluations = predictor.evaluate(testloader)
return evaluations
27. DVCの仕組み
● Data Version Control
● 機械学習で使用するデータをGitと連携してバー
ジョン管理する。
● データはハッシュとともにリモート
ストレージ(S3やGCS等)に保存。
● データの変更を記録してハッシュのみGitで管理
する。
28. DVCの仕組み
# dvcを初期化; git initと同様
$ dvc init
# リモートストレージを追加
$ dvc remote add -d remote_s3 s3://example/path
# データを記録
$ dvc add ./data/train.csv
# dvcデータとコードを記録
$ dvc commit && git add . && git commit
# リモートストレージにデータを追加
$ dvc push
# コードとデータをチェックアウト
$ git checkout ${commit} && dvc checkout
# git pullと同様
$ dvc pull
Git DVC Data Remote
dvc init
dvc remote add
dvc add
git add
git commit
dvc push
git checkout
dvc checkout
dvc pull
dvc commit
29. 学習と評価のバージョンコントロール
# 学習
$ dvc add ./data/train.csv ./params.json
$ python -m src.train -d ./data/train.csv -p ./params.json
saved model to ./model/model.onnx
$ dvc add ./model/model.onnx
# 評価実施
$ dvc add ./data/test.csv
$ python -m src.evaluate -d ./data/test.csv
saved evaluation to ./evaluation/evaluations.json
# 評価レポート作成
$ python -m src.report -d ./evaluate/evaluations.json
Saved report to ./report/report.md
$ dvc add ./evaluation/evaluations.json ./report/report.md
# 評価およびレポートの記録
$ dvc commit && git add . && git commit -m “evaluated”
# push
$ git push && dvc push
Git DVC Data Remote
git add
git commit
dvc commit
dvc add
python evaluate
python report
dvc add
dvc push
git push
dvc add
python train
31. MLFlowによる学習とアーティファクト管理
import mlflow
# 自動ログ
mlflow.sklearn.autolog()
with mlflow.start_run() as run:
x_train, x_test, y_train, y_test = load_dataset()
params = define_params()
model = load_model(params)
model.fit(x_train, y_train)
metrics = model.evaluate(x_test, y_test)
model.save_onnx(“/tmp/model.onnx”)
# ハイパーパラメータ記録
mlflow.log_params(params)
# メトリクス記録
mlflow.log_metrics(metrics)
# アーティファクト管理
mlflow.log_artifact(“/tmp/model.onnx”)
35. DVCとCML
● Data Version Control
● データ分析や機械学習で使ったデータを
バージョン管理する
● Gitみたいに使う
● https://dvc.org/doc
● Continuous Machine Learning
● GitHub ActionとDVCと組み合わせて
データを管理したCI/CDが可能
● Git+CI+CML
● https://github.com/iterative/cml
37. GitHub Actionsでワークフローを書く
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: iterative/setup-cml@v1
- name: ci
env:
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
dvc pull
pytest tests -s -v
docker build test:${commit} .
docker run test:${commit}
python -m src.integrate -m model/model.onnx -o report.md
cat report/report.md >> report.md
cml-publish report/confusion_matrix.png --md >> report.md
cml-send-comment report.md
Remote DVC CML Git
dvc pull
pytest
docker
build
docker run
cml-publish
cml-send-
comment
41. モデルインイメージ
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: iterative/setup-cml@v1
- name: ci
run: |
# 学習済みモデルを取得
dvc pull
# モデルを指定してビルド
docker build
--build-arg MODEL=/models /model.onnx
ml_serving:${commit} .
# Docker Registryにプッシュ
docker push ml_serving:${commit}
# デプロイ
kubectl -n ml_serving apply -f manifests/ml_serving.yaml
Git Remote Docker Reg Server
dvc pull
docker
build
docker push
kubectl apply
42. モデルロード
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: iterative/setup-cml@v1
- name: ci
run: |
# 推論サーバをビルド
docker build ml_serving:${commit} .
# Docker Registryにプッシュ
docker push ml_serving:${commit}
# デプロイ; init_containerでモデルを取得
kubectl -n ml_serving apply -f manifests/ml_serving.yaml
Git Remote Docker Reg Server
docker
build
docker push
kubectl set env
43. 負荷テスト
Load tester LB
Load tester
● 推論器を本番同様のリソースで稼働させて
レイテンシーを測り、ボトルネックを発見、
チューニングする。
● Too bigなモデルでない限り、モデルは変更せずに
実行環境で高速化や可用性強化を図る。
● 推論器のボトルネックは推論モデル。
Webサーバに組み込んで計測する前に、
モデル単体をサーバ内部で連続して
推論させ、推論の平均所要時間を計測する。
● 学習コストの高いディープラーニングモデルを
使う場合、学習前にモデルだけで負荷テストを
実行して遅延を確認しておく。
Profile
入力
前処理
推論
後処理
出力
レイテンシー(
ms)
計測時間
計測時間
リクエスト数/秒
44. 負荷テスト ● 負荷テスト
○ 外部から連続してリクエストを送信。
入力がサイズ不特定の画像やテキストの場合、
ランダムなサイズのデータを用意。
○ CPU使用率が上がらず遅延が発生する場合、
ワーカー数や通信方法を調整する。
NumpyやSklearnであればIntel MKLを使用する
ことも選択肢。
○ メモリリークが発生して根本解決が困難な場合、
Gunicornのmax_requestsパラメータで、一定数の
リクエスト後にワーカープロセスを再起動する
ことで緩和可能。
jitterやgraceful-timeoutと組み合わせる。
○ TensorflowやPytorchであれば前処理含めて
計算グラフに組み込むことで遅延短縮可能。
○ 推論用GPUはコスト対効果次第。
Load tester LB
Load tester
計測時間
リクエスト数/秒
計測時間
リソース
RAM
CPU
48. ● 推論が許容範囲内で正しい
● ソフトウェアのエラー率
● レイテンシーと耐障害性
● リソース利用量と利用料
「推論が正しく動いている」
Client LB LB
時間
RAM
CPU
group
A
CTR
group
B 時間
req/sec
時間
nodes
時間
error rate
レイテンシー(ms)
時間
52. headerで分割するA/Bテスト
新モデル
現モデル
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: iris
namespace: online-ab
spec:
host: iris
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
subsets:
- name: svc
labels:
version: svc
- name: rf
labels:
version: rf
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: iris
namespace: online-ab
spec:
hosts:
- iris
http:
- match:
- headers:
- cookie: test_group
route:
- destination:
host: iris
subset: svc
- route:
- destination:
host: iris
subset: rf
header