คุณจะทำอย่างไรถ้าคุณมีข้อความจำนวนมากและต้องการแยกความหมายออกจากข้อความนั้น
การเริ่มต้นที่ดีคือแบ่งข้อความออกเป็น n-grams .
นี่คือคำอธิบาย :
ในสาขาภาษาศาสตร์เชิงคำนวณและความน่าจะเป็น n-gram คือลำดับที่ต่อเนื่องกันของ n รายการจากลำดับข้อความที่กำหนด – วิกิพีเดีย
ตัวอย่างเช่น :
หากเราใช้คำว่า “สวัสดี สบายดีไหม” จากนั้นยูนิแกรม (ngrams ขององค์ประกอบหนึ่ง) จะเป็น:"Hello", "there", "how", "are", "you"
และ bigrams (ngrams ของสององค์ประกอบ):["Hello", "there"], ["there", "how"], ["how", "are"], ["are", "you"]
.
หากคุณเรียนรู้ได้ดีขึ้นด้วยรูปภาพ นี่คือรูปภาพ:
ตอนนี้เรามาดูกันว่าคุณจะใช้สิ่งนี้ใน Ruby ได้อย่างไร!
กำลังดาวน์โหลดข้อมูลตัวอย่าง
ก่อนที่เราจะทำมือสกปรก เราต้องการข้อมูลตัวอย่างก่อน
หากคุณไม่มีงานใดๆ คุณสามารถดาวน์โหลด Wikipedia หรือบทความในบล็อกได้ ในกรณีนี้ ฉันตัดสินใจดาวน์โหลดบันทึก IRC บางรายการจากช่องของ #ruby freenode
สามารถดูบันทึกได้ที่นี่ :
irclog.whitequark.org/ruby
หมายเหตุเกี่ยวกับรูปแบบข้อมูล :
หากไม่มีเวอร์ชันข้อความธรรมดาของทรัพยากรที่คุณต้องการวิเคราะห์ คุณสามารถใช้ Nokogiri เพื่อแยกวิเคราะห์หน้าและดึงข้อมูลได้
บันทึก irc มีอยู่ในข้อความธรรมดาโดยต่อท้าย .txt
ที่ส่วนท้ายของ URL ดังนั้นเราจะใช้ประโยชน์จากสิ่งนั้น
ชั้นเรียนนี้จะดาวน์โหลดและบันทึกข้อมูลให้เรา:
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
นี่เป็นชั้นเรียนที่ค่อนข้างตรงไปตรงมา
เราใช้ RestClient เป็นไคลเอนต์ HTTP ของเรา จากนั้นเราบันทึกผลลัพธ์ในไฟล์ ดังนั้นเราจึงไม่ต้องร้องขอหลายครั้งในขณะที่เราทำการแก้ไขโปรแกรมของเรา
วิเคราะห์ข้อมูล
เมื่อเรามีข้อมูลแล้ว เราก็สามารถวิเคราะห์ได้
นี่คือคลาส Ngram ง่ายๆ
ในคลาสนี้เราใช้เมธอด Array#each_cons ซึ่งสร้าง ngrams
เนื่องจากวิธีนี้ส่งคืน Enumerator
เราต้องเรียก to_a เพื่อรับ Array
.
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
อย่างที่คุณเห็น อยากทำสิ่งต่างๆ เป็นที่นิยมอย่างมากใน #ruby 🙂
บทสรุป
ตอนนี้ถึงตาคุณแล้ว!
เปิดโปรแกรมแก้ไขของคุณและเริ่มเล่นกับการวิเคราะห์ n-gram อีกวิธีหนึ่งในการดูการทำงานของ n-grams คือ Google Ngram Viewer
การประมวลผลภาษาธรรมชาติ (NLP) อาจเป็นหัวข้อที่น่าสนใจ Wikipedia มีภาพรวมที่ดีของหัวข้อ
คุณสามารถค้นหาโค้ดที่สมบูรณ์สำหรับโพสต์นี้ได้ที่นี่:https://github.com/matugm/ngram-analysis/blob/master/irc_histogram.rb