40

私は NLTK を使用していくつかの古典的なテキストを分析していますが、テキストを文ごとにトークン化する際に問題が発生しています。たとえば、Moby Dickからのスニペットから取得したものは次のとおりです。

import nltk
sent_tokenize = nltk.data.load('tokenizers/punkt/english.pickle')

'''
(Chapter 16)
A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?" says I, "but
that's a rather cold and clammy reception in the winter time, ain't it, Mrs. Hussey?"
'''
sample = 'A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?" says I, "but that\'s a rather cold and clammy reception in the winter time, ain\'t it, Mrs. Hussey?"'

print "\n-----\n".join(sent_tokenize.tokenize(sample))
'''
OUTPUT
"A clam for supper?
-----
a cold clam; is THAT what you mean, Mrs.
-----
Hussey?
-----
" says I, "but that\'s a rather cold and clammy reception in the winter time, ain\'t it, Mrs.
-----
Hussey?
-----
"
'''

Melville の構文が少し古くなっていることを考えると、ここで完璧を期待することはできませんが、NLTK は終端の二重引用符と "Mrs." のようなタイトルを処理できるはずです。ただし、トークナイザーは教師なしトレーニング アルゴの結果であるため、それをいじる方法がわかりません。

より良い文のトークン化に関する推奨事項はありますか? 自分のパーサーをトレーニングするよりも、ハッキングできる単純なヒューリスティックの方が好きです。

4

4 に答える 4

50

次のように、略語のリストをトークナイザーに提供する必要があります。

from nltk.tokenize.punkt import PunktSentenceTokenizer, PunktParameters
punkt_param = PunktParameters()
punkt_param.abbrev_types = set(['dr', 'vs', 'mr', 'mrs', 'prof', 'inc'])
sentence_splitter = PunktSentenceTokenizer(punkt_param)
text = "is THAT what you mean, Mrs. Hussey?"
sentences = sentence_splitter.tokenize(text)

文は次のとおりです。

['is THAT what you mean, Mrs. Hussey?']

更新: これは、文の最後の単語にアポストロフィーまたは引用符が付いている場合 ( Hussey?' のように) は機能しません。したがって、これを回避する手っ取り早い方法は、文末記号 (.!?) に続くアポストロフィと引用符の前にスペースを入れることです。

text = text.replace('?"', '? "').replace('!"', '! "').replace('."', '. "')
于 2012-12-31T15:08:35.377 に答える
41

set に略語を追加することで、より多くの略語を認識するように NLTK の事前トレーニング済みの英文トークナイザーを変更できます_params.abbrev_types。例えば:

extra_abbreviations = ['dr', 'vs', 'mr', 'mrs', 'prof', 'inc', 'i.e']
sentence_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
sentence_tokenizer._params.abbrev_types.update(extra_abbreviations)

略語は最後のピリオドなしで指定する必要がありますが、上記のように内部のピリオドを含める必要があることに注意してください'i.e'。トークナイザーのその他のパラメーターの詳細については、関連するドキュメントを参照してください。

于 2014-08-19T04:52:51.587 に答える
9

パラメータをにPunktSentenceTokenizer.tokenize設定することで、文の残りの部分に「終端」の二重引用符を含めるようにメソッドに指示できます。例については、以下のコードを参照してください。realign_boundariesTrue

Mrs. Husseyのようなテキストが2つの文に分割されるのを防ぐためのクリーンな方法がわかりません。しかし、ここにハックがあります

  • のすべての出現をマングルしMrs. HusseyますMrs._Hussey
  • 次に、テキストを次の文に分割しますsent_tokenize.tokenize
  • 次に、各文について、マングルを解除Mrs._HusseyしてMrs. Hussey

もっと良い方法を知っていればいいのですが、これはピンチでうまくいくかもしれません。


import nltk
import re
import functools

mangle = functools.partial(re.sub, r'([MD]rs?[.]) ([A-Z])', r'\1_\2')
unmangle = functools.partial(re.sub, r'([MD]rs?[.])_([A-Z])', r'\1 \2')

sent_tokenize = nltk.data.load('tokenizers/punkt/english.pickle')

sample = '''"A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?" says I, "but that\'s a rather cold and clammy reception in the winter time, ain\'t it, Mrs. Hussey?"'''    

sample = mangle(sample)
sentences = [unmangle(sent) for sent in sent_tokenize.tokenize(
    sample, realign_boundaries = True)]    

print u"\n-----\n".join(sentences)

収量

"A clam for supper?
-----
a cold clam; is THAT what you mean, Mrs. Hussey?"
-----
says I, "but that's a rather cold and clammy reception in the winter time, ain't it, Mrs. Hussey?"
于 2012-12-31T12:55:50.057 に答える
3

そのため、同様の問題があり、上記の vpekar のソリューションを試しました。

おそらく私のものはある種のエッジケースですが、置換を適用した後に同じ動作を観察しましたが、句読点をその前に配置された引用符に置き換えようとすると、探していた出力が得られました. おそらく、MLA を遵守していないことは、元の引用を 1 つの文として保持することほど重要ではありません。

より明確にするために:

text = text.replace('?"', '"?').replace('!"', '"!').replace('."', '".')

ただし、MLA が重要な場合は、いつでも戻ってこれらの変更を元に戻すことができます。

于 2014-06-04T23:10:36.860 に答える