Вопрос или проблема
Я пытаюсь сделать классификацию текста с помощью 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
возвращает данные в нужном формате. Рассмотрим, как можно правильно реализовать эту функцию и корректировать генератор данных.
- Функция
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
- Генератор данных: Убедитесь, что генератор данных правильно передает данные в модель. В вашем коде есть несколько улучшений:
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 для более глубокого изучения.