关于如何对一个句子进行标记,有很多指南,但我没有找到任何关于如何做相反的事情。
import nltk
words = nltk.word_tokenize("I've found a medicine for my disease.")
result I get is: ['I', "'ve", 'found', 'a', 'medicine', 'for', 'my', 'disease', '.']
是否有任何功能,而不是将标记化的句子恢复为原始状态。由于某种原因,函数tokenize.untokenize()
不起作用。
编辑:
我知道我可以这样做,这可能解决了这个问题,但我很好奇是否有一个集成功能:
result = ' '.join(sentence).replace(' , ',',').replace(' .','.').replace(' !','!')
result = result.replace(' ?','?').replace(' : ',': ').replace(' \'', '\'')
答案 0 :(得分:37)
如今(2016年),nltk
中有一个内置的去语音器 - 它被称为http://usejsdoc.org/tags-typedef.html:
data = ["Hi", ",", "my", "name", "is", "Bob", "!"]
from nltk.tokenize.moses import MosesDetokenizer
detokenizer = MosesDetokenizer()
detokenizer.detokenize(data, return_str=True)
# u'Hi, my name is Bob!'
您需要nltk >= 3.2.2
才能使用分离器。
答案 1 :(得分:10)
要从word_tokenize
转发nltk
,我建议您查看http://www.nltk.org/_modules/nltk/tokenize/punkt.html#PunktLanguageVars.word_tokenize并进行一些逆向工程。
如果没有在nltk上做疯狂的黑客攻击,你可以试试这个:
>>> import nltk
>>> import string
>>> nltk.word_tokenize("I've found a medicine for my disease.")
['I', "'ve", 'found', 'a', 'medicine', 'for', 'my', 'disease', '.']
>>> tokens = nltk.word_tokenize("I've found a medicine for my disease.")
>>> "".join([" "+i if not i.startswith("'") and i not in string.punctuation else i for i in tokens]).strip()
"I've found a medicine for my disease."
答案 2 :(得分:2)
使用here
中的token_utils.untokenize
import re
def untokenize(words):
"""
Untokenizing a text undoes the tokenizing operation, restoring
punctuation and spaces to the places that people expect them to be.
Ideally, `untokenize(tokenize(text))` should be identical to `text`,
except for line breaks.
"""
text = ' '.join(words)
step1 = text.replace("`` ", '"').replace(" ''", '"').replace('. . .', '...')
step2 = step1.replace(" ( ", " (").replace(" ) ", ") ")
step3 = re.sub(r' ([.,:;?!%]+)([ \'"`])', r"\1\2", step2)
step4 = re.sub(r' ([.,:;?!%]+)$', r"\1", step3)
step5 = step4.replace(" '", "'").replace(" n't", "n't").replace(
"can not", "cannot")
step6 = step5.replace(" ` ", " '")
return step6.strip()
tokenized = ['I', "'ve", 'found', 'a', 'medicine', 'for', 'my','disease', '.']
untokenize(tokenized)
"I've found a medicine for my disease."
答案 3 :(得分:2)
from nltk.tokenize.treebank import TreebankWordDetokenizer
TreebankWordDetokenizer().detokenize(['the', 'quick', 'brown'])
# 'The quick brown'
答案 4 :(得分:0)
tokenize.untokenize
不起作用的原因是因为它需要的信息不仅仅是单词。以下是使用tokenize.untokenize
的示例程序:
from StringIO import StringIO
import tokenize
sentence = "I've found a medicine for my disease.\n"
tokens = tokenize.generate_tokens(StringIO(sentence).readline)
print tokenize.untokenize(tokens)
答案 5 :(得分:0)
我建议在标记化中保留偏移量:(标记,偏移量)。 我认为,这些信息对于处理原始句子很有用。
import re
from nltk.tokenize import word_tokenize
def offset_tokenize(text):
tail = text
accum = 0
tokens = self.tokenize(text)
info_tokens = []
for tok in tokens:
scaped_tok = re.escape(tok)
m = re.search(scaped_tok, tail)
start, end = m.span()
# global offsets
gs = accum + start
ge = accum + end
accum += end
# keep searching in the rest
tail = tail[end:]
info_tokens.append((tok, (gs, ge)))
return info_token
sent = '''I've found a medicine for my disease.
This is line:3.'''
toks_offsets = offset_tokenize(sent)
for t in toks_offsets:
(tok, offset) = t
print (tok == sent[offset[0]:offset[1]]), tok, sent[offset[0]:offset[1]]
给出:
True I I
True 've 've
True found found
True a a
True medicine medicine
True for for
True my my
True disease disease
True . .
True This This
True is is
True line:3 line:3
True . .
答案 6 :(得分:0)
我正在使用以下代码,没有任何主要的库函数用于解毒目的。我正在使用一些特定标记的去标记
_SPLITTER_ = r"([-.,/:!?\";)(])"
def basic_detokenizer(sentence):
""" This is the basic detokenizer helps us to resolves the issues we created by our tokenizer"""
detokenize_sentence =[]
words = sentence.split(' ')
pos = 0
while( pos < len(words)):
if words[pos] in '-/.' and pos > 0 and pos < len(words) - 1:
left = detokenize_sentence.pop()
detokenize_sentence.append(left +''.join(words[pos:pos + 2]))
pos +=1
elif words[pos] in '[(' and pos < len(words) - 1:
detokenize_sentence.append(''.join(words[pos:pos + 2]))
pos +=1
elif words[pos] in ']).,:!?;' and pos > 0:
left = detokenize_sentence.pop()
detokenize_sentence.append(left + ''.join(words[pos:pos + 1]))
else:
detokenize_sentence.append(words[pos])
pos +=1
return ' '.join(detokenize_sentence)
答案 7 :(得分:0)
对我来说,当我安装python nltk 3.2.5时,它有用,
pip install -U nltk
然后,
import nltk
nltk.download('perluniprops')
from nltk.tokenize.moses import MosesDetokenizer
如果你正在使用内部pandas数据帧,那么
df['detoken']=df['token_column'].apply(lambda x: detokenizer.detokenize(x, return_str=True))
答案 8 :(得分:0)
没有简单答案的原因是您实际上需要字符串中原始标记的跨度位置。如果您没有,并且您没有对原始标记进行反向工程,则重新组装的字符串将基于对使用的标记规则的猜测。如果您的令牌生成器没有给您带来跨度,那么如果您有三件事,仍然可以这样做:
1)原始字符串
2)原始令牌
3)修改过的令牌(假设您已经以某种方式更改了令牌,因为这是我可以想到的唯一应用程序,如果您已经拥有#1)
使用原始令牌集来识别跨度(如果令牌生成器这样做会更好吗?)并从后到前修改字符串,以使跨度不会随您而改变。
在这里,我正在使用TweetTokenizer,但不要紧,只要您使用的令牌化程序不会更改令牌的值,以使它们实际上不在原始字符串中即可。
tokenizer=nltk.tokenize.casual.TweetTokenizer()
string="One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin."
tokens=tokenizer.tokenize(string)
replacement_tokens=list(tokens)
replacement_tokens[-3]="cute"
def detokenize(string,tokens,replacement_tokens):
spans=[]
cursor=0
for token in tokens:
while not string[cursor:cursor+len(token)]==token and cursor<len(string):
cursor+=1
if cursor==len(string):break
newcursor=cursor+len(token)
spans.append((cursor,newcursor))
cursor=newcursor
i=len(tokens)-1
for start,end in spans[::-1]:
string=string[:start]+replacement_tokens[i]+string[end:]
i-=1
return string
>>> detokenize(string,tokens,replacement_tokens)
'One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a cute vermin.'
答案 9 :(得分:-2)
使用join功能:
您可以执行' '.join(words)
来取回原始字符串。
答案 10 :(得分:-2)
最简单,最直观的方法。 token_list也可以是列表列表。
s=[]
for i in token_list:
s.append(" ".join(i))