您如何在长长的字符流中找到正确的单词?
输入 :
"The revised report onthesyntactictheoriesofsequentialcontrolandstate"
谷歌的输出:
"The revised report on syntactic theories sequential controlandstate"
(考虑到他们产生输出的时间,这已经足够接近了)
你觉得谷歌是怎么做到的?您将如何提高准确性?
您如何在长长的字符流中找到正确的单词?
输入 :
"The revised report onthesyntactictheoriesofsequentialcontrolandstate"
谷歌的输出:
"The revised report on syntactic theories sequential controlandstate"
(考虑到他们产生输出的时间,这已经足够接近了)
你觉得谷歌是怎么做到的?您将如何提高准确性?
我会尝试这样的递归算法:
例如,给它“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 作为答案。
尝试使用以下规则的随机正则文法(相当于隐马尔可夫模型):
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
概率可以从训练集导出,但请参见以下讨论。最可能的解析是使用 Viterbi 算法计算的,该算法在隐藏状态的数量上具有二次时间复杂度,在这种情况下是您的词汇表,因此您可能会遇到大型词汇表的速度问题。但是如果你设置所有的 p_w = 1, q_w = 1 p = .5 这意味着,这些是人工语言模型中的概率,其中所有单词的可能性相同,所有非单词的可能性相同。当然,如果你不使用这种简化,你可以更好地分割,但算法复杂度会下降很多。如果您查看维基百科条目中的重复关系,您可以尝试针对这种特殊情况对其进行简化。直到位置 k 的维特比解析概率可以简化为VP(k) = max_l(VP(k-l) * (1 if text[k-l:k] is a word else .5^l)
您可以将 l 与单词的最大长度绑定,并通过哈希搜索查找所有字母是否构成单词。其复杂性与词汇量无关,并且是O(<text length> <max l>)
. 抱歉,这不是一个证明,只是一个草图,但应该能让你继续前进。另一个潜在的优化,如果您创建字典的 trie,您可以检查子字符串是否是任何正确单词的前缀。因此,当您查询 text[kl:k] 并得到否定答案时,您已经知道对于任何 d 的 text[kl:k+d] 也是如此。要利用这一点,您必须显着重新安排递归,所以我不确定这可以被充分利用(它可以看到评论)。
这是我开始为最近的代码高尔夫开发的 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
高温高压
检查拼写校正算法。这是一篇关于 google 中使用的算法的文章的链接 - http://www.norvig.com/spell-correct.html。在这里,您将找到来自 google 的关于该主题的科学论文。
在进行递归拆分和字典查找之后,为了提高短语中单词对的质量,您可能有兴趣使用单词对的互信息。
这本质上是通过一个训练集并找出单词对的 MI 值,告诉你阿尔伯特辛普森比阿尔伯特爱因斯坦更不可能:)
您可以尝试在 Science Direct 中搜索此主题的学术论文。有关 Mutual 信息的基本信息,请参阅http://en.wikipedia.org/wiki/Mutual_information
去年,我参与了一个搜索引擎项目的短语搜索部分,我试图解析维基百科数据集并对每个单词对进行排名。我有 C++ 中的代码,如果你愿意的话,如果你能找到它的一些用途,可以与你分享。它解析维基媒体并为每个单词对找出相互信息。