18

我从文档中提取了句子列表。我正在预处理这个句子列表以使其更明智。我面临以下问题

我有句子如"more recen t ly the develop ment, wh ich is a po ten t "

我想用查字典来纠正这样的句子?删除不需要的空格。

最终输出应该是"more recently the development, which is a potent "

我会假设这是预处理文本中的一项直接任务?我需要一些指针来寻找这种方法。谢谢。

4

7 回答 7

8

看看单词或文本分割。问题是找到最可能将字符串拆分为一组单词的方法。例子:

 thequickbrownfoxjumpsoverthelazydog

最可能的分割当然应该是:

 the quick brown fox jumps over the lazy dog

这是一篇文章,包括使用Google Ngram语料库解决问题的原型源代码:

该算法起作用的关键是获取有关世界的知识,在这种情况下,某些语言中的词频。我在这里实现了文章中描述的算法的一个版本:

示例用法:

$ python segmentation.py t hequi ckbrownfoxjum ped
thequickbrownfoxjumped
['the', 'quick', 'brown', 'fox', 'jumped']

使用数据,甚至可以重新排序:

$ python segmentation.py lmaoro fll olwt f pwned
lmaorofllolwtfpwned
['lmao', 'rofl', 'lol', 'wtf', 'pwned']

请注意,该算法非常慢 - 它是典型的。

使用 NLTK 的另一种方法:

至于您的问题,您可以连接所有必须的字符串部分以获得单个字符串并在其上运行分段算法。

于 2013-10-30T06:20:54.790 回答
4

您的目标是改进文本,而不一定要使其完美;所以你概述的方法在我看来是有道理的。我会保持简单并使用“贪婪”的方法:从第一个片段开始,只要结果在字典中就可以粘贴;如果结果不是,请吐出到目前为止的内容并从下一个片段重新开始。是的,有时您会在使用类似的情况下犯错误the me thod,因此如果您经常使用它,您可以寻找更复杂的东西。但是,它可能已经足够好了。

您主要需要的是一本大字典。如果您经常使用它,我会将其编码为“前缀树”(又名trie),以便您可以快速找出片段是否是真实单词的开头。nltk 提供了一个Trie 实现。

由于这种虚假分词不一致,我也会用当前文档中已经处理过的词来扩展我的字典;您之前可能已经看到了完整的单词,但现在它被分解了。

于 2013-11-01T23:28:45.400 回答
3

--解决方案一:

让我们将句子中的这些块视为算盘上的珠子,每个珠子都由一个部分字符串组成,珠子可以向左或向右移动以生成排列。每个片段的位置固定在两个相邻片段之间。在当前情况下,珠子将是:

(more)(recen)(t)(ly)(the)(develop)(ment,)(wh)(ich)(is)(a)(po)(ten)(t)

这解决了 2 个子问题:

a)珠子是一个单一的单元,所以我们不关心珠子内的排列,即“更多”的排列是不可能的。

b) 珠子的顺序是不变的,只是它们之间的间距会发生变化。即“more”总是在“recen”之前,以此类推。

现在,生成这些珠子的所有排列,输出如下:

morerecentlythedevelopment,which is a potent
morerecentlythedevelopment,which is a poten t
morerecentlythedevelop ment, wh ich is a po tent
morerecentlythedevelop ment, wh ich is a po ten t
morerecentlythe development,whichisapotent

然后根据它们包含的相关词典中的单词数量对这些排列进行评分,最正确的结果可以很容易地被过滤掉。 more recently the development, which is a potent得分会高于morerecentlythedevelop ment, wh ich is a po ten t

执行珠子排列部分的代码:

import re

def gen_abacus_perms(frags):
    if len(frags) == 0:
        return []
    if len(frags) == 1:
        return [frags[0]]

    prefix_1 = "{0}{1}".format(frags[0],frags[1])
    prefix_2 = "{0} {1}".format(frags[0],frags[1])
    if len(frags) == 2:
        nres = [prefix_1,prefix_2]
        return nres

    rem_perms = gen_abacus_perms(frags[2:])
    res = ["{0}{1}".format(prefix_1, x ) for x in rem_perms] + ["{0} {1}".format(prefix_1, x ) for x in rem_perms] +  \
["{0}{1}".format(prefix_2, x ) for x in rem_perms] + ["{0} {1}".format(prefix_2 , x ) for x in rem_perms]
    return res



broken = "more recen t ly the develop ment, wh ich is a po ten t"
frags = re.split("\s+",broken)
perms = gen_abacus_perms(frags)
print("\n".join(perms))

演示:http: //ideone.com/pt4PSt


--解决方案#2:

我会建议一种替代方法,该方法利用人们已经开发的文本分析智能,这些智能已经由从事类似问题的工作人员开发,并且已经处理过依赖于字典和语法的大型数据语料库,例如搜索引擎。

我不太了解此类公共/付费 API,因此我的示例基于谷歌搜索结果。

让我们尝试使用谷歌:

  1. 您可以继续将您的无效条款提交给 Google,多次通过,并根据您的查找字典继续评估某些分数的结果。通过使用 2 遍您的文本,这是两个相关的输出:

在此处输入图像描述

此输出用于第二遍:

在此处输入图像描述

这使您将转换为“最近的发展,这是一种强大的”。

要验证转换,您将不得不使用一些相似性算法和评分来过滤掉无效/不太好的结果。

一种原始技术可能是使用 difflib 对标准化字符串进行比较。

>>> import difflib
>>> import re
>>> input = "more recen t ly the develop ment, wh ich is a po ten t "
>>> output = "more recently the development, which is a potent "
>>> input_norm = re.sub(r'\W+', '', input).lower()
>>> output_norm = re.sub(r'\W+', '', output).lower()
>>> input_norm
'morerecentlythedevelopmentwhichisapotent'
>>> output_norm
'morerecentlythedevelopmentwhichisapotent'
>>> difflib.SequenceMatcher(None,input_norm,output_norm).ratio()
1.0
于 2013-10-30T06:41:21.163 回答
3

我建议去掉空格并寻找字典单词来分解它。您可以做一些事情来使其更准确。要使其获得文本中没有空格的第一个单词,请尝试获取整个字符串,并从文件中浏览字典单词(您可以从http://wordlist.sourceforge.net/下载几个这样的文件),首先是最长的,而不是从要分段的字符串末尾取下字母。如果你想让它在一个大字符串上工作,你可以让它自动从后面去掉字母,这样你要查找的第一个单词的字符串就只有最长的字典单词。这应该会导致您找到最长的单词,并减少将“异步”分类为“同步”之类的操作。下面是一个示例,它使用原始输入来获取要更正的文本以及一个名为 dictionary.txt 的字典文件:

dict = open("dictionary.txt",'r')                                #loads a file with a list of words to break string up into
words = raw_input("enter text to correct spaces on: ")
words = words.strip()                                            #strips away spaces
spaced = []                                                      #this is the list of newly broken up words
parsing = True                                                   #this represents when the while loop can end
while parsing:
    if len(words) == 0:                                          #checks if all of the text has been broken into words, if it has been it will end the while loop
        parsing = False
    iterating = True
    for iteration in range(45):                                  #goes through each of the possible word lengths, starting from the biggest
        if iterating == False:
            break
        word = words[:45-iteration]                              #each iteration, the word has one letter removed from the back, starting with the longest possible number of letters, 45
        for line in dict:
            line = line[:-1]                                     #this deletes the last character of the dictionary word, which will be a newline. delete this line of code if it is not a newline, or change it to [1:] if the newline character is at the beginning
            if line == word:                                     #this finds if this is the word we are looking for
                spaced.append(word)
                words = words[-(len(word)):]                     #takes away the word from the text list
                iterating = False
                break
print ' '.join(spaced)                                           #prints the output

如果你想让它更准确,你可以尝试使用自然语言解析程序,网上有几个免费的 python 可用。

于 2013-11-20T02:11:10.167 回答
2

这里有一些非常基本的东西:

chunks = []
for chunk in my_str.split():
    chunks.append(chunk)
    joined = ''.join(chunks)
    if is_word(joined):
        print joined,
        del chunks[:]

# deal with left overs
if chunks:
    print ''.join(chunks)

我假设您在某个地方有一组有效的单词可以用来实现is_word. 您还必须确保它处理标点符号。这是一种方法:

def is_word(wd):
    if not wd:
        return False
    # Strip of trailing punctuation. There might be stuff in front
    # that you want to strip too, such as open parentheses; this is
    # just to give the idea, not a complete solution.
    if wd[-1] in ',.!?;:':
        wd = wd[:-1]
    return wd in valid_words
于 2013-10-30T06:37:39.323 回答
2

您可以遍历字典以找到最合适的词。找不到匹配项时将单词加在一起。

def iterate(word,dictionary):
   for word in dictionary:
      if words in possibleWord:
        finished_sentence.append(words)
        added = True
      else:
        added = False
      return [added,finished_sentence]
sentence = "more recen t ly the develop ment, wh ich is a po ten t "
finished_sentence = ""
sentence = sentence.split()
for word in sentence:
  added,new_word = interate(word,dictionary)
  while True:   
    if added == False:
      word += possible[sentence.find(possibleWord)]
      iterate(word,dictionary)
    else:
      break
  finished_sentence.append(word)

这应该有效。对于变量,下载每个英文单词dictionary的 txt文件,然后在程序中打开它。

于 2013-11-20T18:23:55.530 回答
0

我的index.py文件就像

from wordsegment import load, segment
load()
print(segment('morerecentlythedevelopmentwhichisapotent'))

我的index.php文件就像

<html>

<head>
  <title>py script</title>
</head>

<body>
  <h1>Hey There!Python Working Successfully In A PHP Page.</h1>
  <?php
    $python = `python index.py`;
    echo $python;
    ?>
</body>

</html>

希望这会奏效

于 2019-03-20T08:29:21.027 回答