Если вы посмотрите на код для подбора языковой модели вы можете видеть, что по своей сути fit()
обновляет счетчики на основе документов в train_data
:
self.counts.update(self.vocab.lookup(sent) for sent in text)
Однако обратите внимание, что он обновляет эти значения по одному предложению за раз. Каждое предложение полностью независимо друг от друга. Модель не знает, что было до этого предложения и что следует за ним. Кроме того, помните, что вы тренируете модель триграммы, поэтому последние два слова в каждом предложении — ('</s>', '</s>')
. Таким образом, модель узнает, что за '</s>'
следует '</s>'
с очень высокой вероятностью, но она никогда не узнает, что за '</s>'
иногда может следовать '<s>'
.
Таким образом, самое простое решение вашей проблемы — просто вручную начинать новое предложение (т. е. снова вызывать generate()
) каждый раз, когда вы видите '</s>'
. Но допустим, вы не хотите этого делать и хотите, чтобы модель генерировала несколько предложений за один раз.
Из строки документации для padded_everygram_pipeline
:
Creates two iterators:
- sentences padded and turned into sequences of `nltk.util.everygrams`
- sentences padded as above and chained together for a flat stream of words
Таким образом, в отличие от train_data
, padded_sents
содержит все ваши предложения как одну запись:
>>> tokenized_text= [['this', 'is', 'sentence', 'one'],
['this', 'is', 'sentence', 'two']
]
>>> train_data, padded_sents = padded_everygram_pipeline(n, tokenized_text)
>>> padded_sents = list(padded_sents) #we need to do this because padded_sents is a generator and can only be gone through once
>>> print(padded_sents)
['<s>', '<s>', 'this', 'is', 'sentence', 'one', '</s>', '</s>', '<s>', '<s>', 'this', 'is', 'sentence', 'two', '</s>', '</s>']
>>> model = MLE(n)
>>> model.fit(padded_sents, padded_sents) #notice that I'm not using train_data
Хорошие новости: теперь у нас есть пример '<s>'
после '</s>'
. Плохая новость: единственные возможные триграммы, содержащие энграммы для двух разных предложений, — это ('</s>', '</s>', '<s>')
и ('</s>', '<s>', '<s>')
. Таким образом, generate теперь должен генерировать несколько предложений, но содержание этих предложений по-прежнему будет полностью независимым.
Если вы хотите, чтобы содержание предыдущего предложения влияло на содержание следующего, здесь все становится сложнее. Вместо того, чтобы передавать корпус в модель в виде серии предложений, вы можете передать его в виде серии абзацев с несколькими предложениями в каждом:
tokenized_text = [['this', 'is', 'sentence', 'one', '.', 'this', 'is', 'sentence', 'two', '.'],
['this', 'is', 'a', 'second', 'paragraph', '.']
]
Это сработало бы, но теперь '<s>'
и '</s>'
означают не начало и конец предложения, а начало и конец абзаца. И сгенерированные абзацы по-прежнему будут независимы друг от друга. Вы также можете расширить это, чтобы вместо абзацев создавать серии абзацев или целые книги. Это зависит от того, что лучше всего подходит для вашей задачи.
person
acattle
schedule
12.03.2020