Python Убейте предложение

Есть так много руководств о том, как tokenize предложение, но я не нашел никаких способов сделать обратное.

 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() по какой-то причине не работает.

Edit:

Я знаю, что могу это сделать, например, и это, вероятно, решает проблему, но мне любопытно, есть ли для этого встроенная функция:

result = ' '.join(sentence).replace(' , ',',').replace(' .','.').replace(' !','!')
result = result.replace(' ?','?').replace(' : ',': ').replace(' \'', '\'')   

Ответ 1

Вы можете использовать "детекенизатор treebank" - TreebankWordDetokenizer:

from nltk.tokenize.treebank import TreebankWordDetokenizer
TreebankWordDetokenizer().detokenize(['the', 'quick', 'brown'])
# 'The quick brown'

Существует также MosesDetokenizer который был в nltk но был удален из-за проблем с лицензированием, но доступен в виде отдельного пакета Sacremoses.

Ответ 2

Чтобы отменить 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."

Ответ 3

from nltk.tokenize.treebank import TreebankWordDetokenizer
TreebankWordDetokenizer().detokenize(['the', 'quick', 'brown'])
# 'The quick brown'

Ответ 4

используйте 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."

Ответ 5

Причина 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)


Дополнительная справка: Tokenize - Документы Python | Потенциальная проблема

Ответ 6

Я предлагаю сохранить смещения в токенизации: (токен, смещение). Я думаю, эта информация полезна для обработки исходного предложения.

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

Ответ 7

Я использую следующий код без какой-либо основной функции библиотеки для цели дезактивации. Я использую деокенизацию для некоторых конкретных токенов

_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)

Ответ 8

Для меня это сработало, когда я установил python nltk 3.2.5,

pip install -U nltk

затем,

import nltk
nltk.download('perluniprops')

from nltk.tokenize.moses import MosesDetokenizer

Если вы используете insids pandas dataframe, тогда

df['detoken']=df['token_column'].apply(lambda x: detokenizer.detokenize(x, return_str=True))

Ответ 9

Причина в том, что нет простого ответа, на самом деле вам нужны места расположения исходных токенов в строке. Если у вас этого нет, и вы не перепроектируете свою оригинальную токенизацию, ваша вновь собранная строка основывается на догадках о используемых правилах токенизации. Если ваш токенизатор не дал вам пробелов, вы все равно можете это сделать, если у вас есть три вещи:

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

Ответ 10

Используйте функцию join:

Вы можете просто сделать ' '.join(words), чтобы вернуть исходную строку.

Ответ 11

Самый простой и интуитивно понятный способ. token_list также может быть списком списков.

s=[]
for i in token_list:
    s.append(" ".join(i))