【问题标题】:Converting Darknet53 gives "nan" results in Tensorflow 2.0转换 Darknet53 在 Tensorflow 2.0 中给出“nan”结果
【发布时间】:2019-09-13 08:49:09
【问题描述】:

我正在尝试将 Yolo v3 转换为 tensorflow 2.0 我编写了 Darknet53 网络层,我能够在测试输入和实际图像上运行它,但两种情况下的结果都是“nan”

我已经尝试过放大和缩小代码。首先将图像除以 255 以在 0 和 1 之间缩放,如原始论文中那样,然后乘以 255 以检查值是否太低而无法处理。我也尝试了不缩放的原始图像。

这是实际的网络

import tensorflow as tf 

class ResnetIdentityBlock(tf.keras.Model):
    def __init__(self, kernel_size, filters):
        super(ResnetIdentityBlock, self).__init__(name='')
        filters1, filters2, filters3 = filters
        self.conv2a = tf.keras.layers.Conv2D(filters1, (1,1))
        self.bn2a = tf.keras.layers.BatchNormalization()

        self.conv2b = tf.keras.layers.Conv2D(filters2, kernel_size, padding="SAME")
        self.bn2b = tf.keras.layers.BatchNormalization()

        self.conv2c = tf.keras.layers.Conv2D(filters3, (1,1))
        self.bn2c = tf.keras.layers.BatchNormalization()

    def call(self, input_tensor, training=False):
        x = self.conv2a(input_tensor)
        x = self.bn2a(x, training=training)
        x = tf.nn.relu(x)
        print(f"after conv + bn a \n{x.shape}")
        x = self.conv2b(x)
        x = self.bn2b(x, training=training)
        x = tf.nn.relu(x)
        print(f"after conv + bn b \n{x.shape}")
        x = self.conv2c(x)
        x = self.bn2c(x, training=training)
        print(f"after conv + bn c \n{x.shape}")
        x += input_tensor
        print(f"input shape\n {input_tensor.shape}")
        print(f"final shape \n{x.shape}")
        return tf.nn.relu(x)


class Darknet53Block(tf.keras.Model):
    '''the main block of Darknet53, two conv followed by a residual'''
    def __init__(self, filters):
        super(Darknet53Block, self).__init__(name='')
        self.conv2a = tf.keras.layers.Conv2D(filters,1)
        self.bn2a = tf.keras.layers.BatchNormalization(epsilon=1e-05)

        self.conv2b = tf.keras.layers.Conv2D(filters*2, 3, padding="SAME")
        self.bn2b = tf.keras.layers.BatchNormalization(epsilon=1e-05)
    def call(self, input_tensor, training=False):
        x = self.conv2a(input_tensor)
        x = self.bn2a(x, training=training)
        x = tf.nn.leaky_relu(x, 0.1)
        x = self.conv2b(x)
        x = self.bn2b(x, training=training)
        x = tf.nn.leaky_relu(x, 0.1)
        x += input_tensor
        return x 

class Darknet53(tf.keras.Model):
    def __init__(self, *args, **kwargs):
        super(Darknet53, self).__init__(name='')

        self.bn = tf.keras.layers.BatchNormalization(epsilon=1e-05)

        self.conv2a = tf.keras.layers.Conv2D(filters=32,kernel_size=3)
        self.conv2b = tf.keras.layers.Conv2D(filters=64, kernel_size=3, strides=2)
        self.dn_a = Darknet53Block(filters=32)

        self.conv2c = tf.keras.layers.Conv2D(filters=128,kernel_size=3,  strides=2)
        self.dn_b = Darknet53Block(filters=64)

        self.conv2d = tf.keras.layers.Conv2D(filters=256, kernel_size=3, strides=2)
        self.dn_c = Darknet53Block(filters=128)

        self.conv2e = tf.keras.layers.Conv2D(filters=512, kernel_size=3, strides=2)
        self.dn_d = Darknet53Block(filters=256)

        self.conv2f = tf.keras.layers.Conv2D(filters=1024,kernel_size=3,  strides=2)
        self.dn_e = Darknet53Block(filters=512)

    def call(self, input_tensor):
        x = self.conv2a(input_tensor)
        x = self.bn(x)
        x = tf.nn.leaky_relu(x, alpha=0.1)
        x = self.conv2b(x)
        x = self.bn(x)
        x = tf.nn.leaky_relu(x, alpha=0.1)
        x = self.dn_a(x)
        x = self.conv2c(x)
        x = self.bn(x)
        x = tf.nn.leaky_relu(x, alpha=0.1)    
        for i in range(2):
            x = self.dn_b(x)
        x = self.conv2d(x)
        x = self.bn(x)
        x = tf.nn.leaky_relu(x, alpha=0.1)
        for i in range(8):
            x = self.dn_c(x)
        scale_1 = x 

        x = self.conv2e(x)
        x = self.bn(x)
        x = tf.nn.leaky_relu(x, alpha=0.1)
        for i in range(8):
            x = self.dn_d(x)
        scale_2 = x 

        x = self.conv2f(x)
        x = self.bn(x)
        x = tf.nn.leaky_relu(x, alpha=0.1)
        for i in range(4):
            x = self.dn_e(x)
        return scale_1, scale_2, x

这里是测试代码

if __name__ == "__main__":

    import numpy as np
    import cv2 

    darknet = Darknet53()

    img = cv2.imread("20190413_143522_126.jpg")
    img = cv2.resize(img, (416,416))/255.0
    img = img.reshape((1,416,416,3))
    img = np.asarray(img, dtype=np.float32)
    print(img)

    result1, result2, result3 = darknet(img)
    print(result1)
    print(result2)
    print(result3)

我希望输出在 0 和 1 之间。结果的大小很好,但它们似乎都填充了“nan”

【问题讨论】:

    标签: python tensorflow yolo tensorflow2.0


    【解决方案1】:

    由于 tensorflow 2.1.0rc0 即将作为最终版 2.1.0 发布,因此有一个新的 API 专门用于帮助用户找出此类数字问题的根本原因,即 tf.debugging.enable_check_numerics()

    tf.debugging.enable_check_numerics() 是 TF1 中称为 tf.add_check_numerics_ops() 的旧 API 的继承者,TF2 中不支持该 API。

    要在 TF2 中使用新的 API,您只需在构建和运行模型之前将该行添加到代码中的某个位置。举个简单的例子。

    import tensorflow as tf
    
    tf.debugging.enable_check_numerics()  # Add this line to your code.
    
    #...
    darknet = Darknet53()
    result1, result2, result3 = darknet(img)
    
    

    在执行(即darknet(img))调用期间,只要任何操作(无论是急切执行还是在 tf.function 图中执行)在其浮点型张量输出中输出任何无穷大或 NaN,程序都会出错.错误信息会告诉你

    • 操作的名称
    • 输出张量的 dtype 和 shape
    • 输出张量中是否存在 -infinity、+infinity、NaN 或它们的任意组合
    • 最初创建操作的堆栈跟踪(代码行),可帮助您定位问题的根源。 See example screenshot here.

    【讨论】:

      猜你喜欢
      • 2017-12-16
      • 1970-01-01
      • 2022-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 1970-01-01
      • 2021-10-30
      相关资源
      最近更新 更多