#python #tensorflow #yolo #tensorflow2.0
#python #tensorflow #yolo #tensorflow2.0
Вопрос:
Я пытаюсь преобразовать 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 shapen {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»
Ответ №1:
Начиная с tensorflow 2.1.0rc0, который вскоре будет выпущен как окончательный вариант 2.1.0, существует новый API, специально разработанный, чтобы помочь пользователям выяснить основную причину таких числовых проблем, как это, а именно tf.debugging.enable_check_numerics()
.
tf.debugging.enable_check_numerics()
является преемником старого API в TF1 под названием tf.add_check_numerics_ops()
, который не поддерживается в TF2.
Чтобы использовать новый API в TF2, вам просто нужно добавить строку в место в вашем коде, прежде чем ваша модель будет построена и запущена. В качестве упрощенного примера.
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 и форма выходного тензора
- Существуют ли -infinity, infinity, NaN или любая их комбинация в выходном тензоре
- Трассировка стека (строка кода), которая изначально создала op, чтобы помочь вам найти источник проблемы. Смотрите пример скриншота здесь.