Позвольте компьютерам говорить сами за себя

Что такое цепь Маркова?

Если мы собираемся говорить о цепях Маркова, вероятно, будет полезно узнать, что они из себя представляют. Названные в честь математика Андрея Маркова, они представляют собой набор случайных величин, индексированных определенным образом (обычно по времени), которые меняются от состояния к состоянию таким образом, который зависит исключительно от текущего состояния, а не от прошлых событий.

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

Представьте себе игру, в которой вы начинаете с 10 долларов и подбрасываете монету, выигрывая 1 доллар орлом и проигрывая 1 доллар решкой, пока ваши деньги не закончатся. После любого количества подбрасываний мы можем посмотреть на ваш текущий денежный пул - скажем, 8 долларов - и сделать прогноз следующего состояния ваших средств - 7 или 9 долларов - с 50% вероятностью того, что он окажется верным. Никакие сведения о предыдущих подбрасываниях или начальные 10 долларов не влияют на наши шансы правильно угадать, делая это цепью Маркова.

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

Какая разница?

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

Вероятность появления слова - как и шансы подбрасывания монеты 50/50 - зависит от того, что называется n-граммами. N-грамма - это группа из n слов, которые встречаются вместе в исходном тексте. В этой статье мы поговорим о биграммах, сочетаниях двух слов. Предложение глупый настолько же глуп. Имеет биграммы (глупо), (это как), (как глупо) и (глупо имеет.)

Биграммы используются для предсказания следующего слова в предложении на основе выбранного слова. Если мы начнем со слова «глупый», мы увидим, что есть два варианта: (глупо) и (глупо). Вероятность того и другого составляет 50%, поскольку мы не знаем, где мы находимся в предложении. Если мы выбираем «есть», то мы проверяем все биграммы, начинающиеся с «есть», и со 100% уверенностью знаем, что следующее слово будет «как», потому что существует только одна биграмма. Мы заканчиваем (как глупо) и делаем то же самое предположение 50/50, что и раньше. Если бы мы пошли с (глупый делает.), Это закончило бы наш приговор, оставив нас с «глупыми делает». как целая фраза.

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

Я собираюсь понаблюдать за девочкой-боссом, которая показывала рекламу в моей ленте из-за мягкой кровати, и я очень рад видеть меня, и мне было интересно, получаете ли вы громкие уведомления об авторском праве, что футбольная песня в четверг вечером должно быть ужасным опытом.

Не страшный приговор! Футбольная песня в четверг вечером - ужасный опыт. Не обращайте внимания на ту часть, где я произнес фразу "Boss Baby" достаточно, чтобы мой телефон подсказал мне ее. Телефон извлекает из пула все, что вы когда-либо печатали, и объединяет слова в пары, чтобы сэкономить вам немного времени.

Так как бы это выглядело за кулисами? Я написал простую версию на Ruby, чтобы имитировать это поведение.

Код:

Что именно это делает?

Если вы знаете Ruby и хотите проверить это самостоятельно, щелкните ссылку под кодом, чтобы увидеть репозиторий GitHub. Он содержит дополнительные методы абзацев и эссе, которые запускают метод предложения несколько раз.

Давайте кратко рассмотрим каждую из функций.

инициализировать - мы инициализируем нашу цепочку массивом каждого слова из введенного текста по порядку. Кроме того, мы используем #find_enders, чтобы захватить все слова, заканчивающие предложения, чтобы мы могли немного обмануть, чтобы не заканчивать наши предложения такими словами, как «the».

make_sentence - этот метод несколько раз вызывает #find_next, а затем берет все слова, возвращенные из этого, делает первое заглавным и добавляет одно из слов из нашего массива enders с точкой.

find_next - большая часть тяжелой работы выполняется здесь. Мы передаем слово, затем просматриваем наш массив всех исходных слов, и везде, где мы находим совпадение, мы возвращаем слово сразу после нашего ввода. Это дает нам набор слов, которые должны иметь смысл, чтобы соответствовать оригиналу. Если ничего не найдено (либо не было передано ни слова, либо документ закончился после входного слова), он вернет случайное слово из исходного файла.

Но подождите, не так ли?

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

Это также может распространяться на более крупные группы, помимо биграмм - все наши предложения получаются совершенно бессмысленными, а дополнительный контекст в форме триграмм может помочь словам найти более естественные места.

Есть еще сотня вещей, которые мы можем изменить. Но самое главное, что у нас есть базовая линия, с которой нужно работать. Давайте посмотрим на это в действии.

Выносить приговоры

Давайте создадим новую цепочку и создадим предложение со следующим фрагментом:

chain = MarkovChain.new(filepath)
chain.make_sentence

Для исходного файла давайте введем первый набор абзацев из этой статьи и посмотрим, что у нас получится.

«Поскольку нет красных носков, следующие две пары синих носков и не прошлые события, это зеленая стирка».

Вы понимаете, почему мы хотим добавить некоторые обновления. Быстрое сканирование, и это может иметь смысл, но довольно бессвязно. К счастью, мы избежали упоминания о Босс Бэби.

Настоящий эксперт

В процессе написания этого поста я начал задаваться вопросом - почему, учитывая все эти исследования, его пишет я, если я все еще учусь? Есть люди, которые действительно знают, о чем говорят. Я подумал, а почему бы им всем не написать что-нибудь вместе? С помощью моей программы некоторые из самых ярких исследователей цепей Маркова объединили свои труды. Проблема с академическим письмом в том, что оно суховато. Чтобы привнести легкомыслие и более плавную прозу, я смешал текст из статьи ClickHole об истории Джорджа Р. Мартина с лошадьми, когда писал «Игру престолов».

Щелкните здесь для просветления.

Источники для созданной статьи:

ClickHole: когда я начал писать Игру престолов, я не знал, как выглядят лошади.

Статьи: 1, 2, 3, 4, 5.