Pull to refresh

Comments 43

В поисковых системах какой алгоритм применяется в поисковой строке?

Для автоподсказок в поисковой строке на первый взгляд можно было бы использовать какое-нибудь модифицированное префиксное дерево (trie).

Простой коэффициент Жаккара не подойдёт?

Я что-то похожее писал на коленке лет 28 назад, для быстрого поиска имён в адресной книге (поиск по мере набора имени). Там я добавил идею о близком равенстве отдельных множеств букв. Например, буквы е и ё можно считать равными, а буквы с и з, и и е, д и т - близкими. Ну и так далее. Также, учитивались возможные удвоения. Хоть алгоритм был придуман и написан на коленке, но для имён/фамилий он работал очень неплохо.

Держите лучше расстояние Карловского:

function karlovskiy_distance( left: string, right: string ) {

	left = '\b\b' + left + '\f\f'
	right = '\b\b' + right + '\f\f'

	let dist = -4

	for( let i = 0; i < left.length - 2; ++ i ) {
		if( !right.includes( left.slice( i, i+3 ) ) ) ++ dist
	}

	for( let i = 0; i < right.length - 2; ++ i ) {
		if( !left.includes( right.slice( i, i+3 ) ) ) ++ dist
	}

	return Math.max( 0, dist ) / ( left.length + right.length - 8 )
  
}
я пришёл к себе домой | я пришел домой к себе = 0.29
июнь | июль = 0.25
кот | для = 1
кот | кот = 0

  • Простой и быстрый алгоритм.

  • Нормированный от 0 до 1 результат.

  • Перестановка слов не даёт большой дистанции.

  • Маленькие разные слова не дают маленькой дистанции.

  • Не даёт преимущества началу и концу.

  • Различает начало и конец.

  • Работает и со строками разной длины.

  • Годится только для коротких строк.

  • Сложность o(n) .. O(n^2)

  • Не сложно потратить O(log n) памяти и сделать O(n) поддержав заодно и длинные тексты.

Ответ всегда должен получаться от 0 до 1, где 0 - точное совпадение слов, 1 - полное не совпадение слов.

Что-то не сходится. 0 может быть только если не совпала ни одна буква.

То есть для примера сравним варан и комод.

Расстояние по вашей формуле равно нулю, но слова совсем не похожи.

Верно подметили.
На самом деле ровно наоборот: 1 - точное совпадение, 0 - полное не совпадение.

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

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

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

Разве что нарезать по словарю невозможных биграм. А кто и зачем эти пробелы вырезал?

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

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

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

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

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

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

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

У вас тут слишком много недоказанных утверждений. Даже математика инопланетной цивилизации может отличаться очень кардинально (даже 2+2 в их математике будет не равно 4 (точнее не всегда равно), например потому что 2 литра спирта и 2 литра воды не дадут 4 литра смеси), а уж система записи вообще быть совершенно другой.
Банально, у них давно все на биологических компьютерах с системой счисления по основанию пи без целых и отрицальных чисел в принципе, а тетрадка с закорючками вообще не воспринимается как носитель информации.

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

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

Ну вы считаете себе представителем разумной цивилизации? Ну вот вам математическая запись

image

Сможете рассказать, какие математические формулы там записаны не используя гугл или хотя бы как вы сможете понять закономерности? Учитывайте, что это все-таки Земная цивилизация наш предок, от которой мы унаследовали многие принципы современной цивилизации. Сложность расшифровки записей инопланетной цивилизации может быть на пару порядков выше.

Обратите внимание, вы не знаете тут ни систему счисления, ни в какую сторону записываются формулы, ни какие символы будут символами операций, ни как записывается числа (десятичная позиционная система далеко не единственная возможная), более того у вас совершенно нет понятия, какие математические действия тут вообще записаны, может 2+2, а может двойные интегралы, с производными, синусами и косинусами.

Даже если у вас совпадает математическая логика, ни зная ничего о записавшей цивилизации, расшифровка тут очень нетривиальна. Если же понятия совсем разные — практически невозможна.

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

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

Простите, что разрушил ваши представления о мире, я сам был обескуражен, когда впервые осознал эти идеи.

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

Минимизируешь энтропию текста деленного на слова + энтропию словаря, по всем разбиениям. Если делить посимвольно (все слова из одной буквы), словарь получаеться маленький, а текст большой. С другой стороны если взять весь текст как одно слово - тогда на сам текст будет приходиться 0 энтропии, а словарь будет стоить как весь текст без сжатия (с перплексией алфавит на символ). При этом частые сочетания (фразеологизмы) и популярные предлоги скорее всего слипнуться в одно слово. Еще можно добавить штраф за длину слов / KLD между словарем и ципфром.

Как считать энтропию словаря? Энтропия одноэлементного множества не равна нулю?

log(alphabet) * сумму длин всех слов.

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

Начинаю с односимвольных слов, сливаю соседние жадно.

https://pastebin.com/q8Jnkfkh

Вот концовка

https://pastebin.com/fZ5eGa0U

Видно что жадность плохо работает, нужно еще и пересобирать слова.

Пример: "есл им ы" встречается 4 раза, и хотя мы добавили в словарь пару (есл, и), мы не можем ничего сделать с уже построенным "им".

Красиво. Даже на маленькой статье вырисовываются знакомые очертания некоторых слов. А томик войны и мира ваша программа переварить сможет?

Асимптотика не та, но я попробовал.

315058.332   204.849             гово               ри     49     41162       394
314857.649   200.682             ихай              лов     28     41134       394
314657.976   199.673              нул               ся     30     41104       395
314547.888   110.087              лов               на     73     41053       396
314315.691   232.197               че              лов     49     41004       397
314123.157   192.534             напа                в     51     40953       398
313921.508   201.648              пер                е     71     40882       399
313741.424   180.084               ма             лень     27     40855       400
313551.339   190.086             гово             рила     29     40826       401
313376.408   174.931             кото              рый     26     40800       402
298986.794   256.386            сказа                л     78     36302       622
298732.565   254.230            челов                е     49     36253       622
298492.642   239.922            княги               ня     42     36211       623
298281.436   211.206               те             перь     30     36181       623
298093.330   188.106            петер              бур     17     36164       623
297918.569   174.761             васи              лий     23     36141       624
297746.231   172.338              про              дол     29     36112       625
297587.984   158.247             прос                и     42     36070       626
297442.206   145.777           какбуд               то     29     36041       627
297289.781   152.426            графи               ня     27     36014       628
297156.175   133.605            приба               ви     19     35995       628
297040.460   115.715              все              гда     17     35978       628
296925.564   114.897            улыба              ясь     19     35959       629
296811.075   114.488             стве              нно     22     35937       630
296681.633   129.442            сказа            лаона     28     35909       631
296573.243   108.390                с            мотре     24     35885       631
296472.848   100.395                м          ихайлов     26     35859       632

Что-то получилось https://pastebin.com/6xk0ZipK

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

Я имел в виду time complexity, у меня что-то между O(n^2) и O(n^3).

Вот тут код, я наигрался с ним, как минимум убедился что моя идея рабочая https://pastebin.com/uWnsdikr

Да, я как-то не заметил: вы "энтропию" текста делите на количество "слов" в нем. Для больших текстов разве не будет наблюдаться тенденции к измельчению "слов", чтобы увеличить делитель большого слагаемого?

text = \{word_i\};H(text) = \sum_{i}-log(P(word_i))==\sum_{w,cnt_w} -cnt_w \times log(\frac{cnt_w}{n}) = n \times log(n) - \sum_{w,cnt_w}{cnt_w \times \log(cnt_w)}

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

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

Можете проверить на таком примере:

"Вы встретили Машу в Москве Маша жила на шоссе Энтузиастов в большом доме"

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

Для разделения потока символов на слова у нас даже этого нет.

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

При перестановкЕ! Не И, пожалуйста поправьте.

Н-граммы разной длины во всех своих проявлениях и хаки с сортировкой слов по буквам (вот оригинальный блог пост).

В сочетании с существующими библиотеками по оптимизированному расчету расстояний Левенштейна или KNN (k-nearest neighbour search) можно сделать поиск и индекс любой сложности и нужности.

Мне кажется у Джаро есть недостаток. Этот алгоритм не отражает то, что человек "подразумевает" под похожестью.
В статье сравниваются слова:

создание

обедать

И итоговое расстояние получается:

d = (1 / 3) * ( 3 / 8 + 3 / 7 + (3 - 0.5) / 3 ) ≈ 0.33 * ( 0.36 + 0.43 + 0.83 ) ≈ 0.53

Предположим мы уберем лишнюю, не совпадающую букву "с".

оздание

обедать

Тогда слова должны стать "более похожими", но изменится выравнивание букв "да". И это значительно изменит результат алгоритма.

d = (1 / 3) * ( 3 / 7 + 3 / 7 + (3 - 1) / 3 ) ≈ 0.33 * ( 0.42 + 0.42 + 0.33 ) ≈ 0.39
Получается, убрав лишнюю букву, которая мешала совпадению, мы только уменьшили "похожесть". А вот расстояние Левенштейна тут покажет правильную тенденцию.

Примечательно, что мой алгоритм даёт 1 в первом случае так как слова на самом деле совсем и не похожи, а вот во втором уже 0.86, так как имеют общую приставку.

Sign up to leave a comment.

Articles