How to prevent splitting specific words or phrases and numbers in NLTK?
当我对拆分特定单词、日期和数字的文本进行标记时,我遇到了文本匹配问题。在 NLTK 中对单词进行标记时,如何防止诸如”在我的家人中跑步”、”30 分钟步行”或”每天 4 次”之类的短语分裂?
它们不应导致:
1
|
[‘runs’,‘in’,‘my’,‘family’,‘4x’,‘a’,‘day’]
|
例如:
Yes 20-30 minutes a day on my bike, it works great!!
给予:
1
|
[‘yes’,’20-30′,‘minutes’,‘a’,‘day’,‘on’,‘my’,‘bike’,‘,’,‘it’,‘works’,‘great’]
|
我希望将”20-30 分钟”视为一个词。我怎样才能得到这种行为>?
- 糊涂的第一个问题!我认为用标点符号和语法稍微清理一下这个问题是值得的,因为我认为这不是一项简单的任务。我提供了一个解决方案,但我担心它的计算成本可能非常高。让其他一些用户对此有很大帮助。
- 好问题!还有一些用 nltk 编写的函数,它的工作方式与 spacy 语言学步骤/正则表达式模式方法略有不同。
您可以使用 MWETokenizer:
1
2 3 4 5 |
from nltk import word_tokenize
from nltk.tokenize import MWETokenizer tokenizer = MWETokenizer([(’20’, ‘-‘, ’30’, ‘minutes’, ‘a’, ‘day’)]) |
[输出]:
1
|
[‘Yes’, ’20-30_minutes_a_day’, ‘on’, ‘my’, ‘bike’, ‘,’, ‘it’, ‘works’, ‘great’, ‘!’, ‘!’]
|
一个更原则的方法,因为你不知道`word_tokenize 将如何拆分你想要保留的单词:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
from nltk import word_tokenize
from nltk.tokenize import MWETokenizer def multiword_tokenize(text, mwe): mwe = [’20-30 minutes a day’, ‘!!’] |
[输出]:
1
|
[‘Yes’, ’20-30 minutes a day’, ‘on’, ‘my’, ‘bike’, ‘,’, ‘it’, ‘works’, ‘great’, ‘!!’]
|
据我所知,您将很难在标记化的同时保留各种长度的 n-gram,但您可以找到这些 n-gram,如下所示。然后,您可以将语料库中的项目替换为 n-gram,并使用一些连接字符(如破折号)。
这是一个示例解决方案,但可能有很多方法可以实现。重要说明:我提供了一种查找文本中常见 ngram 的方法(您可能需要超过 1 个,因此我在其中放置了一个变量,以便您可以决定要收集多少个 ngram。您可能需要不同的数字对于每种类型,但我现在只给出了 1 个变量。)这可能会错过你认为重要的 ngram。为此,您可以将要查找的内容添加到 user_grams。这些将被添加到搜索中。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import nltk
#an example corpus #tokenize the corpus #create ngrams from n=2 to 5 |
此部分查找常见的 ngram,最多为 5 个。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#if you change this to zero you will only get the user chosen ngrams
n_most_common=1 #how many of the most common n-grams do you want. fdist_bigrams = nltk.FreqDist(bigrams).most_common(n_most_common) #n most common bigrams #concat the ngrams together #next 4 lines create a single list with important ngrams |
此部分允许您将自己的 ngram 添加到列表中
1
2 3 4 5 6 |
#Another option here would be to make your own list of the ones you want
#in this example I add some user ngrams to the ones found above user_grams=[‘ngram1 I like’, ‘ngram 2’, ‘another ngram I like a lot’] user_grams=[x.lower() for x in user_grams] n_grams.extend(user_grams) |
最后一部分执行处理,以便您可以再次标记化并将 ngram 作为标记。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#initialize the corpus that will have combined ngrams
corpus_ngrams=corpus #here we go through the ngrams we found and replace them in the corpus with #retokenize the new corpus so we can find the ngrams print(corpus_ngrams_tokens) Out: [‘a-big-tantrum’, ‘runs-in-my-family’, ‘4x’, ‘a’, ‘day’, ‘,’, ‘every-week’, ‘.’, ‘a-big-tantrum’, ‘is’, ‘lame’, ‘.’, ‘a-big-tantrum’, ’causes’, ‘strife’, ‘.’, ‘it’, ‘runs-in-my-family’, ‘because’, ‘of’, ‘our’, ‘complicated’, ‘history’, ‘.’, ‘every-week’, ‘is’, ‘a’, ‘lot’, ‘though’, ‘.’, ‘every-week’, ‘i’, ‘dread’, ‘the’, ‘tantrum’, ‘.’, ‘every-week’, ‘…’] |
我认为这实际上是一个非常好的问题。
- thanx.如果我想匹配我在数据集中找到的 n-gram f,那么我应该制作自己的列表来匹配它,并且只保留列表中的 n-gram,但这会更耗时?
- 我在代码中包含了该选项。如果您不想同时找到最常见的那些,只需将 n_most_common=1 更改为 n_most_common=0。不过,我希望我的解决方案是独立的和可验证的。我会将其编辑为评论。然后,您可以将所需的 n-gram 添加到 user_gram 列表中。
- 此外,似乎不可能有那么多 ngram 可以同时不常见和重要。换句话说,如果你要费心对这些 ngram 进行标记,那应该是因为它们对你很重要,但如果它们不经常出现,这本身就使它们不那么重要。你应该用开始的方法得到所有重要的常见的,只需要添加一些特定于你的学习的,但这只是我的预感。
- 此外,如果这回答了您的问题,请考虑投票并检查它是否已回答。看看,如果有人回答我的问题怎么办?
来源:https://www.codenong.com/55619297/