Почему моя модель обучается с рванными тензорами, но не с плотными тензорами?

Вопрос или проблема

У меня есть строка букв, которая соответствует “грамматике”. У меня также есть булевские метки в моем обучающем наборе данных о том, соответствует ли строка “грамматике” или нет. В основном, моя модель пытается узнать, соответствует ли строка букв правилам. Это довольно простая задача (я взял ее из учебника).

Я генерирую свой набор данных следующим образом:

def generate_dataset(size):
    good_strings = [string_to_ids(generate_string(embedded_reber_grammar))
                    for _ in range(size // 2)]
    bad_strings = [string_to_ids(generate_corrupted_string(embedded_reber_grammar))
                   for _ in range(size - size // 2)]
    all_strings = good_strings + bad_strings
    X = tf.ragged.constant(all_strings, ragged_rank=1)

    # X = X.to_tensor(default_value=0)

    y = np.array([[1.] for _ in range(len(good_strings))] +
                 [[0.] for _ in range(len(bad_strings))])
    return X, y

Обратите внимание на строку X = X.to_tensor(default_value=0). Если эта строка закомментирована, моя модель обучается без проблем. Однако, если она не закомментирована, обучение не удается, и набор валидации показывает такие же результаты, как случайный выбор (50-50).

Вот моя фактическая модель:

np.random.seed(42)
tf.random.set_seed(42)

embedding_size = 5

model = keras.models.Sequential([
    keras.layers.InputLayer(input_shape=[None], dtype=tf.int32, ragged=True),
    keras.layers.Embedding(input_dim=len(POSSIBLE_CHARS) + 1, output_dim=embedding_size),
    keras.layers.GRU(30),
    keras.layers.Dense(1, activation="sigmoid")
])
optimizer = keras.optimizers.SGD(lr=0.02, momentum = 0.95, nesterov=True)
model.compile(loss="binary_crossentropy", optimizer=optimizer, metrics=["accuracy"])
history = model.fit(X_train, y_train, epochs=5, validation_data=(X_valid, y_valid))

Я использую 0 в качестве значения по умолчанию для плотных тензоров. Функция strings_to_ids не использует 0 для каких-либо значений, а начинается с 1. Также, когда я переключаюсь на использование плотного тензора, я меняю ragged=True на False. У меня нет представления, почему использование плотного тензора вызывает сбой модели, так как я ранее использовал плотные тензоры в подобных задачах.

Для получения дополнительных деталей смотрите решение из книги (упражнение 8) или мой собственный коллаб ноутбук. В качестве оговорки: я изучаю машинное обучение для удовольствия, а не для работы или учебы.

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

Ответ или решение

Почему моя модель обучается с рванными тензорами, но не с плотными?

Когда речь идет о машинном обучении и работе с тензорами, важно понимать, как структурированные данные влияют на процесс обучения. В вашем случае модель демонстрирует успешное обучение с рванными тензорами (ragged tensors), но не может нормально обучаться с плотными тензорами (dense tensors). Давайте подробнее рассмотрим возможные причины этого поведения.

Структура данных

Вы используете рваные тензоры для представления строк символов, которые соответствуют определённой грамматике. Рваные тензоры удобны для работы с последовательностями переменной длины, такими как строки, поскольку они позволяют избежать заполнения нулями, что часто происходит при использовании плотных тензоров. Установив X = X.to_tensor(default_value=0), вы преобразуете рваный тензор в плотный, добавляя заполнение нулями для компановки всех строк в единую матрицу.

Проблемы с записями

Когда вы используете 0 в качестве значения по умолчанию для заполнения плотного тензора, важно учитывать, как это значение соотносится с данными. Вы упомянули, что функция string_to_ids не генерирует 0, что означает, что 0 в вашем датасете, скорее всего, интерпретируется как "недопустимый" или "пустой" ввод. Если разные наборы данных (например, обучающий и валидационный) содержат строки разной длины, вы получите несоответствий в форме тензоров. Это может привести к тому, что модель не сможет учесть этот "пустой" ввод и будет демонстрировать производительность, похожую на случайную.

Неточные размерности

Как вы отметили в последнем обновлении, проблема заключалась в том, что размерность плотного тензора отличалась между обучающим и валидационным наборами. Это может произойти, если самая длинная строка в обучающем наборе отличается от самой длинной строки в валидационном наборе. При использовании рваных тензоров такой проблемы не возникает из-за гибкости их структуры – они могут содержать последовательности различной длины без необходимости их дополнения.

Решения для улучшения обучения

  1. Согласование длины последовательностей: Если вы все-таки хотите использовать плотные тензоры, убедитесь, что длина вводимых строк одинаковая для обучающего и валидационного наборов данных. Это можно сделать, заполняя короткие строки до максимальной длины в обоих наборах.

  2. Изменение значения по умолчанию: Вместо того чтобы использовать 0, можно задать другое значение, которое будет отличаться от всех возможных индексов в вашем наборе данных, чтобы избежать путаницы.

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

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

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

Оцените материал
Добавить комментарий

Капча загружается...