Я пытаюсь использовать архитектуру DenseNet для классификации рентгеновских изображений по https://www.kaggle.com/nih-chest-xrays/data. Модель создает вектор двоичных меток, где каждая метка указывает на наличие или отсутствие 14 возможныхпатологии: ателектаз, кардиомегалия, консолидация, отек, выпот, эмфизема, фиброз, грыжа, инфильтрация, масса, узелки, утолщение плевры, пневмония и пневмоторакс.Например, здоровый пациент будет иметь метку [0,0,0,0,0,0,0,0,0,0,0,0,0,0], тогда как пациент с отеком и выпотом будет иметьметка [0,0,0,1,1,0,0,0,0,0,0,0,0,0].Я построил эту модель с помощью тензорного потока, и, поскольку это проблема классификации по нескольким меткам, я использовал функцию стоимости tf.reduce_mean (tf.losses.sigmoid_cross_entropy (tags, logits)), которая минимизируется с помощью AdamOptimizer.Однако, когда я проверял выходной сигнал сигмоида, все значения были ниже 0,5, в результате чего tf.round (logits) выдает нули для каждого прогноза.Фактические логиты различны для разных входных данных и являются ненулевыми значениями после 10000 итераций, поэтому я не думаю, что исчезающие градиенты являются проблемой.У меня есть два вопроса:
- Может ли эта проблема быть вызвана неправильной реализацией модели?
- Буду ли я "обманывать", если я уменьшу пороговое значение для сигмоидальной функции до0,25 от 0,5 для повышения точности модели?
Спасибо.
Вот код для модели:
def DenseNet(features, labels, mode, params):
depth = params["depth"]
k = params["growth"]
if depth == 121:
N = db_121
else:
N = db_169
bottleneck_output = 4 * k
#before entering the first dense block, a conv operation with 16 output channels
#is performed on the input images
with tf.variable_scope('input_layer'):
#l = tf.reshape(features, [-1, 224, 224, 1])
feature_maps = 2 * k
l = layers.conv(features, filter_size = 7, stride = 2, out_chn = feature_maps)
l = tf.nn.max_pool(l,
padding='SAME',
ksize=[1,3,3,1],
strides=[1,2,2,1],
name='max_pool')
# each block is defined as a dense block + transition layer
with tf.variable_scope('block1'):
for i in range(N[0]):
with tf.variable_scope('bottleneck_layer.{}'.format(i+1)):
bn_l = layers.batch_norm('BN', l)
bn_l = tf.nn.relu(bn_l, name='relu')
bn_l = layers.conv(bn_l, out_chn=bottleneck_output, filter_size=1)
l = layers.add_layer('dense_layer.{}'.format(i+1), l, bn_l)
l = layers.transition_layer('transition1', l)
with tf.variable_scope('block2'):
for i in range(N[1]):
with tf.variable_scope('bottleneck_layer.{}'.format(i+1)):
bn_l = layers.batch_norm('BN', l)
bn_l = tf.nn.relu(bn_l, name='relu')
bn_l = layers.conv(bn_l, out_chn=bottleneck_output, filter_size=1)
l = layers.add_layer('dense_layer.{}'.format(i+1), l, bn_l)
l = layers.transition_layer('transition2', l)
with tf.variable_scope('block3'):
for i in range(N[2]):
with tf.variable_scope('bottleneck_layer.{}'.format(i+1)):
bn_l = layers.batch_norm('BN', l)
bn_l = tf.nn.relu(bn_l, name='relu')
bn_l = layers.conv(bn_l, out_chn=bottleneck_output, filter_size=1)
l = layers.add_layer('dense_layer.{}'.format(i+1), l, bn_l)
l = layers.transition_layer('transition3', l)
# the last block does not have a transition layer
with tf.variable_scope('block4'):
for i in range(N[3]):
with tf.variable_scope('bottleneck_layer.{}'.format(i+1)):
bn_l = layers.batch_norm('BN', l)
bn_l = tf.nn.relu(bn_l, name='relu')
bn_l = layers.conv(bn_l, out_chn=bottleneck_output, filter_size=1)
l = layers.add_layer('dense_layer.{}'.format(i+1), l, bn_l)
# classification (global max pooling and softmax)
with tf.name_scope('classification'):
l = layers.batch_norm('BN', l)
l = tf.nn.relu(l, name='relu')
l = layers.pooling(l, filter_size = 7)
l_shape = l.get_shape().as_list()
l = tf.reshape(l, [-1, l_shape[1] * l_shape[2] * l_shape[3]])
l = tf.layers.dense(l, units = 1000, activation = tf.nn.relu, name='fc1', kernel_initializer=tf.contrib.layers.xavier_initializer())
output = tf.layers.dense(l, units = 14, name='fc2', kernel_initializer=tf.contrib.layers.xavier_initializer()) # [batch_size, 14]
cross_entropy = tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=output) # cost function
cost = tf.reduce_mean(cross_entropy, name='cost_fn')