2017-09-13 3 views
0

私は現在、Tensorflowライブラリに精通していますが、私はバグという根本的な疑問を持っています。Tensorflow:レイヤーサイズはバッチサイズに依存しますか?

MNIST分類用の畳み込みニューラルネットワークを構築しているうちに、自分のmodel_fnを使用しようとしました。通常、次の行が入力フィーチャの形状を変更するために発生します。

であり、-1は入力バッチサイズを表します。

私は私の畳み込み層への入力として、このノードを使用しているので、

x = tf.reshape(x, shape=[-1, 28, 28, 1]) 
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu) 

は、このサイズのすべての私のネットワーク層は、バッチサイズに依存していることを意味するのでしょうか?

私はn = batch_sizeテストイメージを提供する場合にのみ動作する、単一のテスト入力でグラフをフリーズして実行しようとしました。

予測中に入力バッチサイズでネットワークを実行する方法に関するヒントを教えてもらえますか? また、ネットワーク定義のtf.reshapeノード(最初のノードはcnn_layoutを参照)を使用するのが最良の入力ではないと思います。

私は私のネットワーク層アップとmodel_fn

def cnn_layout(features,reuse,is_training): 
with tf.variable_scope('cnn',reuse=reuse): 
    # resize input to [batchsize,height,width,channel] 
    x = tf.reshape(features['x'], shape=[-1,30,30,1], name='input_placeholder') 
    # conv1, 32 filter, 5 kernel 
    conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu, name='conv1') 
    # pool1, 2 stride, 2 kernel 
    pool1 = tf.layers.max_pooling2d(conv1, 2, 2, name='pool1') 
    # conv2, 64 filter, 3 kernel 
    conv2 = tf.layers.conv2d(pool1, 64, 3, activation=tf.nn.relu, name='conv2') 
    # pool2, 2 stride, 2 kernel 
    pool2 = tf.layers.max_pooling2d(conv2, 2, 2, name='pool2') 
    # flatten pool2 
    flatten = tf.contrib.layers.flatten(pool2) 
    # fc1 with 1024 neurons 
    fc1 = tf.layers.dense(flatten, 1024, name='fc1') 
    # 75% dropout 
    drop = tf.layers.dropout(fc1, rate=0.75, training=is_training, name='dropout') 
    # output logits 
    output = tf.layers.dense(drop, 1, name='output_logits') 
    return output 


def model_fn(features, labels, mode): 
    # setup two networks one for training one for prediction while sharing weights 
    logits_train = cnn_layout(features=features,reuse=False,is_training=True) 
    logits_test = cnn_layout(features=features,reuse=True,is_training=False) 

    # predictions 
    predictions = tf.round(tf.sigmoid(logits_test),name='predictions') 
    if mode == tf.estimator.ModeKeys.PREDICT: 
     return tf.estimator.EstimatorSpec(mode, predictions=predictions) 

    # define loss and optimizer 
    loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits_train,labels=labels),name='loss') 
    optimizer = tf.train.AdamOptimizer(learning_rate=LEARNING_RATE, name='optimizer') 
    train = optimizer.minimize(loss, global_step=tf.train.get_global_step(),name='train') 

    # accuracy for evaluation 
    accuracy = tf.metrics.accuracy(labels=labels,predictions=predictions,name='accuracy') 

    # summarys for tensorboard 
    tf.summary.scalar('loss',loss) 

    # return training and evalution spec 
    return tf.estimator.EstimatorSpec(
     mode=mode, 
     predictions=predictions, 
     loss=loss, 
     train_op=train, 
     eval_metric_ops={'accuracy':accuracy} 
    ) 

感謝を追加します!

答えて

0

解決策を簡単に提供したいだけです。以来、私はスケーラブルな生産グレードモデルを構築するのではなく、ローカルでCNNを実行するためのPythonの単純なモデルランナーを作りたいと思っていました。私はtensorflow予測クラスを使用

input_size = 900 

def serving_input_receiver_fn(): 
    inputs = {"x": tf.placeholder(shape=[None, input_size], dtype=tf.float32)} 
    return tf.estimator.export.ServingInputReceiver(inputs, inputs) 

model.export_savedmodel(
    export_dir_base=model_dir, 
    serving_input_receiver_fn=serving_input_receiver_fn) 

ロードし、それを実行するには(再びモデル定義を必要とせずに)

私が使用したモデルをエクスポートするには、。 f.write:Fとして(output_path、 "WB")tf.gfile.GFileで `呼び出し、その後、私はserving_input_receiverを使用していないが、私は` graph_util.convert_variables_to_constantsを(使用してグラフを凍結) `と

from tensorflow.contrib import predictor 

class TFRunner: 
    """ runs a frozen cnn graph """ 
    def __init__(self,model_dir): 
     self.predictor = predictor.from_saved_model(model_dir) 

    def run(self, input_list): 
     """ runs the input list through the graph, returns output """ 
     if len(input_list) > 1: 
      inputs = np.vstack(input_list) 
      predictions = self.predictor({"x": inputs}) 
     elif len(input_list) == 1: 
      predictions = self.predictor({"x": input_list[0]}) 
     else: 
      predictions = [] 
     return predictions 
1

features['x']のランクは、すでに外径がで、実際のバッチサイズはです。したがって、サイズを変更する必要はありません。

私は説明しようとしましょう。

まだserving_input_receiver_fnは表示されていません。また、いくつかの方法がありますが、最終的には原理はすべて同じです。 TensorFlow Servingを使用している場合は、恐らくbuild_parsing_serving_input_receiver_fnを使用します。これは、ソースコードを見て有益だ:

def build_parsing_serving_input_receiver_fn(feature_spec, 
              default_batch_size=None):  
    serialized_tf_example = array_ops.placeholder(
     dtype=dtypes.string, 
     shape=[default_batch_size],          
     name='input_example_tensor') 
    receiver_tensors = {'examples': serialized_tf_example} 
    features = parsing_ops.parse_example(serialized_tf_example, feature_spec) 
    return ServingInputReceiver(features, receiver_tensors) 

は、だからあなたのクライアントでは、1つまたは複数のその中にExample S(のは、長さがNあるとしましょう)を持つリクエストを準備するつもりです。サーバーは、シリアライズされた例を、input_example_tensorプレースホルダーに「フィードされた」文字列のリストとして扱います。形状(None)は動的にリストのサイズ(N)になります。

次に、parse_example opは、プレースホルダ内の各アイテムを解析し、外形寸法がNである各フィーチャに対してTensorをポップアウトします。あなたの場合は、形状= [N、30、30、1]のxになります。

(CloudML Engineなどの他のサービスシステムはExampleオブジェクトでは動作しませんが、原則は同じです)。

+0

(output_graph_def.SerializeToString()) 'を実行します。しかし、私はこれもグラフにミニサイズのサイズを凍結すると思います。 だから明確にする。私は訓練されたモデルを実行するために標準的なテンソルフローライブラリの代わりにサーババックエンドを提供する必要がありますか?私のモデルは本当に小さく、非常に高速に実行する必要があるので、私はかなりリーンなソリューションを探しています。 – openloop

+0

グラフをフリーズしてバッチサイズをグラフにフリーズするかどうかはわかりません。私はそれをすべきではないと言いたい。サーバーのバックエンドなしで比較的簡単に訓練モデルを実行できることに注意してください。モデルをSavedModelとしてエクスポートすることをお勧めします(グラフはフリーズできます)。これにより、移植性が向上し、より良い移植性のライブラリが提供されます(必要に応じて、より高度な提供ソリューションに簡単に卒業するオプションもあります)。 SavedModelで予測を行う方法については、https://stackoverflow.com/a/46139198/1399222をご覧ください。 – rhaertel80

+0

SavedModelを使いたくない場合は、基本的な考え方は 'tensorflow.python.training.saver.import_meta_graph'を使用し、' session.Run'を使用して入力をフィードし、出力をフェッチすることです。そのトリックは、入力と出力のテンソルの正しい名前を取得しています。 – rhaertel80

関連する問題