Machine Learning for Recommendation System — Part 2
กลับมาเจอกันอีกครั้งสำหรับ Recommendation System สำหรับใครที่ยังไม่ได้ดูในส่วนของ Part 1 แนะนำให้ไปดูก่อนนะครับ
ก่อนที่จะเข้าสู่เนื้อหาของบทความนี้ เราลองมาพูดทบทวนของเก่าดีกว่า
Content-based เป็นการที่เราพยายามคาดการ rating ของ user ที่มีต่อ item นั้นๆ โดยอาศัย feature ของ item, ในอีกมุมหนึ่ง Collaborative filtering เราพยายามที่จะเรียนรู้ latent feature ซึ่งเป็นสิ่งที่บ่งบอกถึงลักษณะความเป็น user นั้นๆ (ประมาณว่าเป็น feature แฝงของ user แต่ละคน เช่น ปกติ recommendation system สำหรับ n user และ m item สามารถเขียนแทนได้ด้วย matrix ขนาด n x m โดยข้อมูลใน matrix คือ rating หรือ คะแนนที่แต่ละ user ให้กับแต่ละ item ที่เคยผ่านการ review มาแล้ว เราจะสามารถเขียนแทน matrix ขนาด n x m ใหม่ได้ด้วย (n x k) x (k x m) โดยที่ k คือ ขนาดของ latent feature หรือ feature แฝง เช่น ในกรณี recommendation system หนังที่น่าสนใจ ถ้าเราเลือกค่า k = 3 latent feature ตัวแรกอาจจะสื่อถึง ลักษณะ user หรือ หนังที่เป็นดราม่า, ตัวที่สองอาจจะสื่อถึง ลักษณะ user หรือ หนังที่เป็น sci-fi, ตัวที่สามอาจจะสื่อถึง ลักษณะ user หรือ หนังที่เป็นสยองขวัญ เป็นต้น)
Content-based กับ Collaborative filtering นั้นได้รับการยกย่องให้เป็น (วิธีการสำคัญ ถึงขั้น) state of the art มามากกว่า 10 ปี ของวงการ Recommendation System แต่ก็ยังมีปัญหาอยู่ว่า
- สำหรับ Collaborative filtering เป็นเรื่องที่ยากถ้าเราจะเพิ่ม item ใหม่ๆเข้าไปใน System ของเรา เพราะต้องคำนวณใหม่ทั้งหมด
- การใช้ Collaborative filtering อาจจะนำเราไปสู่การแนะนำ popular item ได้ง่าย ซึ่ง itemที่ดังมันก็แน่นอนอยู่แล้วว่าจะถูกแนะนำ แต่เราอาจจะต้องการแนะนำสิ่งใหม่ๆที่หลากหลายนอกเหนือจาก popular item ให้
- Content-based ก็ทำได้แค่แนะนำสิ่งคล้ายๆกัน
นี้ก็เป็นเพียงตัวอย่างข้อด้อยคร่าวๆ และในปัจจุบันก็เลยมีคนพยายามแก้ไขข้อด้อยของวิธีการเก่าๆ เกิดเทคนิคต่างๆ ในบทความนี้เราขอพูดถึง Hybrid approach หรือที่เรียกกันว่า “Learning to Rank” algorithm
Learning to Rank เองก็มีหลายวิธีการ แต่เราขอพูด 2 ตัวที่เกี่ยวข้องกับการ implement ของเราในบทความนี้ ได้แก่ BPR, WARP
Learning to Rank — BPR
BPR หรือ Bayesian Personalized Ranking from Implicit Feedback ไอเดียของมันก็คือการที่เราสุ่ม user ขึ้นมา 1 คน แล้วสุ่ม positive item และ negative item เพื่อนำมาเปรียบเทียบกัน ถ้าเราบอกมีข้อมูลการ click สินค้าต่างๆ เราจะมีขั้นตอนดังนี้
- สุ่ม user u ขึ้นมา และสุ่ม item i ที่เขาเคย click ให้ item นั้น เป็น positive item
- สุ่ม item jขึ้นมาโดยที่มีจำนวน click น้อยกว่า item i เราก็จะได้ negative item
- ใช้สมการสักอย่างเพื่อทำนาย “score” (ซึ่งสมการก็ขึ้นอยู่กับปัญหา) โดยให้ S(u, i) เป็น score สำหรับ user u กับ item i, S(u, j) ก็ในทำนองเดียวกัน
- พอเราได้ S(u, i), S(u, j) มาแล้ว เราจะได้ว่า X(u, i, j) = S(u, i)-S(u, j) โดยมีความหมายว่า user u ชอบ item i มากกว่า item j เท่าไหร่
- โดยวัตถุประสงค์ก็เพื่อต้องการหาสิ่งที่เราไม่รู้จาก user (ในที่นี้ก็คือจำนวน click) เราก็จะลองหาค่ามาแทน แล้วอัพเดตด้วย stochastic gradient descent (SGD)
Learning to Rank — WARP
WARP หรือ Weighted Approximate-Rank Pairwise loss วิธีการก็คล้ายกับ BPR เลย แต่ที่ต่างกันก็คือ การ update ที่ WARP จะ update เฉพาะ ที่ predict ผิด โดยผิดก็คือการที่ เราบอกว่า negative item มีจำนวน click มากกว่า positive item ซึ่งจากงานวิจัยแล้วด้วยวิธีนี้ทำให้มี precision ที่ดีกว่า BPR
Implementation
เรามาลองทำ Recommendation System ให้แนะนำหนังกันดีกว่า
เริ่มต้นเราก็จะ import library ต่างๆ ขอขอบคุณ helper function
from recsys import * # helper function
from generic_preprocessing import * # helper function
from IPython.display import HTMLratings = pd.read_csv('./data/ratings.csv') # load user-item
ratings.head()
หน้าตาที่ได้ก็จะประมาณนี้ ความหมายก็คือ userId ใดๆ ให้ rating หนัง movieId เป็นเท่าไหร่ โดยมีเวลาการให้บอกมา timestamp
movies = pd.read_csv(‘./data/movies.csv’)
movies.head()
ส่วนตารางนี้ก็จะเป็นรายละเอียดของหนัง แล้วเราก็เอาทั้งหมดนี้มาสร้าง interaction ที่ แต่ละ row คือ user แต่ละคน ให้คะแนนหนังแต่ละเรื่องที่แทนแต่ละ col เป็นเท่าไหร่
interactions = create_interaction_matrix(df = ratings,
user_col = 'userId',
item_col = 'movieId',
rating_col = 'rating')
interactions.head()
user_dict = create_user_dict(interactions=interactions)movies_dict = create_item_dict(df = movies,
id_col = 'movieId',
name_col = 'title')mf_model = runMF(interactions = interactions,
n_components = 30,
loss = 'warp',
epoch = 30,
n_jobs = 4)
เรามาลองเทสกันเลย
rec_list = sample_recommendation_user(model = mf_model,
interactions = interactions,
user_id = 11,
user_dict = user_dict,
item_dict = movies_dict,
threshold = 4,
nrec_items = 10,
show = True)Known Likes:
1- Saving Private Ryan (1998)
2- As Good as It Gets (1997)
3- Titanic (1997)
4- Amistad (1997)
5- Contact (1997)
6- Last of the Mohicans, The (1992)
7- Top Gun (1986)
8- Silence of the Lambs, The (1991)
9- Searching for Bobby Fischer (1993)
10- Fugitive, The (1993)
11- Forrest Gump (1994)
12- Clear and Present Danger (1994)
13- Apollo 13 (1995)
14- Braveheart (1995)
15- Heat (1995)
Recommended Items:
1- Independence Day (a.k.a. ID4) (1996)
2- True Lies (1994)
3- Rock, The (1996)
4- Jurassic Park (1993)
5- Pulp Fiction (1994)
6- Mission: Impossible (1996)
7- Terminator 2: Judgment Day (1991)
8- GoldenEye (1995)
9- Star Wars: Episode IV - A New Hope (1977)
10- Cliffhanger (1993)
Code ทั้งหมดอยู่ใน github และก็จบไปแล้วสำหรับ Hybrid approach และไม่ได้มีเพียงเท่านี้ สำหรับใครที่สนใจเทคนิคต่างๆเพิ่มเติม ขอแนะนำ Link เลยครับ
สุดท้ายนี้ ก็ขอฝากเพจ DataWiz ที่จะคอยแบ่งปันความรู้ทางด้านต่างๆ ไม่ว่าจะเป็น machine learning หรือ ai แล้วส่วนเรื่องต่อไปจะเป็นอะไร เดียวมารอติดตามกันในบทความต่อไปกันเลย