Azure Site Recovery – その概要と、可能なこと・不可能なこと

ASR – その意義と概要

Public Cloud として Azure を選択するメリット (Advantage) の 1 つに、Microsoft が長年培ってきたオンプレミス・テクノロジーとの融合 (ハイブリッド技術) がある。クラウドへの本格参入ができない古い体質の業界や企業では、オンプレミスにある資産を Public Cloud に移すのは不可能かもしれないが、こうした安価でスケーラブルなクラウドが、いざというときのリカバリー サイトとして利用できるなら現実味があるだろう。
Azure Site Recovery (ASR) は、そうした「現実解」のニーズに対応した Public Cloud のサービスと言って良い。

Azure Site Recovery (ASR) を介することで、オンプレミスのマシン イメージを Azure 上に Replication し、いざオンプレミス環境に障害が発生した際には、このバックアップされたイメージ (.vhd) を元に、すぐに Azure 上にマシンを稼働して (Failover して)、VPN や閉域網などを経由して企業内から継続的にサービスを利用可能にする。
Primary の復旧が完了したら、Reverse Replicate といって、稼働中の (Azure 上の) リカバリー サイトを元の Primary サイトへ戻すための仕組み (要するに “Failback”) も提供する。


(From Microsoft Hybrid Cloud Blog)

この Azure Site Recovery (ASR) について、よくある疑問点 (利用時の初歩的な質問) を以下の 3 つの観点でまとめたので、これから導入を検討される方は参考にしていただきたい。
後述の通り、ネットワークまわりをどう設計するかは、充分な考察が必要だ。

ASR – よくある疑問 (まとめ)

対象のソース

Primary として選べるソースタイプとしては、以下が利用可能。
なお、現在、Windows Server 2016 の Physical Server はサポートされていないので注意してほしい。(いずれ対応されると思うが)

  • Physical Machine (On-Premise)
  • Hyper-V 上の Guest VM (On-Premise)
  • VMWare 上の VM (On-Premise)
  • Azure 上の VM

いまでは Azure 上の VM などもリカバリー可能だが、ASR は、当初はオンプレミス上の環境をクラウドにリカバリーして事業継続するためのサービスとして登場しており、ASR を中継することで、On-Premise to Azure だけでなく、Azure を中継した On-Premise to On-Premise のリカバリーに使うことも可能だ。

ネットワーク

ASR ではいろいろなアーキテクチャが考えられるが、ここでは話が混乱しないよう On-premises to Azure で考えてみよう。

上述の通り、Failover 後は、企業内からリカバリー先のマシン (今回の場合、Azure 上のマシン) を利用するため、Azure 上の Recovery Site と On-Premise との間はあらかじめ同じネットワークに入れることになる。(あらかじめ Azure の Site-to-Site VPN や ExpressRoute で Recovery 先と接続しておく。)
このように、ASR 利用時は、DR (Disaster Recovery) 時も踏まえた充分なトポロジー設計が必要になる。

例えば、Azure では、同一ネットワーク上に同一のアドレス空間を持たせることはできないので、Recovery された VM は一般に IP アドレスが変更される。このため、リカバリー対象のマシンで DNS サーバーとの接続が必要になり、Azure の Virtual Network (VNet) 上の DNS Server としてオンプレ側の DNS Server を指定したり、あるいは Failover の際に DNS Server も Replication するなど方針を決める必要があるだろう。(Failover 先の Azure VM で IP Address を同じにすることも不可能ではないが、ASR がこうした仕組みを備えているわけでないため、自身でこうした Subnet Failover (転換処理) を実装することになる。)

ASR は、上述の通りイメージ ベースでの Recovery になるので、すべてを ASR に頼るのではなく、データベース (RDB), AD (Active Directory) などでは、下記のようなコンポーネントが持つ Recovery テクノロジーを組み合わせることも検討する。(Multi-Tier アプリケーションのように複数台のマシンで状態の一貫性が必要になる場合には、Multi VM Consistency という機能を有効化することで一貫性を維持できる。)

また、オンプレミスから Azure への Replication (delta による差分反映など) では一般にインターネット (Azure に向けての inbound の https ポート) が使われるが、以下も考慮しておこう。

  • トラフィック送信にインターネットを使わず、Azure ExpressRoute Public Peering を使うよう構成することも可能
  • ただし、現在、トラフィック送信に Site-to-Site VPN を使うことは不可能

一方、Failback では、一般にインターネット回線は利用できないので注意してほしい。Failback の場合は、Azure 側から On-Premise への https による inbound アクセスがおこなわれるため、Azure Network (Azure VNet) からの VPN か ExpressRoute を介して On-Premise につなぐことになるためだ。(Failback も計画に含めるなら、戻す際のネットワーク構成も考慮する必要がある。)

ネットワーク帯域については、ASR Capacity Planner が使用できる。(この ASR Capacity Planner は、Azure 上の ASR 設定の途中でリンクが表示され、ダウンロードを促すようになっている。)

運用手順

ASR では Failover は自動でおこなわれないので、運用・監視は自身でおこない (または、他製品を組み合わせて)、UI (Azure Portal), スクリプト, SDK などから能動的に Failover を呼び出す。(Failover を呼び出すと、Recovery 先でリカバリー イメージを元に VM が起動する。)
なお、OMS と組み合わせた場合は、既に構成のための機能が OMS に Built-in されている。

下記の 3 種類の Failover が提供されていて、いわゆる障害発生時に呼び出す「Unplanned Failover」は、他の 2 つと異なり Failover 時に最新の Delta Replication は作成しない。(その時点でとられている最新のイメージを元に Failover する。)

  • Test Failover
  • Planned Failover
  • Unplanned Failover

Failover 後の処理は、Azure Automation Runbook を使うことができる。VNet 等の Azure Resource の構成や、VM 内でのセットアップスクリプトの実行などは、Azure Automation Runbook を組み合わせて構成する。

Microsoft Azure : Add Azure Automation runbooks to recovery plans
https://docs.microsoft.com/en-us/azure/site-recovery/site-recovery-runbook-automation

 

ここでは ASR 導入の際の初歩的な疑問を中心にまとめたが、細かなトポロジーや FAQ は以下が参考になるので是非参照してほしい。

Azure Site Recovery support matrix (On-premises to Azure)
https://docs.microsoft.com/en-us/azure/site-recovery/site-recovery-support-matrix-to-azure

Azure Site Recovery FAQ
https://docs.microsoft.com/en-us/azure/site-recovery/site-recovery-faq

 

Advertisements

コマンドで理解する New Azure ML ステップ・バイ・ステップ

新しい Azure Machine Learning (Preview) は基本的にコマンドから使う。(実際、Azure Portal からは一部の機能しか使えない。)

ここでは、このコマンドを順に見くことで、新しい Azure Machine Learning がどのようなものか確認する。
ざっくりと Experimentation と Model Management という独立した 2 つの作業にわかれている。

準備

ここで紹介するコマンドを使うには、後述の Azure Machine Learning Workbench をインストールするか、下記の通り個別にパッケージをインストールする。

pip install azure-cli
pip install azure-cli-ml

CLI コマンドのヘルプを見るには -h オプションを使用する。
この投稿では、コマンドを難解にしない目的から必要最小限の引数しか指定しないが、細かな設定については下記のように確認してほしい。

# show what resource can be used
az ml -h
# show what command can be used for workspace
az ml workspace -h
# show what option can be used for workspace creation
az ml workspace create -h

また、以降を進める前に、CLI から、あらかじめ Azure にログインをしておこう。(az login を実行する。)

Experimentation Account と Workspace の作成

新しい Azure ML のアカウントには Experimentation Account と Model Management Account がある。
モデル構築時は Experimentation Account を作成し、ここに Workspace を作成して、Workspace 内で個々の Project を作成する。

下記は、CLI コマンドを使って、リソースグループ myRG01 に Experimentation Account (名前 exacc01) と Workspace (名前 testws01) を作成している。(なお、Experimentation Account と Workspace は Azure Portal からも作成できる。)

# Create experimentation account
az ml account experimentation create -n "exacc01" -g "myRG01"
# Create workspace
az ml workspace create -a "exacc01" -n "testws01" -g "myRG01"

Training フェーズ (モデルの作成)

Python のコード作成、トレーニング、モデル作成には Azure Machine Learning Workbench (Windows 版、Mac 版) や Visual Studio Code Tools for AI というデスクトップ ツール (IDE) が提供されている。
なお、これらを使うには、あらかじめ前述の Experimentation Account を作っておく必要がある。(起動時に Experimentation Account を確認する。)

aml_workbench

ここではこれらのツールの使い方は説明しないので “チュートリアル : Classify Iris” を参照してほしいが、主に下記のようなことをおこなう。

  • 上記で作成した Workspace に Project を新規作成
  • Data Set を準備・整形 (dataprep)
  • Python で Training のコードを作成 (学習済モデルの作成)
  • 実行と結果の確認

(補足 : Project は単なるローカル環境のフォルダではなく、Azure 上のリソースとして作成される。カレントフォルダーの Project が Active Project として認識され、例えば、Active Project 上で az ml account experimentation show と入力すると、その Project の Experimentation が表示される。)

新しい Azure Machine Learning はツールに依存しておらず (Open で)、その後の作業も含め Azure Machine Learning Workbench などがなくても Azure Machine Learning のサービス全体を利用できるが、実際、Azure Machine Learning を使うなら Workbench を使わないともったいない。理由は、下記の通り Azure Machine Learning Workbench 自体が高機能なためだ。
(言い換えるなら、この Azure Machine Learning Workbench 自体が、新しい Azure Machine Learning の半分を占めているといっても過言ではない。)

  • Data の準備では、元のデータを変えることなく、Data cleaning のための細かなステップをエディタでビジュアルに定義できる。(Power BI などで使われていた手法だ)
    メトリクスごとのデータ プロファイルをみながら編集できる。
  • PROSE と呼ばれる AI による Data Wrangling テクノロジにより、ちょっとしたデータ整形なら、Excel の Autofill のように賢く自動解釈する。(“Diving deep into what’s new with Azure Machine Learning” 参照)
  • トレーニングでは、config を構成し、ローカルマシン以外に、DSVM や HDInsight Spark cluster などを容易に使える。つまり、学習の際、Azure 上の GPU 等の高尚なコンピューティング環境を容易に扱える。(“Configure compute environment” 参照)
    なお、Azure のサービスを介しておこなわれるので、Workbench を使わない場合でも Experimentation Account が必要だ。

Workbench には、他にも Jupyter Notebook とのインテグレーション、ROC 曲線などによる可視化 等、多くのサポート機能を備えている。

Python のコードを作成して学習が完了したら、学習済のモデル ファイル (.pkl) を作成しておく。

Scoring フェーズ

学習済モデル ファイル (.pkl) ができたら、これを元に Scoring のコードを作成して、これを Web Service として発行する。

以下は、付属している Iris の Scoring のサンプルだ。(あやめの種類を区別する Logistic Regression のモデルを扱っている。)
この中の以下の処理に注目してほしい。

  • カレント フォルダから、前述で学習したモデル (下記の model.pkl) をロードしている。
  • 下記の通り、このあとの Web Service 化にそなえて、init() (初期化の処理), run() (Web Service 本体の処理) を定義し、これらを main から呼び出してデバッグする。
  • Azure Machine Learning が提供する generate_schema() 関数で、Input (入力引数), Output などの Web Service の仕様を json で出力している。
# Import data collection library. Only supported for docker mode.
# Functionality will be ignored when package isn't found
try:
  from azureml.datacollector import ModelDataCollector
except ImportError:
  print("Data collection is currently only supported in docker mode. May be disabled for local mode.")
  # Mocking out model data collector functionality
  class ModelDataCollector(object):
    def nop(*args, **kw): pass
    def __getattr__(self, _): return self.nop
    def __init__(self, *args, **kw): return None
  pass

import os

# Prepare the web service definition by authoring
# init() and run() functions. Test the functions
# before deploying the web service.
def init():
  global inputs_dc, prediction_dc
  from sklearn.externals import joblib

  # load the model file
  global model
  model = joblib.load('model.pkl')

  inputs_dc = ModelDataCollector("model.pkl", identifier="inputs")
  prediction_dc = ModelDataCollector("model.pkl", identifier="prediction")

def run(input_df):
  import json

  # append 40 random features just like the training script does it.
  import numpy as np
  n = 40
  random_state = np.random.RandomState(0)
  n_samples, n_features = input_df.shape
  input_df = np.c_[input_df, random_state.randn(n_samples, n)]
  inputs_dc.collect(input_df)

  pred = model.predict(input_df)
  prediction_dc.collect(pred)
  return json.dumps(str(pred[0]))

def main():
  from azureml.api.schema.dataTypes import DataTypes
  from azureml.api.schema.sampleDefinition import SampleDefinition
  from azureml.api.realtime.services import generate_schema
  import pandas

  df = pandas.DataFrame(data=[[3.0, 3.6, 1.3, 0.25]], columns=['sepal length', 'sepal width','petal length','petal width'])

  # Turn on data collection debug mode to view output in stdout
  os.environ["AML_MODEL_DC_DEBUG"] = 'true'

  # Test the output of the functions
  init()
  input1 = pandas.DataFrame([[3.0, 3.6, 1.3, 0.25]])
  print("Result: " + run(input1))

  inputs = {"input_df": SampleDefinition(DataTypes.PANDAS, df)}

  #Genereate the schema
  generate_schema(run_func=run, inputs=inputs, filepath='./outputs/service_schema.json')
  print("Schema generated")

if __name__ == "__main__":
    main()

ここまでで、学習済モデル ファイル (上記の model.pkl)、Web Service の仕様を定義した Json ファイル (上記の service_schema.json)、そしてこの Scoring 用の Python コード (score_iris.py とする) が準備できた。

Computing Environment の作成と設定

以上で必要なファイルは整ったので、Web Service 化して展開 (deploy) する。
ここからは Model Management の作業になるが、必要なファイルさえ揃っていれば、ここまで使ってきた Experimentation Account 等は必要ない。

まず、前提知識をいくつか記載する。

新しい Azure Machine Learning を使った Web Service 化では、展開の際に AKS (Azure Container Service の Kubernetes cluster) と ACR (Azure Container Registry) が使われる。このため、あらかじめ、コマンド az provider register --namespace Microsoft.ContainerRegistry によって Azure Container Registry プロバイダーを登録しておく必要がある。(既に登録済の場合は OK)

また、Web Service 化は、ここで紹介する方法以外に、単一のコマンドですべて生成することもできるが、ここでは構成などを理解できるように、あえて複数コマンドでわけて展開をおこなう。(構造が理解できてきたら、単一コマンドで省力化しても良いだろう。)

まず、展開の前に、展開環境である Computing Environment を下記の通り新規作成する。
ここでは、testenv01 という名前の Computing Environment を East US 2 に作成する。(Kubernetes クラスタの名前は「testenv01」になる。)

なお、下記の -c (--cluster) オプションで Azure Container Service (AKS) が使用されるが、オプションを指定しない場合は local の docker container に展開される。(ここでは省略するが、コマンドを使って local と AKS を切り替えることも可能。)

az ml env setup -n testenv01 -l eastus2 -c

上記のように -g (--resource-group) オプションを省略すると、このコマンドによって testenv01rg と testenv01rg-azureml-cxxxx の 2 つのリソースグループが新規作成され、後者のリソースグループに Azure Container Service の各ノード (VM) が展開される。(xxxx は数字。今回は testenv01rg-azureml-c7294 だった。)
これらのリソースグループはこのあとのコマンドで使うのでおぼえておく。

下記のコマンドで Computing Environment がすべて表示されるので、作成中の環境の provisioning state が Succeeded になるまで待つ。(特に新規に Azure Container Service を作成する場合は、最初のノード作成に時間がかかる。)

az ml env list

Succeeded になったら、下記コマンドを実行して、この作成した環境を Active Compute Environment として設定する。

az ml env set -n testenv01 -g testenv01rg

なお、作成された Compute Environment の情報は Azure 上に保存されるが、この Active Compute Environment はその作業環境上のみ (使用しているクライアント上のみ) の設定なので注意。
以下のコマンドで Active (Current) の環境を確認できる。

az ml env show

Model Management Account の作成と設定

次に、下記コマンドで Model Management Account を新規作成する。(このあと登録するモデルは、ここでバージョン等が管理される。)

az ml account modelmanagement create -l eastus2 -n testmg01 -g myRG01

つぎに、下記コマンドによって、上記で作成した Model Management Account  を使用中の作業環境 (クライアント) における Active な Model Management Account として設定する。

az ml account modelmanagement set -n testmg01 -g myRG01

Active な Model Management Account は下記コマンドで確認できる。

az ml account modelmanagement show

Web Service としての展開 (Deploy)

下記コマンドで、前述で作成した学習済モデル ファイル (model.pkl) を登録する。(何度も登録するとバージョンが 2, 3 とあがっていくので注意。)
この際、登録されたモデルの ID (model id) が出力されるので、これをコピーしておく。(以降では model id を 08ceeb5842eb4fa4a94d47533d7e3aab とする。)

az ml model register -m model.pkl -n model.pkl

つぎに、下記コマンドで、上記で準備した Web Service 用の Scoring のソース (score_iris.py) と仕様 (service_schema.json) を登録して Manifest を作成する。ここで、-i (--model-id) オプションは、上記で登録したモデルの ID である。つまり、使用するモデルは都度 変更できる。
(なお、何度も登録すると Manifest のバージョンがあがっていくので注意。)

この Manifest 作成時に manifest id が出力されるので、これをコピーしておく。(以降では manifest id を 789c3c18-b385-423f-b88c-429a2973b99b とする。)

az ml manifest create -n testmanifest1110 -f score_iris.py -r python -i 08ceeb5842eb4fa4a94d47533d7e3aab -s service_schema.json

この Manifest を使って、下記の通り Image を新規作成して登録する。Image の実体は、ACR (Azure Container Registry) に登録される。(この ACR は、上記の az ml env setup コマンドで新規作成されたリソースグループの中にある。)
作成時、イメージの Id が出力されるので、これをコピーしておく。(以降では image id を a61ba643-884d-4181-a7cb-b1b9c6c48b3e とする。)

az ml image create -n testimage1110 --manifest-id 789c3c18-b385-423f-b88c-429a2973b99b

あとは、この登録されたイメージを使って、下記の通り Web Service を展開して起動する。
今回は使用しないが、追加の Package が必要な場合には -c オプションで Conda Dependencies File (.yml) を指定できる。
なお、下記で “realtime” と指定しているが、今後、”batch” (Azure Batch 展開) も可能になるようだ。

az ml service create realtime --image-id a61ba643-884d-4181-a7cb-b1b9c6c48b3e -n testapp1110 --collect-model-data true

下記の通り出力されるので、出力された service id (testapp1110.testenv01-90e88070.eastus2) をおぼえておく。(このサービスを利用する際に使用する。)

Creating service............................Done
Service ID: testapp1110.testenv01-90e88070.eastus2
Usage for cmd: az ml service run realtime -i testapp1110.testenv01-90e88070.eastus2 -d "{\"input_df\": [{\"petal length\": 1.3, \"petal width\": 0.25, \"sepal width\": 3.6, \"sepal length\": 3.0}]}"
Usage for powershell: az ml service run realtime -i testapp1110.testenv01-90e88070.eastus2 --% -d "{\"input_df\": [{\"petal length\": 1.3, \"petal width\": 0.25, \"sepal width\": 3.6, \"sepal length\": 3.0}]}"
Additional usage information: 'az ml service usage realtime -i testapp1110.testenv01-90e88070.eastus2'

Web Service の利用

展開された Web Service (REST) の URL, Port, エンベロープなどは、下記コマンドで確認できる。

az ml service usage realtime -i testapp1110.testenv01-90e88070.eastus2
Scoring URL:
  http://13.68.115.32:80/api/v1/service/testapp1110/score

Headers:
  Content-Type: application/json
  Authorization: Bearer <key>
    (<key> can be found by running 'az ml service keys realtime -i testapp1110.testenv01-90e88070.eastus2')

Swagger URL:
  http://13.68.115.32:80/api/v1/service/testapp1110/swagger.json

Sample CLI command:
  Usage for cmd: az ml service run realtime -i testapp1110.testenv01-90e88070.eastus2 -d "{\"input_df\": [{\"petal width\": 0.25, \"sepal width\": 3.6, \"sepal length\": 3.0, \"petal length\": 1.3}]}"
  Usage for powershell: az ml service run realtime -i testapp1110.testenv01-90e88070.eastus2 --% -d "{\"input_df\": [{\"petal width\": 0.25, \"sepal width\": 3.6, \"sepal length\": 3.0, \"petal length\": 1.3}]}"

Sample CURL call:
  curl -X POST -H "Content-Type:application/json" -H "Authorization:Bearer <key>" --data "{\"input_df\": [{\"petal width\": 0.25, \"sepal width\": 3.6, \"sepal length\": 3.0, \"petal length\": 1.3}]}" http://13.68.115.32:80/api/v1/service/testapp1110/score

Get debug logs by calling:
  az ml service logs realtime -i testapp1110.testenv01-90e88070.eastus2

Get STDOUT/STDERR or Request/Response logs in App Insights:
  https://analytics.applicationinsights.io/subscriptions/b3ae1c15-4fef-4362-8c3a-5d804cdeb18d/resourcegroups/testenv01rg-azureml-c7294/components/mlcrpaib1917249512d#/discover/home?apptype=Other%20(preview)

ここで認証用に使用する key は、下記コマンドで出力できる。

az ml service keys realtime -i testapp1110.testenv01-90e88070.eastus2
PrimaryKey: 6d452f09a4xxxxxxxxxxxxxxxxxxxxxx
SecondaryKey: ec7453b683xxxxxxxxxxxxxxxxxxxxxx

このため、Fiddler などを使って下記の通り HTTP Request をおこなう。
今回は、あやめの情報 (ガクの幅など) を渡すことで、そのあやめの種類をモデルから推測して返している。

POST http://13.68.115.32:80/api/v1/service/testapp1110/score
Content-Type: application/json
Authorization: Bearer 6d452f09a4xxxxxxxxxxxxxxxxxxxxxx

{
  "input_df": [
    {
      "petal width": 0.25,
      "sepal width": 3.6,
      "sepal length": 3.0,
      "petal length": 1.3
    }
  ]
}
HTTP/1.1 200 OK
content-type: application/json

"\"Iris-setosa\""

Scaling

前述の通り Kubernetes の Cluster が使用されるため、以降は kubectl コマンドで管理できる。
しかし、よく使う Agent Node (Virtual Machine) や Replica の一部の管理タスクは Azure ML のコマンドも使えるので最後に紹介しておこう。

例えば、下記は、Azure ML のコマンドを使って Agent Node (Agent の Virtual Machine) を 3 台に変更する。

az acs scale -g testenv01rg-azureml-c7294 -n testenv01 --new-agent-count 3

下記は、Autoscale の設定を解除して、この Agent 上に動いている Replica を 3 つに設定している。(下記の通り kubectl コマンドを使わずに設定できる。)

az ml service update realtime -i testapp1110.testenv01-90e88070.eastus2 --autoscale-enabled false
az ml service update realtime -i testapp1110.testenv01-90e88070.eastus2 -z 3

 

ご覧のように、新しい Azure Machine Learning を使うと Python で構築した Score (Test) の処理をそのまま Web Service として発行できるが、同じようなことが可能な Server Platform (オンプレミスの製品) として Machine Learning Server というものが使えるのをご存じだろうか。旧 R Server と呼んでいたもので、現在は Python も使えるようになっている。
また、コマンドや構成の一部で runtime として「python」を指定している点に気づいたかと思うが、現在 Model Management のみ R がサポートされているらしく、今後、R の Experimentation やドキュメントも出てくることだろう。
Machine Learning Team Blog で書いているように、これらのプラットフォーム (クラウド版の Azure ML とオンプレ Server の ML Server) は今後 統一化されていく予定らしい。

 

参考にした情報 :

Azure Machine Learning Tutorial – Classify Iris :
https://docs.microsoft.com/en-gb/azure/machine-learning/preview/tutorial-classifying-iris-part-1

Azure Machine Learning Reference :
https://docs.microsoft.com/en-us/azure/machine-learning/preview/data-prep-python-extensibility-overview

R で日本語 OCR (tesseract)

今回実際に必要になった例だが、大量の伝票画像を電子化 (文字化) して、そこから情報を得るようなケースを考えてみたい。
伝票のヘッダー・明細や、項目の位置などは DNN を使ってあらかた学習できるかもしれないが、問題なのは、そこから文字を読み取る作業だ。

MNIST のサンプルなど、文字認識はいまや使い古された画像認識の手法だが、アルファベットや数字とは違い、日本語の場合、漢字も含め相当な数の文字があるため、一から教師あり画像を準備してトレーニングするのは (実際のビジネスでは) 現実的ではないからだ。

そこで、今回、tesseract の R のパッケージを使うことを検討してみた。

使い方

使い方は簡単だ。(今回は、Mac または PC 上の環境を想定する。)
まず、R コンソールなどから、tesseract のパッケージ (バイナリ) をインストールする。

install.packages("tesseract")

既定のバイナリには英語のデータしか入っていないので、Github から日本語の Trained データを落とせば良いが注意がある。
現在 Github にある最新は tesseract 4 のデータだが、CRAN のリポジトリにある tesseract 1.4 パッケージ (R のパッケージ) は tesseract 3.0X がベースになっているので (つまり、tesseract 4 ではない)、tesseract 3.04 ベースの Trained データを落としてくる必要があるのだ。
このため、現在は、以下の通り Branch を指定してダウンロード (Clone) する。

git clone --branch 3.04.00 https://github.com/tesseract-ocr/tessdata.git

下図の通り、各言語ごとの .traineddata がダウンロードされるので、この中の jpn.traineddata を、tesseract のインストール・ディレクトリである %userprofile%\Documents\R\win-library\3.4\tesseract\tessdata にコピーする。

以上で準備完了だ。

今回は Windows や Mac 上でのセットアップ方法だが、本番運用などで Linux に環境を作る際には下記を参照してほしい。

https://github.com/ropensci/tesseract

プログラミング

今回は、下図のサンプル画像を読み込ませよう。

下記の通り、R を使って、日本語用の Trained データ (エンジン) をロードし、これで OCR を行えば良い。

library(tesseract)
tseng <- tesseract(language = "jpn")
text <- ocr(
  "C:\\tmp\\sample.png",
  engine = tseng)
cat(text)

実行結果は、一見、良い感じだ。(下図参照)
今回学習済みデータ (.traineddata) をダウンロードして使ったが、オープンソースなので元データのカスタマイズなども可能らしい。

が、しかし、、、

いろいろやってみたが、今回のような機械で出力した伝票のようなケース (大きさも均一で、一定精度以上のフォント画像) には使えるが、精度の問題で、フリーな手書きの認識などにはまだ耐えられない感じだ。

例えば、文字の大きさ (解像度) を変えると認識率が大きく変わってしまうので、上記の例も、画像サイズによっては誤った結果が返ってくるので注意が必要だ。
また、下図のような手書きのデータもひらがなの「すばる」をまったく認識してくれない状況だった。(解像度を変えると、このひらがなの箇所の結果がいろいろ変化する状況。。。)

日本語については、現状はまだ用途を限定して使う感じだ。(英語の精度はすこぶる良いが)

 

How to create pfx file from crt and key (pem file)

すみません、自分用のメモ。

開発中のテスト目的などで https (SSL/TLS) の証明書設定が必要になった際、わざわざお金を払って証明書の申請をするのは面倒。
こうした場合、ご存じの通り、「Let’s Encrypt」が使用できるので是非。(日本の場合、「SSL なう !」から使用しても良い。)

さて、その際、Certificate の入った crt ファイル (pem 形式) と private key を含む key ファイルが別々に生成されるが、Azure などではご存じの通り .pfx ファイル (private key を含む Personal Information Change) が必要になるため、以下のコマンドで簡単に作成すれば良い。
(Windows 環境の場合、cygwin や git に付属の bash、Windows が提供する bash などを使うと良い。)

openssl pkcs12 -export -out server.pfx -inkey {.key including private key} -in {.crt including certificate}

新規にパスワードを入力するよう促される。

Json.NET (Newtonsoft.Json) の基本的な使い方

意外と困っている人が多いので、今さらだが、まとめ。

JToken を使った基本操作

まず大前提として、使用するオブジェクト構成の理解が超重要。
構成は非常に簡単だ。オブジェクト (例: { "firstname" : "Subaru", "surname" : "Kokubun" })JObject、配列 (例 : [ { "surname" : "Kokubun" }, { "surname" : "Matsuzaki" }, ... ] ) は JArray、文字列や数値などのプリミティブは JValue、そして、これらに共通の親 (継承元) が JToken だ。(この構成を理解していないと、このあとの文書は理解できない !)

例えば、HTTP (REST API) を呼び出して、

{
  "results": [
    {
      "id": 1,
      "name": "pc",
      "price": 100000
    },
    {
      "id": 2,
      "name": "mouse",
      "price": 5000
    },
    {
      "id": 3,
      "name": "phone",
      "price": 30000
    }
  ]
}

の値が返ってきた場合、下記のサンプルコードの通りオブジェクト間を変換して最終的な値を取り出せる。

このサンプルでは、まず、{ "results" : ... } 全体は JObject で受け取り (10 – 11 行目)、results の中は配列なので JArray で受け取り (17 行目)、その配列の要素 1 つ 1 つは object なので JObject で受け取り (18 行目)、その中の値を JValue で受け取って (20, 22 行目)、最後に JValue の Value プロパティで .NET の object 型 (string, long, など) として中身を取得している (21, 23 行目)。

なお、いったん継承元である JToken で受けて、中身の構成に応じて JObject や JArray にキャストしても良い。(以降も同様)

using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Formatting;
using Newtonsoft.Json.Linq;

HttpClient cl = new HttpClient();
cl.DefaultRequestHeaders.Accept.Add(
  new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage res = await cl.GetAsync("http://example.com/someapi");
JObject jres =
  await res.Content.ReadAsAsync<JObject>(new[] { new JsonMediaTypeFormatter() });

// The following result is :
// name is pc, price is 100000.
// name is mouse, price is 5000.
// name is phone, price is 30000.
JArray jarr = (JArray)jres["results"];
foreach (JObject jobj in jarr)
{
  JValue nameValue = (JValue)jobj["name"];
  string name = (string)nameValue.Value;
  JValue priceValue = (JValue)jobj["price"];
  long price = (long)priceValue.Value;
  Console.WriteLine($"name is {name}, price is {price}.");
}

なお、上記の 10 行目で受け取った jres で、jres.ToString() とすれば、Json 全体が (改行や空白など) きれいにフォーマットされた文字列として取得できる。

例えば、下記のサンプルコードのように、いったん JToken (JObject, JArray, JValue など) を使ってオブジェクトを組み立て、それを 14 行目のように HTTP Body の文字列に変換して HTTP (REST) を投げることができる。

using System.Net.Http;
using Newtonsoft.Json.Linq;

// Sent body is :
// {
//   "eventname": "Developer Meeting",
//   "eventdate": "2016-10-24T17:30:00"
// }
JObject newObj = new JObject();
newObj.Add("eventname", new JValue("Developer Meeting"));
newObj.Add("eventdate", new JValue(new DateTime(2016, 10, 24, 17, 30, 0)));
HttpClient cl = new HttpClient();
HttpContent jsonContent = new StringContent(
  newObj.ToString(),
  Encoding.UTF8,
  "application/json");
HttpResponseMessage res = cl.PostAsync(uri, jsonContent).Result;

逆に、文字列から Json.NET の Object (JObject, JArray, 等々) を生成するには、Parse メソッドを使う。
例えば、上述の HTTP (REST API) から Json.NET のオブジェクトを取得するサンプル コードは、下記の通りいったん string で受けて (9 -10 行目)、それを Parse メソッドでオブジェクトに変換する方法で記述しても良い。(以降の処理は、上述と同じソースコードになるので省略。)

using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;

HttpClient cl = new HttpClient();
cl.DefaultRequestHeaders.Accept.Add(
  new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage res = await cl.GetAsync("http://example.com/someapi");
string jstr =
  await res.Content.ReadAsStringAsync();
JObject jres = JObject.Parse(jstr);
...

なお、今回は、返ってくる結果が { "results" : ... } なので JObject で受けているが (上記の 11 行目)、下記の例のように、受け取る内容によって型を変える必要があるので注意してほしい。

using Newtonsoft.Json.Linq;

var obj = JObject.Parse(@"{ ""firstname"" : ""Subaru"", ""surname"" : ""Kokubun"" }");
// Result : "My family name is Kokubun."
Console.WriteLine($"My family name is {obj["surname"]}.");

var arr = JArray.Parse(@"[ { ""surname"" : ""Kokubun"" }, { ""surname"" : ""Matsuzaki"" } ]");
// Result : "Kokubun", "Matsuzaki"
foreach(var item in arr)
{
  Console.WriteLine(item["surname"]);
}

LINQ to JSON

.NET プログラマーなら IEnumerable のオブジェクトで LINQ to Object のクエリー (Select, Where など) が使えることは知っていると思うが、上記で紹介した JToken (JObject, JArray, など) も、for 文をわざわざ使わず、LINQ to JSON を使ってクエリーが実行できる。

本投稿ではこの説明は割愛するが、詳細は「Json.NET Documentation : LINQ to Json」を参照してほしい。

JsonConvert による Serialize / Desirialize

なお、Json のオブジェクトと文字列の変換には、もう 1 つ別の方法もある。

Json.NET 以前の DataContractJsonSerializer の頃から使われていた手法だが、対応するクラス構成を作成しておき、一気に Serialize / Deserialize する方法だ。
下記のサンプルコードは、上述の { "results" : ... } を変換するサンプルをこの方法で書き直したコードだ。

変換後のオブジェクトは自然なクラスなので扱いやすい一方、この方法で注意してほしいのは、あくまで静的に構成が決まっている場合しか使えないという点。中身を確認しながら動的に処理をするケースでは使えないので注意してほしい。

using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

[JsonObject]
public class ReturnedData
{
  [JsonProperty("results")]
  public ItemData[] Results { get; set; }
}

[JsonObject]
public class ItemData
{
  [JsonProperty("id")]
  public int Id { get; set; }
  [JsonProperty("name")]
  public string Name { get; set; }
  [JsonProperty("price")]
  public int Price { get; set; }
}
...

// メインの処理
HttpClient cl = new HttpClient();
cl.DefaultRequestHeaders.Accept.Add(
  new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage res = await cl.GetAsync("http://example.com/someapi");
string jstr =
  await res.Content.ReadAsStringAsync();
ReturnedData jres = JsonConvert.DeserializeObject<ReturnedData>(jstr);
...

Json.NET は、いまや空気のように普通に使われるので、この程度のことは知っておいて損はない。

 

ngrok を ASP.NET で使う (Debug と Capture)

昨今の WebHook や BOT 開発のように、インターネット上で Inbound 呼び出しされる Web アプリの Debug や HTTP Protocol (Raw) Capture をする場合に欠かせない ngrok を ASP.NET と組み合わせて使う場合に必要な設定と動作確認方法を簡単に紹介する。

ASP.NET プロジェクトの設定

ngrok を使うには、まず、ASP.NET のプロジェクトに以下の設定をおこなっておく。

まず、Visual Studio のプロジェクトのプロパティで、[すべてのユーザーにサーバー設定を適用] (Apply server settings to all users) が選択されていることを確認する。(既定では選択されているはず)

apply_settings

開いている Visual Studio ソリューションのフォルダーの .vs\config にある applicationhost.config (IIS Express が使用) を開き、下記の binding を追加しておく。

<configuration>
  . . .

  <system.applicationHost>
    . . .

    <sites>
      . . .

      <site name="WebApplication1" id="2">
        <application path="/" applicationPool="Clr4IntegratedAppPool">
          <virtualDirectory path="/" physicalPath="C:\Demo\WebApplication1\WebApplication1" />
        </application>
        <bindings>
          <binding protocol="http" bindingInformation="*:60587:localhost" />
          <binding protocol="http" bindingInformation="*:60587:*" />
        </bindings>
      </site>
      . . .

ngrok の実行と動作確認

上記の ASP.NET Web アプリケーションを localhost で Debug 実行したら、ngrok をダウンロード (および展開) して、コマンド プロンプトから下記の通り実行する。(60587 は、この ASP.NET Web アプリケーションが実行されている IIS Express でのポート番号)
特に ASP.NET では、Host ヘッダーをちゃんと指定しないと Bad Request (400) になるので、下記の通り指定する。

ngrok http 60587 --host-header="localhost:60587"

上記の実行結果として下記の通り表示されるが、これは、インターネット上の http://ae8b8019.ngrok.io のアドレスが Tunnel されて http://localhost:60587 に行くよ、という意味。

Tunnel Status                 online
Version                       2.0.25/2.1.1
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://ae8b8019.ngrok.io -> localhost:60587
Forwarding                    https://ae8b8019.ngrok.io -> localhost:60587

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

そこで、あとは、ブレークポイントを置いて、http://ae8b8019.ngrok.io に接続すると、Tunnel されてきて、ちゃんとブレークポイントで止まる。

HTTP Capture

Web ブラウザを使って上記出力の http://127.0.0.1:4040 (http://localhost:4040) を表示すると、下図の通り HTTP Protocol (Raw) を Capture できる。
WebHook や BOT で、どのような request が来ているか簡単に確認可能だ。

HTTP_Capture

BOT 開発のように双方向連携をおこなうものは、この ngrok と Fiddler を一緒に使えば、inbound と outbound の双方がキャプチャーできるので、最強のデバッグ環境を手に入れることができる。

 

Office アドイン (JavaScript API for Office) をはじめる人の必読記事

Web の Office Add-in (Excel, Word, PowerPoint, Outlook, etc) をはじめる人のために「Office Add-ins とは ?」、「何ができるの ?」、「どう作るの ?」などをザッと読み物として短くまとめたので告知。(もう何ヶ月か前に記事追加したけど、今更告知ですみません 。。。)

連載1回「JavaScriptで誰でも簡単に作って稼げる Officeアドインとは?」
http://www.atmarkit.co.jp/ait/articles/1301/25/news063.html

連載2回「Office アドインの作り方と、できること/できないこと」
http://www.atmarkit.co.jp/ait/articles/1303/04/news091.html

連載3回「Office 2016 における Office アドイン進化のポイント」
http://www.atmarkit.co.jp/ait/articles/1601/15/news026.html

Office アドインは、Office が掲げるマルチ プラットフォーム戦略 (Mac でも、iPad でも、スマホでも、すべての人に快適に Office を使わせる戦略) に沿ったこれからの時代のアドインだ。