Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyで学ぶNLP:Nグラム分析の楽しさと実践

大量のテキストデータが手元にあり、そこから何らかの意味を抽出したい——そんな場面に遭遇したことはありませんか?

そんなときにまず試したいのが、テキストをNグラム(n-gram)に分割するという手法です。

Nグラムとは何か?

Wikipediaには次のように定義されています。

計算言語学および確率論の分野において、n-gramとは与えられたテキスト列から取り出した、n個の連続した要素からなる列のことである。—— Wikipedia

具体例を見てみましょう

"Hello there, how are you?" というフレーズを例にとると、ユニグラム(1要素のNグラム)は "Hello", "there", "how", "are", "you"、バイグラム(2要素のNグラム)は ["Hello", "there"], ["there", "how"], ["how", "are"], ["are", "you"] となります。

図で見たほうが理解しやすいという方は、次の画像をご覧ください。

Rubyで学ぶNLP:Nグラム分析の楽しさと実践

それでは、これをRubyでどのように実装できるのか見ていきましょう!

サンプルデータのダウンロード

実際にコードを書き始める前に、分析対象となるサンプルデータを用意する必要があります。

手元に適切なデータがない場合は、Wikipediaの記事やブログ記事をいくつかダウンロードしてくるのがおすすめです。今回は、freenodeの #ruby チャンネルのIRCログを使用することにしました。

ログはこちらから入手できます:

irclog.whitequark.org/ruby

データ形式に関する注意点:

分析したいリソースのプレーンテキスト版が用意されていない場合は、Nokogiriを使ってページをパースし、必要なデータを抽出することができます。

今回利用するIRCログは、URLの末尾に .txt を付けるだけでプレーンテキストとして取得できるため、これを活用します。

データのダウンロードと保存を行うクラスは以下のとおりです。

require 'restclient'

class LogParser
  LOG_DIR  = 'irc_logs'

  def initialize(date)
    @date = date
    @log_name = "#{LOG_DIR}/irc-log-#{@date}.txt"
  end

  def download_page(url)
    return log_contents if File.exist? @log_name
    RestClient.get(url).body
  end

  def save_page(page)
    File.open(@log_name, "w+") { |f| f.puts page }
  end

  def log_contents
    File.readlines(@log_name).join
  end

  def get_messages
    page = download_page("https://irclog.whitequark.org/ruby/#{@date}.txt")
    save_page(page)
    page
  end
end

log = LogParser.new("2015-04-15")
msg = log.get_messages

とてもシンプルな構成のクラスです。

HTTPクライアントにはRestClientを採用し、取得した結果はファイルに保存するようにしています。こうすることで、プログラムを修正しながら何度も実行する場合でも、同じリクエストを繰り返し送信せずに済みます。

データの分析

データが揃ったら、いよいよ分析に取りかかりましょう。

まずは、ごくシンプルなNgramクラスを紹介します。

このクラスでは、Nグラムを生成するためにArray#each_consメソッドを使用しています。

このメソッドは Enumerator を返すため、配列として扱うには to_a を呼び出す必要があります。

class Ngram
  def initialize(input)
    @input = input
  end

  def ngrams(n)
    @input.split.each_cons(n).to_a
  end
end

続いて、ループと Hash#merge!、そして Enumerable#sort_by を組み合わせて、処理全体をまとめ上げます。

コードは次のようになります

# Filter words that appear less times than this
MIN_REPETITIONS = 20

total = {}

# Get the logs for the first 15 days of the month and return the bigrams
(1..15).each do |n|
  day = '%02d' % [n]
  total.merge!(get_trigrams_for_date "2015-04-#{day}") { |k, old, new| old + new }
end

# Sort in descending order
total = total.sort_by { |k, v| -v }.reject { |k, v| v < MIN_REPETITIONS }

total.each { |k, v| puts "#{v} => #{k}" }

注:紙面の都合上 get_trigrams_for_date メソッドのコードはここでは省略していますが、GitHubで全文を確認できます。

実際の出力結果はこのようになります

112 => i want to
83  => link for more
82  => is there a
71  => you want to
66  => i don't know
66  => i have a
65  => i need to

ご覧のとおり、「〜したい(want to)」という表現が #ruby チャンネルで非常に人気があることがわかります🙂

まとめ

今度はあなたの番です!

エディタを開いて、ぜひNグラム分析をいろいろと試してみてください。また、Nグラムの動作を視覚的に確認したい方には、Google Ngram Viewerを活用するのもおすすめです。

自然言語処理(NLP)は非常に奥深く魅力的なテーマです。Wikipediaにもわかりやすい概説がありますので、さらに知識を深めたい方はぜひ参照してみてください。

本記事で使用した完全なコードは、こちらから入手できます:https://github.com/matugm/ngram-analysis/blob/master/irc_histogram.rb


  1. Excelで分析用データを入力する2つの簡単な方法|ピボットテーブルと分析ツールの使い方

    ビジネスにおいて、経営状況を正しく評価するためのデータ分析は欠かせません。データ分析を行うことで、潜在的なリスクを把握し、損失を最小限に抑えるための適切な対策を講じることができます。Excelには、こうした分析を効率的に行うためのさまざまな機能が備わっています。この記事では、データ分析のためにExcelへデータを入力・整理する2つの簡単な方法を、わかりやすい手順と図解付きでご紹介します。無料のExcelワークブックはこちらからダウンロードできるので、ぜひ実際に操作しながら練習してみてください。Excelで分析用データを入力する2つの方法まず、今回使用するデータセットをご紹介します。このデータに

  2. データ分析を効率化する5つの実用ツール徹底解説

    データは、かつて想像もできなかった速度と規模で生み出され続けています。「データは石油よりも価値がある」とよく言われますが、もちろん車を動かすことはできません。それでも、機密性の高い財務情報やビジネス情報を含むデータは、企業や業界の大手にとって最大の資産となっています。こうしたデータを構造化された形で管理・活用するためには、データ分析ツールが不可欠です。 データ分析は予測モデリングのアルゴリズムに基づいて動作し、アナリストがデータを記録として整理・管理できるよう支援します。分析はコスト削減だけでなく、より迅速で的確な意思決定の実現にも大きく貢献します。そこで本記事では、ビジネスインテリジェンスや