Конфликт ввода RNN LSTM из-за генератора

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

Я пытаюсь сделать классификацию текста с помощью LSTM RNN на последовательно дополненных до 255 длины последовательностях.

Мои данные для классификации выглядят так

1, 'последовательность 1'

Первый столбец — это метка класса для последовательности. Поскольку я использую собственное представление слов (100 измерений), я создал пользовательский генератор данных и использовал fit_generator API.

Мои данные преобразуются в следующий формат после предварительной обработки

X -> (batch_size, time_steps=255, 100) # 100-мерные вложения слов

Y -> (batch_size, 2) # 2 для меток классов с бинарной классификацией

Вот что я пробовал с пользовательским генератором

def data_generator(file):
    while True:
        with open(file, 'r') as f:
            reader = csv.reader(f)
            for row in reader:
                # Получить встроенную строку кодирует каждую последовательность в её составные векторные представления слов
                # создает 2D np массив размером (max_len, 100)
                yield get_embedded_line(row[1]), to_categorical(row[0], num_classes=2)


input_layer = Input(shape=(255, 100))
lstm1 = LSTM(100, return_sequences=True)(input_layer)
dense1 = Dense(2, activation='softmax')(lstm1)
model = Model(inputs=input_layer, outputs=dense1)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=['accuracy'])
model.fit_generator(data_generator('data.csv'), steps_per_epoch=10)

Модель, определенная выше, даже не компилируется, она выдает следующую ошибку

ValueError: Ошибка при проверке ввода: ожидался input_1 с 3 измерениями, но получен массив с размером (100, 1)

get_embedded_line(row[1]) должен возвращать матрицу размером ( Размер пакета, 255, 100), но он выдает матрицу (100, 1). Пожалуйста, проверьте реализацию функции “get_embedded_line”.

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

Конфликт входных данных RNN LSTM из-за генератора данных: решение проблемы

При выполнении задач классификации текста с использованием рекуррентных нейронных сетей (RNN) и их продвинутых версий, таких как LSTM (Long Short-Term Memory), часто возникает необходимость в создании кастомных генераторов для предобработанных данных. В вашем случае возникает ошибка, указывающая на несоответствие размерностей входных данных, что может быть связано с неправильной реализацией функции, генерирующей последовательности.

Описание проблемы

Как вы указали, ваша модель ожидает входные данные в формате (batch_size, 255, 100), где 255 — количество временных шагов (паддинг последовательности), а 100 — размерность векторных представлений слов. Однако функция get_embedded_line(row[1]) возвращает массив размером (100, 1), что является серьезным несоответствием.

Решение

Чтобы устранить эту ошибку, необходимо убедиться, что ваша функция get_embedded_line возвращает данные в нужном формате. Рассмотрим, как можно правильно реализовать эту функцию и корректировать генератор данных.

  1. Функция get_embedded_line: Это должна быть функция, которая преобразовывает входную строку текста в массив векторных представлений слов, затем формирует общий объем данных в требуемом формате.
import numpy as np

def get_embedded_line(sequence):
    # Предполагается, что у вас есть доступ к обученной модели векторизации, например, Word2Vec или GloVe
    words = sequence.split()  # Разделяем текст на слова
    embedded_sequence = []

    for word in words:
        # Здесь происходит получение вектора для каждого слова
        # Ваша модель векторизации должна возвращать вектор размерности 100 для каждого слова
        vector = your_embedding_model[word] if word in your_embedding_model else np.zeros(100)  # Вектор нулей для отсутствующего слова
        embedded_sequence.append(vector)

   # Теперь заполняем последовательность нулями до 255 шагов
    padded_sequence = np.zeros((255, 100))  # Инициализация массива нулями
    padded_sequence[:min(len(embedded_sequence), 255)] = embedded_sequence[:255]  # Заполнение длинной последовательности

    return padded_sequence
  1. Генератор данных: Убедитесь, что генератор данных правильно передает данные в модель. В вашем коде есть несколько улучшений:
import csv
from keras.utils import to_categorical
from keras.models import Model
from keras.layers import Input, LSTM, Dense

def data_generator(file, batch_size):
    while True:
        with open(file, 'r') as f:
            reader = csv.reader(f)
            batch_X = []
            batch_Y = []
            for i, row in enumerate(reader):
                if i >= batch_size:
                    yield np.array(batch_X), np.array(batch_Y)
                    batch_X, batch_Y = [], []  # Сбрасываем батч

                # Получаем векторизованную последовательность и категориальную метку
                batch_X.append(get_embedded_line(row[1]))
                batch_Y.append(to_categorical(int(row[0]), num_classes=2))

            # Обработка оставшихся данных
            if batch_X and batch_Y:
                yield np.array(batch_X), np.array(batch_Y)

# Определение модели
input_layer = Input(shape=(255, 100))
lstm1 = LSTM(100, return_sequences=False)(input_layer)  # Изменение на False, если нужен только последний вывод
dense1 = Dense(2, activation='softmax')(lstm1)
model = Model(inputs=input_layer, outputs=dense1)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=['accuracy'])

# Запуск обучения
model.fit_generator(data_generator('data.csv', batch_size=32), steps_per_epoch=10)

Заключение

Следуя этим шагам, вы сможете устранить конфликт входных данных, возникающий из-за генератора. Правильная реализация функции преобразования текстов в векторы на основе эмбеддингов, а также соответствующее использование генератора данных, должны помочь вам успешно обучить модель LSTM для задачи классификации текста. Если возникнут дополнительные вопросы или потребуется помощь, вы всегда можете обратиться к сообществу разработчиков или воспользоваться официальной документацией Keras для более глубокого изучения.

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

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