Data Science Essential week 7: Recommendation system(อธิบาย code)

Krirk Arunoprayote
botnoi-classroom
Published in
4 min readOct 2, 2020

บทความนี้จะอธิบาย code ใน colab ประกอบการเรียน DSE week 7 : Recommendation system ครับ

Colab นี้ ก็จะเป็นการใช้ NMF มาช่วยสร้างระบบ recommendation โดยในคลาสได้มีการเก็บข้อมูลจากนักเรียนว่าชอบดาราคนไหนบ้าง โดยให้เลือกมา 3 คนตามลำดับความชอบ เก็บข้อมูลมาแค่นี้ จะแนะนำได้แค่ไหน มาลุ้นไปด้วยกันครับ

เริ่มจาก import library ที่จะใช้ และ เปิดไฟล์ google sheet ที่เก็บข้อมูลเอาไว้มาดูกัน

เบื้องต้นก็ sample ข้อมูลมาดูคร่าวๆ ก่อนเลย เห็นว่าบางคนก็กรอกมายาวมาก เช่น user id 39 กรอกแบบมีวงเล็บมาด้วย

พบว่าแต่ละคนก็กรอกมาไม่เหมือนกัน เบื้องต้นก็จะคลีนข้อมูลกันคร่าวๆ โดยจะทำให้เป็นตัวพิมพ์เล็กทั้งหมด ตัด space ออก และเอาข้อความที่มีวงเล็บออก โดยสร้างฟังก์ชั่น clean() ขึ้นมา

note: บรรทัดที่ 4 จะมีการใช้ regular expression r'\([^)]*\)','' ร่วมกับ method replace เพื่อลบข้อความในวงเล็บออกไปครับ

ลองดูก่อนและหลัง clean ครับ ได้ผลลัพธ์ตามตั้งใจ : space และ ข้อความในวงเล็บหายไปแล้ว

จากนั้นก็จะเก็บเอาชื่อดาราที่ไม่ซ้ำกันมาเก็บไว้ใน series ที่ชื่อ actor_name ก็ทำได้โดยการนำข้อมูลทั้งหมดมาต่อกันและดรอปชื่อที่ซ้ำกันออกไป

ต่อไปก็จะเตรียมเปลี่ยนข้อมูลที่เก็บมาให้เป็นตัวเลข โดยเริ่มจากการสร้าง dataframe ใหม่ ให้มีมิติเท่ากับ จำนวนคนที่กรอกข้อมูล x จำนวนชื่อดาราที่ไม่ซ้ำ และมีค่าเป็น 0 ทั้งหมด โดยใช้ np.zeros

จากนั้นก็เติมค่าเข้าไป ถ้าชอบดาราคนไหนที่สุด ให้ค่า = 3 รองลงมา = 2 และ 1 ตามลำดับ ก็ทำลูปตาม code ก็คือการไปเช็ค user แต่ละคน จาก clean_df ว่าชอบใครบ้าง แล้วมาใส่ค่า 3,2,1 ใน cmat ตามลำดับความชอบ

เมื่อได้ข้อมูลมาเรียบร้อย แต่ว่าข้อมูลส่วนใหญ่มีค่าเป็น 0 Matrix ของเรา sparse มากๆ เราก็มาทำ Matrix Factorization โดยใช้ NMF กัน

Non-negative Matrix Factorization(NMF)

NMF เป็น การวิธีทำ matrix factorization วิธีการหนึ่ง โดยมีเงื่อนไขคือ ค่าใน matrix ต้องไม่เป็นค่าติดลบ (Non-negative) เราก็จะต้องเลือกค่า f เพื่อแตก matrix ออกเป็น 2 matrix ย่อย ตามที่ได้อธิบายในบทความสรุปเนื้อหา https://medium.com/botnoi-classroom/data-science-essential-week-7-recommendation-system-%E0%B8%AA%E0%B8%A3%E0%B8%B8%E0%B8%9B%E0%B9%80%E0%B8%99%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%AB%E0%B8%B2-c8402549399c

เบื้องต้น เลือกค่า f = 20 มาทดสอบก่อน ก็สร้าง NMF model ขึ้นมา แล้วใส่ cmat เข้าไปเทรน

ก็จะได้ matrix ย่อย มา 2 ตัว ตัวแรกตั้งชื่อว่า H โดยรับค่าจากค่าที่เก็บไว้ใน nmf.components_ เราก็จะใช้ np.round ช่วยปัดเศษให้เหลือทศนิยม 2 ตำแหน่ง เอาชื่อ columns มาจาก cmat

ตัวที่2 ตั้งชื่อว่า W โดยโดยเรียกค่าจากค่าที่เก็บไว้ใน nmf.transform(cmat) และใช้ np.round ช่วยปัดเศษให้เหลือทศนิยม 2 ตำแหน่งเช่นกัน และเอาชื่อ column มาจาก index ของ matrix H

นำ W มาคูณแบบดอทกับ H ก็จะได้เป็น matrix reconstructed ซึ่งจะมีค่าใกล้เคียงกับข้อมูลเดิมใน cmat และจะเห็นว่ามีบางข้อมูลเดิมที่เป็น 0 นั้น ตัว NMF ได้เติมค่าเข้ามาให้ด้วย แสดงว่าเราได้ข้อมูลเพิ่มขึ้นมาแล้ว คราวนี้เราก็น่าจะแนะนำดาราได้มากกว่า 3 คนแล้ว

ในทางปฏิบัตินั้น เราก็จะต้องลองค่า f หลายๆ ค่า แล้วดูว่า ค่า f เท่ากับเท่าไหร่ที่ทำให้เราได้ error น้อยที่สุด โดยอาจวนลูป แล้วเช็คค่า error ซึ่งก็ควรเลือกใช้ r2_score เพราะเป็นการรวม error ทั้งกรณีที่ทำนายค่าได้มากและน้อยกว่าความจริง เข้าด้วยกัน

จากนั้นก็สร้างฟังก์ชั่น recomendation() โดยเป็นการดูว่า user id (uid) คนนี้ ชอบดาราคนไหนบ้าง โดยเลือกจำนวนดาราตามค่า topk ที่ใส่เข้าไป โดยค่า default = 5 ก็คือเรียกมาดู 5 คนแรก

อธิบาย code : ลองดูหน้าตาไปทีละขั้นตอน เริ่มจาก reconstructed.T เป็นการ transpose matrix reconstructed ของเรา

ลองทดสอบด้วยค่า uid = 5 และ topk = 20 ก็จะได้เป็น ดารา 20 คนแรก ที่ user id 5 ชอบมากที่สุด

ต่อไปก็จะมาลอง recommend กันแล้ว ก่อนอื่น ก็ต้องสร้าง feature vector ของเราขึ้นมาก่อน ตั้งชื่อว่า my_feature โดยเริ่มต้น ก็ให้ทุกค่าเป็น 0 เพราะเรายังไม่ได้ให้ข้อมูลว่าเราชอบดาราคนไหน

เราจะทดลองใส่ข้อมูลเข้าไปว่าเราชอบ เจนนี่blackpink = 2 ก็ทำได้ตาม code

อธิบาย code ตามบรรทัด:
1 : ลองใส่ข้อมูลเข้าไปว่าเราชอบ เจนนี่blackpink = 2
6 : สร้าง list เปล่าชื่อ similarity ไว้เตรียมเก็บข้อมูลว่า my_feature มีความคล้ายกับ feature vector ของ user id คนอื่นๆ มากน้อยเพียงใด โดยเราสามารถคำนวณความคล้ายคลึงกันของ 2 vector ได้ เท่ากับ 1-(cosine ของ 2 vectorนั้น)
7–8 : วนลูป คำนวณหา similarity ระหว่าง my_feature กับ feature vector ของ user id แต่ละคน แล้วเก็บค่าที่ได้ไว้ใน list ชื่อ similarity
9 : print ค่า similarity ออกมาดู

จะเห็นว่าบางครั้งการคำนวณ similarity จะได้ค่าออกมาเป็น nan ด้วย (ดูที่วงสีแดงไว้) เราก็ต้อง เปลี่ยนค่า nan ให้เป็น 0 ก่อน (เพราะค่า nan เป็นค่าตัวเลขที่มาก ไม่อย่างนั้น เราก็จะมีค่าใกล้เคียงกับคนที่เป็นค่า nan ตลอด) โดยใช้ fillna(0) ใน code บรรทัดที่ 11

15 : ใช้ np.argsort เรียงลำดับค่าจากน้อยไปมาก แล้วเราก็เอาผลลัพธ์ตัวสุดท้าย ซึ่งเป็นตัวที่มีค่ามากที่สุด มาเก็บไว้ในตัวแปร close_to
16 : print ค่า clost_to ออกมาดู ในที่นี้ก็คือ uid 47
17 : print ค่า similartiy ออกมาดู ได้ค่า 0.0687

อธิบายผลลัพธ์ได้ดังนี้

จากการที่เราให้ข้อมูลว่า เราชอบ เจนนี่blackpink = 2 เมื่อไปคำนวณหาความคล้ายกับ feature vector ของคนอื่นแล้ว พบว่า เรามีความคล้ายกับ uid 47 มากที่สุด โดยมีค่าความคล้าย = 0.0687

เราก็สามารถ recommend ดาราคนอื่น ได้ โดยใช้ฟังก์ชั่น recomendation ที่เราสร้างไว้ข้างต้น โดยใช้ค่า userid = close_to (ซึ่งก็คือ 47) และ ให้แสดงผล 10 คนแรก

เย้! ได้ผลลัพธ์ออกมาแล้ว ถึงแม้ว่านักเรียนจะกรอกข้อมูลดาราที่ชอบมาแค่ 3 คน แต่เราสามารถ แนะนำ ดาราที่น่าจะชอบออกมาถึง 10 คนได้เลย ก็ต้องขอบคุณเทคนิค Matrix factorization ที่ช่วยเติมข้อมูลให้เราครับ

--

--

Krirk Arunoprayote
botnoi-classroom

AI enthusiast, currently working as Data Scientist at Botnoi Consulting Co., Ltd.