Пословно текстовая генерация Используя глубокое обучение

В этом примере показано, как обучить сеть LSTM глубокого обучения, чтобы сгенерировать текст пословно.

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

Этот пример читает текст из веб-сайта. Это читает и анализирует код HTML, чтобы извлечь соответствующий текст, затем использует пользовательский мини-пакетный datastore documentGenerationDatastore вводить документы сети как мини-пакеты данных о последовательности. Datastore преобразует документы последовательностям числовых словарей. Нейронная сеть для глубокого обучения является сетью LSTM, которая содержит слой встраивания слова.

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

Можно адаптировать пользовательский мини-пакетный datastore documentGenerationDatastore.m к вашим данным путем настройки функций. Для примера, показывающего, как создать ваш собственный мини-пакетный datastore, смотрите, Разрабатывают Пользовательский Мини-пакетный Datastore (Deep Learning Toolbox).

Загрузите обучающие данные

Загрузите обучающие данные. Считайте код HTML из Алисы в Стране чудес Льюиса Кэрролла из Проекта Гутенберг.

url = "https://www.gutenberg.org/files/11/11-h/11-h.htm";
code = webread(url);

Проанализируйте КОД HTML

Код HTML содержит соответствующий текст в <p> (абзац) элементы. Извлеките соответствующий текст путем парсинга кода HTML с помощью htmlTree и затем находя все элементы с именем элемента "p".

tree = htmlTree(code);
selector = "p";
subtrees = findElement(tree,selector);

Извлеките текстовые данные из поддеревьев HTML с помощью extractHTMLText и просмотрите первые 10 абзацев.

textData = extractHTMLText(subtrees);
textData(1:10)
ans = 10×1 string array
    ""
    ""
    ""
    ""
    ""
    ""
    "Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, ‘and what is the use of a book,’ thought Alice ‘without pictures or conversations?’ "
    "So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her. "
    "There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself, ‘Oh dear! Oh dear! I shall be late!’ (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge. "
    "In another moment down went Alice after it, never once considering how in the world she was to get out again. "

Удалите пустые абзацы и просмотрите первые 10 остающихся абзацев.

textData(textData == "") = [];
textData(1:10)
ans = 10×1 string array
    "Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, ‘and what is the use of a book,’ thought Alice ‘without pictures or conversations?’ "
    "So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her. "
    "There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself, ‘Oh dear! Oh dear! I shall be late!’ (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge. "
    "In another moment down went Alice after it, never once considering how in the world she was to get out again. "
    "The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well. "
    "Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled ‘ORANGE MARMALADE’, but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it. "
    "‘Well!’ thought Alice to herself, ‘after such a fall as this, I shall think nothing of tumbling down stairs! How brave they’ll all think me at home! Why, I wouldn’t say anything about it, even if I fell off the top of the house!’ (Which was very likely true.) "
    "Down, down, down. Would the fall never come to an end! ‘I wonder how many miles I’ve fallen by this time?’ she said aloud. ‘I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think-’ (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) ‘-yes, that’s about the right distance-but then I wonder what Latitude or Longitude I’ve got to?’ (Alice had no idea what Latitude was, or Longitude either, but thought they were nice grand words to say.) "
    "Presently she began again. ‘I wonder if I shall fall right through the earth! How funny it’ll seem to come out among the people that walk with their heads downward! The Antipathies, I think-’ (she was rather glad there was no one listening, this time, as it didn’t sound at all the right word) ‘-but I shall have to ask them what the name of the country is, you know. Please, Ma’am, is this New Zealand or Australia?’ (and she tried to curtsey as she spoke-fancy curtseying as you’re falling through the air! Do you think you could manage it?) ‘And what an ignorant little girl she’ll think me for asking! No, it’ll never do to ask: perhaps I shall see it written up somewhere.’ "
    "Down, down, down. There was nothing else to do, so Alice soon began talking again. ‘Dinah’ll miss me very much to-night, I should think!’ (Dinah was the cat.) ‘I hope they’ll remember her saucer of milk at tea-time. Dinah my dear! I wish you were down here with me! There are no mice in the air, I’m afraid, but you might catch a bat, and that’s very like a mouse, you know. But do cats eat bats, I wonder?’ And here Alice began to get rather sleepy, and went on saying to herself, in a dreamy sort of way, ‘Do cats eat bats? Do cats eat bats?’ and sometimes, ‘Do bats eat cats?’ for, you see, as she couldn’t answer either question, it didn’t much matter which way she put it. She felt that she was dozing off, and had just begun to dream that she was walking hand in hand with Dinah, and saying to her very earnestly, ‘Now, Dinah, tell me the truth: did you ever eat a bat?’ when suddenly, thump! thump! down she came upon a heap of sticks and dry leaves, and the fall was over. "

Визуализируйте текстовые данные, одним словом, облако.

figure
wordcloud(textData);
title("Alice's Adventures in Wonderland")

Подготовка данных для обучения

Создайте datastore, который содержит данные для обучения с помощью documentGenerationDatastore. Чтобы создать datastore, сначала сохраните пользовательский мини-пакетный datastore documentGenerationDatastore.m к пути. Для предикторов этот datastore преобразует документы в последовательности словарей с помощью кодирования слова. Первый словарь для каждого документа соответствует, "запускают текста" лексему. "Запускают текста" лексему, дан строкой "startOfText". Для ответов datastore возвращает категориальные последовательности слов, переключенных одним.

Маркируйте текстовые данные с помощью tokenizedDocument.

documents = tokenizedDocument(textData);

Создайте datastore генерации документов с помощью маркируемых документов.

ds = documentGenerationDatastore(documents);

Чтобы уменьшать объем дополнения добавленного к последовательностям, отсортируйте документы в datastore длиной последовательности.

ds = sort(ds);

Создайте и обучите сеть LSTM

Задайте архитектуру сети LSTM. Чтобы ввести данные о последовательности в сеть, включайте входной слой последовательности и установите входной размер на 1. Затем включайте слой встраивания слова размерности 100 и то же количество слов как кодирование слова. Затем включайте слой LSTM и задайте скрытый размер, чтобы быть 100. Наконец, добавьте полносвязный слой с тем же размером как количество классов, softmax слоя и слоя классификации. Количество классов является количеством слов в словаре плюс дополнительный класс для "конца текста" класс.

inputSize = 1;
embeddingDimension = 100;
numWords = numel(ds.Encoding.Vocabulary);
numClasses = numWords + 1;

layers = [
    sequenceInputLayer(inputSize)
    wordEmbeddingLayer(embeddingDimension,numWords)
    lstmLayer(100)
    dropoutLayer(0.2)
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

Задайте опции обучения. Задайте решатель, чтобы быть 'adam'. Обучайтесь в течение 300 эпох с, изучают уровень 0.01. Установите мини-пакетный размер на 32. Чтобы сохранить данные отсортированными по длине последовательности, установите 'Shuffle' опция к 'never'. Чтобы контролировать процесс обучения, установите 'Plots' опция к 'training-progress'. Чтобы подавить многословный выход, установите 'Verbose' к false.

options = trainingOptions('adam', ...
    'MaxEpochs',300, ...
    'InitialLearnRate',0.01, ...
    'MiniBatchSize',32, ...
    'Shuffle','never', ...
    'Plots','training-progress', ...
    'Verbose',false);

Обучите сеть с помощью trainNetwork.

net = trainNetwork(ds,layers,options);

Сгенерируйте новый текст

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

Чтобы сделать первое предсказание с помощью сети, введите индекс, который представляет, "запускают текста" лексему. Найдите индекс при помощи word2ind функция с кодированием слова, используемым datastore документа.

enc = ds.Encoding;
wordIndex = word2ind(enc,"startOfText")
wordIndex = 1

Для остающихся предсказаний произведите следующее слово согласно множеству предсказания сети. Баллы предсказания представляют вероятностное распределение следующего слова. Произведите слова из словаря, данного именами классов выходного слоя сети.

vocabulary = string(net.Layers(end).Classes);

Сделайте предсказания пословно с помощью predictAndUpdateState. Для каждого предсказания, вход индекс предыдущего слова. Прекратите предсказывать, когда сеть предсказывает конец текстового слова или когда сгенерированный текст является 500 символами долго. Для большого количества данных, длинных последовательностей или больших сетей, предсказания на графическом процессоре обычно быстрее, чтобы вычислить, чем предсказания на центральном процессоре. В противном случае предсказания на центральном процессоре обычно быстрее, чтобы вычислить. Для одного предсказаний временного шага используйте центральный процессор. Чтобы использовать центральный процессор в предсказании, установите 'ExecutionEnvironment' опция predictAndUpdateState к 'cpu'.

generatedText = "";
maxLength = 500;
while strlength(generatedText) < maxLength
    % Predict the next word scores.
    [net,wordScores] = predictAndUpdateState(net,wordIndex,'ExecutionEnvironment','cpu');
    
    % Sample the next word.
    newWord = datasample(vocabulary,1,'Weights',wordScores);
    
    % Stop predicting at the end of text.
    if newWord == "EndOfText"
        break
    end
    
    % Add the word to the generated text.
    generatedText = generatedText + " " + newWord;
    
    % Find the word index for the next input.
    wordIndex = word2ind(enc,newWord);
end

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

Удалите пробелы, которые появляются перед заданными символами пунктуации.

punctuationCharacters = ["." "," "’" ")" ":" "?" "!"];
generatedText = replace(generatedText," " + punctuationCharacters,punctuationCharacters);

Удалите пробелы, которые появляются после заданных символов пунктуации.

punctuationCharacters = ["(" "‘"];
generatedText = replace(generatedText,punctuationCharacters + " ",punctuationCharacters)
generatedText = 
" ‘Sure, it’s a good Turtle!’ said the Queen in a low, weak voice."

Чтобы сгенерировать несколько частей текста, сбросьте сетевое состояние между поколениями с помощью resetState.

net = resetState(net);

Смотрите также

| | | | | | | | | |

Похожие темы