คลังคำถามสัมภาษณ์
รวมคำถามท้ายทุกบท กรองตามหัวข้อหรือค้นหาได้
เริ่มต้น
Data Analyst ต่างจาก Data Scientist ยังไง
DA เน้นตอบคำถามธุรกิจจากข้อมูลที่มีอยู่ เช่น ยอดขายตกเพราะอะไร หรือโปรโมชันได้ผลไหม แล้วสื่อสารผลให้ทีมตัดสินใจ ส่วน Data Scientist เน้นสร้างโมเดลทำนายหรือออกแบบการทดลองที่ซับซ้อนกว่า ในหลายบริษัทสองตำแหน่งนี้มีงานทับกัน
ตอนตอบควรยกตัวอย่างงานจริงประกอบ และบอกว่าตัวเราอยากทำงานแบบไหน
เล่าขั้นตอนการวิเคราะห์ข้อมูลที่คุณเคยทำให้ฟังหน่อย
ตอบตาม 5 ขั้น โดยยกโปรเจกต์จริงหนึ่งงาน เช่น Capstone ของสายนี้ เริ่มจากคำถามธุรกิจที่ได้รับ แล้วเล่าว่าเปลี่ยนเป็นคำถามที่วิเคราะห์ได้ยังไง ใช้ข้อมูลอะไร เจอปัญหาข้อมูลสกปรกแบบไหนและแก้ยังไง ใช้วิธีวิเคราะห์อะไร และสุดท้ายผลนำไปสู่การตัดสินใจอะไร ผู้สัมภาษณ์อยากเห็นวิธีคิด ไม่ใช่แค่รายชื่อเครื่องมือ
SQL
ทำไม WHERE x = NULL ไม่เคยคืนแถวไหนเลย ต้องเขียนยังไงแทน
NULL ใน SQL แปลว่า "ไม่รู้ค่า" ไม่ใช่ค่าว่างเปล่าหรือศูนย์ การเปรียบเทียบใดๆ กับ NULL ด้วย =, <>, > ฯลฯ
จะได้ผลเป็น unknown เสมอ ไม่ใช่ true หรือ false จึงไม่มีแถวไหนผ่านเงื่อนไข WHERE x = NULL เลย
ต้องใช้ IS NULL หรือ IS NOT NULL ซึ่งเป็นตัวดำเนินการพิเศษที่ออกแบบมาสำหรับเช็ก NULL โดยเฉพาะ
อธิบายลำดับการประมวลผลจริงของ SQL query หนึ่งคำสั่ง
แม้จะเขียนตามลำดับ SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT แต่ SQL ประมวลผลจริงตามลำดับนี้: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
นี่คือเหตุผลที่ WHERE ใช้ aggregate function ไม่ได้ (ยังไม่ถึงขั้น GROUP BY) แต่ HAVING ใช้ได้ (ทำงานหลัง GROUP BY แล้ว) และทำไม ORDER BY ถึงใช้ชื่อ alias จาก SELECT ได้ (SELECT ทำงานก่อน ORDER BY)
เจอ bug ว่าตัวเลขหลัง JOIN เยอะกว่าที่ควรจะเป็น สาเหตุที่เป็นไปได้คืออะไร และแก้ยังไง
สาเหตุที่พบบ่อยที่สุดคือ fan-out: JOIN กับตารางที่มีความสัมพันธ์แบบ one-to-many (เช่น 1 ออเดอร์มีหลายรายการสินค้าใน order_items) ทำให้แถวของฝั่ง "one" ถูกคูณซ้ำตามจำนวนแถวฝั่ง "many"
วิธีตรวจสอบ: ลองนับจำนวนแถวก่อนและหลัง JOIN เทียบกัน ถ้าหลัง JOIN เพิ่มขึ้นมาก ให้สงสัยความสัมพันธ์แบบ one-to-many ก่อนเสมอ
วิธีแก้: ใช้ COUNT(DISTINCT ...) เพื่อนับไม่ซ้ำ หรือ aggregate ตารางลูกให้เป็นแถวเดียวต่อคีย์ก่อน
(เช่นด้วย subquery/CTE) แล้วค่อย JOIN
จาก JOIN ทุกแบบ
ทำไม NOT IN ถึงอันตรายเมื่อ subquery มี NULL ควรใช้อะไรแทน
NOT IN (subquery) เทียบค่าของแถวปัจจุบันกับทุกค่าที่ subquery คืนมาทีละตัวด้วย <>
ถ้าใน subquery มีแม้แต่ค่า NULL ปนอยู่ค่าเดียว การเทียบ x <> NULL จะได้ unknown เสมอ
และเมื่อรวม unknown เข้ากับผลลัพธ์อื่นด้วย AND ทั้งชุดจะกลายเป็น unknown (ไม่ผ่านเงื่อนไข) ทุกแถวไปเลย
แม้ว่าจริงๆ แถวนั้นควรจะผ่านก็ตาม
ทางแก้ที่ปลอดภัยกว่าคือใช้ NOT EXISTS แทน เพราะมันแค่เช็คว่า "มีแถวที่จับคู่ได้ไหม" ไม่ได้เทียบค่าทีละตัว
จึงไม่มีปัญหานี้ หรือถ้าจะใช้ NOT IN ต่อไป ต้องกรอง NULL ออกจาก subquery ด้วย IS NOT NULL เสมอ
จาก Subquery และ CTE
จะหา "สินค้าขายดี 3 อันดับต่อหมวด" ด้วย SQL ทำยังไง
ใช้ window function (มักเป็น RANK หรือ ROW_NUMBER) พร้อม PARTITION BY ตามหมวดสินค้า
เรียงตามยอดขายจากมากไปน้อยในแต่ละกลุ่ม แล้วห่อ query นั้นด้วย subquery อีกชั้น
เพื่อกรอง WHERE rnk <= 3 (ใช้ RANK ไม่ใช้ ROW_NUMBER ถ้าอยากให้สินค้าที่ยอดขายเท่ากันติดอันดับพร้อมกัน)
รูปแบบนี้เป็น pattern มาตรฐานสำหรับโจทย์ "top-N ต่อกลุ่ม" ทุกแบบ ไม่ใช่แค่สินค้าขายดี
จาก Window Functions
จะเปรียบเทียบยอดขายแบบเดือนต่อเดือน (MoM) ข้ามปีให้ถูกต้องต้องทำยังไง
ต้องแยกปีออกจากกันเสมอ ไม่ใช่ GROUP BY แค่เลขเดือนจาก EXTRACT(month...) เพราะจะรวมเดือนเดียวกัน
จากคนละปีเข้าด้วยกันโดยไม่ตั้งใจ วิธีที่ถูกต้องมีสองแบบ: (1) ใช้ DATE_TRUNC('month', date_col)
ซึ่งได้ค่าที่เก็บทั้งปีและเดือนไว้ในตัว (เช่น '2024-03-01') หรือ (2) GROUP BY ทั้ง year และ month แยกกัน
ทั้งสองวิธีทำให้เดือนของแต่ละปีถูกนับแยกกันอย่างถูกต้อง
ระหว่างทำโจทย์ SQL สดในห้องสัมภาษณ์ ควรอธิบายความคิดยังไงให้ผู้สัมภาษณ์ตามทัน
เริ่มจากพูดสรุปสั้นๆ ว่าเข้าใจโจทย์ว่ายังไง แล้วถามกลับถ้ามีจุดที่ไม่ชัดเจน (เช่น "นับรวมออเดอร์ที่ยกเลิกด้วยไหม") จากนั้นเล่าแผนคร่าวๆ ก่อนเริ่มเขียน (เช่น "ผมจะ join ตาราง A กับ B ก่อน แล้วค่อย group by") ระหว่างเขียนโค้ด พูดเหตุผลของแต่ละขั้นออกมา ไม่ใช่แค่พิมพ์เงียบๆ และถ้าเขียนแบบง่ายได้ผลลัพธ์คร่าวๆ ก่อน ค่อยบอกว่าจะปรับปรุงยังไงต่อ (เช่น เพิ่มเงื่อนไข หรือแก้ปัญหา edge case) ก็เป็นการแสดงกระบวนการคิดที่ดี
ยกตัวอย่างวิธีหา "อันดับที่ N" โดยไม่ใช้ LIMIT/OFFSET พร้อมอธิบายว่าทำไมบางบริษัทถามแบบนี้
ตัวอย่าง: หาพนักงานที่เงินเดือนสูงเป็นอันดับ 2 — ใช้ DENSE_RANK() OVER (ORDER BY salary DESC) แล้วห่อ
ด้วย subquery กรอง WHERE rnk = 2 (เลือก DENSE_RANK ไม่ใช่ RANK เพราะถ้าเงินเดือนสูงสุดซ้ำกันหลายคน
RANK จะข้ามอันดับ 2 ไปเลย)
บริษัทถามแบบนี้เพราะ LIMIT/OFFSET เป็นเพียง syntax เฉพาะของบางฐานข้อมูล และไม่ได้บอกว่าเข้าใจแนวคิด เรื่องการจัดอันดับข้อมูลจริงๆ — การห้ามใช้ LIMIT/OFFSET บังคับให้ต้องคิดด้วย window function หรือ subquery ซึ่งเป็นทักษะที่ใช้แก้ปัญหาที่ซับซ้อนกว่านี้ได้ด้วย
เจอผลลัพธ์หลัง JOIN ที่ดูเยอะเกินจริง ควรตรวจสอบอะไรก่อน
ให้สงสัยปัญหา fan-out ก่อนเป็นอันดับแรก (ทบทวนจากบทที่ 3) — เกิดเมื่อ JOIN กับตารางที่มีความสัมพันธ์ แบบ one-to-many เช่น 1 ออเดอร์มีหลายรายการสินค้า ทำให้แถวของฝั่ง "one" ถูกคูณซ้ำ
วิธีตรวจสอบเร็วๆ:ลองนับจำนวนแถวก่อน JOIN เทียบกับหลัง JOIN ถ้าต่างกันมาก ให้ดูว่า JOIN
กับตารางไหนที่อาจมีหลายแถวต่อ 1 คีย์ แล้วแก้ด้วย COUNT(DISTINCT ...) บนคีย์ที่ไม่อยากนับซ้ำ
หรือ aggregate ตารางลูกให้เหลือแถวเดียวต่อคีย์ก่อน (ด้วย subquery/CTE) แล้วค่อย JOIN
pandas
ได้ไฟล์ข้อมูลใหม่มาครั้งแรก ควรดูอะไรก่อนเริ่มวิเคราะห์
เริ่มจากดูภาพรวมของโครงสร้างก่อน: shape (มีกี่แถวกี่คอลัมน์), dtypes (แต่ละคอลัมน์เป็นชนิดข้อมูลอะไร),
head() (ตัวอย่างข้อมูลจริง), และ describe() (สรุปสถิติของคอลัมน์ตัวเลข)
หลังจากนั้นควรเช็คคุณภาพข้อมูลคร่าวๆ ด้วย isna().sum() (มีค่าว่างไหม) และ duplicated().sum()
(มีแถวซ้ำไหม) ก่อนเริ่มวิเคราะห์จริง เพื่อรู้ล่วงหน้าว่าต้องทำความสะอาดอะไรบ้าง
ทำไมควรใช้ .loc[เงื่อนไข, คอลัมน์] = ค่า แทนการเขียน df[เงื่อนไข][คอลัมน์] = ค่า เวลาจะแก้ไขข้อมูล
คำตอบสั้นๆ ในบทนี้ (อธิบายเต็มในบทที่ 7 เรื่อง cleaning): df[เงื่อนไข] อาจได้ DataFrame ใหม่ที่เป็นแค่สำเนา
ไม่ใช่ตัวข้อมูลจริง การแก้ไขต่อจากนั้น ([คอลัมน์] = ค่า) จึงอาจไม่มีผลอะไรเลยกับตารางต้นฉบับ
โดยไม่มี error หรือ warning เตือนด้วย ทางที่ปลอดภัยเสมอคือใช้ .loc[เงื่อนไข, คอลัมน์] = ค่า ในคำสั่งเดียว
จาก .loc และ .iloc
จะกรองข้อมูลด้วยหลายเงื่อนไขใน pandas อย่างอ่านง่ายและไม่ error ทำยังไง
ใส่วงเล็บรอบแต่ละเงื่อนไขเสมอเมื่อใช้ &/|/~ (เพราะ Python ให้ตัวดำเนินการเหล่านี้มีความสำคัญสูงกว่า
==/</>) ใช้ isin() แทนเงื่อนไข == หลายอันที่เชื่อมด้วย | และใช้ between() แทนการเขียน
(col >= a) & (col <= b) เต็มรูปแบบ เมื่อเงื่อนไขซับซ้อนมากจริงๆ อาจพิจารณาใช้ .query() แทนเพื่อความอ่านง่าย
อธิบายวิธี "กรองหลังจัดกลุ่ม" ใน pandas เทียบกับ HAVING ใน SQL
SQL มี HAVING แยกจาก WHERE ชัดเจน (WHERE กรองก่อนจัดกลุ่ม, HAVING กรองหลังจัดกลุ่ม)
ส่วน pandas ไม่มีคำสั่งพิเศษสำหรับกรองหลังจัดกลุ่ม ใช้หลักการเดียวกับการกรอง DataFrame ทั่วไป
คือเอาผลลัพธ์จาก groupby(...).agg(...) หรือ .size() (ซึ่งเป็น Series/DataFrame ธรรมดา)
ไปกรองต่อด้วย boolean indexing (result[result > ค่า]) เหมือนกรองตารางทั่วไป ไม่มี syntax ใหม่ต้องเรียนรู้
จาก groupby และ agg
pandas merge() กับ SQL JOIN เหมือนหรือต่างกันยังไง
แนวคิดเดียวกันทุกประการ (how='inner'/'left'/'right'/'outer' ตรงกับ SQL JOIN แต่ละแบบ)
ต่างกันแค่ syntax เท่านั้น ปัญหา fan-out และวิธีหา "แถวที่ไม่มีคู่" ก็เหมือนกันเป๊ะ
เพราะเป็นคุณสมบัติของความสัมพันธ์ระหว่างตาราง ไม่ใช่ของภาษาใดภาษาหนึ่งโดยเฉพาะ
เมื่อไหร่ควรใช้ pivot_table แทน groupby
ใช้ pivot_table เมื่อต้องการนำเสนอผลลัพธ์เป็นตาราง "กว้าง" ที่มี 2 มิติ (แถว×คอลัมน์) พร้อมกัน
เช่น รายงานสรุปที่จะส่งให้คนอื่นอ่านหรือทำเป็น dashboard ในขณะที่ groupby เหมาะกับตอนจะเอาผล
ไปประมวลผลต่อในโค้ด (ผลลัพธ์เป็นรูปแบบยาว จัดการต่อง่ายกว่า)
เจอไฟล์ CSV ใหม่ ขั้นตอนแรกๆ ที่ควรทำเพื่อเช็คคุณภาพข้อมูลมีอะไรบ้าง
ดู shape/dtypes ก่อนเพื่อรู้ขนาดและชนิดข้อมูล ตามด้วย isna().sum() ต่อคอลัมน์ (มีค่าว่างตรงไหนบ้าง)
และ duplicated().sum() (มีแถวซ้ำไหม) จากนั้นเช็ค unique()/nunique() ของคอลัมน์ข้อความสำคัญ
เพื่อเจอปัญหาแบบที่เจอในบทนี้ (ตัวพิมพ์ไม่ตรงกัน ช่องว่างเกิน) ก่อนเริ่มวิเคราะห์จริง
จาก ทำความสะอาดข้อมูล — missing values, duplicates, วันที่หลายรูปแบบ
คอลัมน์วันที่มีหลายรูปแบบปนกัน จะแปลงให้ถูกต้องทั้งหมดยังไง
ห้ามใช้ pd.to_datetime() เฉยๆ (จะ error) และห้ามใช้ format='mixed' กับหรือไม่กับ dayfirst=True
เพียงอย่างเดียว (ทั้งสองแบบให้ผลผิดสำหรับบางรูปแบบ) วิธีที่ถูกต้องคือ parse แยกทีละรูปแบบด้วย
format= ที่ตรงเป๊ะและ errors='coerce' (ให้ค่าที่ไม่ตรงกลายเป็น NaT แทนที่จะ error) แล้วรวมผล
ทั้งหมดด้วย .combine_first() ตามลำดับ สุดท้ายควรเช็คว่า .isna().sum() ของผลลัพธ์เป็น 0 เพื่อยืนยัน
ว่าแปลงครบทุกแถวจริง
จาก ทำความสะอาดข้อมูล — missing values, duplicates, วันที่หลายรูปแบบ
ทำไมการแก้ไข DataFrame ผ่าน chained indexing ถึงเป็นอันตราย และปัจจุบัน (pandas ที่ใช้ Copy-on-Write เป็นค่าเริ่มต้น) มีพฤติกรรมต่างจากเดิมยังไง
df[เงื่อนไข] อาจคืนสำเนา (copy) ของข้อมูล ไม่ใช่ตัวข้อมูลจริง การเขียนต่อด้วย ['col'] = ค่า
(chained indexing) จึงอาจแก้ไขแค่สำเนาชั่วคราวที่ไม่มีใครอ้างอิงถึงอีกแล้ว
ปัจจุบันปัญหานี้อันตรายกว่าเดิม เพราะ pandas เวอร์ชันที่ใช้ Copy-on-Write เป็นค่าเริ่มต้นไม่แสดง
SettingWithCopyWarning เตือนเหมือนเวอร์ชันก่อนหน้าอีกต่อไป — โค้ดดูเหมือนรันผ่านปกติทุกอย่าง
แต่ข้อมูลต้นฉบับไม่ถูกแก้ไขจริงเลย ทางที่ปลอดภัยเสมอคือเขียนในคำสั่งเดียวด้วย .loc[เงื่อนไข, 'col'] = ค่า
จาก ทำความสะอาดข้อมูล — missing values, duplicates, วันที่หลายรูปแบบ
สถิติสำหรับ DA
ทำไมนักวิเคราะห์มักดู median ควบคู่กับ mean เสมอเวลารายงานตัวเลข
เพราะ mean เพียงตัวเดียวอาจทำให้เข้าใจผิดได้ถ้าข้อมูลเบ้ (skewed) หรือมี outlier — เช่นรายได้เฉลี่ยต่อออเดอร์ อาจถูกดึงสูงขึ้นไปมากจากออเดอร์ขนาดใหญ่ไม่กี่ออเดอร์ ทำให้ตัวเลข mean ดูดีเกินความเป็นจริงของ "ออเดอร์ทั่วไป"
การดู median ควบคู่กันช่วยให้เห็นภาพที่สมดุลขึ้น: ถ้า mean กับ median ใกล้กัน ข้อมูลค่อนข้างสมมาตร แต่ถ้าต่างกันมาก (แบบราคาสินค้าหรือยอดขายในร้านนี้) ก็เป็นสัญญาณว่าต้องระวังการตีความ และอาจต้องดู distribution ทั้งหมดเพิ่มเติม
จาก สถิติเชิงบรรยาย
เจอ outlier ในข้อมูลควรทำยังไง
ไม่ควรลบทิ้งทันทีโดยไม่ตรวจสอบ — ขั้นแรกต้องหาที่มาก่อนเสมอว่า outlier นี้เกิดจากอะไร อาจเป็นข้อผิดพลาดในการ บันทึกข้อมูล (เช่น ใส่จำนวนผิดหลัก) หรืออาจเป็นเหตุการณ์จริงที่มีความหมายทางธุรกิจ (เช่น ลูกค้าองค์กรสั่งซื้อจำนวนมาก)
ถ้าเป็นข้อผิดพลาดจริง ค่อยแก้ไขหรือตัดออก แต่ถ้าเป็นค่าจริงที่มีความหมาย ควรเก็บไว้วิเคราะห์แยกต่างหาก หรือใช้สถิติ ที่ทนทานต่อ outlier (เช่น median แทน mean) แทนการลบข้อมูลทิ้งไปเฉยๆ
จาก สถิติเชิงบรรยาย
ทำไมกฎ \|z\| > 3 อาจใช้ไม่ได้ดีกับข้อมูลยอดขาย/รายได้ที่มักเบ้ขวา
กฎนี้อ้างอิงคุณสมบัติของ normal distribution ที่บอกว่าค่าซึ่งห่างจากค่าเฉลี่ยเกิน 3 std จะเจอได้แค่ประมาณ 0.27%
แต่ข้อมูลยอดขาย/รายได้จริงมักเบ้ขวารุนแรง (ลูกค้าส่วนใหญ่ซื้อของราคาปกติ แต่มีบางออเดอร์ใหญ่ผิดปกติดึงหางออกไป)
พอเอากฎนี้ไปใช้จริง จะเจอสัดส่วนที่ \|z\|>3 สูงกว่าทฤษฎีทำนายไว้มาก (ในข้อมูลชุดนี้สูงกว่าเกือบ 8.5 เท่า)
เพราะฉะนั้นควรใช้ z-score เป็นสัญญาณเบื้องต้น ไม่ใช่กฎตายตัว และควรเทียบกับวิธีอื่นประกอบเสมอ
นอกจาก z-score แล้ว มีวิธีอื่นหา outlier อะไรอีกบ้าง
วิธีที่ใช้บ่อยที่สุดอีกแบบคือ IQR method จาก Lesson ที่แล้ว (ค่าที่อยู่นอก Q1 - 1.5*IQR ถึง Q3 + 1.5*IQR)
ซึ่งทนทานต่อความเบ้ของข้อมูลมากกว่า z-score เพราะอิงตำแหน่ง (percentile) ไม่ใช่ค่าเฉลี่ย/std ที่ถูกดึงง่ายโดยค่าสุดขั้ว
นอกจากนี้ยังมีวิธีดูจาก domain knowledge ตรงๆ (เช่น รู้ว่าราคาสินค้าติดลบเป็นไปไม่ได้อยู่แล้ว)
หรือดูกราฟ (histogram/boxplot) ประกอบ ไม่พึ่งตัวเลขสรุปตัวเดียว
อธิบายว่า 95% confidence interval หมายความว่าอะไรให้คนที่ไม่ใช่สายสถิติฟัง
พูดง่ายๆ ว่า: "ถ้าเราสุ่มตัวอย่างขนาดเท่านี้มาคำนวณช่วงแบบนี้ซ้ำๆ กัน 100 ครั้ง จะมีประมาณ 95 ครั้ง ที่ช่วงตัวเลขที่ได้ครอบคลุมค่าเฉลี่ยจริงของทั้งประชากรพอดี" — มันไม่ใช่การบอกว่า "มีโอกาส 95% ที่ค่าเฉลี่ยจริงอยู่ในช่วงนี้ช่วงเดียว" เพราะค่าเฉลี่ยจริงเป็นตัวเลขคงที่ค่าหนึ่งอยู่แล้ว (แค่เราไม่รู้ค่ามัน) สิ่งที่ไม่แน่นอนคือช่วงตัวเลขที่เราคำนวณได้จากตัวอย่างต่างหาก ไม่ใช่ค่าเฉลี่ยจริง
ทำไมขนาดตัวอย่างยิ่งใหญ่ ยิ่งมั่นใจในค่าประมาณมากขึ้น
เพราะ standard error (ความไม่แน่นอนของค่าเฉลี่ยตัวอย่าง) คำนวณจาก sample_std หารด้วยรากที่สองของขนาด ตัวอย่าง (sqrt(n)) — ยิ่ง n ใหญ่ขึ้น ตัวหารก็ใหญ่ขึ้นตาม ทำให้ SE เล็กลง ค่าเฉลี่ยตัวอย่างจึงแกว่งน้อยลง รอบๆ ค่าจริง และ confidence interval ที่ได้ก็จะแคบลง (แม่นยำกว่า) แต่ก็มีจุดคุ้มทุน เพราะ SE ลดลงตาม sqrt(n) ไม่ใช่ตาม n ตรงๆ เพิ่มตัวอย่างจาก 100 เป็น 400 (4 เท่า) SE ลดลงแค่ครึ่งเดียว ไม่ใช่ 4 เท่า
อธิบาย p-value ให้ผู้บริหารที่ไม่ได้เรียนสถิติฟัง โดยไม่ใช้คำว่า "null hypothesis"
อาจอธิบายแบบนี้: "สมมติว่าตัวเลขที่เราอยากตรวจสอบนั้นถูกต้องจริงๆ (เช่น ยอดเฉลี่ยคือ 5000 บาทจริง) ถ้าเราสุ่มตัวอย่างมาดูซ้ำๆ หลายๆ ครั้ง มีโอกาสกี่เปอร์เซ็นต์ที่จะได้ตัวอย่างที่ผลต่างจากตัวเลขนั้นมากเท่ากับหรือมากกว่าที่เราเห็นในครั้งนี้" ถ้าตัวเลขนี้ (p-value) ต่ำมาก แปลว่าสิ่งที่เราสังเกตเห็นไม่น่าจะเกิดจากความบังเอิญเฉยๆ ถ้าตัวเลขไม่ถูกต้องจริง — จุดสำคัญคือ p-value ไม่ได้บอกว่า "ตัวเลขที่อ้างมีโอกาสถูกกี่เปอร์เซ็นต์" มันตอบคำถามกลับด้านกัน
ทำไมการทดสอบทางสถิติที่ไม่ปฏิเสธ H0 ไม่ได้แปลว่าไม่มีความแตกต่างจริง
เพราะ "fail to reject H0" แปลว่าข้อมูลที่มีอยู่ไม่มากพอจะให้หลักฐานที่แข็งแรงพอจะหักล้าง H0 ได้ ไม่ได้แปลว่า H0 ถูกพิสูจน์ ว่าเป็นจริง — สาเหตุที่พบบ่อยคือขนาดตัวอย่างเล็กเกินไป (statistical power ไม่พอ) หรือผลต่างที่แท้จริงมีขนาดเล็กจนตรวจจับ ไม่ได้ด้วยตัวอย่างขนาดนี้ ความแตกต่างจริงอาจยังมีอยู่ แค่ข้อมูลที่เก็บมายังไม่พอจะเห็นมันชัดเจน
ถ้า p-value = 0.049 กับ 0.051 ควรตีความต่างกันมากไหม
ไม่ควรตีความต่างกันมาก — เส้นแบ่ง α=0.05 เป็นธรรมเนียมที่ตกลงกันไว้ล่วงหน้า ไม่ใช่กำแพงที่มีความหมายพิเศษทางสถิติจริงๆ ผลลัพธ์ทั้งสองแทบไม่ต่างกันเลยในแง่ความแข็งแรงของหลักฐาน การตัดสินใจทางธุรกิจที่เปลี่ยนขั้วสุดโต่ง (ทำ/ไม่ทำ) แค่เพราะ p-value ต่างกัน 0.002 จึงเป็นความเสี่ยงที่ควรระวัง ควรดูขนาดของผลต่าง (effect size) และบริบทประกอบด้วยเสมอ ไม่ใช่ยึด เกณฑ์ 0.05 แบบทื่อๆ
ก่อนเชื่อผล A/B test ควรเช็คอะไรก่อนดูที่ p-value
ควรเช็ค sample ratio mismatch (SRM) ก่อนเสมอ คือดูว่าสัดส่วนผู้เข้าทดลองสองกลุ่มใกล้เคียงกับที่ตั้งใจไหม (ปกติควรใกล้ 50/50 ถ้าออกแบบมาแบบนั้น) ถ้าสัดส่วนเบี้ยวไปมาก (เช่น 46/54) แปลว่าระบบสุ่มเข้ากลุ่มอาจมีบั๊ก ทำให้สองกลุ่มมีองค์ประกอบผู้ใช้ต่างกันไปตั้งแต่แรก ซึ่งจะทำให้ผลการทดสอบทั้งหมด (ไม่ว่า p-value จะสวย แค่ไหน) เชื่อถือไม่ได้ นอกจากนี้ควรดู funnel ทีละขั้นด้วย ไม่ใช่แค่ metric สุดท้าย เพื่อให้เข้าใจว่าความ ต่างเกิดขึ้นตรงไหนจริงๆ
อธิบาย sample ratio mismatch และทำไมมันอันตราย
SRM คือสถานการณ์ที่สัดส่วนผู้เข้าทดลองสองกลุ่มไม่ตรงกับที่ออกแบบไว้ เช่น ตั้งใจแบ่ง 50/50 แต่ข้อมูลจริง ออกมา 46/54 มันอันตรายเพราะมักเป็นสัญญาณว่ากระบวนการสุ่มเข้ากลุ่ม (randomization) มีบั๊ก เช่น cache, redirect, หรือ bot บาง segment ตกไปกลุ่มใดกลุ่มหนึ่งมากผิดปกติ — ถ้าเป็นแบบนั้น สองกลุ่มอาจมีองค์ประกอบ ผู้ใช้ต่างกันไปตั้งแต่แรก (ไม่ใช่สุ่มจริง) ทำให้ผลต่างที่วัดได้อาจไม่ได้มาจากตัวแปรที่ทดลองเลย แม้ p-value จะดูมีนัยสำคัญก็ตาม จึงต้องเช็คก่อนเชื่อผลทุกครั้ง
ทีมอยากหยุดทดลองเร็วเพราะเห็นตัวเลขดีขึ้นแล้ว ควรแนะนำยังไง
ควรแนะนำให้กำหนดขนาดตัวอย่าง (sample size) ที่ต้องการล่วงหน้าก่อนเริ่มทดลอง (power analysis) แล้วรอ จนเก็บข้อมูลครบตามแผน เพราะ p-value ที่เห็นระหว่างทางอาจยังไม่สะท้อนผลจริง (ตัวอย่างยังน้อยไป สถิติยัง ไม่นิ่ง) — ถ้าจำเป็นต้องดูผลระหว่างทางจริงๆ ควรใช้วิธี sequential testing ที่ออกแบบมาสำหรับกรณีนี้ โดยเฉพาะ แทนที่จะหยุดทันทีที่เห็นตัวเลขดูดีหรือ p < 0.05 ครั้งแรก ซึ่งเพิ่มความเสี่ยงทั้งพลาดผลจริง (ถ้าหยุดเร็วไป) และได้ผลบวกลวง (ถ้า peek บ่อยเกินไป)
อธิบายความแตกต่างระหว่าง correlation กับ causation ให้ผู้บริหารฟัง พร้อมยกตัวอย่าง
Correlation คือการที่ตัวเลขสองชุด "เคลื่อนไหวไปด้วยกัน" — เห็นแนวโน้มไปในทิศทางเดียวกันหรือตรงข้ามกันอย่างสม่ำเสมอ ส่วน causation คือการที่ตัวหนึ่งเป็น "เหตุ" ที่ทำให้อีกตัวหนึ่งเกิดขึ้นจริงๆ ตัวเลขที่สัมพันธ์กันแรงไม่ได้แปลว่า ตัวหนึ่งเป็นเหตุของอีกตัวหนึ่งเสมอไป
ตัวอย่างที่อธิบายง่าย: ยอดขายไอศกรีมกับจำนวนคนจมน้ำในแต่ละเดือนสัมพันธ์กันสูงมาก แต่ไม่ใช่เพราะไอศกรีมทำให้คน จมน้ำ ทั้งสองสูงขึ้นพร้อมกันเพราะอากาศร้อน/ฤดูร้อน ซึ่งทำให้คนทั้งซื้อไอศกรีมและไปว่ายน้ำมากขึ้น — ในธุรกิจของเรา ก็เจอแบบเดียวกัน เช่น ราคาสินค้ากับต้นทุนสัมพันธ์กันแรงมาก แต่ตัวขับเคลื่อนจริงคือหมวดหมู่สินค้าที่กำหนดทั้งคู่ ไปพร้อมกันตั้งแต่ต้น การจะสรุปว่าอะไรเป็นเหตุของอะไรต้องดูกลไกเบื้องหลัง ไม่ใช่ดูแค่ตัวเลข correlation ตัวเดียว
เจอสองตัวแปรที่สัมพันธ์กันแรงมาก จะตรวจสอบยังไงว่าเป็นเหตุ-ผลกันจริงหรือแค่ confounded
ขั้นแรกคือถ้าเป็นไปได้ ให้ทำ A/B test แบบสุ่มจริง — สุ่มกลุ่มตัวอย่างให้ได้รับ/ไม่ได้รับตัวแปรที่สงสัยว่าเป็นเหตุ แล้ววัดผลที่ตามมา การสุ่มช่วยตัดผลของตัวแปรกวนออกไปได้ ถือเป็นวิธีที่แข็งแรงที่สุดในการพิสูจน์เหตุ-ผล
ถ้าทำ A/B test ไม่ได้ (ข้อมูลเป็น observational ล้วนๆ) ให้ลองควบคุมตัวแปรที่สงสัยว่าเป็นตัวกวน เช่น เทียบ correlation ภายในแต่ละกลุ่มย่อยแยกกัน (เช่น แยกตาม category) ถ้าความสัมพันธ์ยังแรงอยู่แม้ควบคุมตัวแปรกวนแล้ว ก็เป็นหลักฐานที่หนักแน่นขึ้นว่ามีกลไกเชิงตรงอยู่จริง สุดท้ายต้องใช้ domain knowledge ประกอบเสมอ — ถามว่ามีกลไก ทางธุรกิจอะไรที่สมเหตุสมผลรองรับความสัมพันธ์เชิงเหตุ-ผลที่สงสัยไว้หรือไม่
Visualization และ storytelling
ได้โจทย์ "อยากรู้ว่าลูกค้ากลุ่มไหนน่าสนใจที่สุด" แบบกว้างๆ จะเลือกกราฟและเตรียมข้อมูลยังไง
เริ่มจากถามกลับให้คำถามแคบลงก่อนว่า "น่าสนใจ" หมายถึงอะไร — จำนวนคนเยอะ, ใช้จ่ายเยอะ, หรือแนวโน้ม เติบโตเร็ว เพราะแต่ละแบบตอบด้วยกราฟคนละชนิด
ถ้าหมายถึง "กลุ่มไหนใช้จ่ายรวมเยอะที่สุด" (เทียบหมวดหมู่) จะเตรียมข้อมูลแบบ groupby ตามกลุ่มลูกค้า (เช่น channel หรือ city) แล้วรวมยอดใช้จ่าย เรียงจากมากไปน้อย ใช้กราฟแท่ง
ถ้าหมายถึง "แต่ละกลุ่มใช้จ่ายกระจายกว้างแค่ไหน มีลูกค้า VIP โผล่ในกลุ่มไหนบ้าง" จะเปลี่ยนไปใช้ box plot แทน เพราะต้องการเห็นการกระจายและ outlier ไม่ใช่แค่ผลรวม
สรุปคือต้องตีความคำถามกำกวมให้ชัดเจนก่อนเสมอ แล้วค่อยเลือกกราฟ ไม่ใช่เดาชนิดกราฟจากคำถามที่ยังกว้างอยู่
เจอ dataset ใหม่ ขั้นตอนแรกก่อนเลือกชนิดกราฟควรทำอะไร
ขั้นตอนแรกคือทำความเข้าใจคำถามที่จะตอบให้ชัดก่อนเสมอ ไม่ใช่เปิดโปรแกรมแล้วเลือกชนิดกราฟที่ถนัด หรือดูสวยที่สุดก่อนแล้วค่อยหาคำถามมาใส่ทีหลัง เพราะลำดับที่กลับกันมักจบด้วยกราฟที่ดูดีแต่ตอบผิดคำถาม
หลังจากรู้คำถามชัดแล้ว ค่อยดูว่าตัวแปรที่เกี่ยวข้องเป็นชนิดไหน (ตามเวลา, หมวดหมู่, ตัวเลขต่อเนื่อง) แล้วจับคู่กับตารางตัดสินใจ (เทรนด์→เส้น, เทียบหมวด→แท่ง, การกระจาย→histogram/box, ความสัมพันธ์→scatter) สุดท้ายค่อยเตรียมข้อมูลด้วย groupby/sort/pivot ให้อยู่ในรูปที่กราฟชนิดนั้นต้องการ
ทำไมการใส่ title/axis labels ที่ชัดเจนถึงสำคัญพอๆ กับตัวข้อมูลที่ถูกต้อง
ข้อมูลที่ถูกต้องแต่สื่อสารไม่ได้ ก็เหมือนไม่มีประโยชน์ในทางปฏิบัติ — คนอ่านกราฟ (เช่นผู้บริหาร) มักไม่มีเวลา ไล่ดูโค้ดหรือถามที่มาของแต่ละแกน ถ้ากราฟไม่มี title/label ที่ชัดเจน คนอ่านต้องเดาเอง หรือกลับมาถามคนทำอีกที ซึ่งทำให้ insight ที่ควรจะสื่อสารได้เร็วกลับช้าลงหรือถูกตีความผิด title/label ที่ดีทำให้กราฟ "ยืนได้ด้วยตัวเอง" แม้จะถูกส่งต่อไปโดยไม่มีคนอธิบายประกอบ
ถ้าต้องเลือกระหว่าง matplotlib กับ seaborn สำหรับงานสำรวจข้อมูลเร็วๆ (exploratory analysis) จะเลือกอะไรและทำไม
สำหรับงานสำรวจข้อมูลเร็วๆ ที่ข้อมูลอยู่ในรูป DataFrame อยู่แล้ว seaborn มักเป็นตัวเลือกที่เร็วกว่า เพราะเขียน โค้ดสั้นกว่าและได้กราฟที่อ่านง่ายโดยไม่ต้องปรับสไตล์เอง (เช่น sns.boxplot เทียบหลายกลุ่ม หรือ sns.histplot ที่จัดการ bin ให้อัตโนมัติ) แต่ถ้าต้องการควบคุมรายละเอียดที่ seaborn ไม่รองรับตรงๆ หรือทำกราฟที่ไม่ธรรมดา (custom layout ซับซ้อน) ก็ยังต้องพึ่ง matplotlib โดยตรง — สองไลบรารีนี้ใช้ร่วมกันได้เสมอ ไม่ต้องเลือกอย่างใดอย่างหนึ่งตลอดไป
ถ้าต้องออกแบบ dashboard สรุปยอดขายให้ผู้บริหารดูทุกเช้า จะใส่อะไรบ้างและทำไม
เริ่มจาก KPI card ด้านบนสุด: ยอดขายเมื่อวาน/เดือนนี้ พร้อม % เปลี่ยนแปลงเทียบวันก่อน/เดือนก่อน (แสดงทั้งตัวเลขดิบและ % คู่กันเสมอ พร้อมสีเขียว/แดงบอกทิศทาง) เพราะนี่คือคำถามแรกที่ผู้บริหารอยากรู้ เสมอ: "วันนี้ดีขึ้นหรือแย่ลง"
ต่อด้วยกราฟเทรนด์ (เส้น) แสดงยอดขายย้อนหลัง 30-90 วันหรือรายเดือนย้อนหลังทั้งปี เพื่อให้เห็นภาพว่า ตัวเลขล่าสุดอยู่ในบริบทไหน เป็นจุดพีคหรือจุดต่ำผิดปกติหรือเปล่า
แล้วปิดท้ายด้วย breakdown อย่างน้อยหนึ่งมุม เช่น รายได้แยกตามหมวดสินค้าหรือช่องทางขาย (กราฟแท่ง เรียงมากไปน้อย) เพื่อตอบว่าตัวเลขรวมที่เห็นมาจากส่วนไหนเป็นหลัก ถ้ามีที่ว่างอาจเพิ่มอีกหนึ่ง breakdown (เช่น ตามภูมิภาคหรือลูกค้าใหม่/เก่า) แต่จะไม่ยัดเกิน 1 หน้าจอ และรักษาสี/หน่วย/การปัดเศษให้เหมือนกัน ทั้งหน้า เพื่อให้ผู้บริหารกวาดตาดูรอบเดียวแล้วเข้าใจสถานการณ์ได้ทันที ไม่ต้องมาถามเพิ่ม
ได้กราฟยอดขายรายเดือนมา จะเขียน insight สั้นๆ ให้ผู้บริหารยังไง (ยกตัวอย่างประโยคจริง)
เริ่มจากดูว่าเดือนไหนเปลี่ยนแปลงชัดเจนที่สุด แล้วคำนวณ % การเปลี่ยนแปลงเทียบกับเดือนก่อนหน้าหรือ ค่าเฉลี่ยที่เหมาะสม จากนั้นเขียนให้ครบ 4 ส่วน เช่น "ยอดขายเดือน พ.ย. สูงกว่าเดือน ต.ค. 60.73% (จาก 1,281,420 เป็น 2,059,592 บาท) ซึ่งสอดคล้องกับช่วงโปรโมชันปลายปี ควรพิจารณาขยายแคมเปญลักษณะนี้ ในเดือนถัดไป" — มีทั้งตัวเลข เปอร์เซ็นต์ baseline ที่เทียบ และข้อเสนอแนะต่อท้าย ไม่ใช่แค่บอกว่า "ยอดขายดีขึ้น"
ทำไม insight ที่ดีต้องมี "แล้วไง" (so what) ไม่ใช่แค่บรรยายตัวเลข
เพราะเป้าหมายสุดท้ายของการวิเคราะห์ข้อมูลคือช่วยให้คนตัดสินใจได้ ไม่ใช่แค่รายงานข้อเท็จจริง ถ้าบอกแค่ "ลูกค้ากลุ่ม 20% แรกสร้างรายได้ 58.75%" แล้วจบ ผู้อ่านจะรู้ตัวเลขแต่ไม่รู้ว่าต้องทำอะไรต่อ ส่วน "แล้วไง" คือสิ่งที่เชื่อมตัวเลขไปสู่การกระทำ เช่น "ควรทำโปรแกรมรักษาลูกค้ากลุ่มนี้เป็นพิเศษ" ทำให้ insight มีประโยชน์ในการทำงานจริง ไม่ใช่แค่เกร็ดความรู้
เจอ Pareto pattern ในข้อมูลลูกค้า (20% สร้างรายได้ 60%) ควรแนะนำทีมธุรกิจให้ทำอะไรต่อ
ควรแนะนำให้เริ่มจากการระบุตัวตนของลูกค้ากลุ่ม 20% นี้ให้ชัดเจนก่อน (ใครบ้าง ซื้ออะไร ซื้อผ่านช่องทาง ไหน) แล้วออกแบบโปรแกรมดูแลรักษาลูกค้ากลุ่มนี้เป็นพิเศษ เช่น loyalty program หรือบริการ VIP เพราะการสูญเสียลูกค้ากลุ่มนี้ไปกระทบรายได้รวมมากกว่าลูกค้ากลุ่มอื่นมาก ในขณะเดียวกันก็ควรระวังไม่ให้ งบการตลาดทั้งหมดไหลไปหาลูกค้าใหม่จำนวนมากโดยละเลยการดูแลลูกค้าเดิมกลุ่มนี้
Business metrics
ผู้บริหารบอกว่า "ยอดขายเดือนนี้สูงสุดในรอบปี ดีมากเลย" จะถามอะไรต่อก่อนเห็นด้วยเต็มที่
ควรถามต่อว่ารายได้ที่สูงขึ้นมาจากอะไร — ลูกค้าใหม่เพิ่มขึ้นจริง หรือลูกค้าเดิมกลุ่มเล็กใช้จ่ายมากขึ้น (เช็คจำนวนลูกค้า active ประกอบเสมอ) และเทียบกับช่วงเวลาเดียวกันของปีก่อนหรือฤดูกาลปกติด้วย เพราะยอดขายสูงในเดือนที่มีฤดูกาล/แคมเปญพิเศษอาจไม่ยั่งยืนในเดือนถัดไป
จาก เลือกและอ่าน KPI
ถ้าให้เลือก North Star Metric ตัวเดียวสำหรับร้านค้าออนไลน์นี้ จะเลือกอะไรและทำไม
ตัวเลือกที่สมเหตุสมผลคือ "รายได้จากลูกค้าที่ซื้อซ้ำ" หรือ "จำนวนลูกค้า active ต่อเดือน" มากกว่ารายได้รวมเฉยๆ เพราะสะท้อนทั้งคุณค่าที่ลูกค้าได้รับ (กลับมาซื้อซ้ำ) และการเติบโตของฐานลูกค้าไปพร้อมกัน ไม่ใช่แค่ตัวเลขที่ถูกดันขึ้นได้ง่ายจากลูกค้ากลุ่มเล็กกลุ่มเดียว
จาก เลือกและอ่าน KPI
เจอ funnel ที่ conversion ตกฮวบขั้นหนึ่ง จะสืบสาเหตุต่อยังไง (ไม่ใช่แค่รายงานตัวเลข)
ควรแยกดูว่าปัญหากระจุกอยู่ที่ segment ไหน (device, channel, ช่วงเวลา) แล้วดูข้อมูลเชิงคุณภาพประกอบ เช่น รีวิวผู้ใช้ หรือทดลองใช้งานจริงในขั้นนั้นด้วยตัวเอง ก่อนจะสรุปว่าสาเหตุคืออะไร ตัวเลขบอกแค่ "ตรงไหน" ที่มีปัญหา แต่ไม่บอก "ทำไม" — ต้องหาข้อมูลเพิ่มเพื่อตอบ "ทำไม"
จาก วิเคราะห์ funnel
ทำไมการแบ่ง funnel ตาม segment (เช่น device, channel) ถึงสำคัญกว่าดู funnel รวมอย่างเดียว
เพราะตัวเลขรวมอาจกลบปัญหาของ segment หนึ่งไว้ด้วยผลงานที่ดีของอีก segment เช่น ถ้า mobile กับ desktop มี conversion รวมใกล้เคียงกัน อาจดูเหมือนไม่มีปัญหา ทั้งที่จริงขั้นใดขั้นหนึ่งของ device หนึ่งแย่กว่าอีก device มากอย่างมีนัยสำคัญ การแบ่ง segment ช่วยให้เจอจุดที่ควรแก้ไขได้ตรงกว่า
จาก วิเคราะห์ funnel
เจอ cohort หนึ่งมี retention ต่ำกว่าปกติมาก จะสืบสาเหตุยังไง
เริ่มจากตรวจสอบองค์ประกอบของ cohort นั้นก่อน เช่น ช่องทางสมัคร กลุ่มอายุ พื้นที่ หรือแคมเปญที่พาเข้ามา แล้วเทียบสัดส่วนกับภาพรวมทั้งหมดว่าต่างกันชัดเจนไหม ถ้าพบว่า cohort นั้นมีองค์ประกอบเฉพาะที่ต่างจากปกติ (เช่น ส่วนใหญ่มาจากแคมเปญเดียว) ให้ตรวจ retention ของแต่ละองค์ประกอบแยกกันเพื่อยืนยันว่าปัญหาจริงๆ อยู่ตรงไหน
ทีมการตลาดอยากรู้ว่าแคมเปญ promo คุ้มไหม จะตอบยังไงโดยใช้ทั้งจำนวนลูกค้าใหม่และ retention ประกอบกัน
ต้องดูสองด้านคู่กัน: (1) แคมเปญพาลูกค้าใหม่เข้ามาได้เท่าไร (ในกรณีนี้ 300 คน เป็นสัดส่วนใหญ่ของ cohort มิ.ย.) (2) ลูกค้ากลุ่มนั้นกลับมาซื้อซ้ำมากแค่ไหน (promo channel มี retention แค่ 10.33% ต่ำที่สุดในทุกช่องทาง) แล้วเทียบ ต้นทุนแคมเปญกับมูลค่าที่ได้จากลูกค้ากลุ่มนี้ในระยะยาว — ถ้าต้นทุนสูงแต่ลูกค้าส่วนใหญ่ไม่กลับมาซื้อซ้ำเลย แคมเปญนี้อาจไม่คุ้มในระยะยาวแม้จะได้ลูกค้าใหม่เยอะในระยะสั้น
อธิบาย RFM segmentation ให้ทีมการตลาดที่ไม่ถนัดสถิติฟัง
RFM คือการดูลูกค้าสามด้าน — ซื้อล่าสุดเมื่อไร (Recency) ซื้อบ่อยแค่ไหน (Frequency) และใช้จ่ายรวมเท่าไร (Monetary) แล้วให้คะแนนแต่ละด้านเทียบกับลูกค้าคนอื่น จากนั้นรวมคะแนนเพื่อแบ่งลูกค้าเป็นกลุ่มๆ เช่น "ลูกค้าดีเยี่ยม" (คะแนนสูงทุกด้าน) หรือ "เคยดีแต่กำลังจะหายไป" (เคยซื้อบ่อยแต่นานแล้วไม่กลับมา) เพื่อให้ทีม การตลาดออกแบบแคมเปญที่เหมาะกับแต่ละกลุ่มแทนที่จะส่งข้อความเดียวกันให้ทุกคน
จาก RFM segmentation
เจอลูกค้ากลุ่ม "At Risk" (เคยซื้อบ่อยแต่หายไป) ควรทำแคมเปญแบบไหนต่างจากกลุ่ม "Champions"
กลุ่ม At Risk ควรได้รับแคมเปญกระตุ้นให้กลับมา เช่น ส่วนลดพิเศษเฉพาะบุคคล หรือข้อความถามไถ่ว่าทำไมหายไป เพราะเป็นกลุ่มที่เคยมีคุณค่าสูงและมีความเสี่ยงจะเสียไปให้คู่แข่ง ส่วนกลุ่ม Champions ควรได้รับการดูแลรักษาไว้ (เช่น โปรแกรมสมาชิก VIP หรือสิทธิพิเศษ) มากกว่าแคมเปญกระตุ้นให้ซื้อ เพราะพวกเขาซื้ออยู่แล้วสม่ำเสมอ การส่งแคมเปญเดียวกันให้ทั้งสองกลุ่มจะสิ้นเปลืองงบและไม่ตรงจุด
จาก RFM segmentation
ทำไมการกำหนด snapshot date ให้คงที่ (ไม่ใช้วันที่ปัจจุบันจริง) ถึงสำคัญตอนเขียนโค้ดวิเคราะห์แบบนี้
ถ้าใช้วันที่ปัจจุบันจริง (เช่น pd.Timestamp.now()) ค่า recency และคะแนนทุกอย่างที่คำนวณต่อจากนั้นจะเปลี่ยนไป
ทุกครั้งที่รันโค้ดในวันที่ต่างกัน ทำให้ผลลัพธ์ไม่ reproducible — คนอื่นรันโค้ดเดียวกันในวันอื่นจะได้คำตอบไม่ตรงกัน
และตรวจสอบความถูกต้องของโค้ดไม่ได้เลย การกำหนดวันที่คงที่ทำให้ทุกคนได้ผลลัพธ์เดียวกันเสมอ
จาก RFM segmentation
Capstone
อธิบายโปรเจกต์ capstone ของตัวเองใน 30 วินาที ให้คนสัมภาษณ์ฟัง
ใช้โครง: โจทย์ (ตั้งคำถามธุรกิจอะไร) → วิธีตอบ (ใช้ข้อมูลและเทคนิคอะไรบ้าง เช่น SQL/pandas/สถิติ) → ผลลัพธ์ (พบอะไร มีตัวเลขอะไรที่สำคัญ) → แล้วไง (ควรทำอะไรต่อจากสิ่งที่พบ) — โครงนี้ทำให้คำตอบกระชับ มีเหตุผล และแสดงให้เห็นว่าเข้าใจภาพรวมของงาน DA ทั้งวงจร ไม่ใช่แค่ท่องขั้นตอนทางเทคนิค
พื้นฐาน ML และ scikit-learn
อธิบาย data leakage พร้อมยกตัวอย่าง และบอกวิธีสังเกต
leakage คือการที่ข้อมูลจากอนาคตหรือข้อมูลที่ไม่มีตอนทำนายจริงหลุดเข้ามาเป็น feature เช่น ใช้ "จำนวนออเดอร์ทั้งหมดของลูกค้า" ทำนายว่าลูกค้าจะซื้อซ้ำไหม ซึ่งรู้ได้ก็ต่อเมื่อลูกค้าซื้อซ้ำไปแล้ว
วิธีสังเกต: ผลบนชุดทดสอบดีเกินจริง (เช่น accuracy ใกล้ 100% ในโจทย์ที่ควรยาก) หรือ feature ตัวหนึ่งมีอิทธิพลสูงผิดปกติ — ให้ไล่ถามทีละ feature ว่า "ตอนใช้งานจริงเรารู้ค่านี้ ณ เวลาที่ต้องทำนายไหม"
ทำไมผลลัพธ์ของโมเดลถึงต้องเทียบกับ baseline เสมอ
เพราะตัวเลขอย่าง accuracy 64% ไม่มีความหมายถ้าไม่รู้ว่าวิธีที่ง่ายที่สุดได้เท่าไร ในโจทย์ที่คลาสไม่สมดุล การทายคลาสส่วนใหญ่ก็อาจได้สูงอยู่แล้ว (ในข้อมูลนี้ ~59%) baseline บอกว่าโมเดลเพิ่มมูลค่าจริงเท่าไร และช่วยตัดสินว่าคุ้มกับความซับซ้อนที่เพิ่มขึ้นหรือไม่
อธิบายผลของโมเดล regression ให้ผู้บริหารที่ไม่รู้ ML ฟัง (ใช้ MAE และ R² )
ใช้ MAE เล่าเป็นหน่วยที่คนเข้าใจ: "โมเดลทำนายมูลค่าออเดอร์แรกคลาดเคลื่อนเฉลี่ย ~3,800 บาท ดีกว่าการทายค่าเฉลี่ยที่คลาดเคลื่อน ~5,000 บาท" แล้วใช้ R² เสริมว่าอธิบายความผันผวนของมูลค่าได้ราว 30% ที่เหลือเป็นปัจจัยที่ยังไม่มีในข้อมูล จากนั้นบอกข้อจำกัดชัดเจนว่าโมเดลยังไม่แม่นพอจะใช้ตัดสินใจรายบุคคล
ทำไมบางครั้งควรทำนาย log ของ target แทนค่าตรงๆ
เมื่อ target เบ้ขวามาก (ค่าสูงมากไม่กี่ตัวดึงเส้นถดถอย) การแปลง log ทำให้การกระจายสมมาตรขึ้น โมเดลเส้นตรงเข้ากับข้อมูลได้ดีขึ้น แต่ต้องแปลงคำทำนายกลับก่อนรายงาน และระวังว่า metric บนสเกล log ไม่เท่ากับสเกลเดิม จึงควรเทียบผลบนสเกลบาทเสมอ
อธิบายความต่างระหว่าง predict และ predict_proba และเมื่อไรควรใช้ตัวไหน
predict ให้คลาสสุดท้าย (0/1) ที่ตัดสินด้วยเกณฑ์ 0.5 ส่วน predict_proba ให้ความน่าจะเป็นจริง ใช้ predict_proba เมื่ออยากจัดอันดับลูกค้า (ติดต่อคนที่มีโอกาสสูงสุดก่อน) หรืออยากปรับเกณฑ์ตัดสินให้เหมาะกับต้นทุนของงาน และใช้ predict เมื่อต้องการคำตอบสุดท้ายที่ใช้เกณฑ์มาตรฐานแล้ว
อธิบาย odds ratio ของ channel_promo ที่เท่ากับ ~0.11 ให้ทีมการตลาดฟัง
ลูกค้าที่มาจากช่องทาง promo มีโอกาส (odds) ซื้อซ้ำต่ำกว่าช่องทางอ้างอิง (ads) มาก — เหลือประมาณ 11% ของ odds เมื่อเทียบกันโดยปัจจัยอื่นเหมือนกัน ซึ่งสอดคล้องกับที่เห็นจากข้อมูลว่าลูกค้า promo ซื้อซ้ำไม่ถึง 13% เทียบกับกว่า 60% ของช่องทางอื่น สรุปได้ว่าแคมเปญ promo ดึงลูกค้ามาก แต่ส่วนใหญ่ไม่กลับมา
อธิบาย precision กับ recall ให้ผู้บริหารฟังพร้อมตัวอย่างที่ต้องแลกกัน
precision ตอบว่า "คนที่เราส่งโปรโมชันไป ในนั้นมีกี่ % ที่ควรได้จริง" ส่วน recall ตอบว่า "คนที่ควรได้โปรโมชันทั้งหมด เราส่งถึงกี่ %" — ถ้าลดเกณฑ์ให้ส่งกว้างขึ้น recall เพิ่มแต่ส่งพลาดคนไม่ควรได้มากขึ้น (precision ลด) เลือกจุดสมดุลจากต้นทุนของการส่งเกินกับการพลาดลูกค้า
เจอโมเดลที่ accuracy 94% ในโจทย์ที่คลาสเป้าหมายมีแค่ 6% จะตรวจสอบอะไรต่อ
เทียบกับ baseline ที่ทายคลาสส่วนใหญ่ (ซึ่งได้ ~94% อยู่แล้ว) แล้วดู confusion matrix, recall/precision ของคลาสหายาก และ ROC-AUC ถ้า recall ใกล้ 0 แปลว่าโมเดลไม่ได้เรียนรู้อะไรเกี่ยวกับคลาสที่สนใจเลย จากนั้นลองปรับ class_weight หรือ threshold และรายงานตัวชี้วัดที่ตรงกับเป้าหมายทางธุรกิจ
อธิบายว่าทำไมการเลือกโมเดลจากคะแนนบนชุด test หลายรอบจึงเป็นปัญหา
เพราะทุกครั้งที่เลือกจากผลบนชุด test ข้อมูลชุดนั้นถูกใช้ตัดสินใจไปแล้ว คะแนนสุดท้ายจึงดีเกินจริงและไม่ใช่ตัวแทนของข้อมูลใหม่ (test leakage) วิธีที่ถูกคือเลือกโมเดล/hyperparameter ด้วย cross-validation บนชุด train แล้วใช้ชุด test วัดผลรอบสุดท้ายเพียงครั้งเดียว
เจอโมเดลที่ train accuracy 99% แต่ test 55% จะทำอย่างไร
วินิจฉัยว่าเป็น overfitting แล้วลดความซับซ้อนของโมเดล (เช่น จำกัด max_depth, เพิ่ม regularization), เพิ่มข้อมูล หรือลดจำนวน feature จากนั้นวัดซ้ำด้วย cross-validation และเทียบกับ baseline ว่าโมเดลที่ง่ายขึ้นยังชนะ baseline หรือไม่
Feature engineering
one-hot กับ ordinal encoding ต่างกันยังไง และเลือกใช้เมื่อไร
one-hot สร้างคอลัมน์ 0/1 ต่อหนึ่งหมวด ไม่สร้างลำดับ จึงเหมาะกับข้อมูลที่ไม่มีลำดับ (เมือง ช่องทาง วิธีชำระเงิน) ส่วน ordinal แปลงเป็นเลข 0,1,2 ตามลำดับหมวด เหมาะเมื่อหมวดมีลำดับจริงและระยะห่างพอสมเหตุสมผล (เช่น ระดับความพึงพอใจ) ถ้าใช้ ordinal กับข้อมูลที่ไม่มีลำดับ โมเดลเส้นตรงอาจตีความเป็นมาก-น้อยที่ไม่มีอยู่จริง
เจอคอลัมน์ที่มีหมวดเป็นพันๆ ค่า (high cardinality) เช่น รหัสสินค้า จะจัดการอย่างไร
one-hot ตรงๆ จะสร้างคอลัมน์มหาศาลและกระจัดกระจาย ทางเลือกได้แก่ รวมหมวดที่พบน้อยเป็น "อื่นๆ", ใช้ target encoding (คำนวณจาก train เท่านั้น หรือทำแบบ cross-fitted เพื่อกัน leakage), ใช้ embedding หรือโมเดลที่รับหมวดได้โดยตรง และเลือกวิธีด้วย cross-validation
อธิบายว่าทำไมการ fit scaler บนข้อมูลทั้งชุดก่อนแบ่ง train/test จึงเป็น leakage
เพราะ mean/std ที่ใช้ปรับสเกลถูกคำนวณจากข้อมูลที่รวมชุด test — ข้อมูล test จึงมีผลต่อการแปลง feature ที่โมเดลเห็นตอนเทรน ทำให้ผลทดสอบดีเกินจริงเล็กน้อยและไม่ตรงกับสถานการณ์จริงที่ข้อมูลใหม่ยังไม่เคยมีอยู่ตอนเทรน วิธีที่ถูกคือ fit บน train แล้ว transform test ด้วยค่าเดิม (หรือใส่ไว้ใน Pipeline)
ถ้าข้อมูลมี missing 5% ควรเลือกวิธีจัดการอย่างไร
ดูก่อนว่าหายแบบสุ่มหรือมีแบบแผน (เช่น หายเฉพาะกลุ่มลูกค้าบางกลุ่ม) แล้วเลือกจากลบแถว เติม median/mean/ค่าคงที่ หรือเพิ่มคอลัมน์ flag ว่าค่านี้เคยหาย และวัดผลด้วย cross-validation โดยต้องคำนวณค่าที่เติมจาก train เท่านั้น
อธิบายว่า Pipeline ช่วยป้องกัน data leakage อย่างไร
Pipeline ห่อขั้นตอนเตรียมข้อมูลและโมเดลไว้ด้วยกัน ตอน fit จะเรียนรู้ตัวแปลง (mean/std ของ scaler, หมวดของ encoder) จากข้อมูล train เท่านั้น และตอน predict/transform จะใช้ค่าที่เรียนรู้ไว้แล้วกับข้อมูลใหม่ เมื่อใช้ร่วมกับ cross-validation แต่ละ fold จะ fit ตัวแปลงใหม่บนส่วน train ของ fold นั้น ข้อมูลทดสอบจึงไม่มีผลต่อการเตรียมข้อมูลเลย
ถ้าต้องส่งโมเดลไปใช้งานจริง ทำไมควรส่งเป็น pipeline ทั้งก้อน
เพราะข้อมูลดิบที่เข้ามาต้องผ่านการแปลงเหมือนตอนเทรนทุกขั้นตอน ถ้าแยกตัวแปลงกับโมเดลออกจากกัน เสี่ยงที่จะใช้ตัวแปลงคนละชุดหรือลืมขั้นตอน pipeline เดียวช่วยให้ทำนายจากข้อมูลดิบได้ตรงกับตอนเทรนเสมอ และเวอร์ชันของตัวแปลงกับโมเดลอยู่ด้วยกัน
บอกวิธีตัดสินใจว่า feature ที่สร้างขึ้นใหม่ควรเก็บหรือไม่
สร้างเป็นชุดสมมติฐาน (เช่น อัตราส่วน flag การจัดกลุ่ม) แล้วเพิ่มทีละกลุ่มเข้า pipeline เดียวกัน วัดด้วย cross-validation เทียบกับ baseline ที่ไม่มี feature นั้น ดูทั้งค่าเฉลี่ยและความผันผวน (std) ถ้าไม่ดีขึ้นอย่างมีความหมายก็ตัดออก เพราะ feature ที่ไม่ช่วยเพิ่มความซับซ้อนและความเสี่ยง overfit และตรวจด้วยว่า feature นั้นรู้ได้ ณ เวลาทำนายจริง
ยกตัวอย่าง feature ที่ leak และวิธีเลี่ยง
ตัวอย่าง: จำนวนออเดอร์ทั้งหมดของลูกค้า หรือค่าเฉลี่ยของ target ที่คำนวณจากข้อมูลทั้งชุด — ทั้งคู่ใช้ข้อมูลที่ยังไม่มีตอนทำนายจริง วิธีเลี่ยงคือกำหนดจุดเวลาที่ทำนาย (เช่น ณ ออเดอร์แรก) แล้วสร้าง feature จากข้อมูลก่อนหน้านั้นเท่านั้น และคำนวณสถิติที่ใช้ target จาก train เท่านั้น
Tree และ boosting
Decision tree เลือกจุดแยก (split) อย่างไร
ลองทุกคำถามที่เป็นไปได้ (ทุก feature ทุกค่าตัด) แล้วเลือกคำถามที่ทำให้ impurity (เช่น Gini) ของโหนดลูกที่ถ่วงน้ำหนักตามจำนวนแถวลดลงมากที่สุด จากนั้นทำซ้ำในแต่ละกิ่ง (greedy, ทีละขั้น) จนถึงเงื่อนไขหยุด เช่น max_depth, min_samples_leaf หรือโหนดบริสุทธิ์
จาก Decision Tree
ทำไม decision tree ถึง overfit ง่ายและแก้อย่างไร
ถ้าปล่อยให้โตเต็มที่ มันจะแบ่งจนทุกใบบริสุทธิ์ คือจำข้อมูลเทรนรวมทั้ง noise แก้โดยจำกัดขนาด (max_depth, min_samples_leaf, max_leaf_nodes), pruning หรือใช้ ensemble อย่าง random forest / boosting และเลือกไฮเปอร์พารามิเตอร์ด้วย cross-validation
จาก Decision Tree
Random forest ต่างจาก bagging ของ decision tree ธรรมดาอย่างไร
Bagging สุ่มแถวแบบ bootstrap ให้แต่ละต้น แล้วเฉลี่ย Random forest เพิ่มการสุ่ม feature ที่แต่ละ split (max_features) เพื่อให้ต้นไม้ไม่สัมพันธ์กันมากนัก ทำให้เฉลี่ยแล้วลด variance ได้มากกว่า
จาก Random Forest
เมื่อไรที่ random forest ไม่ช่วย
เมื่อสัญญาณในข้อมูลอ่อนหรือ noise สูง ต้นไม้ทุกต้นเรียนรู้ได้ไม่ต่างกันมาก ensemble จึงได้ผลใกล้กับโมเดลง่ายๆ (เช่นในข้อมูล repeat ของเรา) หรือเมื่อ feature engineering สำคัญกว่าตัวโมเดล
จาก Random Forest
อธิบาย gradient boosting ให้คนที่รู้จักแต่ decision tree
เริ่มจากคำตอบง่ายๆ แล้วสร้างต้นไม้เล็กๆ ทีละต้นเพื่อทำนาย "ส่วนที่ยังพลาด" (gradient ของ loss) ของโมเดลปัจจุบัน แล้วบวกเข้าไปโดยคูณ learning_rate ทำซ้ำหลายรอบ ผลรวมของต้นไม้ตื้นๆ เหล่านี้จึงสร้างขอบเขตการตัดสินใจที่ซับซ้อนได้
จะเลือก n_estimators และ learning_rate อย่างไรไม่ให้ overfit
ทั้งสองแลกกัน (ก้าวเล็ก = ต้องรอบมาก) ตั้ง learning_rate ค่อนข้างเล็กแล้วใช้ early stopping (n_iter_no_change + validation_fraction) หรือ validation set แยกเพื่อหยุดตอน validation หยุดดีขึ้น และยืนยันด้วย cross-validation แล้วแตะ test ครั้งเดียว
อธิบายขั้นตอนจูนโมเดลอย่างถูกต้องโดยไม่ให้ test รั่ว
แบ่ง train/test ก่อน จากนั้นใช้ cross-validation บนเฉพาะ train เพื่อเปรียบเทียบชุด hyperparameter (GridSearchCV/RandomizedSearchCV) เลือกชุดที่ดีที่สุด refit บน train ทั้งหมด แล้วประเมินบน test เพียงครั้งเดียวเพื่อรายงานผล ถ้าต้องการผลที่ไม่เอนเอียงมากขึ้นใช้ nested CV
feature importance ของ random forest เชื่อถือได้แค่ไหน
impurity importance คำนวณจากข้อมูลเทรนและเอนเอียงไปหา feature ต่อเนื่อง/มีหลายค่า (ทดลองใส่คอลัมน์สุ่มก็ยังได้อันดับสูง) permutation importance บน validation/test เชื่อถือกว่าเพราะวัดผลกระทบต่อคะแนนจริง แต่ก็ไม่ใช่สาเหตุ และ feature ที่สัมพันธ์กันจะแบ่งความสำคัญกัน
Deep learning เบื้องต้น
อธิบาย MLP สั้นๆ ว่าคำนวณอย่างไร
input คูณน้ำหนักของ layer แรกบวก bias แล้วผ่าน activation (เช่น ReLU) ได้ค่า hidden จากนั้นทำซ้ำกับ layer ถัดไปจนถึง output ซึ่ง sigmoid/softmax แปลงเป็นความน่าจะเป็น ทั้งหมดเป็นการคูณเมทริกซ์และฟังก์ชันไม่เชิงเส้นซ้อนกัน พารามิเตอร์ (น้ำหนักและ bias) ถูกเรียนรู้ด้วย gradient descent
จาก Neuron และ MLP
ทำไม neural network ถึงต้อง scale feature
การอัปเดตน้ำหนักด้วย gradient ขึ้นกับขนาดของ input feature ที่ช่วงกว้างจะทำให้ loss surface บิดเบี้ยว ทำให้ optimizer ต้องใช้ learning rate เล็กหรือติดขัด การ standardize (fit บน train เท่านั้น) ทำให้ทุก feature อยู่ในสเกลใกล้กันและการเทรนเสถียรขึ้น
จาก Neuron และ MLP
อธิบาย gradient descent และบทบาทของ learning rate
ทำซ้ำ: คำนวณ gradient ของ loss ต่อพารามิเตอร์ แล้วขยับพารามิเตอร์สวนทิศ gradient ด้วยก้าว learning rate ถ้า lr เล็กเกินจะช้า ถ้าใหญ่เกินจะข้ามจุดต่ำสุดหรือ diverge จึงมักใช้ lr ที่ปรับด้วย optimizer (เช่น Adam) และตรวจ loss curve
ถ้า loss ของโมเดลเพิ่มขึ้นหรือเป็น nan ระหว่างเทรน ควรตรวจอะไร
สงสัย learning rate สูงเกินไปก่อน (ลดลง), ตรวจว่า scale input แล้ว, ค่าที่มีปัญหา (NaN/inf ในข้อมูล), และ gradient ระเบิด จากนั้นลองเทรนบนข้อมูลเล็กมากๆ ให้ loss ลดจนเกือบ 0 เพื่อตรวจว่าโค้ดถูก
จะทำอย่างไรถ้า neural network overfit ข้อมูลตาราง
ลดความจุของโมเดล (hidden layer เล็กลง), regularization (L2/alpha, dropout ใน framework อื่น), early stopping ด้วย validation set, เพิ่มข้อมูลหรือ augmentation ถ้าทำได้ และเทียบกับ baseline ง่ายๆ เช่น logistic regression/gradient boosting เสมอ เพราะบนข้อมูลตารางขนาดเล็กโมเดลง่ายมักดีเท่ากันหรือกว่า
เมื่อไรที่คุณจะเลือกใช้ deep learning แทน gradient boosting
เมื่อข้อมูลเป็นรูปภาพ ข้อความ เสียง หรือลำดับ (ที่ต้องเรียนรู้ representation เอง) เมื่อมีข้อมูลมหาศาล หรือมี pretrained model ให้ทำ transfer learning สำหรับข้อมูลตารางทั่วไป gradient boosting มักเป็นตัวเลือกแรกเพราะเร็ว แม่น และอธิบายง่ายกว่า
ML Capstone
เล่าโปรเจกต์ ML ของคุณใน 1 นาที ให้คนสัมภาษณ์ฟัง
โครง: โจทย์ธุรกิจและ metric (ทำไมเลือก AUC/accuracy) → baseline → วิธีแบ่งข้อมูลและป้องกัน leakage → โมเดลที่เทียบและผล CV (mean ± std) → โมเดลที่เลือกและเหตุผล → ผลบน test ครั้งเดียว → ข้อจำกัดและขั้นต่อไป การพูดถึงข้อจำกัดอย่างตรงไปตรงมาทำให้น่าเชื่อถือกว่าการโชว์ตัวเลขสวย
พื้นฐาน LLM และ API
อธิบายว่าคุณจะประเมินต้นทุนต่อเดือนของแชตบอตที่ใช้ LLM API อย่างไร
ประมาณ token เฉลี่ยต่อคำขอ (system prompt + ประวัติ + เอกสารที่ดึงมา = input, คำตอบ = output) คูณราคาต่อ token ของแต่ละฝั่ง แล้วคูณจำนวนคำขอต่อเดือน ตรวจกับ usage จริงจาก API ช่วงทดสอบ และหาวิธีลด เช่น ดึงเฉพาะเอกสารที่เกี่ยวข้อง จำกัดประวัติ cache คำถามซ้ำ และใช้โมเดลเล็กกับงานง่าย
ทำไมข้อความภาษาไทยกับภาษาอังกฤษที่ยาวเท่ากันจึงอาจมีต้นทุนต่างกัน
tokenizer แบบ subword ถูกเทรนมาจากข้อมูลที่ภาษาต่างกันในสัดส่วนไม่เท่ากัน ภาษาที่พบน้อยมักถูกแตกเป็นชิ้นเล็กกว่า จึงใช้ token ต่อข้อความมากกว่า ต้นทุนและการใช้ context เพิ่มขึ้น ควรวัดด้วย tokenizer/usage จริงกับข้อมูลของตัวเอง
LLM API ไม่มีความจำ แล้วแชตบอตจำบทสนทนาได้อย่างไร
ตัวแอปเก็บประวัติเองแล้วส่ง messages ที่เกี่ยวข้องกลับไปทุกคำขอ เมื่อประวัติยาวเกินงบ token ต้องตัดหรือสรุปข้อความเก่า (เก็บ system prompt และข้อความล่าสุด) และอาจดึงข้อมูลที่เกี่ยวข้องมาจากฐานความรู้ภายนอกแทนการพกทุกอย่างไว้ในประวัติ
เมื่อไรควรใช้ temperature ต่ำและเมื่อไรควรสูง
งานที่ต้องการความถูกต้อง สม่ำเสมอ เช่น สกัดข้อมูลเป็น JSON หรือตอบจากเอกสาร ควรใช้ต่ำ ส่วนงานที่ต้องการความหลากหลาย เช่น ระดมไอเดีย เขียนสร้างสรรค์ ใช้สูงกว่า และไม่ควรพึ่ง temperature อย่างเดียวเพื่อให้ผลทำซ้ำได้ ควรเก็บ/แคชผลที่สำคัญ
คุณจะทำให้แอปที่เรียก LLM API ทนต่อ rate limit และ downtime ได้อย่างไร
retry เฉพาะข้อผิดพลาดชั่วคราวด้วย exponential backoff + jitter และจำกัดจำนวนครั้ง ตั้ง timeout, ใช้ cache สำหรับคำขอซ้ำ, ใส่ rate limiter ฝั่งเราเพื่อไม่ชนเพดาน, circuit breaker/fallback เมื่อบริการล่มนาน, ทำ idempotency สำหรับคำขอที่มีผลข้างเคียง และบันทึก log/metrics ของทุก retry เพื่อดูแนวโน้ม
เมื่อไรที่การ cache คำตอบของ LLM ไม่เหมาะสม
เมื่อต้องการความหลากหลายของคำตอบ เมื่อคำตอบขึ้นกับข้อมูลที่เปลี่ยนตลอดเวลาหรือบริบทเฉพาะผู้ใช้ (ต้องรวมสิ่งเหล่านั้นในกุญแจหรือไม่ cache) และเมื่อเนื้อหาต้นทางเปลี่ยน (ต้องมี TTL/การล้าง cache) รวมถึงข้อมูลส่วนบุคคลที่ไม่ควรเก็บ
Prompt และ structured output
อธิบายโครงของ prompt ที่ดีสำหรับงานจัดหมวดข้อความ
บอกบทบาทและงาน ระบุชุดป้ายกำกับที่อนุญาต ใส่ตัวอย่าง few-shot ที่ครอบคลุมและมีรูปแบบเดียวกับเอาต์พุตที่ต้องการ ครอบข้อมูลนำเข้าด้วย delimiter และบอกรูปแบบคำตอบที่ต้องการ (เช่น ป้ายกำกับเดียว หรือ JSON) แล้ววัดผลกับชุดตัวอย่างที่มีเฉลยก่อนใช้งานจริง
prompt injection คืออะไรและลดความเสี่ยงอย่างไร
คือการที่ข้อมูลจากผู้ใช้หรือเอกสารภายนอกมีข้อความที่พยายามสั่งโมเดลให้ทำสิ่งอื่น ลดความเสี่ยงด้วยการแยกข้อมูลออกจากคำสั่งด้วย delimiter, บอกว่าเนื้อหานั้นเป็นข้อมูล, ตรวจ/จำกัดผลลัพธ์, และที่สำคัญคือไม่ให้โมเดลมีสิทธิ์ทำสิ่งอันตรายโดยตรงโดยไม่ผ่านการตรวจสิทธิ์ฝั่งโค้ด
คุณจะทำให้ระบบที่ใช้ผลลัพธ์ JSON จาก LLM ทนต่อข้อมูลผิดรูปแบบได้อย่างไร
ใช้ structured output/tool schema ของผู้ให้บริการเพื่อลดปัญหา แต่ตรวจฝั่งเราเสมอ: parse แบบ strict ก่อน ถ้าไม่ได้ลองดึง JSON จากข้อความ ตรวจฟิลด์/ชนิด/enum/ช่วงค่าด้วย schema validator (เช่น pydantic, jsonschema) coerce เฉพาะกรณีปลอดภัย และถ้าไม่ผ่านให้ retry พร้อมส่ง error กลับให้โมเดลแก้ หรือ fallback/ส่งให้คนตรวจ พร้อมบันทึก log อัตราความล้มเหลว
ทำไมผลลัพธ์ของ LLM ควรถูกมองเป็นข้อมูลที่ไม่น่าไว้ใจ
เพราะโมเดลสร้างข้อความตามความน่าจะเป็น ไม่ได้รับประกันรูปแบบหรือความถูกต้อง อาจมีฟิลด์ขาด ชนิดผิด ค่านอกช่วง หรือถูกชักนำด้วย prompt injection การใช้โดยไม่ตรวจอาจทำให้ข้อมูลเสียหรือเกิดช่องโหว่ จึงควรปฏิบัติเหมือนอินพุตจากภายนอกและตรวจก่อนใช้
ออกแบบ guardrail สำหรับแชตบอตลูกค้าอย่างไร
ก่อนส่งเข้า: จำกัดความยาว ปกปิด PII ตรวจ injection เบื้องต้น และแยกข้อมูลออกจากคำสั่ง หลังโมเดลตอบ: ตรวจ schema/ค่าที่อนุญาต ตรวจเนื้อหาที่ห้าม จำกัดความยาว และถ้าไม่ผ่านให้ retry พร้อม feedback จำกัดรอบ แล้ว fallback (ส่งต่อคน) พร้อม log และวัดอัตราการทำงานของแต่ละ guardrail
ทำไมเราจึงไม่ควรพึ่ง regex อย่างเดียวในการป้องกัน prompt injection
ผู้โจมตีเรียบเรียงประโยคได้หลากหลายจนกฎคำสำคัญตามไม่ทัน (recall ต่ำ) และกฎอาจแจ้งเตือนผิดกับข้อความปกติ (precision ต่ำ) จึงควรใช้เป็นตาข่ายชั้นแรก และป้องกันจริงด้วยการจำกัดสิทธิ์ของระบบ ตรวจผลลัพธ์ และให้มนุษย์อนุมัติการกระทำที่มีผลข้างเคียง
Embeddings และ RAG
คุณจะเลือกขนาด chunk สำหรับระบบ RAG อย่างไร
เริ่มจากตัดตามโครงสร้างเอกสาร (หัวข้อ ย่อหน้า) แล้วจำกัดความยาว จากนั้นทดลองหลายขนาดและ overlap บนชุดคำถามที่มีเฉลย วัด hit@k/recall ของ retrieval และปริมาณ token ที่ส่งเข้า prompt พร้อมคุณภาพคำตอบ เลือกจุดที่คุ้ม ระวังตัวชี้วัดที่ดีขึ้นเพียงเพราะ chunk ใหญ่ครอบคลุมทุกอย่าง
chunk เล็กเกินไปและใหญ่เกินไปมีปัญหาอะไร
เล็กเกินไปตัดบริบทขาด ข้อมูลที่ต้องอ่านร่วมกันแยกไปอยู่คนละ chunk และมีจำนวน chunk มาก; ใหญ่เกินไปมีหลายเรื่องปน retrieval ไม่แม่นยำ สิ้นเปลือง token และสิ่งรบกวนทำให้โมเดลตอบแย่ลง
อธิบายว่า vector search ทำงานอย่างไรในระบบ RAG
ทำเวกเตอร์ของทุก chunk ล่วงหน้าเก็บไว้ (vector store) เมื่อมีคำถามก็แปลงเป็นเวกเตอร์ด้วยโมเดลเดียวกัน แล้วคำนวณความคล้าย (มักใช้ cosine) กับทุก chunk และเลือก top-k ที่คล้ายที่สุดมาใส่ใน prompt สำหรับข้อมูลขนาดใหญ่ใช้ดัชนีแบบประมาณ (ANN) เพื่อให้ค้นหาเร็ว
TF-IDF กับ embeddings ต่างกันอย่างไร และเมื่อไรใช้อย่างไหน
TF-IDF เป็นเวกเตอร์แบบ sparse ตามคำที่ตรงกัน อธิบายง่าย เร็ว ไม่ต้องเรียกโมเดล เหมาะกับคำเฉพาะ/รหัส แต่รับมือ paraphrase ไม่ได้ ส่วน embeddings เป็นเวกเตอร์หนาแน่นที่จับความหมาย รับมือการใช้คำต่างกันได้ดีกว่า แต่ต้องมีโมเดลและต้นทุน ในทางปฏิบัติมักใช้ผสมกัน (hybrid) และวัดบนชุดคำถามของตัวเอง
ออกแบบ prompt ของระบบ RAG เพื่อลดการแต่งคำตอบ (hallucination) อย่างไร
สั่งให้ตอบจากบริบทที่ให้เท่านั้น ให้อ้างอิงแหล่งที่มา (doc id) ให้ปฏิเสธเมื่อบริบทไม่มีคำตอบ แล้วตรวจฝั่งโค้ดว่าการอ้างอิงอยู่ในชุดที่ดึงมาจริง ใช้ threshold คะแนน retrieval กรองคำถามนอกขอบเขต ตั้ง temperature ต่ำ และวัดผลด้วยชุดคำถามที่มีเฉลย
MMR ใช้ทำอะไรและเมื่อไรที่ไม่ช่วย
MMR เลือก chunk ทีละอันโดยถ่วงระหว่างความเกี่ยวข้องกับคำถามและความต่างจากอันที่เลือกแล้ว เพื่อลดข้อมูลซ้ำซ้อนในบริบท มีประโยชน์เมื่อฐานความรู้มีเนื้อหาซ้ำ/คล้ายกันมาก แต่ถ้าเอกสารไม่ซ้ำซ้อนอยู่แล้ว (เช่นในตัวอย่างของเรา) จะไม่ช่วยหรืออาจทำให้ hit@k ลดลงเล็กน้อย
คุณจะประเมินระบบ RAG อย่างไร
แยกประเมิน retrieval (hit@k, MRR, recall บนชุดคำถามที่มีเฉลยของเอกสาร) ออกจากคุณภาพคำตอบ (ความถูกต้อง การยึดบริบท/faithfulness การอ้างอิง การปฏิเสธเมื่อไม่มีข้อมูล) วัดแยกตามกลุ่มและรายข้อที่พลาด รายงานความไม่แน่นอน และเก็บชุดตรวจสุดท้ายแยกจากชุดที่ใช้จูน
จาก ประเมิน retrieval: hit@k, MRR และการวิเคราะห์ความผิดพลาด
ถ้า hit@k ต่ำ คุณจะวิเคราะห์หาสาเหตุอย่างไร
ดูรายข้อที่พลาดและอันดับของเฉลย แล้วแยกสาเหตุ: คำถามใช้คำต่างจากเอกสาร (ใช้ embeddings/query expansion/hybrid), chunk ตัดผิดหรือใหญ่เกินไป, เอกสารซ้ำ/กำกวมกันเอง (ปรับเอกสารหรือ metadata), หรือ k น้อยเกินไป (เพิ่ม k + reranker) แก้ทีละอย่างแล้ววัดซ้ำ
จาก ประเมิน retrieval: hit@k, MRR และการวิเคราะห์ความผิดพลาด
Agents และ tool use
อธิบายลำดับการทำงานของ tool use กับ LLM API
ส่งรายการ tools (name, description, input_schema) มาพร้อมคำขอ ถ้าโมเดลต้องการเครื่องมือ มันตอบด้วยคำขอเรียกเครื่องมือ (tool_use: id, name, input) แทนข้อความสุดท้าย โค้ดของเราตรวจอาร์กิวเมนต์ รันฟังก์ชันจริง แล้วส่ง tool_result (พร้อม id เดิม) กลับเป็นข้อความถัดไป วนจนโมเดลตอบข้อความสุดท้าย
คุณจะออกแบบ description และ schema ของเครื่องมืออย่างไรให้โมเดลใช้ถูก
ตั้งชื่อสื่อความหมาย เขียน description ว่าเครื่องมือทำอะไร เมื่อไรควรใช้ และไม่ควรใช้เมื่อไร ระบุชนิดและความหมายของแต่ละพารามิเตอร์ ใช้ enum เมื่อมีค่าที่กำหนดได้ ระบุ required ให้ตรง และให้ผลลัพธ์กลับมาสั้นชัดเจน จากนั้นทดสอบกับคำขอจริงหลายแบบเพื่อดูว่าโมเดลเลือกใช้ถูกไหม
อธิบายว่า agent ต่างจากการเรียก LLM ครั้งเดียวอย่างไร
agent เรียกโมเดลเป็นลูป: โมเดลตัดสินใจว่าจะตอบเลยหรือเรียกเครื่องมือ โค้ดรันเครื่องมือแล้วส่งผลกลับให้โมเดลเห็น วนจนได้คำตอบ จึงทำงานที่ต้องหาข้อมูลหลายขั้นได้ แต่แลกกับต้นทุน ความช้า และความเสี่ยงที่ต้องควบคุม (จำนวนรอบ สิทธิ์ของเครื่องมือ)
คุณจะดีบัก agent ที่ให้คำตอบผิดอย่างไร
ดู trace ทั้งลำดับ (ข้อความ tool_use อาร์กิวเมนต์ tool_result) ว่าโมเดลเลือกเครื่องมือ/อาร์กิวเมนต์ถูกไหม เครื่องมือคืนอะไร โมเดลตีความผลผิดหรือไม่ แล้วแก้ที่ต้นเหตุ (description ของเครื่องมือ รูปแบบผลลัพธ์ prompt) และเก็บกรณีที่ผิดไว้เป็นชุดทดสอบ
คุณจะออกแบบ agent ที่มีเครื่องมือยกเลิกออเดอร์ให้ปลอดภัยอย่างไร
แยกเครื่องมืออ่านอย่างเดียวกับเครื่องมือเขียน ให้เซสชันทั่วไปเห็นเฉพาะอ่านอย่างเดียว การเขียนต้องผ่านการยืนยันจากผู้ใช้/เจ้าหน้าที่ที่ไม่ได้มาจากโมเดล ตรวจสิทธิ์ผู้ใช้กับทรัพยากร (ยกเลิกได้เฉพาะออเดอร์ของตัวเอง) ใส่ idempotency key จำกัดจำนวนรอบและงบ บันทึก audit log ทุกการกระทำ และทดสอบด้วยกรณี injection
คุณจะวัดคุณภาพของ agent อย่างไร
สร้างชุดทดสอบที่มีเฉลย (คำถาม คำตอบ/ผลที่คาด ลำดับเครื่องมือที่ควรเรียก) วัดอัตราสำเร็จ ความถูกต้องของการเลือกเครื่องมือ จำนวนรอบ/ต้นทุน/เวลา และอัตราการทำงานของ guardrail รันหลายครั้งเพราะผลไม่คงที่ วิเคราะห์เคสที่พลาดจาก trace แล้วเพิ่มเป็นเคสทดสอบ
AI Capstone
เล่าโปรเจกต์ RAG ของคุณใน 1 นาทีให้คนสัมภาษณ์ฟัง
โครง: ปัญหา (ตอบคำถามลูกค้าจากฐานความรู้) → สถาปัตยกรรม (chunk/ค้นหา/prompt ที่ยึดบริบทและอ้างอิง/ตรวจผล/fallback) → วิธีประเมิน (ชุดคำถามมีเฉลย hit@k MRR อัตราการปฏิเสธถูก การอ้างอิงถูกต้อง ต้นทุนต่อคำถาม) → ผลและสิ่งที่พลาด (เช่น หมวด returns ที่ paraphrase) → สิ่งที่ทำต่อ (embeddings, hybrid, reranker) การชี้จุดอ่อนพร้อมตัวเลขทำให้น่าเชื่อถือ