るぴブロ

備忘録とかです(*'ω'*)

Custom Vision と Tensorflow2.0 を比べてみました

この記事は Azure AI Advent Calendar 2019 の 22日目の記事となります。

qiita.com

AI を使ってみたいけど…。

近年 AI 技術の急速な発達にともない、様々な AI サービスが誕生しており機械学習ディープラーニングなどの技術により、AI は様々な分野で活用されるようになっています。
こういった流れの中で自社でも AI を活用した事例を増やしたいと思うのは自然な事だと思いますが、 実際に開発を行うとなると非常に専門的な知識が必要だったり、コストがかかったり…
ちょっとやってみようレベルでは中々と敷居が高いかと思います。

Cognitive Services がおすすめ

Cognitive Services は人間の認知する機能の一部を機械で擬似的に再現したサービスで Web API として利用できる AI パーツ。

Microsoft Azure のサービスの中で一番好きなサービス😊
だって、Web App でも、IoT でも、Logic Apps でも、Bot でも、XRでも、VUI でも何でも繋げることが出来るなんて素敵すぎると思いませんか?

2019.12.22 現在のサービス一覧 (27 Services ※5 preview)

  • 決定:よりスマートな意思決定をすばやく行う
  • 言語:非構造化テキストから意味を取り出す
    • Immersive Reader(preview):音声や視覚的な合図を使用して、あらゆる能力の読み手がテキストを理解できるようにする
    • Language Understanding自然言語を解釈する機能を提供
    • QnA Maker:ナレッジベースから質疑応答を、会話形式で行うことができる
    • Text Analytics:センチメント、キー フレーズ、名前付きエンティティを検出
    • Translator Text:60 を超えるサポート言語を検出し、リアルタイムで翻訳
  • 音声:音声処理をアプリやサービスに統合する
  • 視覚:画像、ビデオ、デジタル インク内のコンテンツを識別し、分析する
    • Computer Vision:画像内のコンテンツを分析
    • Custom Vision:ビジネス上のニーズに合うよう画像認識をカスタマイズ
    • Face:イメージ内の人物とその感情を検出して識別
    • Form Recognizer(preview):ドキュメントからテキスト、キーと値のペア、テーブルを抽出
    • Ink Recognizer(preview):デジタル インクや手書き入力を認識し、一般的なシェイプの位置特定
    • Video Indexer:ビデオのビジュアルとオーディオ チャネルを分析し、そのコンテンツにインデックスを設定
  • 検索:World Wide Web から探しているものを見つける
    • Bing Autosuggest:インテリジェントな先行入力機能が追加され、ユーザーはよりすばやくクエリを入力する
    • Bing Custom Search:検索結果に広告が表示されないカスタムの検索エンジンを作成
    • Bing Entity Search:名前付きエンティティを識別して分類し、それに基づいて検索結果を探す
    • Bing Image Search:さまざまな画像検索オプションをアプリに追加
    • Bing News Search:アプリをニュースの検索リソースに変更
    • Bing Spell Check:ユーザーが単語の切れ目、スラング、名前、同音異義語、ブランドを識別して修正
    • Bing Video Search:高度なビデオ検索機能をアプリに追加
    • Bing Visual Search:ユーザーが画像を使用して検索
    • Bing Web Search:安全で広告なしの、位置認識機能を備えた検索をユーザーが利用できるようにし、Web の検索結果、画像、ニュース、ビデオ、ビジュアルから関連情報を表示

実際ににどうなの?

プレビルドのモデルを活用する事を不安に思われる方もいらっしゃるかもしれません。
なので、AI技術の中でもっとも実用化が進んでいる画像認識をPython+TensorFlowとCustom Vision で比べてみました。

Dataset

何でも良かったのですが、せっかく?なので車を使ってみました。 学習枚数はそれぞれ10枚、テストに10枚です。

f:id:rupic:20191222125826p:plain
こんな感じ

datasetsーー test
    |   ∟ ES                 
    |  |
    |   ∟ RX 
    |  
    ∟_ train
        ∟ ES                 
       |
        ∟ RX 

Tensor Flow 2.0

ネットワークは ResNet の 50 層を使ってみます。

def Res50():

    def ResBlock(x, in_f, f_1, out_f, stride=1):
        res_x = Conv2D(f_1, [1, 1], strides=stride, padding='same', activation=None)(x)
        res_x = BatchNormalization()(res_x)
        res_x = Activation("relu")(res_x)

        res_x = Conv2D(f_1, [3, 3], strides=1, padding='same', activation=None)(res_x)
        res_x = BatchNormalization()(res_x)
        res_x = Activation("relu")(res_x)

        res_x = Conv2D(out_f, [1, 1], strides=1, padding='same', activation=None)(res_x)
        res_x = BatchNormalization()(res_x)
        res_x = Activation("relu")(res_x)

        if in_f != out_f:
            x = Conv2D(out_f, [1, 1], strides=1, padding="same", activation=None)(x)
            x = BatchNormalization()(x)
            x = Activation("relu")(x)

        if stride == 2:
            x = MaxPooling2D([2, 2], strides=2, padding="same")(x)
        
        x = Add()([res_x, x])

        return x
        
    
    inputs = Input((img_height, img_width, channel))
    x = inputs
    
    x = Conv2D(64, [7, 7], strides=2, padding='same', activation=None)(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    x = MaxPooling2D([3, 3], strides=2, padding='same')(x)

    x = ResBlock(x, 64, 64, 256)
    x = ResBlock(x, 256, 64, 256)
    x = ResBlock(x, 256, 64, 256)

    x = ResBlock(x, 256, 128, 512, stride=2)
    x = ResBlock(x, 512, 128, 512)
    x = ResBlock(x, 512, 128, 512)
    x = ResBlock(x, 512, 128, 512)

    x = ResBlock(x, 512, 256, 1024, stride=2)
    x = ResBlock(x, 1024, 256, 1024)
    x = ResBlock(x, 1024, 256, 1024)
    x = ResBlock(x, 1024, 256, 1024)
    x = ResBlock(x, 1024, 256, 1024)
    x = ResBlock(x, 1024, 256, 1024)

    x = ResBlock(x, 1024, 512, 2048, stride=2)
    x = ResBlock(x, 2048, 256, 2048)
    x = ResBlock(x, 2048, 256, 2048)

    x = AveragePooling2D([img_height // 32, img_width // 32], strides=1, padding='valid')(x)
    x = Flatten()(x)
    x = Dense(num_classes, activation='softmax', name='out')(x)

    model = Model(inputs=inputs, outputs=[x])

    return model

f:id:rupic:20191222130542p:plain
うーん…な感じですがまぁ良いでしょう。

適当な画像を与えてみます。

f:id:rupic:20191222133233p:plain
LEXUS ES

f:id:rupic:20191222133755p:plain
いい感じにESです(ラベル 0 がES)

Custom Vision

www.customvision.ai

Custom Vision は上記のサイトから新しいプロジェクトを作成して画像をアップロードしてあげる事で簡単にモデルの構築が出来ます。テストも同じサイトから可能。

f:id:rupic:20191222134437p:plain
プロジェクトを作成

f:id:rupic:20191222134724p:plain
画像アップロード時にタグ付けします

f:id:rupic:20191222134817p:plain
右上にあるTrainをクリックする事で学習してくれます

結果的には少し不安ですが、このままいってみます。
今回は quick train で学習したんですが、学習時間を指定してモデルの精度をあげる事もできます。

f:id:rupic:20191222135103p:plain
しっかり ES と判断してくれてますね

f:id:rupic:20191222135148p:plain
これくらいきわどい画像でもしっかり判定してくれてます(RXで正解)

まとめ

最終的な精度だけ見てみるとそんなに変わらないですが、何といっても学習にかかる手間や時間が大幅に短縮されます。※Custom Visionの学習時間は 10 秒程度
学習したモデルを Export して自身のアプリケーションに実装する事も可能なので、ちょっとやってみたいって時にすぐに実装する事ができますね😊

AI を活用したサービスは画像だけでなく、

  • 自社で溜めた知見を元にユーザーからの問合せをチャットボットで行ったり
  • 問合せの内容からセンチメントを分析したり
  • カメラで撮影した画像を判定したり
  • 会話の中から話している言葉や人の特定を行ったり

それはもう何でも AI でいい感じに出来るんじゃないか?なんて思ってしまいがちですが、AI は決して銀の弾丸や魔法の杖ではありません。

課題設定がしっかりできている事、事実に基づいた質の良いデータが十分にある事、しかるべき場所に実装する事で威力を発揮してくれる物なので特性を理解してしっかり利用していきたいですね!