web-dev-qa-db-fra.com

Python Libérez le ton d'une phrase

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(' \'', '\'')   
25
Brana

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 .

46
alecxe

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."
11
alvas
from nltk.tokenize.treebank import TreebankWordDetokenizer
TreebankWordDetokenizer().detokenize(['the', 'quick', 'brown'])
# 'The quick brown'
3
Uri

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."
3
Renklauf

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

0
dparpyani

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 . .
0
alemol

Utilisez la fonction join :

Vous pouvez simplement faire une ' '.join(words) pour récupérer la chaîne d'origine.

0
shaktimaan

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.'
0
gss

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)
0
Asad