Создание текста на шекспировском английском с помощью цепей Маркова
Это мягкое введение в цепи Маркова для генерации текста. Мы собираемся обучить модель с использованием библиотеки Markovify на трех самых известных трагедиях Уильяма Шекспира и посмотреть, будет ли то, что мы создаем, разборчиво и связно. Я понимаю, что эти два термина несколько нечеткие, но я чувствую, что большинство людей поймут мое намерение при их использовании, особенно когда они увидят вариации в создаваемом тексте.
Markovify - это библиотека Python, которая позиционирует себя как простой расширяемый генератор цепей Маркова. Использование включает создание случайных полуправдоподобных предложений на основе существующего текста . И, надо признать, пользоваться им невероятно легко и быстро. Сами по себе цепи Маркова - изящные творения, которые дают вероятности сохранения и изменения для процессов с несколькими состояниями. Я не буду здесь углубляться в математику цепей Маркова, но не стесняйтесь ссылаться на это и это для всестороннего обзора и визуализаций соответственно. Для наших целей я объясню цепи Маркова наглядно.
Глядя на изображение выше, мы видим, что у нас есть три возможных состояния; Облачно, дождливо и солнечно. Цепи Маркова полагаются на текущее состояние, чтобы предсказать будущий результат. Если мы заметим, что сегодня дождь, наши вероятности таковы: вероятность того, что завтра все еще идет дождь, составляет 60%, вероятность того, что будет облачно, составляет 30%, а вероятность того, что будет солнечно, составляет 10%. Та же логика может быть применена, когда мы начинаем с облачного и солнечного состояний.
Так как, черт возьми, это работает с текстом? По сути, каждое слово в нашем корпусе связано со всеми остальными словами с различной вероятностью с использованием цепей Маркова. Итак, если наше начальное слово (состояние) - Ты, Markovify присваивает вероятность каждому второму слову в нашем корпусе того, насколько вероятно, что оно будет следовать за нашим начальным словом. Он может иметь Должен с вероятностью 65% следовать за Ты, а также будет с 20%, может с 10% и так далее и так далее для всего нашего корпуса, который будет составлять последние 5%. . Обратите внимание, что вероятность того, что Ты последует за собой, должна быть близка к 0%, поскольку такое повторение слова не имеет особого смысла и верно почти для всех слов. Чтобы получить более подробные сведения, ознакомьтесь с разделом Фильмы, показатели и размышления здесь.
Создание текста
Итак, мы, наконец, готовы реализовать Markovify для генерации текста. Вы можете найти мою записную книжку Colab здесь на Github. Сначала нам нужно установить наши библиотеки и пакеты.
!pip install nltk !pip install spacy !pip install markovify !pip install -m spacy download en
Мы будем использовать NLTK и spaCy для предварительной обработки текста, поскольку они являются наиболее распространенными, и наша модель будет лучше генерировать текст, если мы сначала его проанализируем. Теперь мы можем импортировать наши библиотеки.
import spacy import re import markovify import nltk from nltk.corpus import gutenberg import warnings warnings.filterwarnings('ignore') nltk.download('gutenberg') !python -m spacy download en
Для этой демонстрации мы собираемся использовать три трагедии Шекспира из корпуса Project Gutenberg NLTK. Сначала мы напечатаем все документы в корпусе Gutenberg, чтобы вы могли смешивать и сопоставлять их по своему усмотрению.
#inspect Gutenberg corpus print(gutenberg.fileids())
Для этой демонстрации мы будем использовать три трагедии Шекспира «Макбет», «Юлий Цезарь» и «Гамлет». Итак, теперь мы импортируем их и проверим текст.
#import novels as text objects hamlet = gutenberg.raw('shapespeare-hamlet.txt') macbeth = gutenberg.raw('shakespeare-macbeth.txt') caesar = gutenberg.raw('shakespeare-caesar.txt') #print first 100 characters of each print('\nRaw:\n', hamlet[:100]) print('\nRaw:\n', macbeth[:100]) print('\nRaw:\n', caesar[:100])
Затем мы создадим служебную функцию для очистки текста с помощью библиотеки re. Эта функция удалит ненужные пробелы и отступы, знаки препинания и т. Д.
#utility function for text cleaning def text_cleaner(text): text = re.sub(r'--', ' ', text) text = re.sub('[\[].*?[\]]', '', text) text = re.sub(r'(\b|\s+\-?|^\-?)(\d+|\d*\.\d+)\b','', text) text = ' '.join(text.split()) return text
Далее мы продолжим очищать наши тексты, удалив заголовки глав и индикаторы и применив нашу функцию очистки текста.
#remove chapter indicator hamlet = re.sub(r'Chapter \d+', '', hamlet) macbeth = re.sub(r'Chapter \d+', '', macbeth) caesar = re.sub(r'Chapter \d+', '', caesar) #apply cleaning function to corpus hamlet = text_cleaner(hamlet) caesar = text_cleaner(caesar) macbeth = text_cleaner(macbeth)
Теперь мы хотим использовать spaCy для анализа наших документов. Более подробную информацию о конвейере обработки текста можно найти здесь.
#parse cleaned novels nlp = spacy.load('en') hamlet_doc = nlp(hamlet) macbeth_doc = nlp(macbeth) caesar_doc = nlp(caesar)
Теперь, когда наши тексты очищены и обработаны, мы можем создавать предложения и объединять наши документы.
hamlet_sents = ' '.join([sent.text for sent in hamlet_doc.sents if len(sent.text) > 1]) macbeth_sents = ' '.join([sent.text for sent in macbeth_doc.sents if len(sent.text) > 1]) caesar_sents = ' '.join([sent.text for sent in caesar_doc.sents if len(sent.text) > 1]) shakespeare_sents = hamlet_sents + macbeth_sents + caesar_sents #inspect our text print(shakespeare_sents)
Предварительная обработка текста завершена, и мы можем начать использовать Markovify для генерации предложений.
#create text generator using markovify generator_1 = markovify.Text(shakespeare_sents, state_size=3)
А теперь самое интересное. Нам просто нужно написать цикл, чтобы генерировать столько предложений, сколько мы хотим. Ниже мы создадим 3 предложения неопределенной длины и еще 3 предложения длиной менее 100 символов.
#We will randomly generate three sentences for i in range(3): print(generator_1.make_sentence()) #We will randomly generate three more sentences of no more than 100 characters for i in range(3): print(generator_1.make_short_sentence(max_chars=100))
Пример текста:
«Он останется, пока ты не придешь. К. Гамлет, эта Жемчужина твоя, вот тебе здоровье».
«Мой достопочтенный лорд, я буду говорить с ним».
Неплохо для шекспировского английского. Но я думаю, что мы можем добиться большего. Мы реализуем POSifiedText с помощью SpaCy, чтобы попытаться улучшить предсказание текста.
#next we will use spacy's part of speech to generate more legible text class POSifiedText(markovify.Text): def word_split(self, sentence): return ['::'.join((word.orth_, word.pos_)) for word in nlp(sentence)] def word_join(self, words): sentence = ' '.join(word.split('::')[0] for word in words) return sentence #Call the class on our text generator_2 = POSifiedText(shakespeare_sents, state_size=3)
И, наконец, напечатайте больше предложений с помощью нашего нового генератора.
#now we will use the above generator to generate sentences for i in range(5): print(generator_2.make_sentence()) #print 100 characters or less sentences for i in range(5): print(generator_2.make_short_sentence(max_chars=100))
Некоторые примеры:
«Он убил меня, мама, беги прочь, прошу тебя, О, это противодействие тебе, фальшивые датские псы».
«Окажи им милость, мы упокоим твоего короля Эрмитов».
В заключение
В этой статье мы рассмотрели, как быстро и легко реализовать Markovify для генерации текста с помощью цепей Маркова. Вы можете увидеть, насколько легко это реализовать и начать работу, как только у вас будет очищенный текст. Я планирую опубликовать больше моделей НЛП / генерации текста с использованием нейронных сетей, преобразователей и других с тем же корпусом с целью сравнения сложности и производительности между ними.