Логика оказала заметное влияние на мою жизнь со средней школы, когда я впервые услышал его песню All I Do. Микстейп, которому принадлежит эта песня, Молодой Синатра, в одиночку сделал меня поклонником хип-хопа во всех его формах, познакомив меня со старыми и новыми стилями, которые я никогда даже не думал слушать. Я могу связать каждую песню этого проекта с определенным чувством или моментом из средней и старшей школы, будь то время великолепной радости или ужасной печали. В результате я никогда не встречал куплета или песни Logic, которые мне не нравились бы, поэтому, когда мне назначили этот проект в классе по науке о данных, который я брал еще в мае, я сразу понял, на каком музыканте я сосредоточусь. на.

Эта лаборатория по программированию, которую мне дали, была для меня самой интригующей и воодушевляющей, поэтому я подумал, что было бы весело написать об этом! Я рассмотрю написанный мной код Python, а затем расскажу о некоторых сильных и слабых сторонах этой реализации, а также о том, как ее можно улучшить в будущем. И, конечно же, огромная благодарность профессору Деннису Сану из Cal Poly SLO за предоставление отличных решений и помощь, а также за предоставление такой замечательной лаборатории для изучения науки о данных!

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

Построение алгоритма

Суть этой реализации заключается в создании биграммы цепи Маркова для представления английского языка. В частности, наша цепочка будет объектом словаря, в котором каждый ключ представляет собой уникальный кортеж, состоящий из слова и следующего за ним слова. Использование биграмм вместо отдельных слов (униграммы) позволяет нам повысить точность и удобочитаемость наших сгенерированных строк, поскольку это определяет нашу модель так, что следующее слово в предложении предсказывается на основе двух предыдущих слов, а не только непосредственно предыдущий (подробнее об этом позже).

Получение данных

Настоящий первый шаг - собрать все тексты песен, которые мы будем анализировать. Для этого я просмотрел в Интернете ссылки на тексты каждой песни Logic, а затем просмотрел каждую ссылку, чтобы собрать из них весь соответствующий текст. Конечным результатом является список, в котором каждый элемент представляет собой строку, содержащую все слова одной песни.

URL-адрес каждой веб-страницы отличался только номером страницы в ее хвосте, поэтому я легко смог сделать этот первый цикл for для итерации по обеим страницам. Созданная мной переменная soup является объектом из библиотеки BeautifulSoup; он делает синтаксический анализ и извлечение данных с веб-сайтов невероятно простым. С помощью библиотеки requests мне удалось передать soup весь HTML-код каждой веб-страницы. Первая таблица на странице содержала все ссылки, которые нам нужны, чтобы перейти к текстам каждой песни Logic, поэтому я использовал еще один цикл for для просмотра каждой строки в таблице; поскольку гиперссылки в HTML обозначаются тегами a и href, я смог найти теги и добавить каждую ссылку в список links. Следующий набор for циклов был использован для перебора каждого из links, которые я только что получил, чтобы захватить каждый абзац текста в каждой песне, что в конечном итоге позволило мне добавить каждый набор song_text к исчерпывающему списку lyrics. Мне пришлось использовать функцию time.sleep, чтобы убедиться, что меня не заблокируют или забанят за слишком быстрое выполнение множества запросов.

Создание цепочки

Наконец-то пора закопаться и начать строить нашу цепь Маркова. Мы пишем функцию, которая перебирает каждое слово во всех текстах Logic, чтобы сгенерировать модель, исследуя каждую последовательность из двух слов и создавая список всех слов, следующих за каждой последовательностью. Для более эффективного и практичного обхода мы используем теги "<START>", "<END>" и "<N>" для обозначения начала, конца и символов новой строки песни соответственно.

Эта train_markov_chain функция принимает lyrics список, который мы создали ранее. Мы инициализируем наш chain клавишей (None, "<START>"), чтобы отметить начало песни. Как вы, наверное, догадались, мы начинаем с ключевого слова None, потому что перед первым словом песни нет слов. Итерируя по каждой песне, мы заменяем все символы новой строки в тексте песни нашим настраиваемым тегом, а затем создаем переменную last_2 для отслеживания текущего / самого последнего ключа, обнаруженного во время итерации. Затем, for каждый word в тексте песни, мы вставляем word в нашу цепочку, соединяя его с текущей клавишей, а затем обновляем текущую клавишу, чтобы отразить тот факт, что мы переходим к следующей word. Если этот новый ключ еще не существует в цепочке, мы можем просто создать его с пустым списком, чтобы отразить тот факт, что его раньше не видели. После обработки последнего word в песне мы добавляем тег “<END>” и переходим к следующей песне в нашей коллекции.

Предсказание текстов песен

После того, как мы построили и вернули словарь, представляющий нашу цепь Маркова, мы можем перейти к последней части алгоритма: генерации предсказанных текстов. Начиная с ключа (None, "<START>") (первого ключа в нашей цепочке), мы случайным образом выбираем одно из слов в списке, связанное с этим ключом, затем сдвигаем ключ, который мы в настоящее время исследуем, чтобы учесть слово, которое мы только что выбрали. Мы продолжаем этот процесс до тех пор, пока наконец не встретим тег "<END>".

Таким образом, собрав весь этот код вместе, мы можем print(generate_new_lyrics(chain)) отображать наши предсказанные тексты песен в консоли. Если вы хотите запустить весь этот код самостоятельно, вы можете проверить мой репозиторий GitHub для доступа к файлам Python и Jupyter Notebook.

Однако необходимо отметить, что, поскольку я использую простую случайную выборку для создания новых текстов песен, я также произвольно выбираю, какой объем вывода я на самом деле получаю. Было несколько избранных случаев, когда я получал меньше одной строки или даже одного слова вывода, но в большинстве случаев алгоритм распечатывал огромное количество предсказанных текстов. Тем не менее, после поиска результатов, которые я получил от многих прогонов алгоритма, я получил в целом несколько довольно хороших текстов, начиная от сырых изюминок и заканчивая совершенно веселыми шутками. Ниже вы найдете мои любимые, все из которых, как мне кажется, довольно точно соответствуют стилю Logic (за исключением нескольких забавных и / или странных, которые я счел обязанным включить).

«Днем она любит курить, да она угаснет»

«Итак, я пыхтел от этого видения, ночь - моя дивизия»

«Я покажу им, как действовать, я встану, а потом на спину»

«Слава Черному Иисусу, теперь они вызывают копов, делайте это ради жизни, которую я надеваю ради реквизита»

«Я почти знал, что он родился с жарой, камень более твердый, чем бетон»

«Малышка, могу ли я найти человечество?»

«Выложи все на улицу, не говоря уже о жаре»

«Этому ублюдку лучше знать, что федералы тупят»

«Моя жизнь не моя, ты мне нужен, чтобы спасти меня»

«Все ищут улицу, не говоря уже о жаре»

«Я продолжаю рэп про всех вас, ребята? К черту все это дерьмо, меня не было по какой-то причине »

«О, боже, боже, чувствую эту злодейскую атмосферу»

«Но я езжу на автобусе от своих проблем, Господи, помоги мне их решить»

«Теперь я молюсь, чтобы кто-нибудь спас меня, независимо от того, во что ты веришь»

«Тебе есть что терять, как проклятому королю»

«Пешки, как правило, продолжают без гудка»

«Ага, знаешь что? Я заставлю мертвых гребаных президентов представлять меня "

«Жизнь, в которую я иду, это фасад»

«Она больше не хочет плакать, обездоленная и менее информированная»

«Я вижу себя в Лувре и знаю, что мой разум шутит надо мной»

«Я чувствую, что убиваю свои мечты, жизнь угасает»

"Почему никто не хочет говорить, что я умею читать рэп"

«Как абракадабра, когда этот фокусник выезжает на дорогу»

«Друзья в моей студии, а я гулял по шоссе»

«Этот рэп - еще один день, еще одна книга»

«Я вижу хороших людей, которые делают дождь, как никто другой»

«Я знаю, с чего начать убийство»

«Эй, я сохраню все эти новые остатки»

«Поверь мне, девочка, я не разозлюсь, если ты слышал, как кто-то лгал»

«Люди думают, что они на его уровне, они не готовы к большему количеству бутылок»

"Любой, кто едет со мной, теперь попробует это понять"

Анализируя наши результаты: сильные и слабые стороны

Наблюдение за многими, многими выходами нашей реализации биграммы и реализацией униграммы позволяет нам сделать некоторые важные выводы:

  1. Предсказания нашей модели точны, но часто повторяются. Важно отметить, что многие из наших предсказанных строк оказались почти идентичными строкам, которые на самом деле написала Логика, т. е. половину строки из одного куплета / песни. совмещена с половиной строки из другого куплета / песни. Этого следовало ожидать, поскольку использование биграмм приводит к меньшей изменчивости предсказываемых слов из-за того, что предсказания основываются на двух предыдущих словах вместо одного самого последнего, что приводит к последовательностям из трех или более слов, происходящих из одной и той же логической лирики. Проще говоря, использование биграмм вместо отдельных слов повышает удобочитаемость и сходство со стилем Logic, но снижает творческий потенциал.
  2. Наша модель медленнее и генерирует меньше результатов. Модель униграммы работает быстрее, потому что объект словаря, представляющий ее цепь Маркова, имеет гораздо меньше ключей. В нашей модели намного больше ключей, потому что она должна обрабатывать кортежи из двух слов. Более того, как я упоминал ранее, были случаи, когда я получал очень мало вывода или вообще не получал, и обычно я получал меньше, чем от реализации униграммы. Это можно объяснить меньшим количеством возможностей для следующего слова, когда мы основываем его на двух предыдущих словах.

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

В поисках лучшего пути

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

Рекуррентная нейронная сеть - один из примеров замены, которую мы можем использовать. Хотя я не буду вдаваться в подробности здесь о RNN, в основном потому, что я сам все еще только взламываю ими поверхность, я сделаю несколько кратких заметок. Двумя ключевыми характеристиками RNN являются то, что они не предполагают, что все входные данные независимы друг от друга и что они способны хранить историю того, что они обработали, и то и другое необходимо для улучшения нашей модели. Для получения дополнительной информации о том, как работают RNN и как их реализовать, посетите страницу Википедии, а также это руководство; Я буду учиться у обоих, чтобы в конечном итоге обновить свой код для более точных прогнозов.

Если вы зашли так далеко, спасибо, что прочитали о моем растущем интересе к машинному обучению и узнали о нем! Наука о данных в целом уже имеет так много увлекательных и творческих приложений. Я с нетерпением жду возможности более подробно изучить множество нюансов и тонкостей по мере того, как я работаю над большим количеством проектов и продолжаю совершенствоваться как разработчик. В конце концов, как однажды написал Logic (и Пол Брандт до него), как небо может быть пределом, если на Луне есть следы?

Особая благодарность моей сестре Келси Камин за мотивацию и конструктивные отзывы, которые она предоставила, когда я написал это!