Computer >> Máy Tính >  >> Lập trình >> Ruby

Ruby NLP:Phân tích N-gram cho niềm vui và lợi nhuận

Bạn sẽ làm gì nếu bạn được giao một bộ sưu tập văn bản lớn và bạn muốn rút ra một số ý nghĩa từ nó?

Một khởi đầu tốt là chia nhỏ văn bản của bạn thành n-gram .

Đây là mô tả :

Trong các lĩnh vực ngôn ngữ học tính toán và xác suất, n-gram là một chuỗi n mục liền nhau từ một chuỗi văn bản nhất định. - Wikipedia

Ví dụ :

Nếu chúng ta sử dụng cụm từ "Xin chào, bạn có khỏe không?" thì các đơn vị (ngram của một phần tử) sẽ là:"Hello", "there", "how", "are", "you" và bigram (ngram của hai phần tử):["Hello", "there"], ["there", "how"], ["how", "are"], ["are", "you"] .

Nếu bạn học tốt hơn với hình ảnh đây là hình ảnh của điều đó:

Ruby NLP:Phân tích N-gram cho niềm vui và lợi nhuận

Bây giờ, hãy xem cách bạn có thể triển khai điều này trong Ruby!

Tải xuống dữ liệu mẫu

Trước khi chúng ta có thể làm bẩn tay, chúng ta sẽ cần một số dữ liệu mẫu.

Nếu bạn không có bất kỳ công việc nào để làm việc, bạn có thể tải xuống một số bài viết trên Wikipedia hoặc blog. Trong trường hợp cụ thể này, tôi quyết định tải xuống một số nhật ký IRC từ kênh của #ruby freenode.

Có thể tìm thấy nhật ký tại đây :

irclog.whitequark.org/ruby

Lưu ý về định dạng dữ liệu :

Nếu không có phiên bản văn bản thuần túy của tài nguyên bạn muốn phân tích, thì bạn có thể sử dụng Nokogiri để phân tích cú pháp trang và trích xuất dữ liệu.

Nhật ký irc có sẵn ở dạng văn bản thuần túy bằng cách thêm .txt ở cuối URL, vì vậy chúng tôi sẽ tận dụng lợi thế đó.

Lớp này sẽ tải xuống và lưu dữ liệu cho chúng tôi:

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

Đây là một lớp khá đơn giản.

Chúng tôi sử dụng RestClient làm ứng dụng khách HTTP của mình và sau đó chúng tôi lưu kết quả vào một tệp để chúng tôi không phải yêu cầu chúng nhiều lần trong khi thực hiện các sửa đổi đối với chương trình của mình.

Phân tích dữ liệu

Bây giờ chúng tôi có dữ liệu của mình, chúng tôi có thể phân tích nó.

Đây là một lớp Ngram đơn giản.

Trong lớp này, chúng tôi sử dụng phương thức Array # each_cons để tạo ra các ngrams.

Bởi vì phương thức này trả về một Enumerator chúng tôi cần gọi to_a trên đó để lấy Array .

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

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

Sau đó, chúng tôi kết hợp mọi thứ lại với nhau bằng cách sử dụng một vòng lặp, Hash#merge! &Enumerable#sort_by .

Như thế này :

# 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}" }

Lưu ý:get_trigrams_for_date phương thức không có ở đây cho ngắn gọn, nhưng bạn có thể tìm thấy nó trên github.

Đây là kết quả đầu ra trông như thế nào :

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

Như bạn có thể thấy muốn làm mọi thứ rất phổ biến trong #ruby 🙂

Kết luận

Bây giờ đến lượt bạn!

Crack mở trình chỉnh sửa của bạn và bắt đầu chơi với một số phân tích n-gram. Một cách khác để xem n-gram đang hoạt động là Google Ngram Viewer.

Xử lý ngôn ngữ tự nhiên (NLP) có thể là một chủ đề hấp dẫn, Wikipedia có một cái nhìn tổng quan về chủ đề này.

Bạn có thể tìm thấy mã hoàn chỉnh cho bài đăng này tại đây:https://github.com/matugm/ngram-analysis/blob/master/irc_histogram.rb