从英语单词中删除字母重复的正确方法?

时间:2016-04-05 11:37:17

标签: nlp sentiment-analysis linguistics

正如标题清楚地描述的那样,我想知道消除英语中人物重复的正确方法是什么,这种重复在社交媒体中常用来夸大这种感觉。由于我正在开发一种软​​件解决方案以纠正错误的单词,我需要一种可应用于大多数英语单词的全局算法。所以,我要求专家学习正确的方法来消除英语单词中的其他字母,而不使用基于学习的方法?

PS。 (1)我使用WordNet 3.0 database以编程方式检查单词是否有效。到目前为止,除了一些例子,例如Word {3.0中定义为veery的单词tawny brown North American trush noted for its song之外,其他很好。当在WordNet中找到该单词时,我会中断字母消除过程。那么有没有其他知识库可以用来代替WordNet?

PS。 (2)其实我在English Language & Usage community问了这个问题。但他们引导我在这里问。

一些例子:

haappyy --> happy
amaaazzinng --> amazing
veeerry --> very

正如你在例子中看到的那样,字母重复的地方各不相同。

2 个答案:

答案 0 :(得分:5)

将带有reduplicated letters的非规范形式映射到其规范形式的一个主要问题是,如果没有上下文,则它是模糊的:考虑例如 meeet - 实际上是遇见还是遇见

解决这个问题的一种方法是测量一个单词"" canonicity"作为在 n -gram模型中给出其上下文(即前面的单词)的概率:被判断为"别名的单词"所讨论的单词(如下所述)并且最常见,因为手头的背景被视为"规范"形式:

正常化

可以将 veeerry very 等形式视为同一形式的变体,即经过修改的"有序的字符包" ,所以,例如两者都被处理为('v','e','r','y')的序列,虽然具有不同的权重:

  • veeerry (('v', 1), ('e', 3), ('r', 2), ('y', 1))
  • 非常(('v', 1), ('e', 1), ('r', 1), ('y', 1))

通过这种方式,这些形式可以像普通特征向量一样处理 - 这将用于加权下面的概率。

混叠

我们需要能够映射,例如 veeerry 非常没有,正如您所描述的那样,与不常见的单词veery匹配。因此,只需将 veeerry 表示为"有序的角色包"没有任何加权意味着 veeerry 同样合理地成为veery的变体 - 它显然不是。但是,由于veery很可能与副词非常lexical distribution非常不同,因此可能会感觉到标准化('v','e','r','y')根据其背景的概率 - 例如:

  1. 这辆车非常大。
  2. 这辆车非常精彩。("这辆车是一首黄褐色的北美画眉,以其歌曲而闻名,#34;)
  3. 即使不考虑这两个例子之间的句法part-of-speech区别(第一个是副词而第二个是名词),这两个不同词的原始统计分布是非常不同的。出于这个原因,给出了一个好的模型,P(veery_1 | "This car is") > P(veery_2 | "This car is a")

    概率加权

    为了关联,例如 veeerry 非常,以便在文本中找到它时将其标准化,同时仍然将veery标准化为非常,我们可以然后只需使用代表 veeerry 的有序包字符的特征向量来计算它与 very veery的距离,然后使用该距离来加权概率在给定的上下文中的每一个:

    best_term(form, context) = argmax(arg=term, (P(term, context) * sim(ordered_bag_of_chars(form), ordered_bag_of_chars(term)))
    

    我已经编写了一些Python代码,以便更好地解释这在现实生活中是如何工作的:

    #!/usr/bin/env python3
    
    from scipy.spatial.distance import cosine
    
    class Vocabulary(object):
        def __init__(self, forms):
            self.forms = forms
            self.form_variations = {}   
            for form in forms:
                unique_symbol_freqs = tuple(count_unique_symbol_freqs(form))
                unique_symbols = tuple(unique_symbol_freq[0] for unique_symbol_freq in unique_symbol_freqs)
                self.form_variations[unique_symbols] = WeightedSymbolSequence(unique_symbol_freqs)
    
    class WeightedSymbolSequence(object):
        def __init__(self, unique_symbols):
            # TODO: Finish implementation
            pass
    
    def count_unique_symbol_freqs(input_seq):
        if len(input_seq) > 0:
            # First process the head symbol
            previous_unique_symbol = (input_seq[0], 1)
            # Process tail symbols; Add extra iteration at the end in order to handle trailing single unique symbols
            tail_iter = iter(input_seq[1:])
            try:
                while True:
                    input_symbol = next(tail_iter)
                    if input_symbol == previous_unique_symbol[0]:
                        previous_unique_symbol = (previous_unique_symbol[0], previous_unique_symbol[1] + 1)
                    else:
                        result_unique_symbol = previous_unique_symbol
                        previous_unique_symbol =  (input_symbol, 1)
                        yield result_unique_symbol
            except StopIteration:
                # The end of the sequence was encountered; Handle a potential last unique symbol
                yield previous_unique_symbol
    
    if __name__ == '__main__':
        from sys import stderr
    
        tests = {"haappyy" : "happy", "amaaazzinng" : "amazing", "veeerry" : "very"}
    
        with open("/usr/share/dict/words", "r") as vocab_instream:
            # TODO: Alias uppercase versions of characters to their lowercase ones so that e.g. "dog" and "Dog" are highly similar but not identical
            vocab = Vocabulary(frozenset(line.strip().lower() for line in vocab_instream))
    
        for form1, form2 in tests.items():
            # First check if the token is an extant word 
            if form1 in vocab.forms:
                print("\"%s\" found in vocabulary list; No need to look for similar words." % form1)
            else:
                form1_unique_char_freqs = tuple(count_unique_symbol_freqs(form1))
                print(form1_unique_char_freqs)
                form2_unique_char_freqs = tuple(count_unique_symbol_freqs(form2))
                dist = cosine([form1_unique_char_freq[1] for form1_unique_char_freq in form1_unique_char_freqs], [form2_unique_char_freq[1] for form2_unique_char_freq in form2_unique_char_freqs])
                # TODO: Get probabilities of form variations using WeightedSymbolSequence objects in "vocab.form_variations" and then multiply the probability of each by the cosine similarity of bag of characters for form1 and form2
    
                try:
                    # Get mapping to other variants, e.g. "haappyy" -> "happy"
                    form1_unique_chars = tuple(form1_unique_char_freq[0] for form1_unique_char_freq in form1_unique_char_freqs)
                    variations = vocab.form_variations[form1_unique_chars]
                except KeyError:
                    # TODO: Use e.g. Levenshtein distance in order to find the next-most similar word: No other variations were found
                    print("No variations of \"%s\" found." % form1, file=stderr)
    

答案 1 :(得分:2)

尝试纠正用户输入的单词的另一种方法是提前生成可能性并存储它们。如果你拿了一个常用单词列表(没有奇怪的鸟类),为重复元音创建了一些规​​则,然后将它们全部添加到你的字典中(例如内存中的三元树),这可能有效。

'very'的重复'e'形式将存储为'veery','veeery',...如果你用频率信息增加Wordnet,'veery'作为'very'的拼写错误将被标记比'鸟'更常见。

我在自然语言引擎中做了类似的事情,我也试图处理另一种常见的社交媒体异常:单词之间缺乏空格。