N-gramを実装と共に解説します【自然言語処理】
自然言語処理のタスクなどで用いられるN-gram。基礎的な内容なので、理解・実装をできるようになっておきたいところです。この記事ではこのN-gramの解説とPythonで実装する方法を紹介します。
N-gramとは
何らかの列を連続するN個の組の列にした表現をN-gramと呼びます。ここで、Nは自然数です。とくにNが1の場合をuni-gram(ユニグラム)、2の場合をbi-gram(バイグラム)、3の場合をtri-gram(トライグラム)と呼びます。
何らかの列と言いましたが、「何らか」は本当に何でも良いです。英単語のような文字列でも良いですし、アルファベット一文字でも良いです。
目で見たほうがわかりやすいと思うので、いくつか例を挙げてみます。
「“I”, “have”, “an”, “apple”」という4つの英単語から成る「文字列の列」があるとします。この列のbi-gramは「(“I”, “have”), (“have”, “an”), (“an”, “apple”)」となります。また、tri-gramは「(“I”, “have”, “an”), (“have”, “an”, “apple”)」です。
同様に、「a, b, c, d, e」という5つのアルファベットから成る「文字の列」のtri-gramは「(a, b, c), (b, c, d), (c, d, e)」になります。
Pythonで一から実装
N-gram表現を得るような関数をPythonを用いて実装してみます。他の言語で実装する場合もやることは同じです。
def ngrams(seq, n):
return [seq[i:i+n] for i in range(len(seq)-n+1)]
sent = ["I", "have", "an", "apple"]
print(ngrams(sent, 2))
# [['I', 'have'], ['have', 'an'], ['an', 'apple']]
関数ngrams
は対象となる入力列とNの値を引数として取り、入力列のN-gram表現がリストのリストとして返されます。
関数内部は、リスト内包表記を利用して記述されています。リストの先頭から順番にインデックスi
を更新していき、i
番目からi+N-1
番目までのN個の要素を一つのリストとして切り出します。このまとめたリストが出力の各要素になります。
ここで、リストの切り出しにはPythonのスライスを利用しています。Pythonのスライスは半開区間で指定するので注意してください。つまり、seq[i:i+n]
はリストseq
のi
番目からi+N-1
番目までの要素を切り出したリストを返します。
返り値の型をタプルのリストにしたい場合は、以下のように変更すれば実現できます。
def ngrams(seq, n):
return [tuple(seq[i:i+n]) for i in range(len(seq)-n+1)]
ライブラリでサクッと実装(NLTK)
とにかくすぐにN-gramを手に入れたいという方はライブラリを使用するのが良いです。ただ、N-gram だけの実装で良いなら自分で書いてしまった方が早いと思います。
今回はNLTK(Natural Language Toolkit)という有名なライブラリを使用する方法を紹介します。NLTKは以下のコマンドでインストール可能です。
$ pip install nltk
次のようにimportするだけですぐに使うことができます。使い方は自作の例で紹介したコードと同様です。返り値がgenerator objectになっているのでその点だけ注意してください。
from nltk import ngrams
sent = ["I", "have", "an", "apple"]
print(list(ngrams(sent, 2)))
# [('I', 'have'), ('have', 'an'), ('an', 'apple')]
Ermi
termina.ioの記事全般を書いています。東京大学 大学院 情理でコンピュータサイエンスを学びました。プログラミング言語など計算機科学全般に興味があります。キーボードやイヤホンなど、身の回りのものに強い拘りを持つ傾向があります。そして、沼にハマって帰らぬ人へと...。
最近の記事
Ermi
termina.ioの記事全般を書いています。東京大学 大学院 情理でコンピュータサイエンスを学びました。プログラミング言語など計算機科学全般に興味があります。キーボードやイヤホンなど、身の回りのものに強い拘りを持つ傾向があります。そして、沼にハマって帰らぬ人へと...。