使って学ぶAWS

AWSで色々やってみるブログ

SageMaker CanvasとRandomForestとCatBoostで性能を簡易に比較してみた。

はじめに

SageMaker Canvasは、SageMakerのAutoMLのようなもので、構造化データを突っ込んで、モデル作成!って押すとモデルが作成される。 今回はその性能を自分の目で確かめてみようと思う。 ちなみにタイトルに性能比較とかたいそうなことが書いてあるけど、ちょっと試してみただけです。 詳細な条件とか、実験計画とかはなしに、気楽な実験です。

DataSet

Allstate Claims Severityデータセットを利用。 Allstate Claims Severity | Kaggle

保険の請求額を推測するモデルを構築すれば良い。簡単に言えば、回帰問題。 カテゴリ変数が多いのでそれをどう扱うかが見せ所なのかも?

モデル作成

SageMaker Canvas

Training

難しいことはひとつもなくて、S3に置いてあるデータを選んで、モデル作成!って押すだけ。 モデル作成中はこんな画面が出てくる。

学習が終わると、こういう画面が出る。 学習データでのRMSEが1868.745。

Inference

testデータにも推論をかけて、kaggleに投稿をしてみる。 testデータに推論をかけるには、あらかじめtestデータをS3などに置き、Canvas上にimportしておく。 Canvasのpredict画面から、データを選ぶだけで、Batch Inferenceが可能である。 推論が終わると下記のような画面が表示され、結果をダウンロードできる。

Evaluation

結果をkaggleに投稿してみる。

Private Score: 1175.67319
Public Score: 1166.37955

ランキングに照らし合わせてみると、だいたい2000位くらい。 フルオートにしてはまぁそこそこうまくいってるような、それなりなような。

RandomForest

手元で簡単なモデルでも学習。 ごく普通にScikit-learnのRandom Forest Regressorで学習、推論。 kaggleに投稿した結果は下記の通り。

Private Score: 1230.21947
Public Score: 1221.70745

さすがにCanvasよりは悪い。ランキングに照らし合わせると、2300位くらい。 どうだろうか・・なんともいえない?

CatBoost

カテゴリ変数がたくさんあるので、CatBoostが強いのではないかと考えてみる。 あまり深く考えず、ごく普通のコードでCatBoostを学習。Canvasに結構肉薄する。

Private Score: 1183.38271
Public Score: 1175.69527

Kaggleのスクショ

ここまでのまとめ画像。

今回の気づき

とりあえずフルオートで作れるし、簡単に試した中では最も性能がよかったので、Canvas結構いいんじゃないかと。 全くコードを書かずにそれなりに性能が出ている。

ただしリーダーボードの上位ほど出るわけでもないし、CatBoostはCrossValidationすらしていないので、自身でコードを書けるならもっと改善できそう。 逆にCanvasを改善する方法は今のところデータを増やすくらいしかないと思っているので、コードを書けるなら無理して使わなくてもいいかもしれない。

ただ、初期検討でとりあえずこのデータでも性能出そう、とかそういう占いには結構便利かも。 なんたって数クリックでモデルが作れるわけだし。

今回はカテゴリ変数が多い問題だったけど他の問題とかも少し試してみたくなる。 とりあえず今回はここまで。

GStreamerでmac bookのカメラをKinesis Video Streamに流す

全体アーキテクチャ

全体像はこんな感じ。2段構え。

  • MacBookのカメラから、Mac内のDockerコンテナに対してストリームを投げる
  • KVS SDKのコンテナからKVSに対してストリームを投げる

f:id:yohei_ok:20220107153054p:plain MacでKVSのSDKをbuildするのが面倒なのでDockerで済ます。 Cloud9を利用することもできるけど、カメラがないので、ローカルのMacで試すことにした。

手順

とりあえず、試したいAWSアカウントを用意しておく。

Dockerイメージのダウンロード

基本的な手順はここに従う。 ただし、ドキュメントのdocker loginのコマンドは古いので注意。下記のようなコマンドを叩けば良い。

aws ecr get-login-password --region us-west-2 | docker login -u AWS --password-stdin https://546150905175.dkr.ecr.us-west-2.amazonaws.com

sudo docker pull 546150905175.dkr.ecr.us-west-2.amazonaws.com/kinesis-video-producer-sdk-cpp-amazon-linux:latest

注意として、プロファイルのdefault regionをap-northeast-1にしていると、エラーが出るので、--regionオプションを忘れないこと。

コンテナ立ち上げ

普通にImageをRunしてあげれば良い。 IoTCoreを使って認証したい場合は、認証用の鍵などを入れたファイルをコンテナ内に用意する必要があるので、マウントするなり、ファイルをコピーするカスタムコンテナを用意する必要がある。今回は-vオプションで、ボリュームマウントをしておく。(その中にIoTCoreの証明書などを入れておく。)

sudo docker run -it -v <LOCAL_DIR>:<CONTAINER_DIR> --network="host" 546150905175.dkr.ecr.us-west-2.amazonaws.com/kinesis-video-producer-sdk-cpp-amazon-linux /bin/bash

Macローカル側でやること

すでにKVS SDKの動く状態のコンテナが立ち上がっているので、そこにめがけてカメラストリームを流し込む必要がある。

Gstreamerのインストール

Homebrewで一発。

brew install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad

gst-launchの実行

下記のようなコマンドでgstreamerを叩く。 宛先はtcpserversinkで、127.0.0.1向け。

$ gst-launch-1.0 autovideosrc ! videoconvert ! video/x-raw,width=1280,height=720 ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! gdppay ! tcpserversink host=127.0.0.1

パイプラインを一時停止 (PAUSED) にしています...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
パイプラインを再生中 (PLAYING) にしています...
New clock: GstSystemClock
Redistribute latency...
WARNING: from element /GstPipeline:pipeline0/GstTCPServerSink:tcpserversink0: Pipeline construction is invalid, please add queues.
追加のデバッグ情報:
../libs/gst/base/gstbasesink.c(1258): gst_base_sink_query_latency (): /GstPipeline:pipeline0/GstTCPServerSink:tcpserversink0:
Not enough buffering available for  the processing deadline of 0:00:00.020000000, add enough queues to buffer  0:00:00.020000000 additional data. Shortening processing latency to 0:00:00.000000000.
0:00:13.6 / 99:99:99.

Dockerコンテナ内でやること

gst-launchの実行

gst-launch-1.0 -v tcpclientsrc host=host.docker.internal ! gdpdepay ! video/x-h264, format=avc,alignment=au ! h264parse ! kvssink stream-name=<STREAM_NAME> iot-certificate=$KVS_IOT_CERTIFICATE aws-region=$KVS_AWS_DEFAULT_REGION

kvssinkで、streamの名前を指定している。
環境変数としてIoTのCertificateとリージョンを渡している。iot-certificateは、IoTCoreでの認証を行う場合の引数。実際の中身は、下記のようになっている。

export KVS_IOT_CERTIFICATE="iot-certificate,endpoint=<KVS_ENDPOINT>,cert-path=<IoT_CERT>,key-path=<IoT_KEY>,ca-path=<IoT_CA>,role-aliases=<IoT_ROLE_ALIAS>"

以上を実行して、マネジメントコンソールなどでKinesis Video Streamのメディア再生を確認すれば、Macのウェブカメラ画像が流れているはず。

Sagemaker notebook instanceでユーザ環境を作る

いつ使う

SageMakerでnotebook instanceのkernelを選択したときに、python3.6、ちょっと古いなぁ、python3.8とか使いたいなぁと思った人向け。

Notebookでterminalを開く

下記コマンドを利用して、conda createする。
例えばpython3.8で作る場合はこんな感じ。
これはEBSボリュームにPython環境を作っており、EC2の再起動で消えないようにするためである。

conda create --prefix /home/ec2-user/SageMaker/kernels/<USER_ENV> python=3.8 ipykernel
source activate /home/ec2-user/SageMaker/kernels/<USER_ENV>
python -m ipykernel install --user --name <USER_ENV> --display-name <USER_ENV>
conda deactivate

このコマンドを叩いたあとに、JupyterのKernelに自身の環境が追加されたことを確認する。

永続化

Sagemakerのインスタンスの再起動で環境の登録が消えてしまうので、起動時に追加されるようにライフサイクル設定を実行する。
一度インスタンスを停止して、Sagemakerのマネコンから、「ライフサイクル設定」を選択。
スクリプトとして下記を入力する。

#!/bin/bash

sudo -u ec2-user -i <<'EOF'

if [ -d "/home/ec2-user/SageMaker/kernels" ]; then
  for env in /home/ec2-user/SageMaker/kernels/*; do
    source activate $env
    python -m ipykernel install --user --name $(basename "$env") --display-name "$(basename "$env")"
    conda deactivate
done
fi

EOF

ノートブックインスタンスの「設定の更新」から、作成したライフサイクル設定を選択すればOK。
次回起動時に登録されているかを確認しておわり。

conda環境の整え方

jupyterの画面で! conda installとかやるのはめんどくさいので、基本的にはTerminalを起動して上記で紹介したコマンド

source activate /home/ec2-user/SageMaker/kernels/<USER_ENV>
conda install ****

という感じでやるとラク

AthenaとQuickSightを試す

参考記事

この記事を多大に参照して、試してみる。

techblog.nhn-techorus.com

S3へのデータの保管

まずはこちらから鎌倉市の職員給与データをダウンロード。 https://www.city.kamakura.kanagawa.jp/opendata/kyuuyo.html

S3にHive形式のPartitionを区切り、データを格納する 。 f:id:yohei_ok:20210330104231p:plain

DBとTableの作成

Athenaでデータベースとテーブルの作成。

DBの作成

Athenaのクエリで作成。 下記コマンドで一発です。

create database DB_NAME

Tableの作成

DDLを書いて、テーブルを作ります。今回のCSV形式データを見たところ、下記のようなDDLで良さそう。

CREATE EXTERNAL TABLE IF NOT EXISTS emp_salary(
  no int,
  level string,
  salary int,
  huyou int,
  tiiki int,
  jukyo int,
  tsukin int,
  tokusyu int,
  jikangai int,
  kyujitsu int,
  yakan int,
  kanri int,
  syuku int,
  kanri_toku int,
  salary_all int,
  bonus int,
  kinben int,
  salary_year int
)
PARTITIONED BY( `year` int)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ","
STORED AS INPUTFORMAT
  "org.apache.hadoop.mapred.TextInputFormat"
OUTPUTFORMAT
  "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat"
LOCATION 's3://BUCKET_NAME/kamakura'
TBLPROPERTIES (
  "has_encrypted_data"="false",
  "skip.header.line.count" = "1",
  "serialization.encoding"="SJIS"
)

Tableの動作確認

MSCK REPAIR TABLE emp_salary

f:id:yohei_ok:20210401094546p:plain

  • SELECTでデータ確認
SELECT * FROM "sample_db"."emp_salary" limit 10;

f:id:yohei_ok:20210401094610p:plain

QuickSight

QuickSightのアカウントを作成する。

先ほどデータを格納したS3バケットへのアクセスだけ注意しつつ、作成する。

分析の追加

  • 「新しい分析→新しいデータセット」をクリックし、新規データソースとしてAthenaを選択する。 f:id:yohei_ok:20210401095408p:plain

  • データソース名は任意につける。 f:id:yohei_ok:20210401095553p:plain

  • すでに作成したテーブルを選択する。 f:id:yohei_ok:20210401095648p:plain

  • データクエリを直接実行を選択し、Visualizeを実行。 f:id:yohei_ok:20210401100138p:plain

SPICEは高速なインメモリ計算エンジンで、高速なダッシュボードの提供だったり高いパフォーマンスがほしいときに使える。詳細はこちらを参照。

Visualize

bonus vs salary

これは参考サイトの元記事そのままですが、可視化してみる。 月収30万円ほどのところでギャップがある。またボーナスと月収はおおむね正相関がある。 f:id:yohei_ok:20210401100724p:plain

bonus vs level

平均ボーナス額と職位の関係を可視化する。 棒グラフに設定をして、x軸にlevel、y軸にbonusを設定。 f:id:yohei_ok:20210401101930p:plain

このままだと合計額となっており、数の多い職位レベル3が最大となってしまうので、平均に切り替え。 f:id:yohei_ok:20210401102224p:plain

さらにx軸の並び替えをすることで、職位順に見ることが可能。 f:id:yohei_ok:20210401102336p:plain

少し体裁を整えると、見やすくなった。 f:id:yohei_ok:20210401102516p:plain

まとめ

  • S3にある程度構造化されたデータを入れて、Athenaでテーブルを作っておくことで、手軽に可視化をすることが可能。
  • 他のサービスとの連携も試してみたい。

【Tips】Docker permissionエラー

エラー内容

このエラー↓が出たときの対処

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock:

対処方法

ユーザーにdockerの権限がないので、与える必要がある。 そのために、dockerのユーザーグループに自身を追加し、次にdocker.sock に書き込み権限を付与する。 流れは下記の通り。

sudo gpasswd -a $(whoami) docker

sudo chgrp docker /var/run/docker.sock

sudo service docker restart

CodePipelineとPytestで自動テスト

別にPythonじゃなくてCでもC++でもいいんだけど、機械学習屋さんとしてはPythonに慣れ親しんでいるので、その例でトライ。 HelloWorldで書いても良かったけど、せっかくなのでgit pushすると、自動でPytestが動くようなもの。

CodeCommitとPytestとbuildファイルの準備

手元のgit環境の準備

CodeCommitにリポジトリを作成して、自在にgit clone, git pushできる環境を作っておく。 EC2にIAMロールを設定してやるのが一番シンプル。

適切なPythonコードの準備

ディレクトリ構成はこんな感じ。今回はtest_1.pyじゃなくて、test_str.pyという名前にする。
f:id:yohei_ok:20210219130901p:plain

test_str.pyは、すごく簡単なテストを置く。

def test_str():
    assert 'a' == 'a'
    assert 'b' == 'b'

buildspec.yamlファイルの準備

こんなファイルを準備。

version: 0.2
 
phases:
  install:
    runtime-versions:
      python: 3.8
    commands:
      - pip3 install pytest
  build:
    commands:
      - echo test
      - pytest --junit-xml=reports/unittest_results.xml

reports:
  pytest_reports:
    files:
      - unittest_results.xml
    base-directory: reports
    file-format: JUNITXML
  • python3.8を使いますという宣言
  • テストをしたいのでpytestをインストール
  • pytestコマンドの実行 オプションとして、レポートファイルを出力

ちなみにpytestはフォーマットに従っていれば、ディレクトリなどを指定しなくても自動でテストファイルを探してテストしてくれる。 buildspec.yamlは下記のようなディレクトリ構成位置に置く。
f:id:yohei_ok:20210219130728p:plain

CodeBuildの準備

ビルドプロジェクトの作成

マネジメントコンソールから、下記の設定で作っていく。

  • プロジェクト名:任意
  • ソース:CodeCommit
  • リポジトリ:既に作ってあるリポジトリ
  • ビルド対象のブランチ:今回はmaster

f:id:yohei_ok:20210219114526p:plain

環境についてはpython機械学習ならUbuntuを選んでおくと良い気がする。確信はない。
(本来は環境がちゃんと用意されたDockerイメージを用意したほうが良いと思う。それは今度勉強する予定。)
ランタイムはStandardでとりあえず動く。 f:id:yohei_ok:20210219114941p:plain

Buildspecは前項で作ったファイルを使うので、buildspecファイルを使用する。を選択。 これでビルドプロジェクトを作成。

CodePipelineの準備

プロジェクト名を任意で付与して作る。

ソースステージ

ビルドステージ

  • プロバイダー:AWS CodeBuild
  • リージョン:アジア・パシフィック(東京)
  • プロジェクト名:CodeBuildの準備で作成したプロジェクト名 残りはデフォルト。 f:id:yohei_ok:20210219125530p:plain

デプロイステージ

今回は自動テストまでをスコープとするので、導入段階をスキップをクリック。 以上でパイプラインを作成できる。

自動テスト

恐らくパイプラインを作っただけで、1回目のパイプラインが流れる、と思う。 テストはエラーが起きないようなテストなので、成功するはず。

以降、コードをPUSHするたびに自動的にパイプラインが流れ、自動テストが実行される。 実行結果はCodeBuildのビルド履歴やレポート履歴で見ることが可能。

IAMロールを使ってCodeCommitからクローンする

EC2を使って、CodeCommitからリポジトリをクローンしたい場合、 credential情報を使わずに、IAMロールを使うことが可能。

IAMロールの設定

EC2にCodeCommitのポリシーをつける。 とりあえずFullAccessを付与。ReadOnlyなどは適宜設定。 f:id:yohei_ok:20210219094206p:plain

gitの設定

gitのcredentialのhelperとして、awsコマンドを用いるように設定する。

$ git config --global credential.helper '!aws --region ap-northeast-1 codecommit credential-helper $@'
$ git config --global credential.UseHttpPath true

cloneする

SSHでEC2に入った状態で、下記コマンドで普通に取得可能

$ git clone http://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/REPOSITORY NAME

EC2からcloneするなら、アクセスキーなどを使用しないほうが圧倒的にスマート。