1

我試圖重新訓練(讀取微調)MobileNet圖像分類器。Tensorflow:同一圖像的不同激活值

由張量流here(來自tutorial)給出的再訓練腳本僅更新新添加的完全連接圖層的權重。我修改了這個腳本來更新預訓練模型的所有圖層的權重。我正在使用MobileNet架構,深度倍數爲0.25,輸入尺寸爲128.

但是,在重新訓練時,我觀察到一個奇怪的現象,如果我將某個特定圖像作爲批量推理的輸入與其他圖像進行比較,一些圖層後的值與圖像單獨傳遞時的值不同。同樣來自不同批次的相同圖像的激活值也是不同的。示例 - 對於兩批 - batch_1 : [img1, img2, img3]; batch_2 : [img1, img4, img5]。 img1的激活與兩個批次都不同。

這裏是我使用的推理碼 -

for tf.Session(graph=tf.get_default_graph()) as sess: 
    image_path = '/tmp/images/10dsf00003.jpg' 
    id_ = gfile.FastGFile(image_path, 'rb').read() 

    #The line below loads the jpeg using tf.decode_jpeg and does some preprocessing 
    id = sess.run(decoded_image_tensor, {jpeg_data_tensor: id_}) 

    input_image_tensor = graph.get_tensor_by_name('input') 

    layerXname='MobilenetV1/MobilenetV1/Conv2d_1_depthwise/Relu:0' #Name of the layer whose activations to inspect. 
    layerX = graph.get_tensor_by_name(layerXname) 
    layerXactivations=sess.run(layerX, {input_image_tensor: id}) 

上面的代碼與在最後一行以下變化一次,因爲它是,一旦執行:

layerXactivations_batch=sess.run(layerX, {input_image_tensor: np.asarray([np.squeeze(id), np.squeeze(id), np.squeeze(id)])}) 

以下是一些圖中的節點:

[u'input', u'MobilenetV1/Conv2d_0/weights', u'MobilenetV1/Conv2d_0/weights/read', u'MobilenetV1/MobilenetV1/Conv2d_0/convolution', u'MobilenetV1/Conv2d_0/BatchNorm/beta', u'MobilenetV1/Conv2d_0/BatchNorm/beta/read', u'MobilenetV1/Conv2d_0/BatchNorm/gamma', u'MobilenetV1/Conv2d_0/BatchNorm/gamma/read', u'MobilenetV1/Conv2d_0/BatchNorm/moving_mean', u'MobilenetV1/Conv2d_0/BatchNorm/moving_mean/read', u'MobilenetV1/Conv2d_0/BatchNorm/moving_variance', u'MobilenetV1/Conv2d_0/BatchNorm/moving_variance/read', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/add/y', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/add', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/Rsqrt', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/mul', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/mul_1', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/mul_2', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/sub', u'MobilenetV1/MobilenetV1/Conv2d_0/BatchNorm/batchnorm/add_1', u'MobilenetV1/MobilenetV1/Conv2d_0/Relu6', u'MobilenetV1/Conv2d_1_depthwise/depthwise_weights', u'MobilenetV1/Conv2d_1_depthwise/depthwise_weights/read', ... ...] 

現在,當layerXname = 'MobilenetV1/MobilenetV1/Conv2d_0/convolution' 上述兩種激活方式都是相同的。 (即 layerxactivations和layerxactivations_batch [0]相同)。 但是在此圖層之後,所有圖層都具有不同的激活值。我覺得'MobilenetV1/MobilenetV1/Conv2d_0/convolution'層對於批量輸入和單個圖像的batchNorm操作有所不同。還是由其他問題引起的問題?

任何幫助/指針,將不勝感激。

回答

0

當您構建mobilenet時,有一個參數叫做is_training。如果不將其設置爲false,則在不同的迭代中,失落層和批處理規範化層將爲您提供不同的結果。批量歸一化可能會改變很小的值,但是由於丟棄了一些輸入值,丟失將會改變它們很多。

看看到mobilnet的簽名:

def mobilenet_v1(inputs, 
       num_classes=1000, 
       dropout_keep_prob=0.999, 
       is_training=True, 
       min_depth=8, 
       depth_multiplier=1.0, 
       conv_defs=None, 
       prediction_fn=tf.contrib.layers.softmax, 
       spatial_squeeze=True, 
       reuse=None, 
       scope='MobilenetV1'): 
    """Mobilenet v1 model for classification. 

    Args: 
    inputs: a tensor of shape [batch_size, height, width, channels]. 
    num_classes: number of predicted classes. 
    dropout_keep_prob: the percentage of activation values that are retained. 
    is_training: whether is training or not. 
    min_depth: Minimum depth value (number of channels) for all convolution ops. 
     Enforced when depth_multiplier < 1, and not an active constraint when 
     depth_multiplier >= 1. 
    depth_multiplier: Float multiplier for the depth (number of channels) 
     for all convolution ops. The value must be greater than zero. Typical 
     usage will be to set this value in (0, 1) to reduce the number of 
     parameters or computation cost of the model. 
    conv_defs: A list of ConvDef namedtuples specifying the net architecture. 
    prediction_fn: a function to get predictions out of logits. 
    spatial_squeeze: if True, logits is of shape is [B, C], if false logits is 
     of shape [B, 1, 1, C], where B is batch_size and C is number of classes. 
    reuse: whether or not the network and its variables should be reused. To be 
     able to reuse 'scope' must be given. 
    scope: Optional variable_scope. 

    Returns: 
    logits: the pre-softmax activations, a tensor of size 
     [batch_size, num_classes] 
    end_points: a dictionary from components of the network to the corresponding 
     activation. 

    Raises: 
    ValueError: Input rank is invalid. 
    """ 
+0

謝謝@jorgemf!正如我在我的問題中懷疑的問題是使用batchNorm並將'is_training'設置爲'False'工作。但這不是正確的方法。理想情況下,應該在訓練時將'is_training'加載爲'True',然後在推斷時將'is_training'加載爲False。但是因爲我自己並沒有自己寫蝙蝠科,而是從MobileNet代碼中加載圖形;我還沒有弄清楚如何做到上述。你可以參考這裏 - https://stackoverflow.com/questions/39353503/tensorflow-tf-slim-model-with-is-training-true-and-false或https://ruishu.io/2016/12/27/batchnorm/ – Krist

+0

@Krist不要忘了標記答案是有效的,如果它幫助你。 – jorgemf

-1

這是由於批標準化。

你是如何運行推斷。您是從檢查點文件加載它還是使用Frozen Protobuf模型?如果您使用凍結模型,您可以預期不同輸入格式的結果類似。

檢查this出。這裏提出了針對不同應用的類似問題。

+0

我不認爲他會凍結圖表,或者您鏈接的問題是由於凍結圖表造成的。 – jorgemf

+0

我說這是由於批量標準化。當您凍結圖表時,運行平均值/平均值的操作會發生變化,並會給出可預測的結果。 –

+1

現在我看到它可能是batch_norm或者dropout圖層。兩者都採用is_training參數 – jorgemf

相關問題