Прогнозирование последовательности точек на изображении - PullRequest
0 голосов
/ 17 июня 2020

Мой обучающий набор - это набор изображений (либо 3 канала, либо 1 из c, я использую только один тип канала). И метки представляют собой последовательность точек в определенном c порядке, который я хочу предсказать по изображениям.

Я использую модель, вдохновленную примером подписи к изображениям на веб-сайте tenorflow. Это тот же подход, который используется в данной статье https://arxiv.org/pdf/1901.03781.pdf

class CNN_Encoder(tf.keras.Model):
    # Since you have already extracted the features and dumped it using pickle
    # This encoder passes those features through a Fully connected layer
    def __init__(self, embedding_dim):
        super(CNN_Encoder, self).__init__()
        self.fc = tf.keras.layers.Dense(embedding_dim)

    def call(self, x):
        x = self.fc(x)
        x = tf.nn.relu(x)
        return x

class RNN_Decoder(tf.keras.Model):
    def __init__(self, embedding_dim, units, output_dim):
        super(RNN_Decoder, self).__init__()
        self.units = units


        self.gru = tf.keras.layers.GRU(self.units,
                                       return_sequences=True,
                                       return_state=True,
                                       recurrent_initializer='glorot_uniform')
        self.fc1 = tf.keras.layers.Dense(self.units)
        self.fc2 = tf.keras.layers.Dense(output_dim)

    def call(self, x, features, hidden):


        x = tf.concat((features, x), axis=-1)
        output, state = self.gru(x)
        x = self.fc1(state)
        x = self.fc2(x)
        return x

    def reset_state(self, batch_size):
        return tf.zeros((batch_size, self.units))

@tf.function
def train_step(img_tensor, target):
    loss = 0


    hidden = decoder.reset_state(batch_size=target.shape[0])
    dec_input = tf.expand_dims([[0., 0.]] * target.shape[0], 1)
    with tf.GradientTape() as tape:

        features = encoder(img_tensor)
        for i in (range(1, target.shape[1])):
            predictions = decoder(dec_input, features, hidden)
            loss += loss_function(target[:, i], predictions)

            # using teacher forcing
            dec_input = tf.expand_dims(target[:, i], 1)
    total_loss = (loss / int(target.shape[1]))
    trainable_variables = encoder.trainable_variables + decoder.trainable_variables
    gradients = tape.gradient(loss, trainable_variables)
    optimizer.apply_gradients(zip(gradients, trainable_variables))
    return loss, total_loss

EPOCHS = 20
batch_size = 8
for epoch in tqdm(range(start_epoch, EPOCHS)):
    start = time.time()
    total_loss = 0

    for (batch, (img_tensor, target)) in enumerate((data_generator(preds_t, labels_t))):
        img_tensor = img_tensor.reshape((-1, 1, 128*128))
        batch_loss, t_loss = train_step(img_tensor, target)
        total_loss += t_loss

        if batch % 100 == 0:
            print ('Epoch {} Batch {} Loss {:.4f}'.format(
              epoch + 1, batch, batch_loss.numpy() / int(target.shape[1])))
        if batch == 10000:

            break
    # storing the epoch end loss value to plot later
    #loss_plot.append(total_loss / num_steps)

    if epoch % 5 == 0:
        ckpt_manager.save()

    print ('Epoch {} Loss {:.6f}'.format(epoch + 1,
                                         total_loss/num_steps))
    print ('Time taken for 1 epoch {} sec\n'.format(time.time() - start))

для вектора функций. Я извлекаю последний слой unet. Таким образом, каждое изображение имеет размер 1x128x128. Я изменил его на 1x1x128 * 128. Затем я прохожу через полностью связанный слой. Затем форма становится 1x1x256

Мои метки, которые я хочу предсказать, являются координатами изображения, поэтому (x, y). Входными данными для слоя gru являются конкатенированные 1x1x256, 1x1x2 (координаты t-1). Который я затем прохожу через 2-слойный слой f c с выходным размером 2 для 2 координат. Я убрал внимание, чтобы получить более простую модель. Нормализирую свои изображения. Я дополняю координатные последовательности 0,0 для начала -1, -1 для конца и -2, -2 для обычного заполнения, чтобы получить одинаковую длину последовательности 350x2.

Сеть, похоже, не многому научилась. Я просто получаю несколько точек, разбросанных по диагонали по изображению. Самая большая разница, которую я вижу с моделью подписи к изображениям, заключается в том, что слова можно преобразовать во вложения, а затем у вас есть 128 функций изображения, 128 функций слов, которые объединяются и передаются в lstm. В моем случае информация о последовательности - это всего одна запись. Может быть, это причина того, что сеть мало учится.

Было бы здорово, если бы у кого-то было какое-то представление о том, что мне следует изменить

1 Ответ

1 голос
/ 25 июня 2020

Ваш вопрос требует определенного опыта и глубокого исследования. Я предлагаю только общие советы по проблеме недостаточной подгонки. Вот список из вещей, которые стоит попробовать .

Лично я бы начал с попытки переобучения на одной партии.

...