- นักวิทยาศาสตร์ข้อมูลแปลงทุกอย่างให้เป็นเวกเตอร์ นี่คือภาษาของ AI
- แต่หากนำ cosine similarity ไปใช้แบบไม่ลืมหูลืมตา ก็อาจพาไปผิดทางได้
- บทความนี้อธิบายวิธีใช้ความคล้ายคลึงอย่างมีเจตนามากขึ้นเพื่อให้ได้ผลลัพธ์ที่ดีกว่า
Embeddings
- Embeddings คือการแทนข้อมูลในรูปแบบเวกเตอร์ ซึ่งมีประโยชน์มากในการแสดงความสัมพันธ์ระหว่างเอนทิตีหรือค้นหารายการที่คล้ายกัน
- ตัวอย่างเช่น "brother" และ "sister" ไม่มีความสัมพันธ์กันในแบบ raw ID แต่เมื่อทำเป็นเวกเตอร์แล้วก็สามารถแสดงความสัมพันธ์เชิงความหมายได้
- เวกเตอร์ถูกใช้เป็นโครงสร้างอินพุตของโมเดลแมชชีนเลิร์นนิง หรือใช้ค้นหาความคล้ายคลึงได้ด้วยตัวเอง
- sentence embeddings ที่อิงกับ LLM เป็นหนึ่งในกรณีใช้งานของ embeddings ที่ได้รับความนิยมมากที่สุดในตอนนี้
- ความสามารถอันทรงพลังนี้มาพร้อมความรับผิดชอบด้านความปลอดภัยของข้อมูลและการใช้งานอย่างมีเจตนา
ตัวอย่าง: เปรียบเทียบประโยคด้วย cosine similarity
- เปรียบเทียบ 3 ประโยค
- A: "Python can make you rich."
- B: "Python can make you itch."
- C: "Mastering Python can fill your pockets."
- การเปรียบเทียบแบบอิงตัวอักษร
- หากเปรียบเทียบ raw string แล้ว A กับ B ต่างกัน 2 ตัวอักษร ส่วน A กับ C ต่างกัน 21 ตัวอักษร
- แต่ในเชิงความหมาย A กับ C คล้ายกันมากกว่า (เกี่ยวกับเงิน)
- การเปรียบเทียบแบบอิงเวกเตอร์
- ใช้ OpenAI text-embedding-3-large เพื่อสร้าง embedding vectors ดังนี้:
- A:
[-0.003738, -0.033263, -0.017596, 0.029024, -0.015251, ...]
- B:
[-0.066795, -0.052274, -0.015973, 0.077706, 0.044226, ...]
- C:
[-0.011167, 0.017812, -0.018655, 0.006625, 0.018506, ...]
- จำนวนมิติของเวกเตอร์: 3072 (ยาว แต่สามารถลดมิติได้โดยไม่ลดคุณภาพ)
- การคำนวณ cosine similarity
- A กับ C: 0.750 (คล้ายกันในเชิงความหมาย)
- A กับ B: 0.576 (คล้ายกันในเชิงตัวอักษร)
- ผลลัพธ์: ความหมายเป็นปัจจัยของความคล้ายคลึงที่สำคัญกว่าการสะกด
cosine similarity คืออะไร?
- cosine similarity คือการวัดความคล้ายคลึงด้วยการคำนวณค่า cosine ของมุมระหว่างเวกเตอร์สองตัว
- เพราะเวกเตอร์อยู่ในปริภูมิหลายมิติ ความเข้าใจเชิงเรขาคณิตแบบสัญชาตญาณจึงมักใช้ไม่ได้ผล
- ในเชิงคณิตศาสตร์ มันคือ dot product ของเวกเตอร์ที่ถูก normalize แล้ว
- คุณสมบัติสำคัญ:
- เวกเตอร์ที่เหมือนกันจะได้ค่า 1
- เวกเตอร์สุ่มจะมีค่าใกล้ 0 (จากผลการเฉลี่ยในปริภูมิหลายมิติ)
- ค่าผลลัพธ์อยู่ระหว่าง -1 ถึง 1
- ความเรียบง่ายนี้อาจชวนให้เข้าใจผิด
- อย่าเข้าใจผิดว่าการที่ค่ามีช่วง 0~1 หมายความว่าเป็นความน่าจะเป็นหรือมาตรวัดที่มีความหมายโดยตรง
- ตัวอย่าง: ค่า 0.6 อาจไม่ได้หมายถึงความคล้ายคลึงที่สูง
- ค่าติดลบบางครั้งอาจสื่อถึงความตรงข้ามเชิงความหมาย
- แต่ส่วนใหญ่มักไร้ความหมายหรือใกล้เคียงกับ noise
- หากลองใช้ GloVe(
glove.6B.300d) เพื่อค้นหาคำที่คล้ายกับ "dog":
- คำที่ใกล้มักเป็นสิ่งที่พอคาดเดาได้
- คำที่ไกลที่สุดมักให้ผลที่ไม่มีความหมาย
- cosine similarity เปรียบเหมือน "duct tape" ที่ช่วยให้เปรียบเทียบเวกเตอร์ได้ง่ายและรวดเร็วในสารพัดรูปแบบ
- ใช้เปรียบเทียบได้ทั้งภาพ ข้อความ เสียง โค้ด ฯลฯ
- แต่มันเป็นเพียงทางแก้เฉพาะหน้า และอาจซ่อนปัญหาที่ลึกกว่านั้นไว้
- เช่นเดียวกับการซ่อมท่อด้วย duct tape มันไม่น่าเชื่อถือและไม่ถาวร
- แม้บางครั้ง cosine similarity จะดูเหมือนใช้ได้ผล แต่เมื่อมันล้มเหลวก็ยากจะรู้สาเหตุ
- มักทำให้ต้องหาทางแก้แบบเฉพาะหน้า ซึ่งอาจก่อปัญหาใหม่ตามมา
ความสัมพันธ์ระหว่าง cosine similarity กับค่าสหสัมพันธ์
- Pearson correlation coefficient คำนวณได้เป็น 3 ขั้นตอน:
- ลบค่าเฉลี่ยเพื่อ center ข้อมูล
- normalize เวกเตอร์ให้เป็น unit vector
- คำนวณ dot product ของเวกเตอร์ทั้งสอง
- หากเวกเตอร์ถูก center และ normalize แล้ว:
- Pearson correlation coefficient = cosine similarity = dot product
- วิธีใช้ในทางปฏิบัติ
- ไม่ได้ center หรือ normalize เวกเตอร์ใหม่ทุกครั้งที่เปรียบเทียบแต่ละคู่
- แต่จะ preprocess ล่วงหน้า แล้วคำนวณเฉพาะ dot product
- หากใช้ cosine similarity ได้ ก็สามารถใช้ Pearson correlation coefficient ได้เช่นกัน
- โดยพื้นฐานแล้วมาตรวัดทั้งสองใช้ได้ในบริบทเดียวกัน
ปัญหาเมื่อใช้ cosine similarity เป็นมาตรวัดความคล้ายคลึง
- การใช้ cosine similarity เป็นเป้าหมายการฝึกของโมเดลแมชชีนเลิร์นนิงนั้นใช้ได้ในเชิงคณิตศาสตร์
- ปัญหาเกิดขึ้นในพื้นที่ที่เกินกว่าความเหมาะสมของ cosine similarity เอง:
- เมื่อ loss function ที่ใช้ฝึกโมเดลไม่ใช่ cosine similarity
- เมื่อเป้าหมายการฝึกต่างจากสิ่งที่แอปพลิเคชันจริงต้องการ
- โดยทั่วไปโมเดลจะถูกฝึกด้วยเวกเตอร์ที่ยังไม่ normalize:
- ตัวอย่าง: ใช้การทำนายความน่าจะเป็นที่อิงกับ dot product และ logistic loss function
- บางโมเดลเรียนรู้ให้รายการในคลาสเดียวกันอยู่ใกล้กันโดยลด Euclidean distance ให้ต่ำสุด
- การ normalize ให้คุณสมบัติทางคณิตศาสตร์บางอย่าง (เช่น จำกัดผลลัพธ์ให้อยู่ระหว่าง -1 ถึง 1) แต่ก็เป็นเพียง "ทางแก้เฉพาะหน้า"
- มีเพียงโมเดลที่ถูกฝึกด้วย cosine similarity หรือฟังก์ชันที่เกี่ยวข้องโดยตรงเท่านั้นที่ถือว่าใช้ได้อย่างปลอดภัย
- แม้โมเดลจะถูกฝึกด้วย cosine similarity อย่างชัดเจน นิยามของคำว่า similarity ก็ยังอาจไม่ชัดเจน:
- นักวิจารณ์วรรณกรรม: ใช้ธีมร่วมกัน
- บรรณารักษ์: การจัดประเภทตามแนว
- ผู้อ่าน: ปฏิกิริยาทางอารมณ์
- นักจัดหน้า: จำนวนหน้าและรูปแบบ
- cosine similarity ทำให้ความหมายหลายแบบถูกยุบเหลือเป็นตัวเลขเดียว จึงชวนให้เข้าใจผิดได้
- ตัวอย่าง: "espresso" กับ "cappuccino"
- word2vec อาจมองว่าสองคำนี้แทบจะเหมือนกัน (ในบริบทสหรัฐฯ)
- แต่ในอิตาลีไม่ได้ถูกมองว่าเหมือนกัน
กรณีที่ cosine similarity ใช้งานล้มเหลว
- ตัวอย่างง่าย ๆ: คำถามตามหากุญแจ
- คำถาม: "What did I do with my keys?"
- ประโยคที่ใช้เปรียบเทียบ:
- "I left them in my pocket"
- "They are on the table"
- "What did I put my wallet?"
- "What I did to my life?"
- ปัญหา
- ผลจากการใช้ cosine similarity:
- ประโยคที่ใกล้ที่สุดกลับเป็นอีกคำถามหนึ่ง ("What I did to my life?") แทนที่จะเป็นคำตอบที่เหมาะสม
- พึ่งพาเพียงความคล้ายของโครงสร้างประโยค ไม่ใช่ความเกี่ยวข้องเชิงความหมาย
- ประโยคเกี่ยวกับ Python มีค่าความคล้ายใกล้ 0 จึงสะท้อนความไม่เกี่ยวข้องได้ถูกต้อง
- ข้อจำกัดในโลกจริง
- ในการใช้งานจริง มักต้องจัดการกับเอกสารนับพัน
- และจะไวต่อ noise มากขึ้นในชุดข้อมูลขนาดใหญ่ที่เกิน context window
- ยิ่งชุดข้อมูลใหญ่ คะแนนความคล้ายก็ยิ่งทำงานเหมือนเกมรูเล็ตในปริภูมิหลายมิติ
แล้วควรใช้อะไรแทน cosine similarity?
แนวทางที่ทรงพลังที่สุด
- ใช้ LLM query:
- ใช้ language model ที่ทรงพลังเพื่อเปรียบเทียบสองรายการ
- ตัวอย่าง: "Is {sentence_a} a plausible answer to {sentence_b}?"
- การใช้ LLM ทำให้เปรียบเทียบอย่างมีความหมายได้:
- แยกแยะคำถามง่าย ๆ กับคำตอบได้
- ส่งผลลัพธ์ออกมาในรูปแบบที่มีโครงสร้าง เช่น JSON ได้
- แต่หากชุดข้อมูลมีขนาดใหญ่ วิธีนี้จะไม่มีประสิทธิภาพและมีต้นทุนสูง
การปรับ embeddings ให้เหมาะสม
- สร้าง embeddings ตามงานเฉพาะ:
- ปรับน้ำหนักของโมเดลเดิมด้วย fine-tuning
- ใช้ความรู้ของโมเดลเพื่อสร้าง embeddings ใหม่ที่โฟกัสมากขึ้นด้วย transfer learning
- ความคล้ายแบบสมมาตร:
- แทนคำถามว่า "A กับ B คล้ายกันหรือไม่?" ในปริภูมิเวกเตอร์
- ลดมิติที่ไม่จำเป็น และเก็บเฉพาะคุณลักษณะที่เกี่ยวข้อง
- ความคล้ายแบบอสมมาตร:
- เช่น แทนคำถามว่า "เอกสาร B เป็นคำตอบที่ถูกต้องของคำถาม A หรือไม่?" เป็นความน่าจะเป็น
- แปลง query และ key ไปยังปริภูมิที่ออกแบบเฉพาะของแต่ละฝั่ง
Prompt engineering
- เพิ่ม prompt เพื่อกำหนดบริบท:
- ตัวอย่าง: "Nationality of {person}" เพื่อเน้นบริบทที่เกี่ยวกับสัญชาติ
- ใช้ประโยคที่เจาะจงมากกว่าพรอมป์ตสั้น ๆ:
- "This is a country that has produced many influential historical figures, including {person}"
- คุณภาพผลลัพธ์ดีขึ้นอย่างมาก แต่ก็ยังไม่สมบูรณ์
การเขียนข้อความใหม่และดึงบริบท
- Preprocess ข้อความก่อนทำ embedding:
- ใช้พรอมป์ตง่าย ๆ เช่น "สรุปข้อความต่อไปนี้เป็นภาษาอังกฤษมาตรฐานภายใน 200 คำ" เพื่อลดความคล้ายแบบผิวเผิน
- มองข้ามองค์ประกอบเชิงรูปแบบที่ไม่จำเป็น (เช่น คำสะกดผิด การจัดรูปแบบ) และโฟกัสที่เนื้อหา
- สร้างบริบทแบบมีโครงสร้าง:
- สรุปบทสนทนากับลูกค้าเพื่อดึงความต้องการและปัญหาออกมาอย่างชัดเจน:
- "Summarize the conversation into up to 10 Markdown points"
- แปลงหน้าข้อมูลให้อยู่ในรูปแบบเดียวกันเพื่อให้จับคู่ได้แม่นยำขึ้น
บทสรุป
- วิธีทางเลือกต่าง ๆ ช่วยชดเชยจุดอ่อนของ cosine similarity และให้ผลลัพธ์ที่เชื่อถือได้มากกว่า
- เลือกและประยุกต์ใช้แนวทางที่เหมาะสมตามสถานการณ์ของโปรเจกต์
สรุป
- ข้อจำกัดของ cosine similarity:
- cosine similarity ให้ค่าอยู่ระหว่าง -1 ถึง 1 แต่ไม่ควรมองค่านั้นเป็นความน่าจะเป็น
- โมเดลส่วนใหญ่ไม่ได้ถูกฝึกโดยมี cosine similarity เป็นเป้าหมาย และผลลัพธ์ก็เป็นเพียงความสัมพันธ์ที่ไม่ได้รับการรับประกัน
- แม้โมเดลจะเรียนรู้ cosine similarity มาแล้ว ก็ยังต้องเข้าใจว่านิยามความคล้ายแบบนั้นตรงกับความต้องการของเราหรือไม่
- วิธีใช้ vector similarity อย่างมีประสิทธิภาพ:
- ฝึก embeddings ที่เฉพาะกับข้อมูล
- ออกแบบ prompt ให้โฟกัสในแง่มุมที่เกี่ยวข้อง
- ทำความสะอาดและทำข้อความให้เป็นมาตรฐานก่อนทำ embedding
2 ความคิดเห็น
สรุปข้อมูลได้ยอดเยี่ยมมากครับ
ความคิดเห็นจาก Hacker News
ในแอปพลิเคชัน RAG ที่ใช้ cosine similarity ควรจัดเรียงผลลัพธ์ใหม่ด้วย "semantic re-ranker" หรือ "L2 re-ranking model"
เวกเตอร์คำช่วยแก้ปัญหาที่คำสองคำอาจมีความเกี่ยวข้องกันสูง แม้จะไม่ปรากฏในบริบทเดียวกัน
ในสหรัฐฯ word2vec อาจมองว่า espresso กับ cappuccino แทบจะเหมือนกัน แต่ในอิตาลีไม่เป็นเช่นนั้น
cosine similarity ถูกใช้ใน semantic search ที่อิง deep learning เป็นส่วนใหญ่
การใช้ LLM query โดยตรงเพื่อเปรียบเทียบสองรายการเป็นแนวทางที่ทรงพลังที่สุด
HyDE เป็นวิธีสร้างคำตอบสมมติสำหรับคำถามแล้วนำไปเปรียบเทียบความคล้ายกัน
cosine similarity และ top-k RAG ให้ความรู้สึกว่าล้าสมัยแล้ว
หลังจากลองใช้แนวทาง RAG แล้วรู้สึกผิดหวัง และคิดว่าควรจัดโครงสร้างให้โมเดลสามารถทำ RAG ได้ระหว่างการฝึก
ในกราฟิก 3D และฟิสิกส์ ความสำคัญและความแม่นยำนั้นชัดเจน แต่ในแมชชีนเลิร์นนิง พื้นที่เวกเตอร์แทนสิ่งต่าง ๆ มากเกินไป จึงทำให้การใช้ dot product ดูคลุมเครือ