Найдите слова в длинном потоке персонажей. Авто-токенизировать
Как вы находите правильные слова в длинном потоке символов?
Вход:
"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
НТН
Ответ 4
Проверить алгоритм коррекции орфографии. Вот ссылка на статью об алгоритме, используемом в google - http://www.norvig.com/spell-correct.html. Здесь вы найдете научную статью по этой теме из Google.
Ответ 5
После выполнения рекурсивного расщепления и поиска в словаре, чтобы повысить качество пар слов в вашей фразе, вам может быть интересно использовать взаимную информацию о парах слов.
Это, по существу, происходит, хотя набор тренировок и выяснение M.I. значения пар слов, которые говорят вам, что Альберт Симпсон менее вероятен, чем Альберт Эйнштейн:)
Вы можете попробовать искать Science Direct для научных статей в этой теме. Для получения базовой информации о взаимной информации см. http://en.wikipedia.org/wiki/Mutual_information
В прошлом году я участвовал в части поиска фразы в проекте поисковой системы, в котором я пытался разобрать хотя бы набор данных по википедии и ранжировать каждую пару слов. У меня есть код на С++, если вам интересно, можете поделиться им с вами, если вы можете его использовать. Он анализирует wikimedia, и каждая пара слов обнаруживает взаимную информацию.