Pythonでいくつかの自然言語ツールを使用するための入門チュートリアル

この記事では主に、Pythonでのいくつかの自然言語ツールの使用に関する入門チュートリアルを紹介します。この記事は、IBM公式ウェブサイトの技術ドキュメントから引用しています。これを必要とする友人
は、Pythonを使用して計算言語学を指導および実践するための優れたツールであるNLTK を参照できますさらに、計算言語学は、人工知能、言語/特殊言語の認識、翻訳、文法チェックなどの分野と密接に関連しています。
NLTKに含まれるもの

NLTKは当然、スタック構造を持つ一連のレイヤーと見なされます。これらのレイヤーは、互いの上に構築されます。文法や人工言語(Pythonなど)の構文解析に詳しい読者にとっては、自然言語モデルの類似した(ただしより難解な)レイヤーを理解することはそれほど難しくありません。
用語集

Corpora:関連テキストのコレクション。たとえば、シェイクスピアの作品はまとめてコーパスと呼ばれ、複数の作者の作品は完全な作品と呼ばれます。

ヒストグラム:データセット内のさまざまな単語、文字、またはその他のアイテムの出現頻度の統計的分布。

構造(構文):セグメントの調査、つまり、文字、単語、または句が完全なセットに連続して現れる統計的関係。

文脈自由文法:4種類の形式文法で構成されるNoam Chomsky階層の2番目のカテゴリ。詳細については、「参考文献」を参照してください。

NLTKには、さまざまな程度に(通常は手動で)前処理された多くの完全なセットが付属していますが、概念的には、各レイヤーは隣接する下位レベルの処理に依存しています。1つは単語分割で、次に単語にラベルを付け、次に単語のグループを名詞句や文などの文法要素に解析します(それぞれに長所と短所があるいくつかのテクノロジーの1つに依存します)。最後に、最終文または他の文法単位を分類します。これらの手順により、NLTKでは、さまざまな要素の発生に関する統計を生成し、処理プロセス自体または統計合計を説明するグラフを描くことができます。

この記事では、低レベルの機能の比較的完全な例をいくつか紹介しますが、ほとんどの高レベルの機能については、簡単に抽象的に説明します。次に、テキスト処理の最初のステップを詳細に分析します。

断词(トークン化)

NLTKで実行できる作業の多く、特に低レベルの作業は、Pythonの基本的なデータ構造を使用して完了することと大差ありません。ただし、NLTKは、タグ付きまたはタグ付きテキストを処理する実用的なクラスを提供するだけでなく、上位層に依存して使用される一連の体系的なインターフェイスを提供します。

具体的には、nltk.tokenizer.Tokenクラスは、テキストの注釈付きフラグメントを格納するために広く使用されています。これらの注釈は、品詞、サブトークン構造、ロゴなど、さまざまな機能をマークできます。 (トークン)大きなテキストのオフセット位置、形態素、文法文の構成要素など。実際、トークンは特別な辞書であり、辞書としてアクセスされるため、必要な任意のキーを保持できます。NLTKではいくつかの特別なキーが使用され、異なるサブルーチンパッケージでは異なるキーが使用されます。

トークンを作成してサブトークンに分割する方法を簡単に分析してみましょう。
リスト1. nltk.tokenizer.Tokenクラスの最初の知識

>>> from nltk.tokenizer import *
>>> t = Token(TEXT='This is my first test sentence')
>>> WSTokenizer().tokenize(t, addlocs=True) # break on whitespace
>>> print t['TEXT']
This is my first test sentence
>>> print t['SUBTOKENS']
[<This>@[0:4c], <is>@[5:7c], <my>@[8:10c], <first>@[11:16c],
<test>@[17:21c], <sentence>@[22:30c]]
>>> t['foo'] = 'bar'
>>> t
<TEXT='This is my first test sentence', foo='bar',
SUBTOKENS=[<This>@[0:4c], <is>@[5:7c], <my>@[8:10c], <first>@[11:16c],
<test>@[17:21c], <sentence>@[22:30c]]>
>>> print t['SUBTOKENS'][0]
<This>@[0:4c]
>>> print type(t['SUBTOKENS'][0])
<class 'nltk.token.SafeToken'>

確率

言語の完全なセットの場合、かなり簡単なことは、さまざまなイベントの頻度分布を分析し、これらの既知の頻度分布に基づいて確率予測を行うことです。NLTKは、固有周波数分布データに基づく確率予測のためのさまざまな方法をサポートしています。ここでそれらの方法を紹介するつもりはありません(「参考文献」にリストされている確率論的チュートリアルを参照)。ただし、確実に期待するものとすでに知っているもの(明らかなスケーリング/正規化だけでなく)の間に何かがある限り、です。あいまいな関係で十分です。

基本的に、NLTKは2種類の頻度分布をサポートしています。ヒストグラムと条件付き頻度分布(条件付き頻度)です。nltk.probability.FreqDistクラスを使用してヒストグラムを作成します。たとえば、次のような単語のヒストグラムを作成できます。
リスト2. nltk.probability.FreqDistを使用して基本的なヒストグラムを作成する

>>> from nltk.probability import *
>>> article = Token(TEXT=open('cp-b17.txt').read())
>>> WSTokenizer().tokenize(article)
>>> freq = FreqDist()
>>> for word in article['SUBTOKENS']:
...   freq.inc(word['TEXT'])
>>> freq.B()
1194
>>> freq.count('Python')
12

確率のチュートリアルでは、「母音で終わる単語の後の単語の長さ」など、より複雑な機能を持つヒストグラムの作成について説明します。nltk.draw.plot.Plotクラスは、ヒストグラムの視覚的表示に使用できます。もちろん、このようにして、NLTKに関連しない高レベルの文法的特徴やデータセットの頻度分布を分析することもできます。

条件付き頻度分布は、通常のヒストグラムより興味深いかもしれません。条件付き頻度分布は2次元のヒストグラムで、初期条件または「コンテキスト」ごとのヒストグラムが表示されます。たとえば、チュートリアルでは、各頭文字に対応する語長の分布を提案しています。このように分析します。
リスト3.条件付き頻度分布:各頭文字に対応する単語の長さ

>>> cf = ConditionalFreqDist()
>>> for word in article['SUBTOKENS']:
...   cf[word['TEXT'][0]].inc(len(word['TEXT']))
...
>>> init_letters = cf.conditions()
>>> init_letters.sort()
>>> for c in init_letters[44:50]:
...   print "Init %s:" % c,
...   for length in range(1,6):
...     print "len %d/%.2f," % (length,cf[c].freq(n)),
...   print
...
Init a: len 1/0.03, len 2/0.03, len 3/0.03, len 4/0.03, len 5/0.03,
Init b: len 1/0.12, len 2/0.12, len 3/0.12, len 4/0.12, len 5/0.12,
Init c: len 1/0.06, len 2/0.06, len 3/0.06, len 4/0.06, len 5/0.06,
Init d: len 1/0.06, len 2/0.06, len 3/0.06, len 4/0.06, len 5/0.06,
Init e: len 1/0.18, len 2/0.18, len 3/0.18, len 4/0.18, len 5/0.18,
Init f: len 1/0.25, len 2/0.25, len 3/0.25, len 4/0.25, len 5/0.25,

言語の観点からみた条件付き頻度分布の優れたアプリケーションは、セット全体でのセグメントの分布を分析することです。もちろん、文法にはいくつかの制限がありますが、構文オプションの選択の研究は、意味論、語用論、および用語のカテゴリに属しています。

ステミング

nltk.stemmer.porter.PorterStemmerクラスは、英語の単語から文法的な(接頭辞)語幹を取得するための非常に便利なツールです。以前はPythonで一般的なフルテキストインデックス検索ツール/ライブラリを作成していたので、この機能は私にとって特にエキサイティングです(Pythonでのフルテキストインデクサーの開発の説明を参照してください)。プロジェクト)。

多数のドキュメントで正確な単語のセットを検索する機能は非常に実用的ですが(gnosis.indexerによって行われた作業)、多くの検索グラフでは、少しあいまいな場合が役立ちます。探しているメールに「複雑」、「複雑」、「複雑」、「複雑」という単語が含まれているかどうかは特にわからないかもしれませんが、大まかに関連していることを覚えています(他の単語が含まれている場合があります)貴重な検索を完了してください)。

NLTKには、単語の語幹抽出のための優れたアルゴリズムが含まれており、語幹抽出アルゴリズムを好みに合わせてカスタマイズできます。
リスト4.形態学的ルートの語幹を抽出する

>>> from nltk.stemmer.porter import PorterStemmer
>>> PorterStemmer().stem_word('complications')
'complic'

実際、gnosis.indexerとその派生物でステミング関数を使用する方法、または完全に異なるインデックス作成ツールを使用する方法は、使用シナリオによって異なります。幸い、gnosis.indexerには、簡単にカスタマイズできるオープンインターフェイスがあります。完全にステムで構成されるインデックスが必要ですか?または、インデックスに完全な単語と語幹の両方を含めますか?結果のステミング一致と完全一致を分離する必要がありますか?gnosis.indexerの将来のバージョンでは、いくつかの種類のステム抽出機能を導入しますが、エンドユーザーは引き続き別の方法でカスタマイズしたい場合があります。

いずれの場合も、ステミングを追加することは一般的に非常に簡単です。最初に、gnosis.indexer.TextSplitterを指定してドキュメントからステミングを取得します。次に、もちろん、(オプションで)検索条件を使用して検索を実行します。インデックス検索を実行する前にそのステムを抽出するには、MyIndexer.find()メソッドをカスタマイズします。

PorterStemmerを使用しているときに、nltk.tokenizer.WSTokenizerクラスは、チュートリアルが警告するほど実際には使いにくいことに気付きました。概念的な役割を処理できますが、実際のテキストの場合、「単語」とは何かをより明確に識別できます。幸い、gnosis.indexer.TextSplitterは堅牢なワードブレーカーツールです。例:
リスト5.貧弱なNLTK単語分割ツールに基づく語幹抽出

>>> from nltk.tokenizer import *
>>> article = Token(TEXT=open('cp-b17.txt').read())
>>> WSTokenizer().tokenize(article)
>>> from nltk.probability import *
>>> from nltk.stemmer.porter import *
>>> stemmer = PorterStemmer()
>>> stems = FreqDist()
>>> for word in article['SUBTOKENS']:
...   stemmer.stem(word)
...   stems.inc(word['STEM'].lower())
...
>>> word_stems = stems.samples()
>>> word_stems.sort()
>>> word_stems[20:40]
['"generator-bas', '"implement', '"lazili', '"magic"', '"partial',
'"pluggable"', '"primitives"', '"repres', '"secur', '"semi-coroutines."',
'"state', '"understand', '"weightless', '"whatev', '#', '#-----',
'#----------', '#-------------', '#---------------', '#b17:']

一部の語幹を見ると、コレクションのすべての語幹がインデックス作成に使用できるとは限りません。多くは実際の単語ではなく、他の単語はダッシュで結合された複合語であり、いくつかの無関係な句読点が単語に追加されます。より良い単語セグメンテーションツールで試してみましょう:
リスト6. 単語セグメンテーションツールでスマートヒューリスティックを使用したステム抽出

>>> article = TS().text_splitter(open('cp-b17.txt').read())
>>> stems = FreqDist()
>>> for word in article:
...   stems.inc(stemmer.stem_word(word.lower()))
...
>>> word_stems = stems.samples()
>>> word_stems.sort()
>>> word_stems[60:80]
['bool', 'both', 'boundari', 'brain', 'bring', 'built', 'but', 'byte',
'call', 'can', 'cannot', 'capabl', 'capit', 'carri', 'case', 'cast',
'certain', 'certainli', 'chang', 'charm']

ここでは、いくつかの単語に複数の可能な展開があり、すべての単語が単語または形態素のように見えることがわかります。単語のセグメンテーション方法は、ランダムなテキストコレクションに不可欠です。公平を期すために、NLTKにバンドルされている完全なセットは、WSTokenizer()を通じて使いやすく正確な単語のセグメンテーションツールとしてパッケージ化されています。堅牢で実用的なインデクサーを取得するには、堅牢なワードブレーカーツールを使用する必要があります。

タグ付け、チャンク、解析を追加する

NLTKの最大の部分は、さまざまな複雑さのさまざまなパーサーで構成されています。ほとんどの場合、この紹介では詳細を説明しませんが、彼らが達成しようとしていることの概要を説明します。

ロゴは特別な辞書、具体的には単語の文法上の役割を示すタグキーを含むことができる特別な辞書であることの背景を忘れないでください。NLTKの完全なドキュメントには通常、ラベルが付けられた特別な言語がいくつかありますが、ラベルなしのドキュメントに独自のラベルを追加することもできます。

パーティショニングは、「ラフ分析」に多少似ています。つまり、ブロック作業の進行状況は、文法コンポーネントの既存の記号、または手動で追加した記号、または正規表現とプログラムロジックを使用して半自動で生成した記号に基づいています。ただし、正確には、これは真の解析ではありません(同じ生成規則はありません)。例:
リスト7.ブロックの構文解析/タグ付け:単語とより大きな単位

>>> from nltk.parser.chunk import ChunkedTaggedTokenizer
>>> chunked = "[ the/DT little/JJ cat/NN ] sat/VBD on/IN [ the/DT mat/NN ]"
>>> sentence = Token(TEXT=chunked)
>>> tokenizer = ChunkedTaggedTokenizer(chunk_node='NP')
>>> tokenizer.tokenize(sentence)
>>> sentence['SUBTOKENS'][0]
(NP: <the/DT> <little/JJ> <cat/NN>)
>>> sentence['SUBTOKENS'][0]['NODE']
'NP'
>>> sentence['SUBTOKENS'][0]['CHILDREN'][0]
<the/DT>
>>> sentence['SUBTOKENS'][0]['CHILDREN'][0]['TAG']
'DT'
>>> chunk_structure = TreeToken(NODE='S', CHILDREN=sentence['SUBTOKENS'])
(S:
 (NP: <the/DT> <little/JJ> <cat/NN>)
 <sat/VBD>
 <on/IN>
 (NP: <the/DT> <mat/NN>))

前述のチャンク化作業は、nltk.tokenizer.RegexpChunkParserクラスで、擬似正規表現を使用して構文要素を構成する一連のタグを記述することで実現できます。以下は、確率論的チュートリアルの例です。
リスト8.ラベルの正規表現を使用したチャンク化

>>> rule1 = ChunkRule('<DT>?<JJ.*>*<NN.*>',
...        'Chunk optional det, zero or more adj, and a noun')
>>> chunkparser = RegexpChunkParser([rule1], chunk_node='NP', top_node='S')
>>> chunkparser.parse(sentence)
>>> print sent['TREE']
(S: (NP: <the/DT> <little/JJ> <cat/NN>)
 <sat/VBD> <on/IN>
 (NP: <the/DT> <mat/NN>))

実際の分析は、私たちを多くの理論的な分野に導きます。たとえば、トップダウンパーサーは可能なすべての製品を確実に検出できますが、頻繁な(指数)バックトラックのために非常に遅くなる可能性があります。Shift-reduceの方が効率的ですが、一部の製品を見逃す可能性があります。どちらの場合でも、文法規則の宣言は、人工言語の文法宣言の解析に似ています。このコラムではかつて、SimpleParse、mx.TextTools、Spark、gnosis.xml.validityのいくつかを紹介しました(「参考文献」を参照)。

さらに、NLTKは、トップダウンおよびシフトリデュースパーサーに加えて、「チャートパーサー」も提供します。これにより、部分的な仮定を作成して、特定のシーケンスでルールを完成させることができます。この方法は、効果的で完全な方法です。鮮やかな(おもちゃレベルの)例を見てみましょう:
リスト9.文脈自由文法の基本的な製品を定義する

>>> from nltk.parser.chart import *
>>> grammar = CFG.parse('''
...  S -> NP VP
...  VP -> V NP | VP PP
...  V -> "saw" | "ate"
...  NP -> "John" | "Mary" | "Bob" | Det N | NP PP
...  Det -> "a" | "an" | "the" | "my"
...  N -> "dog" | "cat" | "cookie"
...  PP -> P NP
...  P -> "on" | "by" | "with"
...  ''')
>>> sentence = Token(TEXT='John saw a cat with my cookie')
>>> WSTokenizer().tokenize(sentence)
>>> parser = ChartParser(grammar, BU_STRATEGY, LEAF='TEXT')
>>> parser.parse_n(sentence)
>>> for tree in sentence['TREES']: print tree
(S:
 (NP: <John>)
 (VP:
  (VP: (V: <saw>) (NP: (Det: <a>) (N: <cat>)))
  (PP: (P: <with>) (NP: (Det: <my>) (N: <cookie>)))))
(S:
 (NP: <John>)
 (VP:
  (V: <saw>)
  (NP:
   (NP: (Det: <a>) (N: <cat>))
   (PP: (P: <with>) (NP: (Det: <my>) (N: <cookie>))))))

確率的文脈自由文法(またはPCFG)は、各製品を確率に関連付ける文脈自由文法です。同様に、確率分析用のパーサーもNLTKにバンドルされています。

何を待ってるの?

NLTKには、この短い紹介ではカバーできない他の重要な機能があります。たとえば、NLTKには、「ナイーブベイジアン」や「最大エントロピー」などの統計的手法を使用したテキスト分類のための完全なフレームワークがあります。まだスペースがあっても、その本質を説明することはできません。ただし、NLTKの下位層でも、教育と実際のアプリケーションの両方に使用できる実用的なフレームワークになると思います。

読んでいただきありがとうございます
。大学でpythonを学ぶことを選んだとき、コンピュータの基礎がおかしいことに気付きました。学業資格はあり
ませんでした。これは何もする必要はありません。それを補うことしかできません。道は、Pythonのコア知識を学び続け、コンピューターの基礎の詳細な研究を整理し、平凡になりたくない場合は、コーディングに参加して成長を続けてください!
実は、ここには技術だけでなく、それ以外のものもあり、例えば「絹糸」というよりも、どうやってプログラマーとして絶妙な存在になるのか、プログラマー自体が高貴な存在ですね。[参加するにはクリックしてください]自分らしくなりたい、高貴な人になりたい、是非!

元の記事を54件公開 22のような 30,000以上の訪問

おすすめ

転載: blog.csdn.net/chengxun03/article/details/105567908