私はPythonでRESTサーバーを実行しています。アクセスポイントで画像を取得し、テンソルフローモデルを使用して画像上のものを予測します。サーバーを起動した後、イメージをRESTエンドポイントに送信しています。ロードされたモデルは、自分で訓練したインセプションモデルです。これはテンソルフローのチェックポイントファイルからロードされ、重みを復元します。計算後にGPUでTensoflowが動作しないようにします
import os
import tensorflow as tf
from cnn_server.server import file_service as dirs
from slim.datasets import dataset_utils
from slim.nets import nets_factory as network_factory
from slim.preprocessing import preprocessing_factory as preprocessing_factory
def inference_on_image(bot_id, image_file, network_name='inception_v4', return_labels=1):
model_path = dirs.get_model_data_dir(bot_id)
# Get number of classes to predict
protobuf_dir = dirs.get_protobuf_dir(bot_id)
number_of_classes = dataset_utils.get_number_of_classes_by_labels(protobuf_dir)
# Get the preprocessing and network construction functions
preprocessing_fn = preprocessing_factory.get_preprocessing(network_name, is_training=False)
network_fn = network_factory.get_network_fn(network_name, number_of_classes)
# Process the temporary image file into a Tensor of shape [widht, height, channels]
image_tensor = tf.gfile.FastGFile(image_file, 'rb').read()
image_tensor = tf.image.decode_image(image_tensor, channels=0)
# Perform preprocessing and reshape into [network.default_width, network.default_height, channels]
network_default_size = network_fn.default_image_size
image_tensor = preprocessing_fn(image_tensor, network_default_size, network_default_size)
# Create an input batch of size one from the preprocessed image
input_batch = tf.reshape(image_tensor, [1, 299, 299, 3])
# Create the network up to the Predictions Endpoint
logits, endpoints = network_fn(input_batch)
restorer = tf.train.Saver()
with tf.Session() as sess:
tf.global_variables_initializer().run()
# Restore the variables of the network from the last checkpoint and run the graph
restorer.restore(sess, tf.train.latest_checkpoint(model_path))
sess.run(endpoints)
# Get the numpy array of predictions out of the
predictions = endpoints['Predictions'].eval()[0]
sess.close()
return map_predictions_to_labels(protobuf_dir, predictions, return_labels)
私は、最先端のCCNののtensorflow実装のコレクションをtf.model.slim
を使用インセプションV4モデルのグラフを作成するには:ここでグラフを構築し、分類を実行機能があります。当初のモデルは、ここで構築されています:https://github.com/tensorflow/models/blob/master/slim/nets/inception_v4.pyをしてファクトリメソッドを介して提供:https://github.com/tensorflow/models/blob/master/slim/nets/nets_factory.py
期待どおりに動作everythig最初の画像の場合:
ValueError: Variable InceptionV4/Conv2d_1a_3x3/weights already exists, disallowed. Did you mean to set reuse=True in VarScope? Originally defined at:
:
2017-07-17 18:00:43.831365: I tensorflow/core/common_runtime/gpu/gpu_device.cc:908] DMA: 0
2017-07-17 18:00:43.831371: I tensorflow/core/common_runtime/gpu/gpu_device.cc:918] 0: Y
2017-07-17 18:00:43.831384: I tensorflow/core/common_runtime/gpu/gpu_device.cc:977] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1080, pci bus id: 0000:01:00.0)
192.168.0.192 - - [17/Jul/2017 18:00:46] "POST /classify/4 HTTP/1.1" 200 -
第二の画像は、次のエラーを作成します
これを私が理解するのは、グラフが最初に作成され、次にどこかに存在するということです。 2番目のイメージを送信すると、関数を再度呼び出すことになり、既存のグラフを再作成しようとするとエラーが発生します。今、私はいくつかのことを試してみました:
全体のTensorflowを停止: 私はtensorflow全体的に停止し、GPU上でデバイスを毎回再作成してみました。これは最善の解決策です。この方法では、サーバーが動作しているときにGPUがTensorflowによって占有されないためです。私はsess.close()
でそれをやろうとしましたが、うまくいきませんでした。 nvidia-smi
は、最初のイメージを処理した後もGPUでプロセスを表示します。何とかそのデバイスにアクセスしようとしましたが、利用できるデバイスの一覧はdevice_lib.list_local_devices()
で取得できます。しかし、これによってGPU上のテンソルフロープロセスを操作するオプションはありませんでした。サーバを停止すると、テンソルフローセッションを開始した初期のPythonスクリプトも、GPUのテンソルフローを強制終了します。各分類後にサーバーを再起動するのは、洗練された解決策ではありません。
グラフのリセットまたは削除 グラフをいくつかの方法でリセットしようとしました。しかし、エラーが同じまま、
graph = endpoints['Predictions'].graph
for key in graph.get_all_collection_keys():
graph.clear_collection(key)
デバッグがグラフコレクションはその後空であることを示しています。一つの方法は、私が実行していますテンソルからグラフを取得するすべてのコレクションを反復処理し、それらをクリアすることです。もう1つの方法は、デフォルトのグラフとしてwith graph.as_default:
というエンドポイントからグラフを設定することです。計算後にグラフが削除されることを期待しないうちにグラフが作成されているからです。それはしませんでした。
設定reuse=true
変数のスコープに変数のスコープは、あなたがinception_v4.py
で設定できるオプションの再利用を、持っています。
def inception_v4(inputs, num_classes=1001, is_training=True,
dropout_keep_prob=0.8,
reuse=None,
scope='InceptionV4',
create_aux_logits=True):
trueに設定すると、最初にグラフを作成する変数が存在しないというエラーが発生します。
それは私が考えるもう一つの方法は、 一度モデルを作成し、次にそれを再利用し resuing、一度モデルをロードする、すなわち、ネットワーク工場をもう一度呼び出すことは避けてください。これは、サーバーが複数のモデルを保持し、それぞれ異なる数のクラスで動作するため、問題があります。これは、これらのモデルのそれぞれについてグラフを作成し、それらをすべて生きて維持し、何らかの形で維持しなければならないことを意味します。これは可能ですが、モデルが常に同じで、重さと最終レイヤーが異なるだけなので、オーバーヘッドが大きくなり、いくぶん冗長です。重みは既にチェックポイントファイルに格納されており、実装ではtf.model.slim
を使用すると、出力のクラス数が異なるグラフを簡単に作成できます。
私はここでアイデアがありません。最も望ましい解決策は、GPU上でテンソルフローを完全に終了し、関数が呼び出されるたびにゼロからデバイスを再作成することです。
誰でも助けてくれることを願っています。
ありがとうございます。
返信用のタンク。グラフを再利用するということは、いくつかの非常に大きな開始v4モデルをメモリ内に保持することを意味します。それは私にとっては良い考えのようには思えません。特に、グラフを削除する手段を提供しているようです。また、テンソルフローが依然としてGPUを占めるという問題が残っている。標準的な設定では、その間に他のプロセスがGPU上で何もすることはできませんが、これも望ましくありません。私は推論の後に終了する専用のスレッドで関数を開始することを選択しました(私の答えは以下を参照)。それは私のためにはうまくいく。 – molig