Il y a tellement de guides sur la façon de symboliser une phrase, mais je n'en ai trouvé aucun sur la façon de faire le contraire.
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', '.']
Existe-t-il une fonction qui ramène la phrase à jetons à son état d'origine? La fonction tokenize.untokenize()
pour une raison quelconque ne fonctionne pas.
Éditer:
Je sais que je peux faire par exemple ceci et cela résout probablement le problème mais je suis curieux de savoir s'il existe une fonction intégrée pour cela:
result = ' '.join(sentence).replace(' , ',',').replace(' .','.').replace(' !','!')
result = result.replace(' ?','?').replace(' : ',': ').replace(' \'', '\'')
Vous pouvez utiliser "treebank detokenizer" - TreebankWordDetokenizer
:
from nltk.tokenize.treebank import TreebankWordDetokenizer
TreebankWordDetokenizer().detokenize(['the', 'quick', 'brown'])
# 'The quick brown'
Il y a aussi MosesDetokenizer
qui était dans nltk
mais qui a été supprimé à cause de problèmes de licence , mais il est disponible sous la forme Sacremoses
package autonome .
Inverser Word_tokenize
de nltk
, je suggère de regarder dans http://www.nltk.org/_modules/nltk/tokenize/punkt.html#PunktLanguageVars.Word_tokenize et de faire de l'ingénierie inverse.
À moins de faire des hacks fous sur nltk, vous pouvez essayer ceci:
>>> 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."
from nltk.tokenize.treebank import TreebankWordDetokenizer
TreebankWordDetokenizer().detokenize(['the', 'quick', 'brown'])
# 'The quick brown'
utilisation token_utils.untokenize
de ici
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."
Pour moi, cela a fonctionné lorsque j'ai installé python nltk 3.2.5,
pip install -U nltk
puis,
import nltk
nltk.download('perluniprops')
from nltk.tokenize.moses import MosesDetokenizer
Si vous utilisez l'intérieur pandas dataframe, alors
df['detoken']=df['token_column'].apply(lambda x: detokenizer.detokenize(x, return_str=True))
La raison tokenize.untokenize
ne fonctionne pas parce qu'il a besoin de plus d'informations que des mots. Voici un exemple de programme utilisant 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)
Aide supplémentaire: Tokenize - Python Docs | Problème potentiel
Je propose de conserver les décalages dans la tokenisation: (token, offset). Je pense que ces informations sont utiles pour le traitement de la phrase d'origine.
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]]
Donne:
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 . .
Utilisez la fonction join :
Vous pouvez simplement faire une ' '.join(words)
pour récupérer la chaîne d'origine.
La raison pour laquelle il n'y a pas de réponse simple est que vous avez réellement besoin des emplacements de portée des jetons d'origine dans la chaîne. Si vous ne l'avez pas et que vous n'effectuez pas d'ingénierie inverse de votre tokenisation d'origine, votre chaîne réassemblée est basée sur des suppositions concernant les règles de tokenisation qui ont été utilisées. Si votre tokenizer ne vous a pas donné d'étendue, vous pouvez toujours le faire si vous avez trois choses:
1) La chaîne d'origine
2) Les jetons originaux
3) Les jetons modifiés (je suppose que vous avez changé les jetons d'une manière ou d'une autre, car c'est la seule application à laquelle je pense si vous en avez déjà # 1)
Utilisez le jeu de jetons d'origine pour identifier les portées (ne serait-ce pas bien si le tokenizer faisait cela?) Et modifiez la chaîne d'arrière en avant afin que les portées ne changent pas au fur et à mesure.
Ici, j'utilise TweetTokenizer, mais cela ne devrait pas avoir d'importance tant que le tokenizer que vous utilisez ne change pas les valeurs de vos jetons afin qu'ils ne soient pas réellement dans la chaîne d'origine.
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.'
J'utilise le code suivant sans aucune fonction de bibliothèque principale à des fins de détokéisation. J'utilise la détokénisation pour certains jetons spécifiques
_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)