Caffe2-quick-guide

提供:Dev Guides
移動先:案内検索

Caffe2-はじめに

ここ数年、ディープラーニングは機械学習の大きなトレンドになりました。 Vision、Speech Recognition、Natural Language Processing (NLP)でこれまで解決できなかった問題を解決するために適用されました。 ディープラーニングが適用されており、その有用性を示しているドメインはさらに多くあります。

  • Caffe(高速機能埋め込み用の畳み込みアーキテクチャ)は、 Berkeley Vision and Learning Center(BVLC)で開発された深層学習フレームワークです。 Caffeプロジェクトは、Ph.Dの間にYangqing Jiaによって作成されました。 カリフォルニア大学バークレー校。 Caffeは、ディープラーニングを試す簡単な方法を提供します。 C ++で記述されており、 *Python および Matlab のバインディングを提供します。

    *CNN* (Convolutional Neural Network)、 *LSTM* (Long Short Term Memory)、FC(Fully Connected)など、さまざまなタイプの深層学習アーキテクチャをサポートしています。 GPUをサポートしているため、ディープニューラルネットワークを含む本番環境に最適です。 また、 *NVIDIA* 、CUDA Deep Neural Networkライブラリ*(cuDNN)*、Intel Math Kernel Library *(Intel MKL)*などのCPUベースのカーネルライブラリもサポートしています。

2017年4月、米国 ベースのソーシャルネットワーキングサービス会社Facebookは、現在RNN(Recurrent Neural Networks)を含むCaffe2を発表し、2018年3月にCaffe2はPyTorchに統合されました。 Caffe2の作成者とコミュニティメンバーは、さまざまな問題を解決するためのモデルを作成しました。 これらのモデルは、事前にトレーニングされたモデルとして公開されています。 Caffe2は、作成者がこれらのモデルを使用し、データセットを予測するための独自のネットワークを作成するのに役立ちます。

Caffe2の詳細に入る前に、*機械学習*と*深層学習*の違いを理解しましょう。 これは、Caffe2でモデルが作成および使用される方法を理解するために必要です。

機械学習とディープラーニング

従来の機械学習アルゴリズムであれ、ディープラーニングであれ、機械学習アルゴリズムでは、データセット内の特徴の選択は、望ましい予測精度を得るために非常に重要な役割を果たします。 従来の機械学習技術では、*機能の選択*は、ほとんどが人間の検査、判断、およびドメインの深い知識によって行われます。 機能選択のためにテストされたいくつかのアルゴリズムから助けを求める場合があります。

従来の機械学習フローは、次の図に示されています-

機械学習

深層学習では、特徴選択は自動的に行われ、深層学習アルゴリズム自体の一部です。 これは以下の図に示されています-

ディープラーニング

深層学習アルゴリズムでは、*機能エンジニアリング*が自動的に行われます。 一般に、機能のエンジニアリングには時間がかかり、ドメインの優れた専門知識が必要です。 自動特徴抽出を実装するために、ディープラーニングアルゴリズムは通常大量のデータを要求するため、数千から数万のデータポイントしかない場合、ディープラーニング手法では満足のいく結果が得られない場合があります。

ディープラーニングアルゴリズムは、データが大きい場合、機能エンジニアリングが少ないかまったくないという利点が追加された従来のMLアルゴリズムと比較して、より良い結果をもたらします。

Caffe2-概要

ここで、ディープラーニングに関するいくつかの洞察を得たので、Caffeとは何かの概要を説明します。

CNNのトレーニング

画像を分類するためのCNNをトレーニングするプロセスを学びましょう。 プロセスは、次のステップで構成されています-

  • データの準備-このステップでは、トレーニングとテスト用のすべての画像が同じサイズになるように、画像を中央で切り取り、サイズを変更します。 これは通常、画像データに対して小さなPythonスクリプトを実行することにより行われます。
  • モデル定義-このステップでは、CNNアーキテクチャを定義します。 構成は* .pb(protobuf)*ファイルに保存されます。 典型的なCNNアーキテクチャを次の図に示します。
  • ソルバー定義-ソルバー構成ファイルを定義します。 ソルバーはモデルの最適化を行います。
  • モデルトレーニング-組み込みのCaffeユーティリティを使用してモデルをトレーニングします。 トレーニングには、かなりの時間とCPU使用率がかかる場合があります。 トレーニングが完了すると、Caffeはモデルをファイルに保存します。このファイルは、後でテストデータと予測の最終展開で使用できます。

トレーニングCNN

Caffe2の新機能

Caffe2には、すぐに使用できる多くの事前トレーニング済みモデルがあり、新しいモデルとアルゴリズムのコミュニティの貢献を非常に頻繁に活用します。 作成したモデルは、クラウドのGPUパワーを使用して簡単にスケールアップでき、クロスプラットフォームライブラリを使用してモバイルでの大衆の使用にまで縮小できます。

CaffeよりもCaffe2で行われた改善は、次のように要約することができます-

  • モバイル展開
  • 新しいハードウェアのサポート
  • 大規模な分散トレーニングのサポート
  • 量子化された計算
  • Facebookでストレステスト済み

事前学習済みモデルのデモ

Berkeley Vision and Learning Center(BVLC)サイトでは、事前にトレーニングされたネットワークのデモを提供しています。 このような画像分類のネットワークの1つは、https://caffe2.ai/docs/learn-more#null__caffe-neural-network-for-image-classificationに記載されているリンクから入手でき、下のスクリーンショットに示されています。

事前学習済みモデル

スクリーンショットでは、犬の画像が分類され、予測精度でラベル付けされています。 また、画像の分類に* 0.068秒*しかかからなかったとも述べています。 画面の下部にあるオプションで画像URLを指定するか、画像自体をアップロードすることにより、自分で選択した画像を試すことができます。

Caffe2-インストール

これで、Caffe2の機能について十分な洞察を得たので、今度は自分でCaffe2を実験してみましょう。 事前に訓練されたモデルを使用するか、独自のPythonコードでモデルを開発するには、まずマシンにCaffe2をインストールする必要があります。

リンクhttps://caffe2.ai/docs/getting-startedl?platform=mac&configuration=prebuilt[https://caffe2.ai/docs/getting-startedl]にあるCaffe2サイトのインストールページで、プラットフォームとインストールタイプを選択するには、次のようにします。

インストールページ

上記のスクリーンショットでわかるように、 Caffe2 は、モバイルプラットフォームを含むいくつかの一般的なプラットフォームをサポートしています。

ここで、このチュートリアルのすべてのプロジェクトがテストされる* MacOSインストール*の手順を理解します。

MacOSのインストール

インストールは以下に示すように4つのタイプにすることができます-

  • 事前に作成されたバイナリ
  • ソースからビルド
  • Dockerイメージ

好みに応じて、インストールタイプとして上記のいずれかを選択します。 ここに記載されている手順は、*ビルド済みバイナリ*用のCaffe2インストールサイトによるものです。 * Jupyter環境*にはAnacondaを使用します。 コンソールプロンプトで次のコマンドを実行します

pip install torch_nightly -f
https://download.pytorch.org/whl/nightly/cpu/torch_nightlyl

上記に加えて、次のコマンドを使用してインストールされるいくつかのサードパーティのライブラリが必要になります-

conda install -c anaconda setuptools
conda install -c conda-forge graphviz
conda install -c conda-forge hypothesis
conda install -c conda-forge ipython
conda install -c conda-forge jupyter
conda install -c conda-forge matplotlib
conda install -c anaconda notebook
conda install -c anaconda pydot
conda install -c conda-forge python-nvd3
conda install -c anaconda pyyaml
conda install -c anaconda requests
conda install -c anaconda scikit-image
conda install -c anaconda scipy

Caffe2 Webサイトのチュートリアルの一部では、次のコマンドを使用してインストールされる zeromq のインストールも必要です-

conda install -c anaconda zeromq

Windows/Linuxのインストール

コンソールプロンプトで次のコマンドを実行します-

conda install -c pytorch pytorch-nightly-cpu

お気づきのように、上記のインストールを使用するにはAnacondaが必要です。 * MacOSインストール*で指定されている追加パッケージをインストールする必要があります。

インストールのテスト

インストールをテストするために、小さなPythonスクリプトを以下に示します。これをJuypterプロジェクトでカットアンドペーストして実行できます。

from caffe2.python import workspace
import numpy as np
print ("Creating random data")
data = np.random.rand(3, 2)
print(data)
print ("Adding data to workspace ...")
workspace.FeedBlob("mydata", data)
print ("Retrieving data from workspace")
mydata = workspace.FetchBlob("mydata")
print(mydata)

上記のコードを実行すると、次の出力が表示されるはずです-

Creating random data
[[Adding data to workspace ...
Retrieving data from workspace
[[The screenshot of the installation test page is shown here for your quick reference −

image:/caffe2/testing_installation.jpg[Testing Installation]

Now, that you have installed Caffe2 on your machine, proceed to install the tutorial applications.

=== Tutorial Installation

Download the tutorials source using the following command on your console −

[source,result,notranslate]

git clone --recursive https://github.com/caffe2/tutorials caffe2_tutorials

After the download is completed, you will find several Python projects in the *caffe2_tutorials *folder in your installation directory. The screenshot of this folder is given for your quick perusal.

[source,result,notranslate]

/Users/yourusername/caffe2_tutorials

image:/caffe2/tutorial_installation.jpg[Tutorial Installation]

You can open some of these tutorials to see what the* Caffe2 code* looks like. The next two projects described in this tutorial are largely based on the samples shown above.

It is now time to do some Python coding of our own. Let us understand, how to use a pre-trained model from Caffe2. Later, you will learn to create your own trivial neural network for training on your own dataset.

Caffe2-事前学習済みモデルへのアクセスの検証

Pythonアプリケーションで事前に訓練されたモデルを使用することを学ぶ前に、まずモデルがマシンにインストールされ、Pythonコードを介してアクセス可能であることを確認しましょう。

Caffe2をインストールすると、事前にトレーニングされたモデルがインストールフォルダーにコピーされます。 Anacondaがインストールされているマシンでは、これらのモデルは次のフォルダーにあります。

anaconda3/lib/python3.7/site-packages/caffe2/python/models

これらのモデルの存在については、マシンのインストールフォルダを確認してください。 あなたは、次の短いPythonスクリプトでインストールフォルダからこれらのモデルをロードしてみることができます-

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)

スクリプトが正常に実行されると、次の出力が表示されます-

/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/init_net.pb
/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/predict_net.pb

これにより、 squeezenet モジュールがマシンにインストールされ、コードからアクセスできることが確認されます。

これで、Caffe2 squeezenet 事前学習済みモジュールを使用して画像分類用の独自のPythonコードを作成する準備が整いました。

事前学習済みモデルを使用した画像分類

このレッスンでは、事前に訓練されたモデルを使用して、特定の画像内のオブジェクトを検出する方法を学習します。 squeezenet 事前学習済みモジュールを使用して、特定の画像内のオブジェクトを非常に正確に検出および分類します。

新しい Juypter Notebook を開き、手順に従ってこの画像分類アプリケーションを開発します。

ライブラリのインポート

まず、以下のコードを使用して必要なパッケージをインポートします-

from caffe2.proto import caffe2_pb2
from caffe2.python import core, workspace, models
import numpy as np
import skimage.io
import skimage.transform
from matplotlib import pyplot
import os
import urllib.request as urllib2
import operator

次に、いくつかの*変数*を設定します-

INPUT_IMAGE_SIZE = 227
mean = 128

トレーニングに使用される画像は明らかにさまざまなサイズになります。 これらすべての画像は、正確なトレーニングのために固定サイズに変換する必要があります。 同様に、テスト環境と実稼働環境で予測するイメージも、トレーニング中に使用したものと同じサイズに変換する必要があります。 したがって、値 227 を持つ INPUT_IMAGE_SIZE という上記の変数を作成します。 したがって、すべての画像をサイズ 227x227 に変換してから、分類器で使用します。

また、値 128 を持つ mean という変数を宣言します。この変数は、後で分類結果を改善するために使用されます。

次に、画像を処理するための2つの関数を開発します。

画像処理

画像処理は2つのステップで構成されます。 1つ目は画像のサイズを変更することであり、2つ目は画像を中央でトリミングすることです。 これらの2つのステップでは、サイズ変更とトリミングのための2つの関数を作成します。

画像のサイズ変更

最初に、画像のサイズを変更する関数を作成します。 前述のように、画像のサイズを 227x227 に変更します。 だから私たちは次のように関数*リサイズ*を定義しましょう-

def resize(img, input_height, input_width):

幅を高さで割ることにより、画像のアスペクト比を取得します。

original_aspect = img.shape[1]/float(img.shape[0])

アスペクト比が1より大きい場合、画像が広いこと、つまりランドスケープモードであることを示します。 私たちは今、次のコードを使用して画像の高さを調整し、サイズ変更された画像を返します-

if(original_aspect>1):
   new_height = int(original_aspect * input_height)
   return skimage.transform.resize(img, (input_width,
   new_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

アスペクト比が 1 未満の場合、*縦モード*を示します。 次のコードを使用して幅を調整します-

if(original_aspect<1):
   new_width = int(input_width/original_aspect)
   return skimage.transform.resize(img, (new_width,
   input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

アスペクト比が 1 の場合、高さ/幅の調整は行われません。

if(original_aspect == 1):
   return skimage.transform.resize(img, (input_width,
   input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

完全な機能コードは、クイックリファレンスのために以下に示されています-

def resize(img, input_height, input_width):
   original_aspect = img.shape[1]/float(img.shape[0])
   if(original_aspect>1):
      new_height = int(original_aspect * input_height)
      return skimage.transform.resize(img, (input_width,
       new_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)
   if(original_aspect<1):
         new_width = int(input_width/original_aspect)
         return skimage.transform.resize(img, (new_width,
         input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)
   if(original_aspect == 1):
         return skimage.transform.resize(img, (input_width,
         input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

次に、画像の中心を切り取るための関数を作成します。

画像のトリミング

次のように crop_image 関数を宣言します-

def crop_image(img,cropx,cropy):

私たちは次のステートメントを使用して画像の寸法を抽出します-

y,x,c = img.shape

次の2行のコードを使用して、画像の新しい開始点を作成します-

startx = x//2-(cropx//2)
starty = y//2-(cropy//2)

最後に、新しい次元で画像オブジェクトを作成することにより、トリミングされた画像を返します-

return img[starty:starty+cropy,startx:startx+cropx]

クイックリファレンスのために、機能コード全体を以下に示します-

def crop_image(img,cropx,cropy):
   y,x,c = img.shape
   startx = x//2-(cropx//2)
   starty = y//2-(cropy//2)
   return img[starty:starty+cropy,startx:startx+cropx]

次に、これらの機能をテストするコードを作成します。

画像処理

まず、画像ファイルをプロジェクトディレクトリ内の images サブフォルダーにコピーします。 tree.jpg ファイルがプロジェクトにコピーされます。 次のPythonコードは画像を読み込み、コンソールに表示します-

img = skimage.img_as_float(skimage.io.imread("images/tree.jpg")).astype(np.float32)
print("Original Image Shape: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Original image')

出力は次のとおりです-

画像の処理

元の画像のサイズは 600 x 960 であることに注意してください。 このサイズを 227 x 227 の仕様に合わせて変更する必要があります。 以前に定義した* resize *関数を呼び出すと、このジョブが実行されます。

img = resize(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after resizing: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Resized image')

出力は以下のとおりです-

元の画像

画像サイズは 227 x 363 になりました。 アルゴリズムへの最終フィードのために、これを 227 x 227 にトリミングする必要があります。 この目的のために、以前に定義されたクロップ関数を呼び出します。

img = crop_image(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after cropping: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Center Cropped')

以下は、コードの出力です-

画像のトリミング

この時点で、画像のサイズは 227 x 227 であり、さらに処理する準備ができています。 画像軸を交換して、3つの色を3つの異なるゾーンに抽出します。

img = img.swapaxes(1, 2).swapaxes(0, 1)
print("CHW Image Shape: " , img.shape)

以下が出力です-

CHW Image Shape: (3, 227, 227)

最後の軸が配列の最初の次元になっていることに注意してください。 次のコードを使用して3つのチャネルをプロットします-

pyplot.figure()
for i in range(3):
   pyplot.subplot(1, 3, i+1)
   pyplot.imshow(img[i])
   pyplot.axis('off')
   pyplot.title('RGB channel %d' % (i+1))

出力は以下のとおりです-

寸法

最後に、次の3行のコードを使用して、 Red Green Blue を* Blue Green Red(RGBからBGR)*に変換し、より良い結果を得るために平均値を削除し、バッチサイズ軸を追加するなど、画像に対していくつかの追加処理を行います-

# convert RGB --> BGR
img = img[(2, 1, 0), :, :]
# remove mean
img = img * 255 - mean
# add batch size axis
img = img[np.newaxis, :, :, :].astype(np.float32)

この時点で、画像は* NCHW形式*であり、ネットワークに送信する準備ができています。 次に、事前に訓練されたモデルファイルを読み込み、予測のために上記の画像をそのファイルにフィードします。

処理されたイメージ内のオブジェクトの予測

最初に、Caffeの事前トレーニングモデルで定義された init および predict ネットワークのパスを設定します。

モデルファイルパスの設定

前の説明から、事前に訓練されたモデルはすべて models フォルダーにインストールされていることを思い出してください。 次のようにこのフォルダへのパスを設定します-

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")

次のように、 squeezenet モデルの init_net protobufファイルへのパスを設定します-

INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')

同様に、次のように predict_net protobufへのパスを設定します-

PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')

診断目的で2つのパスを印刷します-

print(INIT_NET)
print(PREDICT_NET)

出力と一緒に上記のコードは、あなたのクイックリファレンスのためにここに与えられています-

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)

出力は以下に記載されています-

/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/init_net.pb
/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/predict_net.pb

次に、予測変数を作成します。

予測子の作成

私たちは次の2つのステートメントを使用してモデルファイルを読み取ります-

with open(INIT_NET, "rb") as f:
   init_net = f.read()
with open(PREDICT_NET, "rb") as f:
   predict_net = f.read()

予測子は、2つのファイルへのポインターをパラメーターとして Predictor 関数に渡すことによって作成されます。

p = workspace.Predictor(init_net, predict_net)
*p* オブジェクトは予測子であり、任意の画像内のオブジェクトを予測するために使用されます。 各入力画像は、 *tree.jpg* ファイルに対して以前に行ったように、NCHW形式でなければならないことに注意してください。

オブジェクトの予測

特定の画像内のオブジェクトを予測するのは簡単です。コマンドを1行実行するだけです。 特定の画像でオブジェクトを検出するために、 predictor オブジェクトで run メソッドを呼び出します。

results = p.run({'data': img})

予測結果は results オブジェクトで利用できるようになりました。これを読みやすくするために配列に変換します。

results = np.asarray(results)

次のステートメントを使用して理解のために配列の次元を印刷します-

print("results shape: ", results.shape)

出力は次のようになります-

results shape: (1, 1, 1000, 1, 1)

ここで不要な軸を削除します-

preds = np.squeeze(results)
*preds* 配列の *max* 値を取得することで、最上位の述語を取得できるようになりました。
curr_pred, curr_conf = max(enumerate(preds), key=operator.itemgetter(1))
print("Prediction: ", curr_pred)
print("Confidence: ", curr_conf)

出力は次のとおりです-

Prediction: 984
Confidence: 0.89235985

ご覧のように、モデルはインデックス値 984 のオブジェクトを* 89%*の信頼度で予測しています。 984のインデックスは、検出されたオブジェクトの種類を理解する上であまり意味がありません。 インデックス値を使用して、オブジェクトの文字列化された名前を取得する必要があります。 モデルが認識するオブジェクトの種類とそれに対応するインデックス値は、githubリポジトリで利用できます。

ここで、984のインデックス値を持つオブジェクトの名前を取得する方法を確認します。

結果の文字列化

次のようにgithubリポジトリへのURLオブジェクトを作成します-

codes = "https://gist.githubusercontent.com/aaronmarkham/cd3a6b6ac0
71eca6f7b4a6e40e6038aa/raw/9edb4038a37da6b5a44c3b5bc52e448ff09bfe5b/alexnet_codes"

私たちはURLの内容を読みます-

response = urllib2.urlopen(codes)

応答には、すべてのコードとその説明のリストが含まれます。 応答のいくつかの行は、それが何を含むかを理解するために以下に示されています-

5: 'electric ray, crampfish, numbfish, torpedo',
6: 'stingray',
7: 'cock',
8: 'hen',
9: 'ostrich, Struthio camelus',
10: 'brambling, Fringilla montifringilla',

次のように for ループを使用して、配列全体を反復処理して984の目的のコードを見つけます-

for line in response:
   mystring = line.decode('ascii')
   code, result = mystring.partition(":")[::2]
   code = code.strip()
   result = result.replace("'", "")
   if (code == str(curr_pred)):
      name = result.split(",")[0][1:]
      print("Model predicts", name, "with", curr_conf, "confidence")

あなたがコードを実行すると、次の出力が表示されます-

Model predicts rapeseed with 0.89235985 confidence

これで、別の画像でモデルを試すことができます。

別の画像を予測する

別の画像を予測するには、画像ファイルをプロジェクトディレクトリの images フォルダーにコピーするだけです。 これは、以前の tree.jpg ファイルが保存されているディレクトリです。 コード内の画像ファイルの名前を変更します。 以下に示すように、必要な変更は1つだけです

img = skimage.img_as_float(skimage.io.imread("images/pretzel.jpg")).astype(np.float32)

元の画像と予測結果を以下に示します-

予測画像

出力は以下に記載されています-

Model predicts pretzel with 0.99999976 confidence

ご覧のとおり、事前学習済みのモデルは、指定された画像内のオブジェクトを非常に正確に検出できます。

完全なソース

所定の画像内のオブジェクト検出に事前に訓練されたモデルを使用する上記のコードの完全なソースは、クイックリファレンスのためにここに記載されています-

def crop_image(img,cropx,cropy):
   y,x,c = img.shape
   startx = x//2-(cropx//2)
   starty = y//2-(cropy//2)
   return img[starty:starty+cropy,startx:startx+cropx]
img = skimage.img_as_float(skimage.io.imread("images/pretzel.jpg")).astype(np.float32)
print("Original Image Shape: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Original image')
img = resize(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after resizing: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Resized image')
img = crop_image(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after cropping: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Center Cropped')
img = img.swapaxes(1, 2).swapaxes(0, 1)
print("CHW Image Shape: " , img.shape)
pyplot.figure()
for i in range(3):
pyplot.subplot(1, 3, i+1)
pyplot.imshow(img[i])
pyplot.axis('off')
pyplot.title('RGB channel %d' % (i+1))
# convert RGB --> BGR
img = img[(2, 1, 0), :, :]
# remove mean
img = img * 255 - mean
# add batch size axis
img = img[np.newaxis, :, :, :].astype(np.float32)
CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)
with open(INIT_NET, "rb") as f:
   init_net = f.read()
with open(PREDICT_NET, "rb") as f:
   predict_net = f.read()
p = workspace.Predictor(init_net, predict_net)
results = p.run({'data': img})
results = np.asarray(results)
print("results shape: ", results.shape)
preds = np.squeeze(results)
curr_pred, curr_conf = max(enumerate(preds), key=operator.itemgetter(1))
print("Prediction: ", curr_pred)
print("Confidence: ", curr_conf)
codes = "https://gist.githubusercontent.com/aaronmarkham/cd3a6b6ac071eca6f7b4a6e40e6038aa/raw/9edb4038a37da6b5a44c3b5bc52e448ff09bfe5b/alexnet_codes"
response = urllib2.urlopen(codes)
for line in response:
   mystring = line.decode('ascii')
   code, result = mystring.partition(":")[::2]
   code = code.strip()
   result = result.replace("'", "")
   if (code == str(curr_pred)):
      name = result.split(",")[0][1:]
      print("Model predicts", name, "with", curr_conf, "confidence")

この時点で、事前学習済みモデルを使用してデータセットの予測を行う方法がわかっています。

次は、 Caffe2 で*ニューラルネットワーク(NN)*アーキテクチャを定義し、データセットでトレーニングする方法を学習します。 ここで、単純な単一層NNを作成する方法を学習します。

Caffe2-独自のネットワークの作成

このレッスンでは、Caffe2で*シングルレイヤーニューラルネットワーク(NN)を定義し、ランダムに生成されたデータセットで実行する方法を学習します。 ネットワークアーキテクチャ、印刷入力、出力、重み、およびバイアス値をグラフィカルに描写するコードを作成します。 このレッスンを理解するには、*ニューラルネットワークアーキテクチャ、それらで使用される*用語*および*数学*に精通している必要があります。

ネットワークアーキテクチャ

次の図に示すように、単一層NNを構築したいと考えてみましょう-

ネットワークアーキテクチャ

数学的には、このネットワークは次のPythonコードで表されます-

Y = X * W^T + b

ここで、 X、W、b はテンソル、 Y は出力です。 3つのテンソルすべてにランダムデータを入力し、ネットワークを実行して Y 出力を調べます。 ネットワークとテンソルを定義するために、Caffe2はいくつかの*演算子*関数を提供します。

Caffe2オペレーター

Caffe2では、 Operator は計算の基本単位です。 Caffe2 *演算子*は次のように表されます。

Caffe2オペレーター

Caffe2は、オペレーターの包括的なリストを提供します。 現在設計しているネットワークでは、FCと呼ばれる演算子を使用します。これは、入力ベクトル X を2次元の重み行列 W と1次元のバイアスで完全に接続されたネットワークに渡す結果を計算しますベクトル b 。 つまり、次の数式を計算します

Y = X * W^T + b
*X* の寸法は*(M x k)、W *の寸法は*(n x k)*、 *b* は*(1 x n)*です。 出力 *Y* の次元は*(M x n)*です。ここで、 *M* はバッチサイズです。

ベクトル X および W の場合、 GaussianFill 演算子を使用してランダムデータを作成します。 バイアス値 b を生成するには、 ConstantFill 演算子を使用します。

次に、ネットワークの定義に進みます。

ネットワークを作成する

まず、必要なパッケージをインポートします-

from caffe2.python import core, workspace

次に、次のように core.Net を呼び出してネットワークを定義します-

net = core.Net("SingleLayerFC")

ネットワークの名前は SingleLayerFC として指定されます。 この時点で、netというネットワークオブジェクトが作成されます。 これまでのところ、レイヤーは含まれていません。

テンソルの作成

ここで、ネットワークに必要な3つのベクトルを作成します。 まず、次のように GaussianFill 演算子を呼び出してXテンソルを作成します-

X = net.GaussianFill([], ["X"], mean=0.0, std=1.0, shape=[2, 3], run_once=0)
*X* ベクトルの次元は *2 x 3* で、平均データ値は0,0、標準偏差は *1.0* です。

同様に、次のように W テンソルを作成します-

W = net.GaussianFill([], ["W"], mean=0.0, std=1.0, shape=[5, 3], run_once=0)
*W* ベクトルのサイズは *5 x 3* です。

最後に、サイズ5のバイアス b 行列を作成します。

b = net.ConstantFill([], ["b"], shape=[5,], value=1.0, run_once=0)

さて、コードの最も重要な部分が来て、それはネットワーク自体を定義しています。

ネットワークの定義

私たちは次のPythonステートメントでネットワークを定義します-

Y = X.FC([W, b], ["Y"])

入力データ XFC 演算子を呼び出します。 重みは W で指定され、バイアスはbで指定されます。 出力は Y です。 または、次のPythonステートメントを使用してネットワークを作成することもできますが、これはより冗長です。

Y = net.FC([X, W, b], ["Y"])

この時点で、ネットワークは単純に作成されます。 ネットワークを少なくとも1回実行するまで、データは含まれません。 ネットワークを実行する前に、そのアーキテクチャを調べます。

印刷ネットワークアーキテクチャ

Caffe2は、作成された net オブジェクトでProtoメソッドを呼び出すことで確認できるJSONファイルでネットワークアーキテクチャを定義します。

print (net.Proto())

これは、次の出力を生成します-

name: "SingleLayerFC"
op {
   output: "X"
   name: ""
   type: "GaussianFill"
   arg {
      name: "mean"
      f: 0.0
   }
   arg {
      name: "std"
      f: 1.0
   }
   arg {
      name: "shape"
      ints: 2
      ints: 3
   }
   arg {
      name: "run_once"
      i: 0
   }
}
op {
   output: "W"
   name: ""
   type: "GaussianFill"
   arg {
      name: "mean"
      f: 0.0
   }
   arg {
      name: "std"
      f: 1.0
   }
   arg {
      name: "shape"
      ints: 5
      ints: 3
   }
   arg {
      name: "run_once"
      i: 0
   }
}
op {
   output: "b"
   name: ""
   type: "ConstantFill"
   arg {
      name: "shape"
      ints: 5
   }
   arg {
      name: "value"
      f: 1.0
   }
   arg {
      name: "run_once"
      i: 0
   }
}
op {
   input: "X"
   input: "W"
   input: "b"
   output: "Y"
   name: ""
   type: "FC"
}

上記のリストでわかるように、最初に演算子 X、W および b を定義します。 例として W の定義を調べてみましょう。 W のタイプは GausianFill として指定されます。 平均*はフロート *0.0 として定義され、標準偏差はフロート 1.0 として定義され、形状*は *5 x 3 です。

op {
   output: "W"
   name: "" type: "GaussianFill"
   arg {
      name: "mean"
       f: 0.0
   }
   arg {
      name: "std"
      f: 1.0
   }
   arg {
      name: "shape"
      ints: 5
      ints: 3
   }
   ...
}

あなた自身の理解のために Xb の定義を調べてください。 最後に、ここで再現されている単一層ネットワークの定義を見てみましょう。

op {
   input: "X"
   input: "W"
   input: "b"
   output: "Y"
   name: ""
   type: "FC"
}

ここでは、ネットワークタイプは FC (完全接続)で、入力として X、W、bY が出力です。 このネットワーク定義は冗長すぎるため、大規模なネットワークの場合、その内容を調べるのは退屈になります。 幸いなことに、Caffe2は作成されたネットワークのグラフィカルな表現を提供します。

ネットワークのグラフィカル表現

ネットワークのグラフィカルな表現を取得するには、次のコードスニペットを実行します。これは基本的にPythonコードの2行のみです。

from caffe2.python import net_drawer
from IPython import display
graph = net_drawer.GetPydotGraph(net, rankdir="LR")
display.Image(graph.create_png(), width=800)

あなたがコードを実行すると、次の出力が表示されます-

グラフィック表現

大規模なネットワークの場合、グラフィック表示はネットワーク定義エラーの視覚化とデバッグに非常に役立ちます。

最後に、ネットワークを実行します。

ランニングネットワーク

*workspace* オブジェクトで *RunNetOnce* メソッドを呼び出してネットワークを実行します-
workspace.RunNetOnce(net)

ネットワークが1回実行されると、ランダムに生成されるすべてのデータが作成され、ネットワークに供給されて出力が作成されます。 ネットワークの実行後に作成されるテンソルは、Caffe2では blobs と呼ばれます。 ワークスペースは、作成してメモリに保存する blobs で構成されます。 これはMatlabに非常に似ています。

ネットワークを実行した後、次の print コマンドを使用して、ワークスペースに含まれる blobs を調べることができます。

print("Blobs in the workspace: {}".format(workspace.Blobs()))

次の出力が表示されます-

Blobs in the workspace: ['W', 'X', 'Y', 'b']

ワークスペースは、 X、Wb の3つの入力BLOBで構成されていることに注意してください。 また、 Y という出力BLOBが含まれています。 これらのブロブの内容を調べてみましょう。

for name in workspace.Blobs():
   print("{}:\n{}".format(name, workspace.FetchBlob(name)))

次の出力が表示されます-

W:
[[X:
[[e+00 1.5279824e+00 1.1889904e+00]
[ 6.7048723e-01 -9.7490678e-04 2.5114202e-01]]
Y:
[[b:
[1. 1. 1. 1. 1.]

すべての入力がランダムに作成されるため、マシン上のデータまたは実際にはネットワークの実行ごとのデータは異なることに注意してください。 これで、ネットワークが正常に定義され、コンピューターで実行されました。

Caffe2-複雑なネットワークの定義

前のレッスンでは、ささいなネットワークを作成し、それを実行してその出力を調べる方法を学びました。 複雑なネットワークを作成するプロセスは、上記のプロセスに似ています。 Caffe2は、複雑なアーキテクチャを作成するための膨大な演算子セットを提供します。 演算子のリストについては、Caffe2のドキュメントを確認することをお勧めします。 さまざまなオペレーターの目的を研究した後、あなたは複雑なネットワークを作成し、それらを訓練することができます。 ネットワークのトレーニングのために、Caffe2はいくつかの*事前定義された計算ユニット*-演算子を提供します。 解決しようとしている種類の問題に合わせてネットワークをトレーニングするための適切なオペレーターを選択する必要があります。

ネットワークが満足のいくようにトレーニングされると、前に使用した事前トレーニング済みモデルファイルと同様のモデルファイルに保存できます。 これらのトレーニングされたモデルは、他のユーザーの利益のためにCaffe2リポジトリに提供される場合があります。 または、トレーニング済みのモデルを自分の本番用に配置することもできます。

概要

ディープラーニングフレームワークであるCaffe2では、データを予測するためにいくつかの種類のニューラルネットワークを試すことができます。 Caffe2サイトは、多くの事前トレーニングモデルを提供します。 特定の画像内のオブジェクトを分類するために、事前に訓練されたモデルの1つを使用することを学びました。 また、選択したニューラルネットワークアーキテクチャを定義することも学びました。 このようなカスタムネットワークは、Caffeの多くの事前定義された演算子を使用してトレーニングできます。 トレーニングされたモデルは、実稼働環境に取り込むことができるファイルに保存されます。