【问题标题】:Tensorflow: Simple 3D Convnet not learningTensorflow:简单的 3D Convnet 不学习
【发布时间】:2018-12-19 19:15:32
【问题描述】:

我正在尝试创建一个用于图像分割的简单 3D U-net,只是为了学习如何使用图层。因此,我进行步幅为 2 的 3D 卷积,然后进行转置反卷积以恢复相同的图像大小。我也过度拟合了一个小集(测试集),只是为了看看我的网络是否在学习。

我在 Keras 中创建了相同的网络,它工作得很好。现在我想在 tensorflow 中创建,但我遇到了麻烦。

成本略有变化,但无论我做什么(降低学习率、添加更多 epoch、添加更多层、更改批量大小……)输出始终相同。我相信网络没有更新权重。我确定我做错了什么,但我可以找到它。任何帮助将不胜感激。

这是我的代码

def forward_propagation(X):

    if ( mode == 'train'): print(" --------- Net --------- ")

    # Convolutional Layer 1
    with tf.variable_scope('CONV1'):
        Z1 = tf.layers.conv3d(X, filters = 16, kernel =[3,3,3], strides = [ 2, 2, 2], padding='SAME', name = 'S2/conv3d')
        A1 = tf.nn.relu(Z1, name = 'S2/ReLU')
        if ( mode == 'train'): print("Convolutional Layer 1 S2 " + str(A1.get_shape()))

    # DEConvolutional Layer 1
    with tf.variable_scope('DeCONV1'):
        output_deconv1 = tf.stack([X.get_shape()[0] , X.get_shape()[1], X.get_shape()[2], X.get_shape()[3], 1])
        dZ1 = tf.nn.conv3d_transpose(A1,  filters = 1, kernel =[3,3,3], strides = [2, 2, 2], padding='SAME', name = 'S2/conv3d_transpose')
        dA1 = tf.nn.relu(dZ1, name = 'S2/ReLU')

        if ( mode == 'train'): print("Deconvolutional Layer 1 S1 " + str(dA1.get_shape()))

    return dA1


def compute_cost(output, target, method = 'dice_hard_coe'):

    with tf.variable_scope('COST'):       

        if (method == 'sigmoid_cross_entropy') :
            # Make them vectors
            output = tf.reshape( output, [-1, output.get_shape().as_list()[0]] )
            target = tf.reshape( target, [-1, target.get_shape().as_list()[0]] )
            loss = tf.nn.sigmoid_cross_entropy_with_logits(logits = output, labels = target)
            cost = tf.reduce_mean(loss)

    return cost

以及模型的主要功能:

def model(X_h5, Y_h5, learning_rate = 0.009,
          num_epochs = 100, minibatch_size = 64, print_cost = True):


    ops.reset_default_graph()                         # to be able to rerun the model without overwriting tf variables
    #tf.set_random_seed(1)                             # to keep results consistent (tensorflow seed)
    #seed = 3                                          # to keep results consistent (numpy seed)
    (m, n_D, n_H, n_W, num_channels) = X_h5["test_data"].shape   #TTT          
    num_labels = Y_h5["test_mask"].shape[4] #TTT
    img_size = Y_h5["test_mask"].shape[1]  #TTT
    costs = []                                        # To keep track of the cost
    accuracies = []                                   # To keep track of the accuracy



    # Create Placeholders of the correct shape
    X, Y = create_placeholders(n_H, n_W, n_D, minibatch_size)

    # Forward propagation: Build the forward propagation in the tensorflow graph
    nn_output = forward_propagation(X)
    prediction = tf.nn.sigmoid(nn_output)

    # Cost function: Add cost function to tensorflow graph
    cost_method = 'sigmoid_cross_entropy' 
    cost = compute_cost(nn_output, Y, cost_method)

    # Backpropagation: Define the tensorflow optimizer. Use an AdamOptimizer that minimizes the cost.
    optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(cost)

    # Initialize all the variables globally
    init = tf.global_variables_initializer()


    # Start the session to compute the tensorflow graph
    with tf.Session() as sess:

        print('------ Training ------')

        # Run the initialization
        tf.local_variables_initializer().run(session=sess)
        sess.run(init)

        # Do the training loop
        for i in range(num_epochs*m):
            # ----- TRAIN -------
            current_epoch = i//m            

            patient_start = i-(current_epoch * m)
            patient_end = patient_start + minibatch_size

            current_X_train = np.zeros((minibatch_size, n_D,  n_H, n_W,num_channels))
            current_X_train[:,:,:,:,:] = np.array(X_h5["test_data"][patient_start:patient_end,:,:,:,:]) #TTT
            current_X_train = np.nan_to_num(current_X_train) # make nan zero

            current_Y_train = np.zeros((minibatch_size, n_D, n_H, n_W, num_labels))
            current_Y_train[:,:,:,:,:] = np.array(Y_h5["test_mask"][patient_start:patient_end,:,:,:,:]) #TTT
            current_Y_train = np.nan_to_num(current_Y_train) # make nan zero

            feed_dict = {X: current_X_train, Y: current_Y_train}
            _ , temp_cost = sess.run([optimizer, cost], feed_dict=feed_dict)

            # ----- TEST -------
            # Print the cost every 1/5 epoch
            if ((i % (num_epochs*m/5) )== 0):              

                # Calculate the predictions
                test_predictions = np.zeros(Y_h5["test_mask"].shape)

                for j in range(0, X_h5["test_data"].shape[0], minibatch_size):

                    patient_start = j
                    patient_end = patient_start + minibatch_size

                    current_X_test = np.zeros((minibatch_size, n_D,  n_H, n_W, num_channels))
                    current_X_test[:,:,:,:,:] = np.array(X_h5["test_data"][patient_start:patient_end,:,:,:,:])
                    current_X_test = np.nan_to_num(current_X_test) # make nan zero

                    current_Y_test = np.zeros((minibatch_size, n_D, n_H, n_W, num_labels))
                    current_Y_test[:,:,:,:,:] = np.array(Y_h5["test_mask"][patient_start:patient_end,:,:,:,:]) 
                    current_Y_test = np.nan_to_num(current_Y_test) # make nan zero

                    feed_dict = {X: current_X_test, Y: current_Y_test}
                    _, current_prediction = sess.run([cost, prediction], feed_dict=feed_dict)
                    test_predictions[j:j + minibatch_size,:,:,:,:] = current_prediction

                costs.append(temp_cost)
                print ("[" + str(current_epoch) + "|" + str(num_epochs) + "] " + "Cost : " + str(costs[-1]))
                display_progress(X_h5["test_data"], Y_h5["test_mask"], test_predictions, 5, n_H, n_W)

        # plot the cost
        plt.plot(np.squeeze(costs))
        plt.ylabel('cost')
        plt.xlabel('epochs')
        plt.show()

        return  

我用以下方式调用模型:

model(hdf5_data_file, hdf5_mask_file, num_epochs = 500, minibatch_size = 1, learning_rate = 1e-3)

这些是我目前得到的结果:

编辑: 我试过降低学习率,但没有帮助。我也尝试过使用 tensorboard 调试,但权重没有更新:

我不确定为什么会这样。 我在 keras 中创建了相同的简单模型,它工作正常。我不确定我在 tensorflow 中做错了什么。

【问题讨论】:

  • 我的猜测是学习步长太大,以至于你迈出一步然后砰的一声……ReLus 都开始饱和了。两种确认方法是使用leaky Relus,或者大幅降低学习率。无论如何,泄漏的 ReLus 可能是个好主意
  • 嗨@bremen_matt,我降低了学习率但没有任何成功。我还使用了 tensordoard 调试并注意到权重没有更新。有什么想法吗?
  • 我会尝试将那些 relus 更改为泄漏的 relus。如果你被推到一切都是 0 的 relus 一边,学习就会停止。
  • 如果删除 nan_to_num() 调用会发生什么?你有很多 NaN 吗?如果是这样,请尝试找出原因,因为如果这样做,看起来计算有问题,整个网络将输出 0,而 ReLU 将无法学习任何东西。

标签: python tensorflow image-processing deep-learning


【解决方案1】:

不确定您是否仍在寻求帮助,因为我将在您发布日期半年后回答这个问题。 :) 我列出了我的观察结果以及一些建议供您在下面尝试。我的主要观察结果是正确的......那么你可能只需要喝杯咖啡/睡个好觉。

初步观察:

  • tf.reshape( output, [-1, output.get_shape().as_list()[0]] ) 似乎错了。如果您更喜欢扁平化矢量,它应该类似于tf.reshape(output,[-1,np.prod(image_shape_list)])

其他观察:

  • 有了这样一个浅层网络,我怀疑网络是否有足够的空间分辨率来区分肿瘤体素和非肿瘤体素。您能否展示与纯 tf 实现相比的 keras 实现和性能?我可能会选择 2 层以上,让我们。 假设有 3 层,每层的步幅为 2,输入图像宽度为 256,那么在最深的编码器层,您将以 32 的宽度结束。 (如果您的 GPU 内存有限,请对输入图像进行下采样。)
  • 如果更改损失计算不起作用,正如@bremen_matt 提到的,减少 LR 说可能是 1e-5。
  • 在基本架构调整之后,您“感觉”网络是一种学习方式并且没有卡住,尝试增加训练数据,在训练期间添加 dropout、batch norm,然后可能通过添加判别器来弥补您的损失。

【讨论】:

  • 正如我所提到的,这只是为了让代码正常工作。我不指望它能解决问题,尽管 keras 只用这两层就做得不错。此外,正如编辑中所述,我试图降低 LR,但没有运气。这个网络的全部目的只是为了获得与我在 keras 中获得的相同结果,但使用的是 tensorflow。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 2021-05-14
相关资源
最近更新 更多