Найдите слова в длинном потоке персонажей. Авто-токенизировать

Как вы находите правильные слова в длинном потоке символов?

Вход:

"The revised report onthesyntactictheoriesofsequentialcontrolandstate"

Выход Google:

"The revised report on syntactic theories sequential controlandstate"

(что достаточно близко, учитывая время, когда они произвели выход)

Как вы думаете, Google это делает? Как бы вы увеличили точность?

Ответ 1

Я бы попробовал такой рекурсивный алгоритм:

  • Попробуйте вставить пробел в каждую позицию. Если левая часть - это слово, то повторяйтесь в правой части.
  • Подсчитайте количество действительных слов/количество полных слов во всех конечных выходах. Вероятно, ваш ответ с наилучшим соотношением.

Например, задание "thesentenceisgood" будет выполняться:

thesentenceisgood
the sentenceisgood
    sent enceisgood
         enceisgood: OUT1: the sent enceisgood, 2/3
    sentence isgood
             is good
                go od: OUT2: the sentence is go od, 4/5
             is good: OUT3: the sentence is good, 4/4
    sentenceisgood: OUT4: the sentenceisgood, 1/2
these ntenceisgood
      ntenceisgood: OUT5: these ntenceisgood, 1/2

Итак, вы бы выбрали OUT3 в качестве ответа.

Ответ 2

Попробуйте стохастическую регулярную грамматику (эквивалентную скрытым марковским моделям) со следующими правилами:

for every word in a dictionary:
stream -> word_i stream with probability p_w
word_i -> letter_i1 ...letter_in` with probability q_w (this is the spelling of word_i)
stream -> letter stream with prob p (for any letter)
stream -> epsilon with prob 1

Вероятности могут быть получены из набора тренировок, но см. следующее обсуждение. Наиболее вероятный синтаксический анализ вычисляется с использованием алгоритма Витерби, который имеет квадратичную временную сложность в количестве скрытых состояний, в этом случае ваш словарь, чтобы вы могли столкнуться с проблемами скорости с большими словарями. Но что, если вы установите все p_w = 1, q_w = 1 p =.5 Это означает, что это вероятности в искусственной языковой модели, где все слова одинаково вероятны, а все не-слова одинаково маловероятны. Конечно, вы могли бы сегментировать лучше, если бы не использовали это упрощение, но сложность алгоритма снижается совсем немного. Если вы посмотрите на рекуррентное отношение в записи в википедии, вы можете попробовать и упростить его для этого особого случая. Вероятность разбора viterbi до положения k может быть упрощена до VP(k) = max_l(VP(k-l) * (1 if text[k-l:k] is a word else .5^l). Вы можете связать l с максимальной длиной слова и найти, если буквы l образуют слово с поиском хэша. Сложность этого не зависит от размера словаря и составляет O(<text length> <max l>). Извините, это не доказательство, просто эскиз, но вам нужно идти. Другая потенциальная оптимизация, если вы создаете три словаря, вы можете проверить, является ли подстрока префиксом любого правильного слова. Поэтому, когда вы запрашиваете текст [k-l: k] и получаете отрицательный ответ, вы уже знаете, что то же самое верно для текста [k-l: k + d] для любого d. Чтобы воспользоваться этим, вам придется значительно изменить рекурсию, поэтому я не уверен, что это может быть полностью использовано (это может видеть комментарий).

Ответ 3

Вот код в Mathematica, который я начал разрабатывать для недавнего гольф-гольфа.
Это минимальный согласованный, не жадный, рекурсивный алгоритм. Это означает, что предложение "перо тяжелее меча" (без пробелов) возвращает {"перо может превышать меч]:)

findAll[s_] :=
  Module[{a = s, b = "", c, sy = "="},
  While[
   StringLength[a] != 0,
   j = "";
   While[(c = findFirst[a]) == {} && StringLength[a] != 0,
    j = j <> StringTake[a, 1];
    sy = "~";
    a = StringDrop[a, 1];
   ];
   b = b <> " " <> j ;
   If[c != {},
    b = b <> " " <> c[[1]];
    a = StringDrop[a, StringLength[c[[1]]]];
   ];
  ];
   Return[{StringTrim[StringReplace[b, "  " -> " "]], sy}];
]

findFirst[s_] :=
  If[s != "" && (c = DictionaryLookup[s]) == {}, 
   findFirst[StringDrop[s, -1]], Return[c]];

Пример ввода

ss = {"twodreamstop", 
      "onebackstop", 
      "butterfingers", 
      "dependentrelationship", 
      "payperiodmatchcode", 
      "labordistributioncodedesc", 
      "benefitcalcrulecodedesc", 
      "psaddresstype", 
      "ageconrolnoticeperiod",
      "month05", 
      "as_benefits", 
      "fname"}

Выход

 twodreamstop              = two dreams top
 onebackstop               = one backstop
 butterfingers             = butterfingers
 dependentrelationship     = dependent relationship
 payperiodmatchcode        = pay period match code
 labordistributioncodedesc ~ labor distribution coded es c
 benefitcalcrulecodedesc   ~ benefit c a lc rule coded es c
 psaddresstype             ~ p sad dress type
 ageconrolnoticeperiod     ~ age con rol notice period
 month05                   ~ month 05
 as_benefits               ~ as _ benefits
 fname                     ~ f name

НТН

Ответ 5

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

Это, по существу, происходит, хотя набор тренировок и выяснение M.I. значения пар слов, которые говорят вам, что Альберт Симпсон менее вероятен, чем Альберт Эйнштейн:)

Вы можете попробовать искать Science Direct для научных статей в этой теме. Для получения базовой информации о взаимной информации см. http://en.wikipedia.org/wiki/Mutual_information

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