フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

Image processing algorithm - Index -

技術開発室の馮 志聖(マイク)です。

I will list some image processing algorithm. And I will introduce detail from next time. It is important for understand how computer know the real world. Computer vision include acquiring, processing, analyzing and understanding digital images.

Edge detection

  • Canny
    f:id:fengchihsheng:20191213145831p:plain
    Canny
  • Sobel
    f:id:fengchihsheng:20191213145906p:plain
    Sobel X
    f:id:fengchihsheng:20191213145926p:plain
    Sobel Y
    f:id:fengchihsheng:20191213145948p:plain
    Sobel
  • Prewitt
    f:id:fengchihsheng:20191213150011p:plain
    Prewitt
  • Laplacian
    f:id:fengchihsheng:20191213150037p:plain
    Laplacian
  • Laplacian of Gaussian
    f:id:fengchihsheng:20191213150057p:plain
    Laplacian of Gaussian

Edge detection (RGB)

f:id:fengchihsheng:20191216101605p:plain
Edge detection (RGB)
f:id:fengchihsheng:20191216101626p:plain
Edge detection (RGB)
f:id:fengchihsheng:20191216101646p:plain
Edge detection (RGB)

Background subtraction

  • Differential
    f:id:fengchihsheng:20191213150431p:plain
    Differential
  • Otsu
    f:id:fengchihsheng:20191213150453p:plain
    Otsu
  • Binary
    f:id:fengchihsheng:20191213150512p:plain
    Binary
  • Adaptive Mean Thresholding
    f:id:fengchihsheng:20191213150532p:plain
    Adaptive Mean Thresholding
  • Adaptive Gaussian Thresholding
    f:id:fengchihsheng:20191213150546p:plain
    Adaptive Gaussian Thresholding

Corner detection

  • Harris operator
    f:id:fengchihsheng:20191213154003p:plain
    Harris operator
  • Shi and Tomasi
    f:id:fengchihsheng:20191213154026p:plain
    Shi and Tomasi
  • Features from accelerated segment test (FAST)
    f:id:fengchihsheng:20191213163337p:plain
    Features from accelerated segment test (FAST)

Blob detection

  • Laplacian of Gaussian (LoG)
    f:id:fengchihsheng:20191213173044p:plain
    Laplacian of Gaussian (LoG)
  • Difference of Gaussians (DoG)
    f:id:fengchihsheng:20191213173106p:plain
    Difference of Gaussians (DoG)
  • Determinant of Hessian (DoH)
    f:id:fengchihsheng:20191213173125p:plain
    Determinant of Hessian (DoH)
  • Maximally stable extremal regions (MSER)
    f:id:fengchihsheng:20191213180130p:plain
    Maximally stable extremal regions (MSER)
  • Optical character recognition (OCR)
    f:id:fengchihsheng:20191213182619p:plain
    Optical character recognition (OCR)

Ridge detection

  • Hessian matrix
    f:id:fengchihsheng:20191216095911p:plain
    Hessian matrix

Hough transform

  • Generalized Hough transform
    f:id:fengchihsheng:20191216113113p:plain
    Generalized Hough transform
  • Hough transform
    f:id:fengchihsheng:20191216115716p:plain
    Hough transform
  • Line Segment Detector (LSD)
    f:id:fengchihsheng:20191216120038p:plain
    Line Segment Detector (LSD)
  • Fast Line Detector (FLD)
    f:id:fengchihsheng:20191216120057p:plain
    Fast Line Detector (FLD)

Structure tensor

  • Gradient Structure tensor (GST)
    f:id:fengchihsheng:20191216145635p:plain
    Gradient Structure tensor (GST)

Feature description

  • Oriented FAST and rotated BRIEF (ORB)
    f:id:fengchihsheng:20191217105404p:plain
    Oriented FAST and rotated BRIEF (ORB)
  • AgastFeatureDetector
    f:id:fengchihsheng:20191217112104p:plain
    AgastFeatureDetector
  • Features from accelerated segment test (FAST)
    f:id:fengchihsheng:20191217112133p:plain
    Features from accelerated segment test (FAST)
  • Maximally stable extremal regions (MSER)
    f:id:fengchihsheng:20191217112200p:plain
    Maximally stable extremal regions (MSER)
  • KAZE Features
    f:id:fengchihsheng:20191217112231p:plain
    KAZE Features
  • Accelerated-Kaze Features (A-Kaze)
    f:id:fengchihsheng:20191217105341p:plain
    Accelerated-Kaze Features (A-Kaze)
  • Binary Robust Invariant Scalable Keypoints (BRISK)
    f:id:fengchihsheng:20191217105322p:plain
    Binary Robust Invariant Scalable Keypoints (BRISK)
  • Scale-invariant feature transform (SIFT)
    f:id:fengchihsheng:20191217105256p:plain
    Scale-invariant feature transform (SIFT)
  • Speeded up robust features (SURF)
    f:id:fengchihsheng:20191217112304p:plain
    Speeded up robust features (SURF)
  • Histogram of oriented gradients (HOG)
    f:id:fengchihsheng:20191216151117p:plain
    Histogram of oriented gradients (HOG)
  • Local Binary Pattern (LBP)
    f:id:fengchihsheng:20191217132849p:plain
    Local Binary Pattern (LBP)
  • Grey Level Co-occurrence Matrices (GLCM)
    f:id:fengchihsheng:20191216150811p:plain
    GLCM black space

Signal processing

  • Fast Fourier transform (FFT)
    f:id:fengchihsheng:20191217140122p:plain
    Fast Fourier transform (FFT) Magnitude Spectrum
    f:id:fengchihsheng:20191217140431p:plain
    High Pass Filtering
  • Discrete Fourier transform (DFT)
    f:id:fengchihsheng:20191217140451p:plain
    Discrete Fourier transform (DFT) Magnitude Spectrum
    f:id:fengchihsheng:20191217140755p:plain
    Low Pass Filtering

Shape detection

  • Morphological Snakes
    f:id:fengchihsheng:20191217132032p:plain
    Morphological Active Contours without Edges (MorphACWE)
    f:id:fengchihsheng:20191217132107p:plain
    Morphological Geodesic Active Contours (MorphGAC)

最後に

I will update more and more algorithm in this page. If I add new blog for detail algorithm, I will also update here too.

Face Recognition on JavaScript

技術開発室の馮 志聖(マイク)です。

前回の投稿。 cloud.flect.co.jp

I will introduce face recognition on javascript. And some algorithm for feature detection. Recently,JavaScript engines and browsers have become more powerful that building full-blown applications in JavaScript is not only feasible, but increasingly popular.

Feature detection

In computer vision and image processing feature detection includes methods for computing abstractions of image information and making local decisions at every image point whether there is an image feature of a given type at that point or not. The resulting features will be subsets of the image domain, often in the form of isolated points, continuous curves or connected regions.

Machine learning

  • Neural Structured Learning (NSL)
    f:id:fengchihsheng:20191216142248p:plain
    Neural Structured Learning (NSL)

https://www.tensorflow.org/neural_structured_learning

Google Tensorflow Blog have some content about "Neural Structured Learning in TensorFlow".

https://medium.com/tensorflow/introducing-neural-structured-learning-in-tensorflow-5a802efd7afd

Visualizing ML training using TensorFlow.js and Baseball data.

observablehq.com

https://medium.com/tensorflow/predicting-balls-and-strikes-using-tensorflow-js-2acf1d7a447c

Face Detection & Recognition

Check this video from Youtube and see how Haar working.

www.youtube.com

face-api.js

Face-api.js is a JavaScript API for face detection and face recognition in the browser implemented on top of the tensorflow.js core API. It implements a series of convolutional neural networks (CNNs), optimized for the web and for mobile devices. face-api.js implements the models SSD Mobilenet V1, Tiny Face Detector, and the experimental MTCNN.

f:id:fengchihsheng:20191217143524j:plain
Face future
https://www.sciencedirect.com/science/article/pii/S1077314215000727

f:id:fengchihsheng:20191217143806p:plain
Facial Landmark
https://www.semanticscholar.org/paper/Facial-Landmark-Tracking-by-Tree-Based-Deformable-Uric%C3%A1r-Franc/eb97fabbe07999fe799f352dedf62acc7a65b6f0

DEMO

  • Detect Feeling
    f:id:fengchihsheng:20191217150424p:plain
    Neutral
    f:id:fengchihsheng:20191217150455p:plain
    Happy
    f:id:fengchihsheng:20191217150518p:plain
    Sad
    f:id:fengchihsheng:20191217150554p:plain
    Surprised
  • Verification
    f:id:fengchihsheng:20191217150627p:plain
    Verified
    f:id:fengchihsheng:20191217150809p:plain
    Unverified
  • Video Human emotions detection


Human emotions detection

Web verification base on face recognition


Web verification base on face recognition

Some idea for using case

f:id:fengchihsheng:20191212163919p:plain
Realtime face verification on Website

最後に

Face recognition can use on many verification case.

Reference

Feature detection
Face Recognition
JS library

AWS Step Function をユニットテストするには

エンジニアの佐藤です。こんにちは。今回は「AWS Step Function のユニットテスト」を構想し、実装までに直面した課題と私が考えた解決方法についてお話ししたいと思います。

AWS Step Functionとは

公式ページに書かれてますが、 Step Functions は様々なサービスをつなげて「サーバーレス・ワークフロー」を編成する仕掛けです。 AWS には古来から様々なワークフロー支援サービスがありますが、その中では最も新しいものです。

ことの始まり

筆者はある日、とある業務システムをどうやって実装したものかと考えていました。AWSでやってくれという話でしたので、AWSの各種サービスを比較検討し、最終的にStep Functionsを選択しました。重視したポイントは以下のようなものです。

  1. 拡張性が高い。
  2. 高可用性設計。
  3. ワークフローの進捗が視覚的に確認できる。
  4. ワークフロー定義が読みやすい。

今回の業務システムには短時間で完了する軽いタスクと、リソースも時間も必要な重いタスクの2種類があり、筆者は前者をLambda Functionに、後者をECS(Fargate)で実行することにしました。

Step Functionのユニットテスト・・・って?

ところで昨今のシステム開発は、テストコードを記述してユニットテストを行うのが一般的です。筆者はこのStep Functionsで作成されるワークフロー設定(ステートマシン)についてのユニットテストを構想しました。ところが、考えていくうちに、これが結構深いタスクであることに、徐々に気がついてきました。一般的な話ですが、システムを人間の体に例えると、手足に相当する機能のユニットテストについては、準備作業はそれほど難しくありません。一方で中枢的な機能のテストのための準備作業は大きくなりがちです。動作が確実な仮の末端部品を接続してあげる必要があるからです。「ワークフロー管理」機能は、この観点から言うとシステムの最も中枢的な部分であり、その単体テストのためには仮の末端部品の接続が必要ということになります。今回で言えば、Lambda FunctionとECSに仮のモジュールを入れてあげる必要がある。

Lambda FunctionとECSの仮のモジュール、と構想したところで、筆者は更に寒気を覚えました。よく考えてみるとこの2つ、機能コードを配置するまでの作業がそれなりに手間なのです。例えばLambda Functionの場合、以下のようなステップがあります。

  1. ライブラリを含めた機能コードのアーカイブ
  2. アーカイブのS3への配置
  3. IAMの設定
  4. Lambda Functionの設定

ECSの場合はこうなります。

  1. 機能コードを含むDockerコンテナのビルド
  2. ECRへコンテナを配置
  3. IAMの設定
  4. タスク定義の作成

この「Lambda Functionの設定」と「タスク定義の作成」には、環境変数などの設定も含まれます。テスト用の仮のモジュールなどと言いながら、一式全部必要なわけです。ステートマシンのテストをするために「システムの設計方針に従って各種の設定を発行・注入する仕掛け」の開発が必要になる・・・そう気がついた筆者は、とんでもないことを始めてしまったのではないかと、暗い気持ちになりました。中でも筆者が負担に感じたのがIAMです。Lambda FunctionもECSも機能コードの実行環境であり、実行の際に「インフラ的にできること(実行権限)」の範囲をIAMロールとして定義する必要があります。しかしこれがまた、慎重さと地道な努力を要する作業なのです。「とりあえずAdmin!」とやっつけたい気持ちはやまやまですが、これは悪魔の囁き。権限設定はミニマムからスタートしないと、権限のダイエットはとても大変なのです。

なお、Lambda FunctionとStep Functionsについては、AWSがローカルランタイムを配布していますが、今回は利用を見送りました。ローカル版のFargateはありませんし、ローカル環境固有の設定負担や互換性問題もあるでしょう。それなら最初から本物を使ったほうがいい、ユニットテスト用のAWSアカウントを短時間使うだけならそんなに経費もかからない、と判断しました。

各種設定の発行・注入する仕掛け・・・って?

で、その仕掛けをどうしたのかというと、この点は大変悩んだところでした。

筆者が最初に検討したのはAWS Cloud Formationでした。しかし調べていくと、これはこれで良くないところがあると思いました。まず引っかかったのが、テンプレートの入出力がいずれもリストとなっており、階層的にできない点です。また、最終的にJSONYAML形式のテンプレートにする必要があり、いくつか見て回った範囲ではこのテンプレートの調整負担が大きく見え、Colud Formationは見送りました。

次に検討したのがCDKでした。re:Invent18で発表されたもので、基本的にNodeJSやPythonなどのプログラム言語でCloud Formationのテンプレートを効率的に作成する仕掛けです。しかしこちらはStep Functionsの実装がまだプレビュー状態で、またステートマシンの定義方法が独特で良くないと思いました。また、ランダムな付加文字列の入ったリソース名となる点も、やり込むと散らかって良くないだろうなと思えました。

筆者が最終的に選択したのは、以下のような方式でした。

  1. まずプロジェクト名に連なる一連の名前体系を決め、これを環境変数で設定する。
  2. Python言語でdeploy.pyとundeploy.pyを記述し、ここからboto3 SDKを用いて直接リソースの作成と削除を行う。リソース定義は、これらのソースコードに記述する。
  3. ユニットテストはdeploy.py実行 -> テスト -> undeploy.py実行のフローで行う。

幸いなことに今回のシステムの開発言語はPythonでした。そしてAWSリソースの定義は、たいていJSONで書かれており、Python言語のdictionaryとほとんど同義(しかもコメントも挿入できる)。そして複数のリソース定義を体系的に作っていくにはプログラムフローが効率的で、デプロイ自体もその延長でSDKを呼び出してやってしまえば、小さくまとまらないかと目論んだわけです。

最初に「プロジェクト名に連なる一連の名前体系を決める」ですが、今回構想した「Step FunctionsステートマシンがLambda FunctionとECSコンテナを実行する」実装の場合、以下のようになりました。

export AWS_ACCOUNT_ID=`aws sts get-caller-identity --output json | jq -r -j ".Account"`
export AWS_DEFAULT_REGION=`aws configure get default.region | tr -d \\n`
export PROJECT_NAME=project01

export LAMBDA_FUNCTION_NAME="${PROJECT_NAME}_lambda"
export LAMBDA_FUNCTION_ARCHIVE_NAME="${FUNCTION_NAME}.zip"
export S3_LAMBDA_ARCHIVE_PATH="${PROJECT_NAME}/${FUNCTION_ARCHIVE_NAME}"
export BUCKET_NAME=s3_bucket_name12345s
export LAMBDA_POLICY_NAME="${PROJECT_NAME}LambdaPolicy"
export LAMBDA_ROLE_NAME="${PROJECT_NAME}LambdaRole"
export LAMBDA_FUNCTION_ARN="arn:aws:lambda:${AWS_DEFAULT_REGION}:${AWS_ACCOUNT_ID}:function:${LAMBDA_FUNCTION_NAME}:prd"

export ECR_REPOSITORY_NAME=$PROJECT_NAME
export ECS_CLUSTER_NAME=$PROJECT_NAME
export ECS_CONTAINER_TAG="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}:latest"
export ECS_TASK_ROLE_NAME="${PROJECT_NAME}TaskRole"
export ECS_TASK_POLICY_NAME="${PROJECT_NAME}TaskPolicy"
export ECS_TASK_EXECUTION_ROLE_NAME="${PROJECT_NAME}TaskExecutionRole"
export ECS_TASK_EXECUTION_POLICY_NAME="${PROJECT_NAME}TaskExecutionPolicy"
export ECS_TASK_DEFINITION_NAME="${PROJECT_NAME}Task"
export ECS_SUBNETS="subnet-12345678"

export SFN_NAME=$PROJECT_NAME
export SFN_ROLE_NAME="${PROJECT_NAME}SfnRole"
export SFN_POLICY_NAME="${PROJECT_NAME}SfnPolicy"

もういきなりお腹いっぱいな感じがありますが、ここに列挙したどれ一つ不要なものはありません。機能コードをサーバーレスに埋めていくとは、こういう手間を伴うものなのです。

デプロイコードとユニットテスト

そしてここからLambda Function、ECSコンテナ、そしてStep Functionsステートマシンをデプロイするコードを書いていくわけですが、ステートマシンをデプロイする部分をご紹介すると、以下のようになりました。

def deploy():
    print('deploying...')

    # (中略)

    containerDef = {
        'CLUSTER_ARN': f"arn:aws:ecs:{AWS_DEFAULT_REGION}:{AWS_ACCOUNT_ID}:cluster/{ECS_CLUSTER_NAME}",
        'TASK_DEFINITION_NAME': ECS_TASK_DEFINITION_NAME,
        'CONTAINER_TAG': ECS_CONTAINER_TAG,
        'ENVIRONMENTS': [
            {
                "Name":"TASK_TOKEN",
                "Value.$":"$$.Task.Token"
                },
            {
                "Name":"DATA",
                "Value.$":'$'
            }
        ]
    } # end of containerDef

    sm = get_steps(
        lambdaFunctionArn=LAMBDA_FUNCTION_ARN,
        containerDefinition=containerDef
    )

    sfnClient = boto3.client('stepfunctions')
    print('creating state machine...')
    # print(json.dumps(sm, indent=4))
    res = sfnClient.create_state_machine(
        name=SFN_NAME,
        definition=json.dumps(sm, indent=4),
        roleArn=f'arn:aws:iam::{AWS_ACCOUNT_ID}:role/{SFN_ROLE_NAME}',
        tags=[TAG_sl]
    )
# end of deploy

Step Functionsのステートマシン自体は、JSON文書として記述されます。ここへステートマシンから実行するLambda FunctionやECSのタスク情報を含めていくわけですが、これをステートマシン定義取得関数get_stepsの引数で指定するようにしておきました。 こうすれば、ユニットテストからこのデプロイコードが呼び出されたときに、本番とは違う仮のLambda FunctionやECSタスク情報を設定することができるだろうとの目論見です。

get_steps自体は以下のような実装になりました。

def get_steps(
    lambdaFunctionArn=None,
    containerDefinition=None
):
    SFN_NAME = os.environ['SFN_NAME']

    sm = {
        "Comment": SFN_NAME,
        "StartAt": "STEP1",
        "TimeoutSeconds": 300,
        "States": {
            "STEP1": {
                "Type": "Task",
                "Resource": lambdaFunctionArn,
                "TimeoutSeconds": 10,
                "InputPath": "$.input",
                "ResultPath": "$.res1",
                "OutputPath": "$",
                "Next": "STEP2",
                "Catch": [ {
                    "ErrorEquals": [ "States.ALL" ],
                    "Next": "FAILED"
                }]
            }, # end of STEP1
            "STEP2": {
                "Type": "Task",
                "Resource": "arn:aws:states:::ecs:runTask.waitForTaskToken",
                "TimeoutSeconds": 300,
                "Parameters": __create_ecs_parameters(containerDefinition),
                "InputPath": "$.res1",
                "ResultPath": "$.res2",
                "OutputPath": "$",
                "Next": "SUCCEEDED",
                "Catch": [ {
                    "ErrorEquals": [ "States.ALL" ],
                    "Next": "FAILED"
                }]
            }, # end of STEP2
            "SUCCEEDED": {
                "Type": "Succeed"
            },
            "FAILED": {
                "Type": "Fail"
            }
        } # end of States
    } # end of sm

    return sm
# end of get_steps

これはステートマシンのユニットテストの方法論の開発のためのテストのために仮組みしたものですが、これが下の図のようなステートマシンになります。

f:id:masashi-sato-flect:20191209141151p:plain
ステートマシン

予想外に苦労したのが __create_ecs_parameters の部分です。ステートマシンからECSを呼び出すにはタスク定義のARNを指定する必要がありますが、このタスク定義は更新の度に「project01Task:77」のように末尾の序数が加算されていき、この数字を指定する手段はありません。つまり目的のコンテナが指定されているタスク定義を(たいていは最新のタスク定義でしょうが)掘り出すしかないようなのです。これを掘り出してステートマシンのコンテナ定義を作成するのが、下記のような内容の __create_ecs_parameters 関数になります。

def __create_ecs_parameters(container_definitions):

    ECS_SUBNETS          = os.environ['ECS_SUBNETS'].split(',')
    TASK_DEFINITION_NAME = container_definitions['TASK_DEFINITION_NAME']
    CONTAINER_TAG        = container_definitions['CONTAINER_TAG']
    
    ecsClient = boto3.client('ecs')

    lTd = []
    nextToken = None
    while True:
        params = {
            'familyPrefix': TASK_DEFINITION_NAME,
            'status':       'ACTIVE',
            'sort':         'DESC'
        }
        if nextToken != None:
            params['nextToken'] = nextToken
        res = ecsClient.list_task_definitions(**params)

        if 'nextToken' in res:
            nextToken = res['nextToken']
        lTd.extend(res['taskDefinitionArns'])
        if nextToken is None:
            break
    # end of while (true)

    tdArn = ''
    for td in lTd:
        tdDesc = ecsClient.describe_task_definition(
            taskDefinition=td
        )
        image = tdDesc['taskDefinition']['containerDefinitions'][0]['image']
        # print(image)
        if image == CONTAINER_TAG:
            tdArn = td
            break
    # end of for (td)
    if tdArn == '':
        raise Exception(f'no task definition {TASK_DEFINITION_NAME} found for container {CONTAINER_TAG}')

    ret = {
        'LaunchType': 'FARGATE',
        'Cluster': container_definitions['CLUSTER_ARN'],
        'TaskDefinition': tdArn,
        'Overrides': {
            'ContainerOverrides': [{
                'Name': TASK_DEFINITION_NAME,
                'Environment': container_definitions['ENVIRONMENTS']
            }] # end of ContainerOverrides
        }, # end of Overrides
        'NetworkConfiguration': {
            'AwsvpcConfiguration': {
                'Subnets': ECS_SUBNETS,
                'AssignPublicIp': 'ENABLED'
            }
        } # end of NetrowkConfiguration
    }
    return ret
# end of __create_ecs_parameters

このような工夫を経て、ようやく当初の目的の「ステートマシンのユニットテスト」に到達しました。テストコード全体は以下のようになりました。

class TestSfn(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        deploy(test=True)
    # end of setUpClass

    @classmethod
    def tearDownClass(cls):
        undeploy()
    # end of tearDownClass   
    
    def test_sfn(self):
        
        AWS_ACCOUNT_ID     = os.environ['AWS_ACCOUNT_ID']
        AWS_DEFAULT_REGION = os.environ['AWS_DEFAULT_REGION']
        SFN_NAME           = os.environ['SFN_NAME']
        
        sfnClient = boto3.client('stepfunctions')
        
        execName = SFN_NAME + '_' + str(datetime.now().timestamp())
        input = {
            'input': {"Number1":10,"Number2":5}
        }
        
        res = sfnClient.start_execution(
            stateMachineArn=f'arn:aws:states:{AWS_DEFAULT_REGION}:{AWS_ACCOUNT_ID}:stateMachine:{SFN_NAME}',
            name=execName,
            input=json.dumps(input)
        )
        execArn = res['executionArn']
        res = {}
        while True:
            res = sfnClient.describe_execution(
                executionArn=execArn
            )
            status = res['status']
            if status != 'RUNNING':
                print(res)
                break
            time.sleep(5)
        # end of while True
        output = json.loads(res['output'])
        self.assertEqual(output['res2']['Difference'], 5)
    # end of test_sfn
# end of class TestClass01

このテストコードを実行することで、当初の目論見であったステートマシンのユニットテストが実行できるようになりました。テスト用のLambda Functionやコンテナと組み合わせれば、複雑な状態管理の作り込みと繰り返しの動作確認が可能になったと思います。

ふり返って、どうか

正直なところ、なかなか複雑な気持ちです。ステート管理・高可用性・柔軟かつ効率的なリソースアロケーションを目標として計画した目論見でしたが、結局CI/CDみたいなことをやることになってしまいました。Step Functionを本格的に業務活用しようとすると、自動デプロイの仕掛けを何かしら用意する必要があると感じました。設計目標はクリアできそうですが、けっこう大変でした。

特に設定が煩雑になったのはECSを呼び出す部分です。この点については以下のような支援機能がStep Functionに用意されていると、より開発作業が効率的になるのではないかと思いました。

  • ステートマシンとECSの入出力の高機能化。ステートマシンの入力値をJSONのまま受け渡しできるAPIの追加など。(現状では環境変数文字列にする必要がある。)
  • 個別のステートマシンからはECRのコンテナのみを指定して実行できるように簡略化。ステートマシン全体に既定のコンテナクラスタやタスク定義を設定する機能など。

最後までお読みいただきありがとうございました。

フレクトが行くAWS re:Invent 2019 (12/5)

CI事業部ウエダです。こんばんは

本日はFLECTとして参加するのは最終日となります。

先ほどre:Playが終わり、ホテルに戻ってきたの余韻に浸りながらre:Playの速報をお送りしたいと思います

会場

f:id:flect-ueda:20191206171311j:plain 各レセプション会場でもすごい人数ですが、一堂に集まるのでとにかく広いです。 セキュリティのためか持ち込むものも厳格に決められています。 とはいえ、飲食物は用意していただけるので特に必要なものはありません。

食事

会場につくとまず食事 f:id:flect-ueda:20191206171257j:plain 様々な料理が屋台として出店されています。

1つ1つの食事の量は少なめなので食べ比べる楽しみがあります。

また食事とは別に、飲み物を提供する場所が点在しており、好きなものを注文できます。 f:id:flect-ueda:20191206172622j:plain

テント

大きなテントがいくつか用意されておりそれぞれ、ライブやハウスミュージックが大音量でかかっています。 f:id:flect-ueda:20191206172825j:plain ライブは近くで聞くと重低音が響き、迫力があります。

f:id:flect-ueda:20191206173726j:plain 別のテントではいい感じのリズムで周りを盛り上げます。

ゲーム

大型のゲームと80〜90年代のレトロゲームが設置してあります。 f:id:flect-ueda:20191206172855j:plain 私は試しにボタン早押しゲームに参加しました。

接戦の結果勝利することができましたが、対戦相手とは互いの検討を祝してレトロゲームをやったりと楽しめました。

こういった意図しない出会いの場が生まれるものre:inventのいいところだと思います。

ドローン

最後はドローンです。夜空に様々な形を繰り出す姿は圧巻です。

最後にIntelのロゴを表示するのはご愛嬌でしたが、、、 f:id:flect-ueda:20191206173222j:plain

大変エキサイティングな体験ができた1週間でした。

名残惜しいですがこれから帰国です。

この体験を業務で生かして行こうと思います。

フレクトが行くAWS re:Invent 2019 (12/4)

みなさんこんにちは。技術開発室の岡田です。

現在ラスベガスで絶賛開催中のAWS re:invent2019に参加しています。 昨日のキーノートでは怒涛の新サービス発表がありましたね。 特に私の担当している機械学習関連では、SageMakerの新サービスが多く発表され、スーパーエキサイティングな1日になりました。 興奮醒めやらぬ状況ではありますが、この発表をうけて新たに追加されたセッションも含め、本日までに参加できた機械学習関連のセッションについて、ご報告したいと思います。 (ちょっと専門用語が多めになります。)

ちなみに、今日も朝ごはんと昼ご飯は提供されました。😊

キーノート振り返り

f:id:Wok:20191205053101j:plain

昨日のキーノートでは、レイヤごとに次の新サービス・機能が発表されました。

  • Framework

    • TensorFlow: 20%高速化(MASK R-CNN)
    • PyTorch: 22%高速化(同上)
    • mxnet: 22%高速化(同上)
  • SageMaker

    • SageMaker Studio IDE: 以下のものを含むMLのための統合開発環境
    • SageMaker Notebooks: 起動の高速化や、コンテナ管理と連動できるように拡張したNotebook
    • SageMaker Experiments: 実験ごとのパラメータや設定を管理
    • SageMaker Debugger: トレーニング中に発生した問題をリアルタイムに特定
    • SageMaker Autopilot: トレーニングに最適なパラメータを探索
    • SageMaker Monitor: 運用中のモデルの精度をモニタリング
  • Service

    • Amazon Kendra:検索
    • Amazon Fraud Detector: 不正検知
    • Amazon Cloud Guru: コードレビュー
    • Contact Lens:コールセンタ向け

これらに関連して追加されたセッションのうち、本日までに次のものに参加することができました。

  • Optimizing Your Machine Learning Models on Amazon SageMaker
  • The new Amazon SageMaker Model Monitor: Address concept drift & model quality
  • Intro to Amazon SageMaker Debugger: Get insights into ML model training
  • Introducing Amazon SageMaker Studio, the first full IDE for ML

また、関連して次のものもセッションに参加しました。

  • Leadership session: Machine learning

Optimizing Your Machine Learning Models on Amazon SageMaker

機械学習モデルをトレーニングするときのパラメータをSageMaker Autopilotを用いて自動でチューニングして、よりよいモデルを作成するワークショップです。

パラメータチューニングの方法にはグリッドサーチやランダムサーチを使うことが多いですが、SageMaker Autopilotはガウス過程回帰とベイズ最適化を用いてパラメータを探索します。また、ここでチューニングできるパラメータは一般的なハイパーパラメータに加え、機械学習アルゴリズム自体も自動で選択してくれます。さらに、Feature Engineeringも実施してくれるようです(!?)。探索の結果いくつかの候補を出してくれるので、(一般的には)もっともよいメトリックのモデルを選択する、ということになります。

ただ、やはり会場ではパラメータチューニングに伴って発生する料金についての質問が出ていました。パラメータチューニングするためには何度もトレーニングを実施する必要があり、大量の計算リソースを必要としますので、当然の懸念だと思います。そして回答も至極当然の回答で、探索(トレーニング)にかかった時間だけそのインスタンスの料金を払うことになるよ、とのことでした。大きなモデルに使うと結構な料金がかかってしまうのではないかという不安はありますね。ただ、グリッドサーチよりも少ないイテレーションでより良いパラメータを見つけてくれる期待はあるので、グリッドサーチをやる前提であるのであれば、代わりにこちらを使った方が安上がりになる可能性もあります。また、あまり機械学習に詳しくない人にとっては、ほぼ全自動でモデルの性能を向上させることができるという点は見逃せません。このため結構使われるのではないかと思います。とても期待のできる機能だと思いました。

このワークショップで用いたノートブックは下記のgithub上にあります。 実行する際には使用したリソースの料金が発生しますのでご留意ください。

なお、このノートブックのLab2を実行すると、Autopilotで作成したパラメータの候補の一覧を中間生成物のノートブックで見ることができます。残念ながらワークショップで利用した環境のものはすでに消されてしまったようで詳細確認できなくなってしまいましたが、記憶だとFeature Importanceなど使ってしっかりFEしてたような気がします。いや、すごい。

The new Amazon SageMaker Model Monitor: Address concept drift & model quality

SageMaker Model Monitorのセッションです。

concept driftは、ざっくり説明すると、モデル作成中に想定した世界が時間の流れとともに変化し、モデルが現実世界に対応できなくなることです。一般的には、上記のAutopilotのようなことを行い、モデル作成の際に与えられたデータを用いて、そこで(汎化性能も含た)最高の性能を出せるようにチューニングします。しかし、時間とともに取得できるデータのばらつきが変わるため、徐々に性能が劣化していきます。例えば、温暖化の影響を受けて天候が変わるとか。最近の日本の気候もだいぶ変わったように思いますよね。このため、モデルは作成時点が最も精度が高く、徐々に劣化していくといわれたりします。

Model Monitorはこの劣化度合いをモニタリングして、一定の条件に至るとアラートを上げる機能とのことです。ただ、今回の説明を聞く限り、この劣化を検知するための条件は、(Model Monitorがリコメンドしてくれるようですが、最終的には)モデル開発者が決める必要があるようです。下図のBaseline statistics and constraintsのところですね。このため、ちょっと機械学習の知識がないと敷居が高いのではないかという印象でした。Autopilotで自動でモデルチューニングした後にこの条件を作成し、その良しあしを判断ができるのかが気になるところです。 f:id:Wok:20191205184705j:plain

とはいえ、concept driftの話はFLECTが扱っている案件でも話題になりますので期待したい機能です。

Intro to Amazon SageMaker Debugger: Get insights into ML model training

SageMaker Debuggerのセッションです。

大規模なモデルを作成した経験をお持ちの方であればお分かりになると思いますが、モデルのトレーニングにはかなりの時間がかかります。なので、トレーニングを開始したら数日放置しておくということもあると思います。そして数日後にトレーニングが完了したモデルを確認すると期待したほどの精度向上がなく落ち込むと。このような悲劇を回避するためにTensorflowであれば、TensorBoardを用いたりCallbackをうまく使って通知を上げたりするのが一般的かと思います。ただ、これを行うためにはモデル開発のコードを修正する必要があり、かなり神経を使います。Sage Maker Debuggerはコード変更することなくトレーニング時の異常をリアルタイムに検知、報告してくれる機能とのことです。

f:id:Wok:20191205192023j:plainレーニング中に作成されるデータ(おそらくチェックポイント)をS3に保管しし、逐一それを解析する処理を起動するという感じでしょうか。 確かに、デバッグコードをモデル開発のコードに直接書くと見通しが悪くなったりしがちなので、そういう意味で地味にありがたい機能だと思います。

Introducing Amazon SageMaker Studio, the first full IDE for ML

SageMaker Studioのセッションです。

SageMaker Studioは、今回発表のあった各種機能を取り込んだ機械学習モデルの統合開発環境となります。

図のような繰り返し開発を行うときに活躍します。 f:id:Wok:20191205185115j:plain 左の箱のBuildフェーズはNoteBooksを使ってAutopilotでチューニング、Debuggerでデバッグしながら中央の箱と行ったり来たりのイテレーションを行う。このイテレーションはExperimentsで管理され、最終的にはソリューションとして最適なモデルをデプロイできる。デプロイした後はMonitorでコンセプトドリフトを監視して問題があれば再度モデルを作り直す。という流れになるかと思います。

こう考えると、さすが機械学習開発プロセスを熟知しているAWSの統合環境だなと思いました。 おそらくここまで機械学習のモデル開発の流れに合わせて機能を組み込んだ開発環境は見たことがないので、今回のSageMaker Studioの発表で開発プロセスが一段レベルアップした感じです。 今後、Google, MSといった他社の出方が気になります。

Leadership session: Machine learning

本セッションはキーノートの直後に実施されたものです。基本はキーノートの発表に沿ったものが説明されましたが、キーノートでは語られなかっ た情報もありました。

一つ目がDeep Java Library(DJL)です。

Java開発者にend-endの機械学習開発APIを提供するようです。 従来AWSのForecasting teamでは、データサイエンティストチームがPythonを用いて作成したモデルを、Javaで開発しているML Infraチームが数週間かけてリファクタリングして使っていたのだそうです。多くのエンタプライズサービスはJavaで書かれているのだから、このコストはいろんな開発現場で発生しているはず。そこでDJLを使って初めからJavaで作成しておくことで、このコストを削減するということのようだ。 実際に、AWSのForecasting TeamはDJLを使うことで開発期間を30%削減できるようになったそうです。 f:id:Wok:20191205201741j:plain

確かにPython,特にJupyterNotebookで作成するコードはそのまま使えないことは、私もよく経験することなので、なるほどなとは思いました。

二つ目はSQL for MLです。 下図の例では、Amazon Aurora Amazon SageMaker, Amazon Comprehendと連携して、リアルタイムで推論結果を返します。 f:id:Wok:20191205193559j:plain まぁ、そういう流れになるだろうなという範疇ではあります。個人的にはSQLがあまり得意ではないので、DBという形すら取らずに、すべて自然言語でDBからAIからすべてのデータソースをクエリできるようにしてほしい。

さいごに

以上が私が参加した機械学習のセッションのご報告となります。 FLECTは明日が最後の参加日となります。そして、明日はキーノートがあります。また何か大きな発表があったら、さすがに体力が持たないかも。 どこかの会社様は数十人体制で来てるとのこと。大当たりでしたねー。今回のような大幅アップデートを4人で捌くのは正直きつい。 来年は偉い人にお願いして増員してもらうかな。そして私は来年も来たいなー。 ということで最終日。頑張って楽しんできます!では、おやすみなさい。(こちらは午前3時。)

フレクトが行くAWS re:Invent 2019 (12/3)

みなさん初めまして、CI事業部のウエダです。 今回が初のre:invent参加となります。

業務ではAWSは絶賛利用中で、日々AWSの新しい機能を学びそれを業務に反映し良いサイクルを回すことを心がけております。

海外のイベントともあり戸惑うことはありますがre:invent中は刺激的な毎日を過ごしております。

初めての朝食

f:id:flect-ueda:20191204160641j:plain

美味しそうな料理で迷いますが、連日の食事のボリュームで胃がもたれ気味だったのでコーヒーとマフィンだけの軽い食事で済ませました。

怒涛の新サービスラッシュ

1日目の発表に物足りなさを感じていた身としては嬉しい悲鳴です。

現地から社内へSlackで現地の状況を共有しているのですが、最初から最後まで休まるところがなかったです。

個人的には業務に直接関係のある、インスタンスタイプの追加、Amazon EKS on AWS Fargate、Amazon S3 Access Points、Amazon CodeGuru辺りが気になりました。 f:id:flect-ueda:20191204152455j:plain

早く情報を収集して使いこなせるようにならないと思いきや、幸いなことに、新サービス用のセッションが追加されました。 スケジュールの組み直しで大忙しです。

SageMaker、RedShiftのサービスが劇的に増えたので、そろそろ本腰を入れて機械学習とBigDataに力を入れないと、、、 f:id:flect-ueda:20191204162051j:plain こうして見ると改めて今回のSageMakerのサービスの充実具合が分かりますね

説明がひと段落したタイミングでバンド生演奏でこれまでの説明内容に沿った曲が流れ最後に歌詞が表示される演出はよかったですね。 f:id:flect-ueda:20191204152500j:plain 発表の内容によっては演出過剰でシラけてしまうリスクがありますが、今回発表のあったサービスはどれも期待以上のものなので、会場の盛り上がりがすごかったです。

帰国したら、既存のシステム構成をまた見直さないと、、、

ワークショップに参加

セッションだとどうしても受け身になりがちなので、せっかくチャンスなのでジャンルは問わず様々なレベルのワークショップに参加しています。

やはりワークショップだと実際に手を動かすので記憶に残りやすいですね。

気になる費用や、面倒臭いVPCなどの下準備は専用のアカウントを発行してくれるのですぐに課題に取りかかることができ有意義な時間を過ごせました。

最高レベルの400番台のものも参加し、時間が厳しいのでタイムアウトとなってしまいましたが、何をやっているかは理解できていたので日々の実務の成果が確認でき感慨深かったです。

とはいえ言語の壁が難しいですね。今の私のレベルでは聞きとるところまでで精一杯です。

こちらの意図を言葉で表せないないのがもどかしいです。精進しなけば、、、

AWS DeepComposerの実機をGET

Midnight Madnessで発表のあったDeepComposerです。 サービス発表時に現場の盛り上がりを目の当たりにしただけに、なんとかワークショップに参加して無事実機を手に入れることができました。 f:id:flect-ueda:20191204162515j:plain 自分の拙いピアノ演奏した曲を簡単な操作でJazz調、Rock調のちゃんとした曲になるのは興味深かったです。

ワークショップの後、別会場で実機を受け取るのですが、みんな気になるのか、その箱の中は何かと複数の人から聞かれました。

SalesforceブースでAWSのTrailheadを実施

f:id:flect-ueda:20191204160406j:plain スタンプラリーで2つ以上集めるともれなくグッズをもらえるということでやってみました。

先日のdreamforceで発表のあったAWSのトレイルと実施してコーディのぬいぐるみをGETしました。

まだこれからどんな発表があるか分かりませんが、残る期間も楽しんで挑戦したいと思います。

Heroku のアドオン「Sqreen」で簡単にWAF!

こんにちは。エンジニアのヤス・コバヤシです。

Heroku Advent Calendar 2019 5日目を担当させていただきます!

qiita.com

Webアプリケーションを開発するにあたって気をつけなければいけないのはセキュリティ対策ですよね。

OWASPトップ10とかブルートフォース攻撃(総当たり攻撃)とかアカウント乗っ取りとか、脆弱性を悪用した攻撃にどう対処していくかは悩みどころです。

いくらWEB APIREST APIの仕様に沿ってガチガチにガードしたと言っても、それはその攻撃自体をWebアプリケーションの中で受け止めてチェックすることになるので、フレームワークやライブラリに脆弱性があったらひとたまりもありません。

ですのでWebアプリケーションに届く前にガードする必要があるわけですね。

それが皆さんご存知のWAF(ウェブアプリケーションファイアウォール)になります。

ところでこのWAFですが、AWS には AWS WAF 、Azure には Azure Web アプリケーション ファイアウォールと言うものがありますが。。。

HerokuにはWAFがあるの?

あります!

それが「Sqreen」です。 elements.heroku.com

と言う事で今回は Heroku のAddOn「Sqreen」のご紹介をしたいと思います。

「Sqreen」ってどんな感じ?

構築する前に「これはどんなアドオンなの?どんな機能があるの?」と気になる事かと思います。

画面をお見せしながらご紹介しますね。

f:id:yasuyuki-kobayashi-flect:20191203165038p:plain
Monitoring画面

「Sqreen」はリアルタイムで攻撃をブロックし、セキュリティ状況を可視化してくれます。 これがメイン画面とも言えるMonitoring画面です。

f:id:yasuyuki-kobayashi-flect:20191203165325p:plain
Settings画面

設定画面では攻撃があった時にどんなHttp Statusで返すかと言う設定ができたり、IPアドレスによるガードや受け入れを設定できるブラックリストホワイトリストの設定もできたり、

f:id:yasuyuki-kobayashi-flect:20191203170055p:plain
Integrarion画面

攻撃があったりした時に通知する先も設定できて、先日Heroku NewRelic APMを始めよう!でお伝えしたNewRelicやSlackへの通知、WebhookでPOST先を指定する事もできます。

f:id:yasuyuki-kobayashi-flect:20191203170720p:plain
Alertモード画面

もちろんメールでの送信も可能。

また緊急度(高/中/低)によって通知も「直ちに」「1日のダイジェスト」「1週間のダイジェスト」と設定できます。

このように「Sqreen」はフレキシブルに設定できるので、アプリケーション運用時には頻繁にSqreenコンソールに確認に行かなくても良いし、大したことのないセキュリティアラートで深夜に起こされる、呼び出される事もないです(笑)。

f:id:yasuyuki-kobayashi-flect:20191203171739p:plain
WAFルール画面

そしてWAFですが、デフォルトで50ものルールがすでに設置されています。

「Sqreen」を構築しただけですぐにWAFが機能するのは嬉しいですね。

もちろん御自身のルールを追加する事も可能ですし、既存のルールをどのように扱うか(”何もしない”とかも)をコントロール可能です。

f:id:yasuyuki-kobayashi-flect:20191203171649p:plain
WAF画面

またいくつかのルールに引っかかるようなアクセスをしたIPは「15分間遮断する」と言った、攻撃者を諦めさせる嬉しい機能も!

その他の機能

「Sqreen」はWAFだけの機能じゃないです。

f:id:yasuyuki-kobayashi-flect:20191203173927p:plain
Protections

「クリックジャッキング」「クロスサイトスクリプティング」「MIME Sniffing」と言ったクライアント側のセキュリティ保護対策、そして自身のアプリケーションの脆弱性までチェックして教えてくれます。

Webアプリケーションの中も外もしっかり保護してくれる、もう至れり尽くせりですね。

そしてWebアプリケーションに「Sqreen」を搭載した成果が!

「で、このSqreenってやつは本当にガードしてくれるの?」と半信半疑な方もいらっしゃるのではないでしょうか。

我々が構築したWebアプリケーションに「Sqreen」を搭載したんですが、

f:id:yasuyuki-kobayashi-flect:20191204112759p:plain
インシデント画面
なんとウクライナ(またはウクライナ経由)の攻撃を見事にガードしてくれました!!

「Sqreen」は攻撃者の位置をIPアドレスから逆探知もしてくれるんですよ。

すごくないですか。

構築方法は?

皆さんいかがでしたか? 「Sqreen」なかなかの高機能でしょ。 プランは無料からもありますのでこれをアドオンしない理由はありませんよね。

さて最後に「Sqreen」の構築方法ですが、

f:id:yasuyuki-kobayashi-flect:20191204093758p:plain
AddOn
アドオンしただけではすぐには動きません。 Webアプリケーションを守るために「Sqreen」を関連づける(dynoの中で「Sqreen」監視プログラムを動かし「Sqreen」本体に認識させる)ことが必要です。

この設定方法に関しては皆さん様々な言語でWebアプリケーションを構築していると思いますので、私が説明するよりこちらをご覧ください。

devcenter.heroku.com

英語ですけどブラウザの翻訳機能(最近はかなりいい感じに翻訳してくれるようになりましたよね)を使えば簡単に読んで理解できますよ。

それではみなさん、「Sqreen」を搭載して"ハッピーHerokuライフ"をお過ごしください!