Глубокое обучение с помощью Tensorflow: персонализированный цикл обучения, который обучается с помощью одного элемента за раз

#python #tensorflow

Вопрос:

Мне нужно использовать пакет с элементом разного размера, поэтому я пытаюсь создать персонализированный цикл обучения, основная идея состоит в том, чтобы начать с того, который поставляется от keras:

 for epoch in range(epochs):
    for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):
        with tf.GradientTape() as tape:
            logits = model(x_batch_train, training=True)  
            loss_value = loss_fn(y_batch_train, logits)
        grads = tape.gradient(loss_value, model.trainable_weights)
        optimizer.apply_gradients(zip(grads, model.trainable_weights))
 

и добавьте cicle по размеру пакета, таким образом, я могу обучать сеть по одному элементу за раз и обновлять вес только после того, как каждый элемент пакета пройдет через newtork. Что-то вроде:

 for epoch in range(epochs):
    for training in range(trainingsize):
       for batch in range(batchsize):
            with tf.GradientTape() as tape:
               logits = model(x, training=True)  # Logits for this minibatch
               loss_value = loss_fn(, logits)
            grads = tape.gradient(loss_value, model.trainable_weights)
     optimizer.apply_gradients(zip(grads, model.trainable_weights))
 

где x и y-это один элемент пакета.

Но я замечаю, что таким образом я рассматриваю только последнюю партию ( потому что грады написаны на машинке).

Как я могу с этим справиться? Я не знаю, как «объединить» разные выпускники.

Также одно любопытство: я думал, что переменная create с операторами «with» действительна только внутри оператора, так как же возможно, что ее использование снаружи работает?

Обновить


Я попробовал решение SoheilStar, но tape.gradient возвращает вектор [None, None, None, None], а в «apply_gradients» сказано: «Градиенты не предусмотрены для какой-либо переменной: [‘conv1d/ядро:0’, ‘conv1d/смещение:0’, ‘плотный/ядро:0’, ‘плотный/смещение:0’]».

Я не знаю, как отлаживать в этом случае, чтобы найти проблему

Существует основная часть кода, который я использую:

 optimizer = keras.optimizers.Adam( learning_rate=0.001,name="Adam")
loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True)

model = keras.Sequential()
model.add(Conv1D(2, ksize, activation='relu', input_shape=ishape))
model.add(GlobalMaxPooling1D(data_format="channels_last"))
model.add(Dense(2, activation='sigmoid'))


for epoch in range(epochsize):
    batchp=1
    for k in range(trainingsize):
        loss_value = tf.constant(0.)
        mini_batch_losses=[]
        for s in range(batchsize):
            X_train, y_train = loadvalue(batchp) #caricamento elementi
            with tf.GradientTape() as tape:
                logits = model(X_train , training=True)
                loss_value = loss_fn(y_train, logits)
            mini_batch_losses.append(loss_value)
            batchp  = 1
        loss_avg = tf.reduce_mean(mini_batch_losses)
        grads = tape.gradient(loss_avg, model.trainable_weights)
        optimizer.apply_gradients(grads_and_vars=zip(grads, model.trainable_weights))
 

ОБНОВЛЕНИЕ 2:
Я замечаю, что если я изменю тренировочный цикл таким образом, это сработает, но я не понимаю, почему и правильно ли это:

 for epoch in range(epochsize):
    batchp=1
    for k in range(trainingsize):
        loss_value = tf.constant(0.)
        mini_batch_losses=[]
        with tf.GradientTape() as tape:
            for s in range(batchsize):
                X_train, y_train = loadvalue(batchp)
                logits = model(X_train , training=True)
                tape.watch(X_train)
                loss_value = loss_fn(y_train, logits)
            mini_batch_losses.append(loss_value)
            batchp  = 1
            loss_avg = tf.reduce_mean(mini_batch_losses)
        grads = tape.gradient(loss_avg, model.trainable_weights)
        optimizer.apply_gradients(grads_and_vars=zip(grads, model.trainable_weights))
 

Ответ №1:

переменная градации содержит только градиенты переменных. чтобы применить их, вам нужно переместить оптимизатор в последний цикл For. но почему бы не написать обычный цикл обучения, а затем установить размер пакета равным единице?

= = = = = = Обновление

вы можете рассчитать потери для каждой выборки в последнем цикле For, а затем выполнить метод reduce_mean, чтобы рассчитать среднее значение потерь, а затем рассчитать градации. код обновлен.

 for epoch in range(epochs):
    for training in range(trainingsize):
       mini_batch_losses = []
       for batch in range(batchsize):
            with tf.GradientTape() as tape:
               logits = model(x, training=True)  # Logits for this minibatch
               loss_value = loss_fn(y_true, logits)
            mini_batch_losses.append(loss_value)
       loss_avg = tf.reduce_mean(mini_batch_losses)
       grads = tape.gradient(loss_avg , model.trainable_weights)
       optimizer.apply_gradients(zip(grads, model.trainable_weights))
 

Комментарии:

1. (Спасибо за ответ!) Потому что я не хочу обновлять его после каждого элемента. Идея состоит в том, чтобы использовать пакет, но у меня есть элемент пакета разного размера, и по какой-то причине я не хочу делать что-то вроде заполнения нуля

2. Да! Вот так это может сработать. Но у меня есть только один вопрос: я не знаю,как работает градиентная лента в деталях, проблема в том, что градиентная лента называется в другое время, прежде чем вычислять градиент?

3. если вы знакомы с выполнением графика tf, в списке loss_avg вы просто знаете, каков график потерь каждого образца. в градиенте ленты градиент произошел по отношению к модели vars. после каждого градуса он вычислит среднее значение всех градусов. приведенный выше код равен вычислению градации для каждой партии, а затем вычисляет среднее значение, а затем передает его оптимизатору. попробуйте написать это на бумаге и сделайте это от начала до конца.

4. Спасибо за помощь, я начинаю читать о графике и теперь больше clear..so я пытаюсь применить ваше решение, но что-то не получается… вы можете мне помочь? (я обновил вопрос)