การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน
ทำความเข้าใจว่าเมื่อใดเวกเตอร์ฝังแบบหนาแน่นพลาดคำสำคัญที่ตรงกันทุกประการ และเมื่อใด BM25 พลาดการถอดความเชิงความหมาย รวมถึงเหตุใดการใช้ทั้งสองแบบร่วมกันจึงให้ผลดีกว่าแต่ละแบบอย่างสม่ำเสมอ
การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
สัญญาณการค้นคืนสองแบบที่แตกต่างกันโดยพื้นฐาน
ระบบค้นคืนสมัยใหม่อาศัยสัญญาณที่แตกต่างกันสองแบบ: การค้นคืนแบบหนาแน่น เข้ารหัสความหมายลงในปริภูมิเวกเตอร์ต่อเนื่อง ขณะที่ การค้นคืนแบบเบาบาง นับจำนวนครั้งที่คำตรงกันปรากฏ สัญญาณทั้งสองส่งเสริมกัน ไม่สามารถใช้แทนกันได้ การทำความเข้าใจจุดแข็งและจุดอ่อนของแต่ละแบบคือขั้นตอนแรกในการสร้างระบบที่ใช้ทั้งสองแบบได้อย่างมีประสิทธิภาพ
การทำงานของเวกเตอร์แทนความหมายแบบหนาแน่น
การค้นคืนแบบหนาแน่นจะแปลงทั้งคำค้นและเอกสารแต่ละรายการเป็นเวกเตอร์มิติสูงโดยใช้ตัวเข้ารหัสโครงข่ายประสาท การวัดความคล้ายคลึงทำโดยใช้ ระยะโคไซน์ หรือผลคูณจุดระหว่างเวกเตอร์ เนื่องจากตัวเข้ารหัสได้รับการฝึกด้วยคลังข้อความขนาดใหญ่ วลีที่มีความหมายเกี่ยวข้องกันจึงอยู่ใกล้กันในปริภูมิเวกเตอร์ แม้ไม่มีคำร่วมกันเลย นี่คือข้อได้เปรียบสำคัญของการค้นคืนแบบหนาแน่น
from openai import OpenAI
import numpy as np
client = OpenAI()
def embed(text: str) -> list[float]:
resp = client.embeddings.create(
model='text-embedding-3-small',
input=text,
)
return resp.data[0].embedding
def cosine_similarity(a, b):
a, b = np.array(a), np.array(b)
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
q = embed('How do I cancel my subscription?')
d = embed('Steps to unsubscribe from the service')
print(cosine_similarity(q, d)) # high similarity despite different wordsจุดที่การค้นคืนแบบหนาแน่นล้มเหลว
โมเดลแบบหนาแน่นทำงานได้ไม่ดีเมื่อพบ คำที่พบได้ยาก ซึ่งมีสัดส่วนน้อยระหว่างการฝึกตัวเข้ารหัส คำค้นที่มีหมายเลขรุ่นผลิตภัณฑ์เฉพาะอย่าง RTX-4090-Ti-OC ชื่อยาทางการแพทย์ หรือตัวระบุภายในที่เป็นกรรมสิทธิ์ มักไม่ตรงกับเอกสารที่ถูกต้อง เพราะตัวเข้ารหัสไม่มีการแทนค่าลำดับโทเคนนั้นที่เรียนรู้ไว้ เวกเตอร์จึงไปอยู่ในตำแหน่งที่ไม่เป็นประโยชน์ในปริภูมิเวกเตอร์แทนความหมาย
การทำงานของการค้นคืนแบบเบาบาง BM25
BM25 (Best Matching 25) เป็นฟังก์ชันจัดอันดับเชิงความน่าจะเป็นที่ให้คะแนนเอกสารตามความถี่ที่คำค้นปรากฏในเอกสาร โดยปรับตามความยาวเอกสารและลดผลของการอิ่มตัวของความถี่คำ ผลลัพธ์คือ เวกเตอร์คะแนนแบบเบาบาง ซึ่งมิติส่วนใหญ่เป็นศูนย์ เพราะเอกสารมีคำศัพท์เพียงส่วนน้อยของคลังคำศัพท์ทั้งหมด
# BM25 scoring formula (conceptual)
# score(D, Q) = sum over query terms t of:
# IDF(t) * (tf(t,D) * (k1 + 1)) / (tf(t,D) + k1 * (1 - b + b * |D|/avgdl))
# k1 controls term frequency saturation (typically 1.2-2.0)
# b controls document length normalization (typically 0.75)
# IDF(t) = log((N - df(t) + 0.5) / (df(t) + 0.5))
# N = total documents, df(t) = documents containing term t
# tf(t,D) = frequency of t in document D, |D| = doc length, avgdl = average doc lengthจุดแข็งของ BM25: คำตรงและศัพท์เฉพาะ
BM25 โดดเด่นกับคำค้นที่มี ศัพท์เทคนิค ชื่อผลิตภัณฑ์ รหัสข้อผิดพลาด และตัวระบุที่เป็นตัวเลขแบบตรงกันทุกประการ ซึ่งควรจับคู่ให้แม่นยำ คำค้น ORA-01017 (รหัสข้อผิดพลาดของ Oracle) จะจัดอันดับเอกสารที่มีสตริงตรงกันนี้ไว้สูงกว่าเอกสารที่เพียงพูดถึงการตรวจสอบสิทธิ์ฐานข้อมูลโดยทั่วไปอย่างมาก สิ่งนี้เป็นไปไม่ได้สำหรับโมเดลแบบหนาแน่นที่ไม่เคยพบรหัสดังกล่าวมาก่อน
from rank_bm25 import BM25Okapi
corpus = [
'Oracle database ORA-01017 invalid username or password logon denied',
'Database authentication and connection troubleshooting guide',
'How to resolve login errors in Oracle and MySQL databases',
]
tokenized_corpus = [doc.lower().split() for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
query = 'ORA-01017 error fix'
scores = bm25.get_scores(query.lower().split())
print(dict(zip(range(len(corpus)), scores)))
# doc 0 scores highest because it contains ORA-01017จุดที่ BM25 ล้มเหลว: การถอดความและคำพ้องความหมาย
BM25 ไม่สามารถรับรู้ การถอดความเชิงความหมาย เอกสารเกี่ยวกับ 'การซ่อมเครื่องยนต์รถยนต์' จะได้คะแนนเป็นศูนย์สำหรับคำค้นเกี่ยวกับ 'การบำรุงรักษามอเตอร์รถ' เพราะไม่มีคำตรงกันเลย ปัญหาคำศัพท์ไม่ตรงกันนี้ ซึ่งบางครั้งเรียกว่า ช่องว่างทางคำศัพท์ ทำให้การค้นหาด้วยคำสำคัญล้วนพลาดเนื้อหาที่เกี่ยวข้องจำนวนมาก เพียงเพราะใช้คำต่างกันเพื่อสื่อแนวคิดเดียวกัน
from rank_bm25 import BM25Okapi
corpus = [
'automobile engine repair and maintenance tips',
'car motor maintenance guide for beginners',
'vehicle powertrain service intervals',
]
tokenized = [doc.split() for doc in corpus]
bm25 = BM25Okapi(tokenized)
scores = bm25.get_scores(['car', 'motor', 'maintenance'])
print(scores)
# doc 1 scores high, doc 0 and 2 score lower despite being semantically relatedหลักฐานจากการทดสอบมาตรฐาน: แบบผสมชนะอย่างสม่ำเสมอ
การทดสอบมาตรฐานบน BEIR, MS MARCO และชุดข้อมูลถาม-ตอบระดับองค์กรแสดงอย่างสม่ำเสมอว่า การค้นคืนแบบผสมมีประสิทธิภาพเหนือกว่าการค้นคืนแบบหนาแน่นหรือแบบเบาบางเพียงอย่างเดียว 5-15 เปอร์เซ็นต์ในด้าน NDCG@10 การปรับปรุงมีมากที่สุดในชุดข้อมูลที่ผสมคำค้นเพื่อค้นหาข้อเท็จจริง (ซึ่ง BM25 ช่วยได้) กับคำค้นแบบถอดความ (ซึ่งเวกเตอร์แทนความหมายแบบหนาแน่นช่วยได้) ไม่มีวิธีค้นคืนใดวิธีเดียวที่เด่นที่สุดสำหรับคำค้นทุกประเภท
การวิเคราะห์ประเภทคำค้น: เครื่องมือค้นคืนใดชนะ
คุณสามารถคาดการณ์ได้ว่าเครื่องมือค้นคืนใดจะทำงานได้ดีกว่าโดยวิเคราะห์ประเภทคำค้น การค้นคืนแบบหนาแน่น ชนะในคำถามเชิงแนวคิด การถอดความ และคำค้นหัวข้อกว้าง BM25 ชนะในคำค้นที่มีชื่อเฉพาะ หมายเลขรุ่น ข้อมูลโค้ด อักษรย่อ และศัพท์เทคนิคที่พบได้ยาก การค้นคืนแบบผสมจะชนะเสมอเมื่อไม่ทราบประเภทคำค้นล่วงหน้า ซึ่งแทบจะเป็นเช่นนั้นเสมอในการใช้งานจริง
# Query type heuristics
def predict_retriever_advantage(query: str) -> str:
tokens = query.split()
has_numbers = any(t[0].isdigit() for t in tokens)
has_uppercase_acronyms = any(t.isupper() and len(t) > 2 for t in tokens)
is_short = len(tokens) <= 4
if has_numbers or has_uppercase_acronyms:
return 'BM25 likely wins (exact terms)'
elif is_short:
return 'Dense likely wins (semantic matching needed)'
else:
return 'Hybrid recommended (mixed signals)'ปัญหาคะแนนเข้ากันไม่ได้
การรวมผลลัพธ์แบบหนาแน่นและแบบเบาบางไม่ใช่เรื่องง่าย เนื่องจากคะแนนของทั้งสองแบบอยู่บน สเกลที่เข้ากันไม่ได้ ความคล้ายคลึงแบบโคไซน์ให้ค่าระหว่าง -1 ถึง 1 ขณะที่ BM25 ให้คะแนนบวกที่ไม่มีขอบเขตตายตัวและขึ้นอยู่กับขนาดคลังข้อมูล คุณไม่สามารถนำคะแนนมาบวกกันโดยตรงได้ วิธีมาตรฐานคือใช้ การผสานตามอันดับ แทนการผสานตามคะแนน กล่าวคือรวมรายการที่จัดอันดับแล้วแทนคะแนนดิบ
การตัดสินใจเชิงปฏิบัติ: ควรใช้แต่ละวิธีเมื่อใด
ใช้การค้นคืนแบบ หนาแน่นเท่านั้น เมื่อคลังข้อมูลของคุณอยู่ในโดเมนแคบ มีคำศัพท์สม่ำเสมอ และคุณต้องการการสรุปเชิงความหมายครอบคลุมคำถามที่ใช้ถ้อยคำต่างกัน ใช้ BM25 เท่านั้น เมื่อคำถามส่วนใหญ่เป็นการค้นหาแบบระบุข้อมูล โดยใช้ตัวระบุที่ตรงกัน และชุดข้อมูลมีขนาดเล็กพอที่จะค้นหาแบบไล่ตรวจทั้งหมดได้ ใช้แบบ ผสม ในระบบ RAG สำหรับใช้งานจริงทุกระบบที่ประเภทคำถามมีความหลากหลาย เพราะค่าใช้จ่ายเพิ่มเติมไม่มาก แต่ช่วยเพิ่มความครอบคลุมในการค้นคืนได้อย่างมีนัยสำคัญ
ข้อแลกเปลี่ยนด้านประสิทธิภาพและโครงสร้างพื้นฐาน
การค้นคืนแบบหนาแน่นต้องใช้ การค้นหาเพื่อนบ้านใกล้เคียงโดยประมาณที่เร่งความเร็วด้วย GPU หรือฐานข้อมูลเวกเตอร์ ซึ่งเพิ่มต้นทุนโครงสร้างพื้นฐาน BM25 ทำงานบน CPU ทั้งหมดโดยใช้ดัชนีกลับด้านและรวดเร็วมาก การค้นคืนแบบผสมต้องใช้ส่วนประกอบโครงสร้างพื้นฐานทั้งสองแบบ รวมถึงขั้นตอนการผสาน ผลลัพธ์ที่ดีขึ้นด้านความครอบคลุมในการค้นคืนทำให้ความซับซ้อนที่เพิ่มขึ้นคุ้มค่าสำหรับกรณีใช้งานจริงส่วนใหญ่ แต่ต้องพิจารณาเทียบกับงบประมาณโครงสร้างพื้นฐานของคุณด้วย
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับข้อแลกเปลี่ยนระหว่างการค้นคืนแบบหนาแน่นและแบบเบาบางจากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า การค้นคืนแบบหนาแน่นจับความหมายเชิงความหมายได้ แต่ทำงานได้ไม่ดีเมื่อพบคำที่ตรงกันแบบเฉพาะเจาะจงและพบได้ยาก การค้นคืนแบบเบาบางด้วย BM25จัดการคำสำคัญที่ตรงกันได้ดี แต่พลาดคำถามที่ใช้ถ้อยคำต่างกัน และ การค้นคืนแบบผสมให้ผลดีกว่าวิธีใดวิธีหนึ่งเพียงอย่างเดียวอย่างสม่ำเสมอสำหรับคำถามหลายประเภท คะแนนของทั้งสองวิธีเข้ากันไม่ได้และต้องผสานด้วยการผสานตามอันดับแทนการบวกคะแนน ต่อไปเราจะนำการค้นหาด้วยคำสำคัญ BM25 มาใช้งานใน Python
เรียนรู้ Python ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน”
ทำความเข้าใจว่าเมื่อใดเวกเตอร์ฝังแบบหนาแน่นพลาดคำสำคัญที่ตรงกันทุกประการ และเมื่อใด BM25 พลาดการถอดความเชิงความหมาย รวมถึงเหตุใดการใช้ทั้งสองแบบร่วมกันจึงให้ผลดีกว่าแต่ละแบบอย่างสม่ำเสมอ คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน
- การสร้างการค้นหาด้วยคำสำคัญ BM25
- การรวมอันดับแบบผกผันเพื่อผสานคะแนน
- การค้นหาแบบผสมใน Pinecone และ pgvector