Embedding คืออะไร และทำไมจึงสำคัญ
(simonwillison.net)- Embedding คือการแปลงคอนเทนต์อย่างข้อความ รูปภาพ หรือโค้ดให้เป็นอาร์เรย์เลขทศนิยมความยาวคงที่ เพื่อให้ค้นหารายการที่ใกล้กันทางความหมายได้ด้วยการคำนวณระยะทาง
- ในเวกเตอร์สเปซที่สร้างจากโมเดลเดียวกัน แม้จะไม่รู้ความหมายของตัวเลขแต่ละตัว ก็สามารถใช้ cosine similarity เปรียบเทียบเอกสารที่เกี่ยวข้อง รูปภาพที่คล้ายกัน หรือชิ้นส่วนโค้ดได้
- ในกรณีที่ใช้ OpenAI
text-embedding-ada-002เพื่อเก็บบทความ TIL 472 บทความเป็นเวกเตอร์ 1,536 มิติ คิวรีค้นหาบทความที่เกี่ยวข้องใช้เวลาประมาณ 400ms และค่าใช้จ่ายในการทำ embedding ทั้งหมด 402,500 token อยู่ที่ประมาณ $0.04 - แม้ใช้เพียงโมเดลแบบโลคัลและชุดเครื่องมือขนาดเล็ก ก็สามารถทำการค้นหา README, ค้นหาโค้ด, ค้นหารูปภาพ, clustering และ RAG ได้ โดยมี
LLM,llm-sentence-transformers,Symbex,CLIP,E5-large-v2เป็นตัวอย่าง - semantic search ที่อิง embedding ไม่พึ่งพาการตรงกันของคำอย่างแม่นยำ จึงเป็นกลไกหลักใน RAG เช่น Q&A จากเอกสารภายในองค์กร โดยนำข้อความคัดตอนที่เกี่ยวข้องใส่เข้าไปใน prompt ของ LLM
แนวคิดพื้นฐานของ Embedding
- Embedding คือวิธีแปลงคอนเทนต์หนึ่งชิ้นให้เป็นอาร์เรย์ของเลขทศนิยม
- ไม่ว่าคอนเทนต์จะยาวเท่าใด ความยาวของอาร์เรย์จะเท่ากันเสมอ
- ความยาวของอาร์เรย์ถูกกำหนดโดยโมเดล embedding ที่ใช้ เช่น 300, 1,000 หรือ 1,536 ตัวเลข
- อาร์เรย์นี้สามารถมองได้เหมือน พิกัด ในสเปซหลายมิติ
- ตำแหน่งในสเปซแสดงถึงความหมายของคอนเทนต์ตามที่โมเดล embedding เข้าใจ
- คุณลักษณะของคอนเทนต์ เช่น สี รูปร่าง หรือแนวคิด อาจสะท้อนอยู่ในนั้น
- แม้จะไม่เข้าใจความหมายของตัวเลขแต่ละตัวอย่างครบถ้วน ก็ยังใช้ความสัมพันธ์ของตำแหน่งเพื่อทำงานที่มีประโยชน์ได้ เช่น การค้นหารายการที่อยู่ใกล้กัน
การแนะนำคอนเทนต์ที่เกี่ยวข้อง: กรณีบล็อก TIL
- ในไซต์ TIL ที่มีบทความ 472 บทความ ได้คำนวณ เวกเตอร์ embedding 1,536 มิติ ของแต่ละบทความด้วยโมเดล OpenAI
text-embedding-ada-002- เวกเตอร์ถูกเก็บไว้ในฐานข้อมูล SQLite ของไซต์
- บทความที่เกี่ยวข้องถูกค้นหาโดยคำนวณ cosine similarity ระหว่างเวกเตอร์ของบทความเป้าหมายกับเวกเตอร์ของบทความอื่นทั้งหมด แล้วคืนค่า 10 รายการที่ใกล้ที่สุด
- ผลลัพธ์อันดับต้น ๆ ของบทความตัวอย่าง “Geospatial SQL queries in SQLite using TG, sqlite-tg and datasette-sqlite-tg” ประกอบด้วยบทความเกี่ยวกับ SQLite, SpatiaLite, GDAL และ query SQL เชิงพื้นที่
- similarity กับตัวเองคือ 1.0
sqlite_geopoly.mdคือ 0.8817322855676049spatialite_viewing-geopackage-data-with-spatialite-and-datasette.mdคือ 0.8813094978399854
- คิวรีสำหรับคำนวณบทความที่เกี่ยวข้องใช้เวลาประมาณ 400ms จึงคำนวณ similarity 10 อันดับแรกสำหรับบทความทั้งหมดไว้ล่วงหน้าแล้วเก็บในตาราง
similarities - ค่าใช้จ่าย OpenAI embedding API สำหรับไซต์ TIL อยู่ที่ประมาณ 402,500 token ด้วยอัตรา $0.0001/1,000 token รวมเป็น $0.04
- โมเดลแบบ proprietary ต้องระวังด้านการดำเนินงาน
- OpenAI เคยยุติการให้บริการโมเดล embedding รุ่นเก่าบางรุ่น
- หากมี embedding ที่บันทึกไว้ด้วยโมเดลเดิมจำนวนมาก อาจต้องคำนวณใหม่ตามโมเดลที่ยังรองรับเพื่อทำ embedding ให้คอนเทนต์ใหม่
- OpenAI สัญญาว่าจะรับผิดชอบค่าใช้จ่ายในการ re-embed ด้วยโมเดลใหม่ แต่ความเสี่ยงจากการพึ่งพาโมเดล proprietary ยังคงอยู่
- โมเดลที่มีไลเซนส์เปิดสามารถรันบนฮาร์ดแวร์ของตนเองได้ จึงหลีกเลี่ยงความเสี่ยงจากการปิดโมเดล
ทำความเข้าใจเวกเตอร์สเปซด้วย Word2Vec
- Efficient Estimation of Word Representations in Vector Space จาก Google Research คือบทความ Word2Vec ที่เผยแพร่เมื่อ 16 มกราคม 2013
- Word2Vec เป็นโมเดล embedding รุ่นแรก ๆ ที่แปลงคำหนึ่งคำเป็นอาร์เรย์ตัวเลข 300 ตัว
- turbomaze.github.io/word2vecjson เป็นเดโมที่ให้สำรวจคำ 10,000 คำและอาร์เรย์ตัวเลข 300 ตัวของแต่ละคำได้
- คำที่ใกล้กับ “france” ได้แก่
french,belgium,paris,germany,italy,spain
- คำที่ใกล้กับ “france” ได้แก่
- ความสัมพันธ์ยังปรากฏผ่านการคำนวณเวกเตอร์ได้ด้วย
- หากนำเวกเตอร์ “germany” บวกกับ “paris” แล้วลบ “france” เวกเตอร์ผลลัพธ์จะใกล้กับ “berlin” มากที่สุด
- แสดงให้เห็นว่าโมเดลจับความสัมพันธ์ด้านสัญชาติและภูมิศาสตร์ไว้ในเวกเตอร์สเปซ
- Word2Vec ฝึกด้วยคอนเทนต์ 1.6 พันล้านคำ ส่วนโมเดล embedding ปัจจุบันฝึกด้วยชุดข้อมูลที่ใหญ่กว่ามาก จึงจับความสัมพันธ์ได้หลากหลายกว่า
คำนวณ embedding ด้วยเครื่องมือ LLM
- LLM เป็นเครื่องมือบรรทัดคำสั่งและไลบรารี Python สำหรับจัดการ large language model
- ติดตั้งได้ด้วย
pip install llmหรือbrew install llm - โดยค่าเริ่มต้นสามารถใช้ร่วมกับ OpenAI API ได้
- ติดตั้งได้ด้วย
- เมื่อติดตั้งปลั๊กอิน จะสามารถเพิ่ม language model หรือ embedding model ใหม่ได้
- ปลั๊กอิน
llm-sentence-transformersเป็นปลั๊กอินที่ครอบไลบรารี SentenceTransformers- สามารถดาวน์โหลดโมเดล
all-MiniLM-L6-v2จาก Hugging Face มาใช้แบบโลคัลได้ - คำสั่ง
llm embedแสดงผลประโยคหนึ่งประโยคเป็นอาร์เรย์ตัวเลข JSON
- สามารถดาวน์โหลดโมเดล
- embedding ในรูปอาร์เรย์ตัวเลขเดี่ยว ๆ ไม่ได้มีความหมายมากนัก จะมีประโยชน์เมื่อบันทึกไว้แล้วนำไปเปรียบเทียบ
llm embed-multiสามารถทำ embedding ให้คอนเทนต์หลายรายการในครั้งเดียวและเก็บไว้ในตาราง SQLite ที่เรียกว่า collection- คำสั่งตัวอย่างค้นหาไฟล์
README.mdทั้งหมดใต้โฮมไดเรกทอรี แล้วเก็บไว้ใน collectionreadmes - ตัวเลือก
--storeเก็บข้อความต้นฉบับไว้ในตาราง SQLite ด้วย - ผลลัพธ์คือไฟล์
README.md16,796 ไฟล์ถูกบันทึก และใช้เวลาประมาณ 30 นาทีบนคอมพิวเตอร์โลคัล
- คำสั่งตัวอย่างค้นหาไฟล์
Semantic search และ “vibes-based search”
- คำสั่ง
llm similarค้นหารายการที่คล้ายกับประโยคอินพุตจาก collection ของ embedding ที่บันทึกไว้ - เมื่อนำประโยค
sqlite backup toolsไปค้นหา collectionreadmesผลลัพธ์อันดับต้น ๆ จะเป็น README ของโปรเจกต์เกี่ยวกับการแบ็กอัป SQLite หรือโปรเจกต์ที่เกี่ยวข้อง เช่นsqlite-diffable,sqlite-dump,sqlite-generate,sqlite-history,sqlite-utils - ไม่มีการรับประกันว่าเอกสารผลลัพธ์จะมีคำว่า “backups” อยู่โดยตรง
- หากคอนเทนต์ คล้ายกันทางความหมาย กับคำค้น ก็อาจปรากฏเป็นผลลัพธ์ได้
- วิธีนี้คือ semantic search และในต้นฉบับเรียกว่า vibes-based search
- การตรงกันของข้อความอย่างแม่นยำเพียงอย่างเดียวไม่สามารถช่วยให้ผู้ใช้ค้นพบสิ่งที่ต้องการได้เสมอไป จึงมีประโยชน์กับ search engine สำหรับคอนเทนต์หลากหลายประเภท
Embedding โค้ด: Symbex และ Datasette
- Symbex เป็นเครื่องมือสำหรับสำรวจ symbol ใน codebase Python
- สร้างขึ้นเพื่อค้นหา function และ class ของ Python ได้อย่างรวดเร็วแล้วส่งต่อให้ LLM
- ต่อมาสามารถคำนวณ embedding ของ function ทั้งหมดใน codebase เพื่อสร้าง search engine สำหรับโค้ดได้
- Symbex สามารถแสดง symbol ที่พบเป็น JSON หรือ CSV และฟอร์แมตนั้นสามารถใช้เป็นอินพุตของ
llm embed-multiได้ - ตัวอย่างการทำ embedding ให้ function และ class method ทั้งหมดของโปรเจกต์ Datasette ใช้โมเดล gte-tiny
gte-tinyเป็นไฟล์ขนาด 60MBsymbex '*' '*:*' --nlแสดง function และ class method ในไดเรกทอรีปัจจุบันเป็น newline-delimited JSONllm embed-multi ... --format nlรับเอาต์พุตนั้นเป็นอินพุตโดยตรงเพื่อทำ embedding
- หลังจากนั้นใช้ Datasette และปลั๊กอิน datasette-llm-embed เพื่อรัน semantic search สำหรับโค้ดด้วย SQL ได้
- SQLite ถูกใช้เป็น จุดรวมศูนย์ ที่เชื่อมเครื่องมือหลายตัวเข้าด้วยกัน
- ดึง function ออกจากโค้ด
- ส่งผ่านโมเดล embedding
- บันทึกผลลัพธ์ลง SQLite
- ค้นหาด้วย SQL
ใช้ CLIP ทำ embedding ข้อความและรูปภาพในสเปซเดียวกัน
- CLIP เป็นโมเดลที่ OpenAI เปิดตัวในเดือนมกราคม 2021 ซึ่งสามารถทำ embedding ได้ทั้งข้อความและรูปภาพ
- จุดสำคัญคือการนำข้อความและรูปภาพเข้าไปอยู่ใน เวกเตอร์สเปซเดียวกัน
- ตำแหน่ง embedding ของสตริง “dog” และตำแหน่ง embedding ของรูปสุนัขจะอยู่ใกล้กันในสเปซเดียวกัน
- สามารถใช้ข้อความค้นหารูปภาพที่เกี่ยวข้อง หรือใช้รูปภาพค้นหาข้อความที่เกี่ยวข้องได้
- เดโม CLIP ที่รันในเบราว์เซอร์ สร้างเป็น Observable notebook และรันโมเดล CLIP ภายในเบราว์เซอร์
- หน้าเว็บโหลดทรัพยากร 158MB
- โมเดลข้อความของ CLIP มีขนาด 64.6MB และโมเดลรูปภาพมีขนาด 87.6MB
- มีตัวอย่างการคำนวณคะแนน similarity ต่อข้อความต่าง ๆ สำหรับภาพชายหาด
beach: 26.946%city: 19.839%sunshine: 24.146%california beach: 27.427%
- สิ่งสำคัญไม่ใช่แค่การถาม similarity ระหว่างรูปภาพใด ๆ กับคำหนึ่งคำ แต่คือการสร้างอินเทอร์เฟซค้นหาไว้บนสิ่งนั้น
Faucet Finder: การค้นหารูปภาพด้วย CLIP
- Faucet Finder เป็นเครื่องมือค้นหาแบบเฉพาะทางสำหรับค้นหารูปก๊อกน้ำในห้องน้ำ
- Drew Breunig รวบรวมรูปก๊อกน้ำ 20,000 รูปจากซัพพลายเออร์ก๊อกน้ำ และคำนวณ CLIP embedding
- การใช้งานใช้ LLM และปลั๊กอิน llm-clip
- deploy ด้วย Datasette
- เครื่องมือนี้ช่วยค้นหาก๊อกน้ำอื่นที่มีลักษณะคล้ายกับก๊อกน้ำบางรุ่นได้
- หากชอบก๊อกน้ำราคาแพง ก็สามารถหาตัวเลือกที่ถูกกว่าซึ่งมีลักษณะคล้ายกันได้
- เดโมของ Drew ใช้ embedding ที่คำนวณไว้ล่วงหน้า จึงแสดงผลลัพธ์ที่คล้ายกันได้โดยไม่ต้องรันโมเดล CLIP บนเซิร์ฟเวอร์
- ต่อมามีการ deploy โมเดล CLIP ฝั่งเซิร์ฟเวอร์บน Fly.io และสร้างเดโม Observable notebook ที่ผสาน API embedding สตริงข้อความกับ API ตาราง embedding ของก๊อกน้ำ
- สามารถค้นหารูปก๊อกน้ำแบบอิงความหมายด้วยคำค้นอย่าง “gold purple” ได้
Clustering และการแสดงภาพ 2D
- นอกจากการแนะนำคอนเทนต์ที่เกี่ยวข้องและ semantic search แล้ว embedding ยังใช้กับ clustering ได้
- llm-cluster เป็นปลั๊กอินที่ใช้ sklearn.cluster ของ scikit-learn เพื่อทำ clustering
- สามารถใช้ GitHub issues API และ paginate-json เพื่อสร้าง collection
llm-issuesจากชื่อ issue ของ repositorysimonw/llmแล้วสร้าง 10 cluster ได้ - ตัวเลือก
llm cluster llm-issues 10 --summaryส่งข้อความของ cluster ไปให้ LLM เพื่อสร้างชื่อที่สื่อความหมาย- ตัวอย่างชื่อ ได้แก่ “Log Management and Interactive Prompt Tracking”, “Continuing Conversation Mechanism and Management”
- สเปซมิติสูงแสดงภาพได้ยาก จึงสามารถลดมิติด้วย principal component analysis (PCA)
- Matt Webb สร้าง embedding จากคำอธิบายตอนของพอดแคสต์ BBC
In Our Timeด้วย OpenAI embedding แล้วสร้างภาพ 2D ด้วย PCA - แม้ลดจาก 1,536 มิติเหลือ 2 มิติ ตอนที่เกี่ยวกับสงครามในประวัติศาสตร์หรือการค้นพบทางวิทยาศาสตร์สมัยใหม่ก็ยังปรากฏอยู่ใกล้กัน
- Matt Webb สร้าง embedding จากคำอธิบายตอนของพอดแคสต์ BBC
จำแนกประโยคด้วยตำแหน่งเฉลี่ย
- embedding ยังใช้กับการจำแนกประเภทได้
- ขั้นแรกคำนวณตำแหน่งเฉลี่ยของกลุ่ม embedding ที่ถูกจำแนกด้วยวิธีหนึ่งไว้ก่อน
- จากนั้นเปรียบเทียบว่า embedding ของคอนเทนต์ใหม่อยู่ใกล้ตำแหน่งใดมากกว่า เพื่อกำหนดหมวดหมู่
- Getting creative with embeddings ของ Amelia Wattenberger เป็นกรณีให้คะแนนว่าประโยคเป็นรูปธรรมมหรือนามธรรมเพียงใด
- สร้างตัวอย่างประโยคที่เป็นรูปธรรมและนามธรรม แล้วคำนวณตำแหน่งเฉลี่ยของแต่ละกลุ่ม
- ประโยคใหม่จะได้คะแนนตามตำแหน่งที่อยู่ใกล้ระหว่างตำแหน่งเฉลี่ยทั้งสอง
- คะแนนนี้ยังสามารถแปลงเป็นสีที่สื่อแบบคร่าว ๆ ว่าประโยคนั้นนามธรรมหรือรูปธรรมเพียงใด
RAG: Q&A จากเอกสารส่วนตัวและเอกสารภายในองค์กร
- ผู้ที่เคยใช้ ChatGPT มักสงสัยว่าจะทำให้ตอบคำถามโดยอิงโน้ตส่วนตัวหรือเอกสารภายในบริษัทได้อย่างไร
- คำตอบอาจไม่ใช่การฝึกโมเดล custom ราคาแพง แต่เป็นการผสาน LLM สำเร็จรูปกับ retrieval-augmented generation (RAG)
- ขั้นตอนพื้นฐานของ RAG นั้นเรียบง่าย
- ผู้ใช้ถามคำถาม
- ค้นหาคอนเทนต์ในเอกสารส่วนตัวที่ดูเกี่ยวข้องกับคำถาม
- ใส่ข้อความคัดตอนที่เกี่ยวข้องและคำถามเดิมเข้าไปใน prompt โดยรักษาข้อจำกัดด้านขนาดของ LLM
- LLM ตอบโดยอิงจากคอนเทนต์เพิ่มเติมที่ให้มา
- ข้อจำกัดด้านขนาดโดยทั่วไปอยู่ในระดับ 3,000~6,000 คำ
- ส่วนที่ยากของ RAG คือการค้นหาข้อความคัดตอนที่ดีที่สุดสำหรับใส่ใน prompt
- semantic search ที่อิง embedding เหมาะสำหรับรวบรวมคอนเทนต์ที่มีแนวโน้มเกี่ยวข้องสูง
ทำ Q&A แบบออฟไลน์จากบล็อกด้วย E5-large-v2
- ตัวอย่าง RAG ที่อิงคอนเทนต์บล็อกใช้ E5-large-v2
- ประโยคคำถามและคำตอบมีไวยากรณ์ต่างกัน คำถามจึงไม่ได้ถูกจับว่าใกล้ทางความหมายกับเอกสารที่มีคำตอบเสมอไป
- E5-large-v2 รองรับคอนเทนต์สองประเภท
- factual sentence ทำ embedding เป็น phrase
- question ทำ embedding เป็น query
- คล้ายกับวิธีที่ CLIP นำรูปภาพและข้อความเข้าไปไว้ในสเปซเดียวกัน
- ทำ embedding ให้ 19,000 ย่อหน้าของบล็อกเป็น phrase และทำ embedding ให้คำถามเป็น query เพื่อค้นหาย่อหน้าที่ใกล้กับคำตอบ
- ตัวอย่างนี้ทำ RAG ด้วยสคริปต์ Bash หนึ่งบรรทัด
- ใช้
llm similarค้นหาย่อหน้าที่เกี่ยวข้อง - ใช้
jqดึงคอนเทนต์ - ส่งคำถามและย่อหน้าไปยังโมเดล Llama 2 Chat 7B ที่รันบนโน้ตบุ๊กโลคัล
- ใช้
- สำหรับคำถาม
What is shot-scraper?ระบบสร้างคำตอบว่าshot-scraperเป็นยูทิลิตี Python ที่ครอบ Playwright และทำให้การจับภาพหน้าจอเว็บเพจและการ scrape ด้วย JavaScript เป็นอัตโนมัติผ่าน command-line interface และ workflow การตั้งค่าด้วย YAML - คำตอบที่สร้างขึ้นไม่ได้ตรงกับประโยคเดิมในคอนเทนต์บล็อกแบบเป๊ะ ๆ
ตัวเลือกที่ปรับแต่งได้ในการใช้งานจริง
- LangChain เป็นเฟรมเวิร์กสำหรับสร้างฟังก์ชันบน LLM และ RAG เป็นหนึ่งในฟังก์ชันหลักของ LangChain
- สามารถสร้างฟังก์ชันเดียวกันบน LangChain ได้ แต่ต้องลงทุนอย่างมากในการทำความเข้าใจ LangChain
- ที่นี่เลือกใช้ชุดเครื่องมือขนาดเล็กที่นำมาประกอบกัน มากกว่าเฟรมเวิร์กเดียวที่แก้ทุกอย่าง
- ฟังก์ชันระยะทางใช้ cosine similarity เป็นค่าเริ่มต้น
- ยังไม่ได้ลองฟังก์ชันระยะทางอื่น
- RAG มีองค์ประกอบที่ปรับได้หลายอย่าง เช่น ฟังก์ชันระยะทาง โมเดล embedding กลยุทธ์ prompt และ LLM
- ตัวอย่างเหล่านี้มีขนาดสูงสุดประมาณ 20,000 embedding และในระดับนี้ยังสามารถคำนวณ brute force cosine similarity กับทั้งหมดแล้วได้ผลลัพธ์ในเวลาที่สมเหตุสมผล
- สำหรับข้อมูลที่ใหญ่กว่า เช่น วัตถุ 1 พันล้านรายการ vector database หรือส่วนขยายของฐานข้อมูลที่มีอยู่เป็นตัวเลือกหนึ่ง
- SQLite มี sqlite-vss
- PostgreSQL มี pgvector
- FAISS ของ Facebook ก็ถูกใช้ในการทดลอง และมีปลั๊กอิน Datasette ที่ใช้งานสิ่งนี้คือ datasette-faiss
- แนวโน้มที่คาดหวังในอนาคตคือ multimodal model และโมเดลที่เล็กลง
- Facebook ImageBind ฝึก joint embedding ของ 6 modality ได้แก่ รูปภาพ ข้อความ เสียง ความลึก ความร้อน และข้อมูล IMU
- โมเดลที่เล็กลงอย่าง
gte-tinyขนาด 60MB เพิ่มความเป็นไปได้ในการรันบนอุปกรณ์จำกัดหรือในเบราว์เซอร์
อ่านเพิ่มเติม
- What are embeddings? by Vicki Boykis
- Text Embeddings Visually Explained by Meor Amer for Cohere
- The Tensorflow Embedding Projector: เครื่องมืออินเทอร์แอคทีฟสำหรับสำรวจสเปซ embedding
- Learn to Love Working with Vector Embeddings: รวมบทเรียนเกี่ยวกับ vector embedding จาก Pinecone
1 ความคิดเห็น
ความเห็นจาก Hacker News
หลังจากโพสต์บทความนี้ไป ก็เจอแหล่งข้อมูลเพิ่มอีกไม่กี่ชิ้นที่ช่วยให้ เข้าใจ embedding ในระดับที่ลึกขึ้น
บทความของผมตั้งใจเขียนให้อยู่ในระดับสูงมาก โดยเน้นการประยุกต์ใช้งานเป็นหลัก
Text Embeddings Visually Explained ของ Cohere: https://txt.cohere.com/text-embeddings/
เครื่องมือ Tensorflow Embedding Projector: https://projector.tensorflow.org/
What are embeddings? ของ Vicki Boykis ก็น่าอ่านเช่นกัน: https://vickiboykis.com/what_are_embeddings/
กำลังจะเพิ่มไว้ในส่วน “further reading” ด้านล่างของหน้า
ใช้ embedding เพื่อเพิ่ม engagement ของบทความที่เกี่ยวข้อง และส่วนตัวมองว่า embedding เป็นเครื่องมือทรงพลังที่ถูกประเมินค่าต่ำเกินไป
มันใช้สำรวจระหว่างเอกสารหรือข้อความคัดย่อด้วยความคล้ายคลึงกันได้ หรือจะใช้หาเนื้อหาที่มีความโดดเด่นแตกต่างก็ได้ และค่อนข้าง “ปลอดภัย” เพราะไม่ต้องกังวลเรื่อง hallucination
วิธีที่ embedding ถูกสร้างขึ้นก็อาจน่าสนใจเช่นกัน ตัวอย่างเช่นแนวทางแบบ ตัดชั้นการจัดหมวดหมู่ทิ้งหลังการฝึก หรือแนวทางอย่าง EfficientNet
มันกำลังกลายเป็นรากฐานสำคัญของ machine learning
ใน computer vision และอัลกอริทึม visual SLAM นั้น embedding ได้กลายเป็นวิธีมาตรฐานโดยพฤตินัยสำหรับการรู้จำสถานที่ และคล้ายกับเนื้อหาในบทความนี้มาก
เรียกว่า “bag-of-word place recognition” และทุกวันนี้ถูกใช้ในไลบรารีโอเพนซอร์สแทบทั้งหมด
แกนหลักคือส่งแต่ละภาพผ่าน pipeline การดึงคุณลักษณะและตัวบรรยาย เพื่อ “ฝัง” ภาพนั้นเป็นเวกเตอร์ที่บรรจุคุณลักษณะเด่น N อันดับแรก
ระหว่างที่กล้องเคลื่อนที่ ระบบจะสร้างฐานข้อมูลภาพที่เรียกว่า keyframe และภาพจะถูกเก็บเป็นเวกเตอร์ที่มีมิติต่ำกว่ามาก
จากนั้นจึง query ฐานข้อมูลด้วยภาพทั้งหมด และหาคู่ที่ตรงที่สุดจากฐานข้อมูลเวกเตอร์ด้วยวิธีอย่าง cosine similarity
ถ้ามีการจับคู่ ก็สามารถคำนวณ stereo constraint ระหว่างภาพ query กับภาพที่จับคู่ เพื่ออัปเดตแผนที่ได้
งานวิจัยต้นฉบับคือ [1] และ implementation ที่มีชื่อเสียงที่สุดคือ https://github.com/dorian3d/DBoW2
[1]: https://www.google.com/search?client=firefox-b-d&q=Bags+of+B...
เป็น เอกสารอ้างอิงสำหรับผู้เริ่มต้น ที่ยอดเยี่ยม
ก่อนหน้านี้ผมเคยทำแอปโน้ตบน iOS เอง และการเพิ่ม embedding เข้าไปในระบบ full-text search เดิมนั้น 1) ง่ายอย่างน่าประหลาด และ 2) ทรงพลังมากกว่าที่คาดไว้ตอนแรกมาก
ตอนค้นหา “dog” ผมก็รู้อยู่แล้วว่าน่าจะเจอโน้ตที่มีคำว่า “canine” ด้วย แต่เพิ่งมาเข้าใจจริง ๆ ตอนลองค้นหาประมาณว่า “สัตว์เลี้ยงที่ฉันน่าจะชอบ” แล้วพบว่ามันดึงโน้ตเกี่ยวกับสัตว์หลายรายการที่มีอารมณ์เชิงบวกออกมาได้
นั่นเป็นช่วงเวลา “อ๋อ!” ครั้งใหญ่ครั้งแรกของผม
ตอนนั้น PR ของ DocsGPT จาก Supabase มีประโยชน์มากในฐานะโค้ดตัวอย่าง: https://github.com/supabase/supabase/pull/12056
แอปจำนวนมากพึ่งพาชื่อหรือคำนามเฉพาะอย่างมาก และหลายครั้งก็มีบริบทไม่เพียงพอ
ถ้าเรียกสุนัขเลี้ยงด้วยชื่ออย่างเดียวโดยไม่มีคำอธิบาย โมเดล embedding บางตัวอาจจับสิ่งนี้ไม่ได้
คำนามเฉพาะอย่างชื่อคน สถานที่ หรือชื่อถนน อาจสำคัญมากต่อการทำให้การค้นหาแบบ personalized หรือเฉพาะโดเมนใช้งานได้จริง แต่โมเดลภาษาทั่วไปไม่รู้สิ่งเหล่านี้
สงสัยว่ามีวิธีที่เป็นรูปธรรมในการจัดการปัญหานี้หรือไม่
ตอนนี้คำถามใหญ่ที่สุดคือจะสร้าง หนึ่ง embedding จากข้อความมากแค่ไหน
ควรทำเป็นรายประโยค หรือรวมทั้งบล็อกของประโยคที่อยู่ในหนึ่งหน้าของแอปโน้ตเป็นก้อนเดียวดี
ตัวอย่างคลาสสิกของ word embedding คือ King - Man + Woman = Queen
ในปริภูมิเวกเตอร์มันทำงานได้ดี แต่พอฉายลงมาเป็น 2 มิติแล้วกลับมองภาพตามได้ไม่ค่อยชัด
จากประสบการณ์ของผม PCA, MDS และ t-SNE ก็เป็นแบบเดียวกันทั้งหมด: https://bhugueney.gitlab.io/test-notebooks-org-publish/jupyt...
นี่คือ JupyterLite Notebook ที่ทำ word embedding ในเบราว์เซอร์ และไม่แนะนำให้รันบนสมาร์ตโฟน
อยากรู้ว่ามีวิธีไหนบ้างในการทำ visualization ของตัวอย่าง word embedding แบบคลาสสิกให้อ่านง่าย
ถ้าอยากให้ตั้งฉากกันจริง ๆ ก็ใช้ Gram-Schmidt ได้
ใน 3 มิติสามารถเพิ่มแกน Z เป็น “king”-“queen” ได้อีกแกน และเวอร์ชันที่ทำให้ตั้งฉากจะใกล้กับแนวคิดเรื่องระยะทางที่โมเดลมองเห็นมากกว่า
ใน 2 มิติ ถึงจะไม่สามารถแสดงได้ว่าเมื่อคำนวณ “king”-“man”+“woman” แล้วมันคลาดจาก “queen” ไปมากแค่ไหน แต่ระยะอื่น ๆ ที่เหลือยังได้อย่างถูกต้อง
ใน 3 มิติน่าจะให้ระยะทางที่ถูกต้องได้
ปกติแล้ว “queen” ถูกเลือกเพราะเป็นคำที่มี embedding ใกล้กับ X="king"-"man"+"woman" มากที่สุด
ในกราฟ 2 มิติอาจแสดงคำที่ใกล้ถัดมาอีกสักสองสามคำ และใส่ค่าระยะตั้งฉากจากระนาบ 2 มิติให้แต่ละคำด้วย
แบบนั้น “queen” ก็ควรเป็นคำที่มีผลรวมของระยะยกกำลังสองจาก X และระยะตั้งฉากยกกำลังสองจากระนาบน้อยที่สุด จึงพอดูด้วยตาเปล่าได้ระดับหนึ่ง
ประมาณว่า “4 มิติไม่สามารถทำ visualization ได้… อย่างน้อยผมก็ทำไม่ได้ เพราะผมมี brane แค่สามอัน” เป็นการเล่นคำระหว่าง branes กับ brains
ภายหลัง ChatGPT ก็ยอมรับว่ามันแต่งขึ้นเองและขอโทษ
จากนั้นมันยังยกคำพูดของ John von Neumann, H. G. Wells และ Ian Stewart มาอีก และปิดท้ายด้วยคำตอบประมาณว่า “ถ้าจะทำ visualization ของ 4 มิติ ก็ให้ทำ visualization ของ 3 มิติก่อนแล้วพูดว่า ‘n+1’” ซึ่งคล้ายมุกที่ผมจำได้มากที่สุด แต่ตลกน้อยกว่า
เลยลองให้มันแต่งคำคมหลอน ๆ แบบ Deepak Chopra เกี่ยวกับการทำ visualization ของปริภูมิหลายมิติ ผลคือมันปล่อยคำคมปลอมที่ฟังดูน่าเชื่อถือออกมาเพียบ โดยปนคำอย่าง septillion-dimensional embeddings, Hilbert space, Poincaré conjecture, Heisenberg uncertainty principle และ Shannon entropy เข้าไป
ความผิดพลาดที่พบบ่อยในตรีโกณมิติภาคปฏิบัติคือการคำนวณ รากที่สอง ทั้งที่ไม่จำเป็น
ในโค้ดตัวอย่าง
magnitude_a = sum(x * x for x in a) * 0.5และmagnitude_b = sum(x * x for x in b) * 0.5ไม่จำเป็นต้องมี*0.5ถ้าแค่จะเปรียบเทียบค่า cosine ก็เปรียบเทียบค่าที่ยกกำลังสองไว้ได้เลย จึงหลีกเลี่ยงการคำนวณรากที่มีต้นทุนสูงได้
คล้ายกัน ใน elliptic curve cryptography ก็จะพยายามเลื่อนการคำนวณที่แพงอย่างการหา inverse ออกไปให้นานที่สุด หรือถ้าแค่ต้องเปรียบเทียบสองจุด บางครั้งก็เลี่ยงการคำนวณค่า canonical ไปเลย
ถ้าไม่ใช่แบบนั้นก็คงแทนที่ด้วย โค้ด SIMD ระดับล่างไปแล้ว
dot_product = sum(x * y for x, y in zip(a, b))แบบนี้เหรอ ทำไมไม่ใช้ การคำนวณแบบเวกเตอร์ของ numpy ก็แอบสงสัยแต่พอเห็นว่ามีประโยคว่า “ให้ ChatGPT เขียนโค้ด cosine similarity หลายเวอร์ชัน” ก็เข้าใจเลย
ข้อแรก เวลาจะอธิบายให้คนอื่นฟัง รู้สึกว่าไวยากรณ์ของ numpy กลับทำให้เข้าใจยากขึ้น
ข้อสอง numpy ไม่ใช่ dependency ที่เบาที่สุด
ถ้าต้องการประสิทธิภาพก็จะใช้ แต่มันไม่อยากให้เป็นตัวเลือกตั้งต้น
ถ้าอยากดู Show HN, สตาร์ตอัปจาก ProductHunt, บริษัท YC หรือ GitHub repository ที่เกี่ยวกับ LLM embeddings สามารถหาได้อย่างรวดเร็วใน LLM-Embeddings-Based Search Engine MVP ที่เพิ่งเปิดตัว
https://payperrun.com/%3E/search?displayParams={%22q%22:%22L...
ผมคาดว่าถ้ากด ปุ่มฟิลเตอร์ หลายปุ่ม ผลการค้นหาจะอัปเดตทันที และไม่คิดว่าจะต้องค้นหาใหม่
เข้าใจได้ว่าทำไมถึงออกแบบแบบนั้น
นี่น่าสนใจที่สุดในบรรดาสิ่งที่ผมอ่านเกี่ยวกับ “AI” ในช่วงไม่กี่เดือนที่ผ่านมา
ทุกครั้งที่เห็น embedding model ในรายการก็สงสัยมาตลอดว่ามันคืออะไร และก็สงสัยด้วยว่าทำไมทุกคนถึงพูดถึง vector DB กันหมด
มันทำให้ผมนึกวิธีนำไปใช้กับ side project ที่ทำค้างมานานได้ทันที
ถ้าทุกเอกสารมี embedding หมด การจัดกลุ่มข้อมูลผู้ใช้แบบที่มีประโยชน์อาจกลายเป็นสิ่งที่ทำได้จริง
อยากรู้ว่ามีใครเคยใช้ เพื่อนบ้านใกล้เคียงโดยประมาณ และการทำคลัสเตอร์กับเอมเบดดิงในงานอื่นบ้างไหม
ความเป็นไปได้ที่นึกออกคือการฉายภาพลงบนแกนตามอำเภอใจ การทำดัชนี และการจัดเรียง เช่นแกนอย่าง “ร้อน-เย็น”, “สุข-เศร้า”, “SF-สัจนิยม”, “เชิงวรรณศิลป์-เชิงพาณิชย์”
นอกจากการทำการจัดประเภทแบบ SVM ในปริภูมิเอมเบดดิง การทำอนุมานแบบ word2vec อย่าง woman-man+king=queen หรือการดึงหนึ่งเลเยอร์ของ LLM ออกมาแล้ว ก็น่าจะมีวิธีเรียนรู้เอมเบดดิงโดยตรงได้ด้วย
รู้ว่ามีการใช้การเรียนรู้เชิงเปรียบเทียบอยู่ แต่ก็ดูเหมือนว่ายังน่าลองสำรวจวิธีอื่น เช่น เรียนรู้เอมเบดดิงร่วมกับเครือข่ายประสาทสำหรับฟังก์ชัน แล้วสร้างสมการฟังก์ชันเพื่อคำนวณค่า loss แบบ mean squared error
น่าแปลกที่ดูเหมือนจะโฟกัสกับการค้นหาเชิงความหมายมากเกินไป และน่าจะมีการประยุกต์ใช้อื่นที่น่าสนใจอีกแน่
อย่างแรกกับอย่างที่สามจริง ๆ แล้วแทบจะเป็นเรื่องเดียวกัน
ในคอมพิวเตอร์วิทัศน์ เราอาจอยากเปลี่ยนภาพในเชิงความหมาย เช่น เพิ่มแว่นตาให้รูปภาพ และงานที่เห็นในโฆษณา Google ก็เป็นตัวอย่างของสิ่งนี้
งานแบบนี้ทำกันใน ปริภูมิแฝง
ใน normalizing flow จะชัดเป็นพิเศษ เพราะมันแปลงปริภูมิให้เป็นแบบเกาส์เซียน
โมเดล diffusion ก็ทำสิ่งคล้ายกันด้วยวิธีประมาณ แต่ไม่ผันกลับได้ แม้ว่าจะย้อนกลับได้
เราฉายภาพ ประโยค หรือข้อมูลที่อยากปรับแต่งเข้าไป แล้วจัดการมันในปริภูมิเกาส์เซียน ก่อนจะย้อนกลับไปยังปริภูมิเป้าหมาย
แต่อาจเป็นไปได้ว่าคำว่าเอมเบดดิงเป็นคำที่ถูกใช้ซ้อนหลายความหมายเกินไป เลยทำให้สับสนกัน
อาจกำลังนึกถึงแค่บล็อกแรกที่แปลงโทเคนจำนวนเต็มแบบไม่ต่อเนื่องให้เป็นค่าทศนิยมแบบต่อเนื่อง
แต่เอมเบดดิงนั้นก็ถูกเรียนรู้เช่นกัน ดังนั้นแม้จะกลายเป็นเหมือนตาราง lookup ก็ยังเป็นกระบวนการของโครงข่ายประสาทอยู่ดี
มีการใช้ SVM ในปริภูมินี้ด้วย
มันคล้ายกับปริภูมิแฝง แต่ดูเป็นนามธรรมกว่าเล็กน้อย
อย่างน้อยเอมเบดดิงก็ควรเป็นฟังก์ชันหนึ่งต่อหนึ่ง ตามคณิตศาสตร์น่ะนะ…
การเรียนรู้เอมเบดดิงโดยตรงก็คือโมเดลเอมเบดดิงดั้งเดิมอย่าง Word2Vec ตามตัวอักษรเลย
พบรูปแบบการเขียนที่หลากหลายและคำย่อจำนวนมาก เช่น การใส่ขีดกลาง ไม่ใส่ขีดกลาง หรือเว้นวรรคในชื่อทางเคมีและชีวเคมี
บางทีอาจสร้างพจนานุกรมคำศัพท์เทคนิคได้ด้วย
ไม่แน่ใจว่าจะไปได้ไกลถึงระดับคำนิยามแค่ไหน แต่ถึงเวกเตอร์อย่างเดียวจะมีข้อจำกัด มันก็ยังเป็นจุดตั้งต้นได้
มีความเป็นไปได้สูงที่คนอื่นก็เคยสร้างพจนานุกรมด้วยวิธีแบบนี้เช่นกัน
ผมเคยลองเล่นกับเอมเบดดิงและทำ use case ระดับโปรดักชันมาบ้าง มันเป็นเครื่องมือที่ยอดเยี่ยมและเปิดทางให้กับการประยุกต์ใช้เจ๋ง ๆ ได้มากมาย
แต่พอทำในโดเมนเฉพาะ ก็จะชนกับข้อจำกัดของโมเดลเอมเบดดิงสำเร็จรูป
โมเดลสำเร็จรูปมีมิติจำนวนมาก แต่บางมิติสำคัญกับการจัดประเภท ความคล้ายของคอนเทนต์ หรือการทำคลัสเตอร์ในแอปพลิเคชันของผม ขณะที่บางมิติไม่สำคัญ
พูดอีกอย่างคือ เวกเตอร์สองตัวอาจดูใกล้กันเพราะอยู่ใกล้กันในมิติที่เราไม่สนใจ
หวังว่าจะมีเครื่องมือและงานเขียนที่ดีกว่านี้สำหรับ การปรับจูนละเอียดโมเดลเอมเบดดิง
เครื่องมือแบบนี้มีมานานแล้ว เช่น ติดป้ายกำกับข้อมูลสักเล็กน้อย แล้วฝึก SVM สำหรับการจัดประเภทบนปริภูมิเอมเบดดิง