การจัดเก็บข้อมูลแบบกรัม


12

ฉันหวังว่าจะระดมสมองเล็กน้อยเกี่ยวกับเรื่องการจัดเก็บข้อมูลn -gram ในโครงการของฉันฉันพยายามในการแก้ปัญหาทางภาษาที่ฉันรู้ทั้งหมด ( nรายการ -1) ข้อมูลและต้องการที่จะคาดเดาสถิติของฉันnใช้สอดแทรกเชิงเส้นมากกว่าที่บังคับใช้ทั้งหมดn -grams (ใช่มีตัวแท็กเกอร์ที่กำหนดแท็กให้กับคำที่รู้จักตามพจนานุกรมและต้นไม้ต่อท้ายที่พยายามเดาชนิดคำสำหรับคำที่ไม่รู้จัก; องค์ประกอบn -gram ที่กล่าวถึงที่นี่จะได้รับมอบหมายด้วยการแก้ไขความคลุมเครือ)

วิธีการเริ่มต้นของฉันคือการเก็บข้อมูลn -grams (สำหรับn = 1..3 ที่สังเกตได้ทั้งหมดคือ monogram, bigram, trigram) ในฐานข้อมูล SQL ที่เกี่ยวข้องและเรียกมันต่อวัน แต่ข้อกำหนดของโครงการของฉันอาจเปลี่ยนเป็นความยาวเวกเตอร์อื่น ๆ ( n ) และฉันต้องการให้แอปพลิเคชันของฉันปรับให้เหมาะกับ 4 กรัมโดยไม่ต้องทำงานมาก (อัปเดตสคีมาอัปเดตรหัสแอปพลิเคชัน ฯลฯ ); นึกคิดฉันจะบอกให้แอปพลิเคชันของฉันทำงานด้วย 4 กรัมในขณะนี้โดยไม่ต้องเปลี่ยนรหัสมาก (หรือเลย) และฝึกอบรมข้อมูลจากแหล่งข้อมูลที่กำหนด

เพื่อสรุปข้อกำหนดทั้งหมด:

  • ความสามารถในการเก็บข้อมูลn -gram (เริ่มแรกสำหรับn = {1, 2, 3}
  • ความสามารถในการเปลี่ยนชนิดของn -grams ที่ควรใช้ (ระหว่างการเรียกใช้แอปพลิเคชัน)
  • ความสามารถในการ (อีกครั้ง) ฝึกอบรมข้อมูลn- gram (ระหว่างการเรียกใช้แอปพลิเคชัน)
  • ความสามารถในการสืบค้นแหล่งข้อมูล (เช่นถ้าฉันสังเกต A, B, C ฉันต้องการทราบรายการที่สังเกตบ่อยที่สุดสำหรับสิ่งที่อาจตามมาโดยใช้ชุดข้อมูล 4-, 3, 2, 2, 1 กรัม )

    แอปพลิเคชันส่วนใหญ่จะอ่านอย่างหนักชุดข้อมูลส่วนใหญ่มักจะไม่ได้รับการอบรมใหม่บ่อยครั้ง

  • โซลูชันนี้ใช้. NET Framework (สูงถึง 4.0)

ทีนี้การออกแบบแบบไหนที่จะเหมาะกับงานแบบนี้ดีกว่า?

  • ตารางคงที่จัดการโดยเซิร์ฟเวอร์ SQL (MSSQL, MySQL, ... ) สำหรับแต่ละn (เช่นตารางเฉพาะสำหรับ bi-grams, tri-grams ฯลฯ )
  • หรือโซลูชันฐานข้อมูลเอกสาร NoSQL ที่จัดเก็บn -1 เป็นคีย์ของเอกสารและเอกสารเองมีค่าn- th และความถี่ที่สังเกตได้หรือไม่
  • หรือสิ่งที่แตกต่างกันอย่างไร

3
ฉันคิดว่าสิ่งนี้จะเหมาะกว่าใน Stack Overflow
Konrad Rudolph

1
บางทีโครงสร้างข้อมูล trie (คำนำหน้าต้นไม้) อาจเหมาะกับความต้องการของคุณหรือไม่
Schedler

1
ฉันขอแนะนำ Stack Overflow หรือแม้แต่cstheory.stackexchange.com
Steve

โอเคขอบคุณ. ฉันจะพยายามทำให้คำถามตรงนี้
แมนนี่

4
คำถามนี้เหมาะอย่างยิ่งสำหรับ programmers.stackexchange.com และไม่ควรโยกย้ายไปยัง stackoverflow, IMO มันเป็นคำถามแบบ“ สถานการณ์ไวท์บอร์ด” ที่ควรถามที่นี่ ตรวจสอบเมตาเพื่อดูรายละเอียด
281377

คำตอบ:


8

เนื่องจากคุณจะไม่ทราบช่วงที่เหมาะสมที่สุดของ N คุณจึงต้องการเปลี่ยนได้อย่างแน่นอน ตัวอย่างเช่นหากแอปพลิเคชันของคุณคาดการณ์ว่าข้อความบางข้อความเป็นภาษาอังกฤษคุณอาจต้องการใช้อักขระ N-grams สำหรับ N 3..5 (นั่นคือสิ่งที่เราพบในการทดลอง)

คุณยังไม่ได้แชร์รายละเอียดเกี่ยวกับแอปพลิเคชันของคุณ แต่ปัญหานั้นชัดเจนเพียงพอ คุณต้องการแสดงข้อมูล N-Gram ในฐานข้อมูลเชิงสัมพันธ์ (หรือโซลูชันที่ใช้เอกสาร NoSQL) ก่อนที่จะแนะนำวิธีแก้ปัญหาด้วยตัวคุณเองคุณอาจต้องการดูวิธีการต่อไปนี้:

  1. วิธีเก็บ Google ngrams ในฐานข้อมูลได้ดีที่สุด
  2. การจัดเก็บ n-grams ในฐานข้อมูลใน <n จำนวนตาราง
  3. การจัดการ Google Web 1T 5 กรัมด้วยฐานข้อมูลเชิงสัมพันธ์

ตอนนี้เมื่อไม่ได้อ่านลิงก์ข้างต้นใด ๆ ฉันขอแนะนำวิธีการฐานข้อมูลเชิงสัมพันธ์ที่เรียบง่ายโดยใช้หลายตารางหนึ่งตารางสำหรับ N-gram แต่ละขนาด คุณสามารถใส่ข้อมูลทั้งหมดในตารางเดียวด้วยคอลัมน์ที่จำเป็นสูงสุด (เช่นเก็บ bigrams และ trigrams ใน ngram_4 โดยปล่อยคอลัมน์สุดท้ายเป็นโมฆะ) แต่ฉันแนะนำให้ทำการแบ่งพาร์ติชันข้อมูล ขึ้นอยู่กับเอ็นจิ้นฐานข้อมูลของคุณตารางเดี่ยวที่มีแถวจำนวนมากสามารถส่งผลเสียต่อประสิทธิภาพการทำงาน

  create table ngram_1 (
      word1 nvarchar(50),
      frequency FLOAT,
   primary key (word1));

  create table ngram_2 (
      word1 nvarchar(50),
      word2 nvarchar(50),
      frequency FLOAT,
   primary key (word1, word2));

  create table ngram_3 (
      word1 nvarchar(50),
      word2 nvarchar(50),
      word3 nvarchar(50),
      frequency FLOAT,
   primary key (word1, word2, word3));

  create table ngram_4 (
      word1 nvarchar(50),
      word2 nvarchar(50),
      word3 nvarchar(50),
      word4 nvarchar(50),
      frequency FLOAT,
   primary key (word1, word2, word3, word4));

ถัดไปฉันจะให้คำค้นหาที่จะให้คำถัดไปที่เป็นไปได้มากที่สุดที่ได้รับจากตารางแกรมทั้งหมดของคุณ แต่ก่อนอื่นนี่คือตัวอย่างข้อมูลที่คุณควรแทรกลงในตารางด้านบน:

  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'building', N'with', 0.5)
  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'hit', N'the', 0.1)
  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'man', N'hit', 0.2)
  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'the', N'bat', 0.7)
  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'the', N'building', 0.3)
  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'the', N'man', 0.4)
  INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'with', N'the', 0.6)
  INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'building', N'with', N'the', 0.5)
  INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'hit', N'the', N'building', 0.3)
  INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'man', N'hit', N'the', 0.2)
  INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'the', N'building', N'with', 0.4)
  INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'the', N'man', N'hit', 0.1)
  INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'with', N'the', N'bat', 0.6)
  INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'building', N'with', N'the', N'bat', 0.5)
  INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'hit', N'the', N'building', N'with', 0.3)
  INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'man', N'hit', N'the', N'building', 0.2)
  INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'the', N'building', N'with', N'the', 0.4)
  INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'the', N'man', N'hit', N'the', 0.1)

หากต้องการค้นหาคำถัดไปที่เป็นไปได้มากที่สุดคุณจะต้องใช้แบบสอบถามเช่นนี้

  DECLARE @word1 NVARCHAR(50) = 'the'
  DECLARE @word2 NVARCHAR(50) = 'man'
  DECLARE @word3 NVARCHAR(50) = 'hit'
  DECLARE @bigramWeight FLOAT = 0.2;
  DECLARE @trigramWeight FLOAT = 0.3
  DECLARE @fourgramWeight FLOAT = 0.5

  SELECT next_word, SUM(frequency) AS frequency
  FROM (
    SELECT word2 AS next_word, frequency * @bigramWeight AS frequency
    FROM ngram_2
    WHERE word1 = @word3
    UNION
    SELECT word3 AS next_word, frequency * @trigramWeight AS frequency
    FROM ngram_3
    WHERE word1 = @word2
      AND word2 = @word3
    UNION
    SELECT word4 AS next_word, frequency * @fourgramWeight AS frequency
    FROM ngram_4
    WHERE word1 = @word1
      AND word2 = @word2
      AND word3 = @word3
    ) next_words
  GROUP BY next_word
  ORDER BY SUM(frequency) DESC

หากคุณเพิ่มตาราง ngram เพิ่มเติมคุณจะต้องเพิ่มส่วนคำสั่ง UNION อื่นลงในแบบสอบถามด้านบน คุณอาจสังเกตเห็นว่าในแบบสอบถามแรกฉันใช้ word1 = @ word3 และในคิวรีที่สอง word1 = @ word2 AND word2 = @ word3 นั่นเป็นเพราะเราจำเป็นต้องจัดตำแหน่งสามคำในแบบสอบถามสำหรับข้อมูล ngram หากเราต้องการคำถัดไปที่มีโอกาสมากที่สุดสำหรับลำดับสามคำเราจะต้องตรวจสอบคำแรกในข้อมูล bigram เทียบกับคำสุดท้ายของคำในลำดับนั้น

คุณสามารถปรับแต่งพารามิเตอร์น้ำหนักตามที่คุณต้องการ ในตัวอย่างนี้ฉันคิดว่าลำดับที่สูงกว่า "n" กรัมจะเชื่อถือได้มากขึ้น

PS ฉันจะโครงสร้างรหัสโปรแกรมเพื่อจัดการตาราง ngram_N จำนวนเท่าใดก็ได้ผ่านการกำหนดค่า คุณสามารถเปลี่ยนโปรแกรมให้ใช้ช่วง N-gram N (1..6) ได้อย่างชัดเจนหลังจากสร้างตาราง ngram_5 และ ngram_6


ด้วยข้อความค้นหานี้ฉันเห็นเฉพาะคะแนนความถี่ที่คุณมี ฉันจะเลือกคำที่คาดคะเนต่อไปได้อย่างไร ข้อใดเกี่ยวข้องกับประโยคมากที่สุด
TomSawyer

จุดดี @TomSawyer ฉันเพิ่มข้อมูลตัวอย่างในคำตอบและให้ตัวอย่างแบบสอบถามที่ส่งคืนคำถัดไปที่เป็นไปได้มากที่สุด
Matthew Rodatus

Tks สำหรับการอัปเดตของคุณ แต่เราจะคำนวณความถี่ที่นี่ได้อย่างไร ie: in ngram_2, วลีที่building withมี freq คือ 0.5 คำถามเดียวกันกับ@bigramWeightนั่นคืออะไร ฉันแม้ว่า freq คือฟิลด์จะอัปเดตทุกครั้งที่เราอัปเดตฐานข้อมูล คือถ้าผู้ใช้ป้อนสตริงมากขึ้นความถี่สำหรับสตริงนี้จะถูกคำนวณใหม่หรือไม่ 0.5 คือ 0.5 เปอร์เซ็นต์ของเวลาที่ใช้ทั้งหมดหรืออัตราการปรากฏของแต่ละวลี?
TomSawyer

bigramWeight และ trigramWeight (ฯลฯ ) เป็นวิธีการคำนวณน้ำหนัก n-g ต่างๆในการคำนวณโดยรวม เป็นวิธีที่ง่ายในการบอกว่า n-gg ที่มีเอนโทรปีที่ยาวกว่าและคุณอาจต้องการให้พวกเขา "นับ" มากกว่า n-g ที่สั้นกว่า
Matthew Rodatus

ในแง่ของการอัพเดทฐานข้อมูลเห็นได้ชัดว่าฉันไม่ได้ครอบคลุมรายละเอียดทั้งหมดและมีพื้นที่สำหรับการปรับปรุงมากมาย ตัวอย่างเช่นแทนที่จะเก็บ nvarchars ในตาราง ngram คุณอาจต้องการ tokenize ลงในตารางคำ (word_id INT, word NVARCHAR) จากนั้นอ้างถึง word_ids ในตาราง ngram หากต้องการอัปเดตตารางเกี่ยวกับการฝึกอบรมซ้ำที่ถูกต้องคุณเพียงแค่อัปเดตฟิลด์ความถี่
Matthew Rodatus

3

ตรงกันข้ามกับสิ่งที่คนอื่น ๆ กำลังแนะนำฉันขอแนะนำให้หลีกเลี่ยงโครงสร้างข้อมูลใด ๆ ที่ซับซ้อนกว่า hashmap หรือที่เก็บคีย์ - ค่า

โปรดทราบข้อกำหนดการเข้าถึงข้อมูลของคุณ: a) คำขอ 99% - แบบสอบถาม ngram "aaa-bbb-ccc" และเรียกคืนค่า (หรือ 0) b) คำขอ 1% - การแทรก / ปรับปรุงจำนวน ngram c ที่เฉพาะเจาะจง) ไม่มี (ค).

วิธีที่มีประสิทธิภาพมากที่สุดคือเรียกดูด้วยการค้นหาครั้งเดียว คุณสามารถใช้ตัวคั่น out-of-bounds (หรือหลบหนี) เพื่อรวม n-gram แบบเต็มในสตริงเดี่ยว (เช่น "alpha | beta | gamma" สำหรับ 3 กรัม, "alpha" สำหรับ unigram, ฯลฯ ) และเพียงดึงข้อมูลนั้น ( โดยแฮชของที่) นั่นเป็นวิธีที่ซอฟต์แวร์ NLP ค่อนข้างใช้

หากข้อมูล ngram ของคุณมีขนาดเล็ก (เช่น <1 gb) และพอดีกับหน่วยความจำฉันแนะนำให้ใช้โครงสร้างหน่วยความจำในโปรแกรมที่มีประสิทธิภาพ (แฮชแมปต้นไม้ลอง ฯลฯ ) เพื่อหลีกเลี่ยงค่าใช้จ่าย และเป็นอนุกรม / ดีซีเรียลไลซ์เป็นไฟล์แฟลต หากข้อมูล ngram ของคุณเป็นเทราไบต์หรือมากกว่านั้นคุณอาจเลือกที่เก็บคีย์ - ค่า NoSQL แบ่งออกเป็นหลายโหนด

เพื่อประสิทธิภาพที่เพิ่มขึ้นคุณอาจต้องการแทนที่คำทั้งหมดทุกที่ด้วยรหัสจำนวนเต็มเพื่อให้อัลกอริทึมหลักของคุณไม่เห็นสตริงใด ๆ (ช้า) เลย ดังนั้นจึงแตกต่างกันเล็กน้อยในการใช้แนวคิดเดียวกัน


1

ไม่ได้มีประสิทธิภาพมากที่สุด แต่ง่ายและแต่งงานกับฐานข้อมูลอย่างที่คุณต้องการ:

Table: word
Colums:
word (int, primary key) - a unique identifier for each word
text (varchar) - the actual word

Table: wordpos
Columns:
document (int) - a unique identified for the document of this word
word (int, foreign key to word.word) - the word in this position
pos (int) - the position of this word (e.g., first word is 1, next is 2, ...)

wordpos ควรมีดัชนีในเอกสารและ pos

bigrams คือ:

select word1.text as word1, word2.text as word2
from wordpos as pos1, wordpos as pos2, word as word1, word as word2
where pos1.document = pos2.document
      and pos1.pos = pos2.pos - 1
      and word1.word = pos1.word
      and word2.word = pos2.word

จากนั้นคุณสามารถนับ () และจัดกลุ่มตามความถี่และสิ่งของ

หากต้องการเปลี่ยนเป็นตรีโกณมิติมันเป็นการง่ายที่จะสร้างสตริงนี้เพื่อรวม word3

ฉันเคยทำมาแล้วจริง ๆ (แม้ว่า SQL ที่นั่นอาจจะมีสนิมเล็กน้อย) ฉันตัดสินชุดไฟล์แฟลตที่สามารถค้นหาได้อย่างง่ายดายจากนั้นสตรีมจากดิสก์ ค่อนข้างขึ้นอยู่กับฮาร์ดแวร์ของคุณว่าจะทำอย่างไรดี


1

ในขณะที่พยายามปรับปรุงการค้นหาอย่างง่ายของแอปพลิเคชันของฉันให้เป็น bigrams และ trigrams จาก unigrams โดยพื้นฐานแล้วฉันเห็นคำถามของคุณ

หากหนึ่งในความต้องการคือความสามารถในการสืบค้นระบบไฟล์แบบกระจายหรือฐานข้อมูลนี่อาจเป็นสิ่งที่น่าสนใจสำหรับคุณเช่นกัน Pibiri and Venturini 2018 "การจัดการชุดข้อมูล N-Gram ขนาดใหญ่อย่างมีประสิทธิภาพ" แสดงวิธีที่มีประสิทธิภาพในการเก็บข้อมูล n-gram เงื่อนไขของรันไทม์และพื้นที่ พวกเขาเสนอการใช้งานของพวกเขาที่ https://github.com/jermp/tongrams

แต่ละ "n" ของ n-grams จะถูกเก็บไว้ในตารางที่แยกต่างหากซึ่งเข้าถึงได้โดยฟังก์ชันแฮชที่สมบูรณ์แบบขั้นต่ำพร้อมความสามารถในการเลือกและสืบค้นที่รวดเร็ว ตารางเป็นแบบคงที่และสร้างขึ้นโดยรหัสหลักโดยใช้อินพุตในรูปแบบของไฟล์ข้อความของ Google n-grams

ฉันยังไม่ได้ใช้รหัส แต่มีหลายวิธีที่คุณสามารถทำได้กับข้อกำหนดเปิดของคุณว่าข้อความค้นหาของคุณมาจากที่ใด

วิธีหนึ่ง: หากใช้. NET เทียบเท่ากับเซิร์ฟเล็ตกับฐานข้อมูลหรือที่เก็บข้อมูลและถ้าคุณต้องการประหยัดพื้นที่เก็บข้อมูลให้เก็บตาราง ngram แต่ละตารางในรูปแบบไบนารีในฐานข้อมูล / ที่เก็บข้อมูลเป็นตารางเป็นหนึ่งตัวเลือก (ฐานข้อมูลเดียว ตาราง / datastore สำหรับไฟล์สแตติกที่เกิดขึ้นของรหัส ngram ที่มีประสิทธิภาพสำหรับทุก 1 กรัมและอีก 2 กรัมทั้งหมด) การสืบค้นจะถูกเรียกใช้โดยเรียกใช้โค้ด n-gram ที่มีประสิทธิภาพ (servlet ของคุณสามารถเข้าถึงได้) การทำงานเพื่อสร้างฐานข้อมูลแบบกระจายที่ใช้รหัส n-gram ที่มีประสิทธิภาพเพื่อเข้าถึงไฟล์บนระบบไฟล์แบบกระจาย โปรดทราบว่าตารางฐานข้อมูลไบนารี / datastore แต่ละตารางมีข้อ จำกัด ขนาดไฟล์ของระบบไฟล์พื้นฐาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.