Professional Documents
Culture Documents
Xây Dựng Chương Trình Gợi ý Phim Dựa Vào Tập Dữ Liệu Movie Len
Xây Dựng Chương Trình Gợi ý Phim Dựa Vào Tập Dữ Liệu Movie Len
Lời mở đầu
MovieLens là một tập dữ liệu được sử dụng rộng rãi cách đây nhiều năm. Hôm nay, mình
sẽ sử dụng tập dữ liệu này và mô hình ALS của spark để xây dựng chương trình dự đoán
phim cho người dùng.
Chuẩn bị dữ liệu
Các bạn có thể download tập dữ liệu MovieLens ở
link https://grouplens.org/datasets/movielens/. Các bạn có thể download trực tiếp 2 file
nén ở link http://files.grouplens.org/datasets/movielens/ml-latest-small.zip và
link http://files.grouplens.org/datasets/movielens/ml-latest.zip.
Ở trên bao gồm 2 tập dữ liệu. chúng ta tạo thư mục datasets và download rồi bỏ chúng
vào trong thư mục đấy.
complete_dataset_url = 'http://files.grouplens.org/datasets/movielens/ml-latest.zip'
small_dataset_url = 'http://files.grouplens.org/datasets/movielens/ml-latest-
small.zip'
import os
datasets_path = 'datasets'
if not os.path.exists(datasets_path):
os.makedirs(datasets_path))
import urllib
import zipfile
if not os.path.exists(small_dataset_url):
small_f = urllib.urlretrieve (small_dataset_url, small_dataset_path)#Download
with zipfile.ZipFile(small_dataset_path, "r") as z:#Giải nén
z.extractall(datasets_path)
if not os.path.exists(small_dataset_url):
complete_f = urllib.urlretrieve (complete_dataset_url,
complete_dataset_path)#Download
with zipfile.ZipFile(complete_dataset_path, "r") as z:#Giải nén
z.extractall(datasets_path)
Trong thư mục giải nén, chúng ta sẽ có các file ratings.csv, movies.csv, tags.csv,
links.csv, README.txt.
Lưu ý nhỏ:
Ở tập dữ liệu ratings, chúng ta chỉ giữ lại các trường (UserID, MovieID,
Rating) bỏ đi trường timestamp vì không cần thiết.
Ở tập dữ liệu movies chúng ta giữ lại trường (MovieID, Title) và bỏ đi trường
genres vì lý do tương tự.
small_movies_raw_data = sc.textFile(small_movies_file)
small_movies_raw_data_header = small_movies_raw_data.take(1)[0]
Collaborative Filtering
Ở đây, tôi sẽ không đề cập đến lọc cộng tác là gì, các bạn có nhu cầu tìm hiểu có thể
xem ở bài post khác hoặc tham khảo trên wiki. Chúng ta sẽ tập trung vào tìm hiểu cách
sử dụng ALS trong thư viện MLlib của Spark. Các tham số của thuật toán này bao gồm:
numBlocks: số lượng block được sử dụng trong tính toán song song (-1 với ý
nghĩa là auto configure).
rank: số lượng nhân tố ẩn (latent factor) trong mô hình.
iterations: số lần lặp.
lambda: tham số của chuẩn hoá(regularization ) trong ALS.
implicitPrefs specifies whether to use the explicit feedback ALS variant or one
adapted for implicit feedback data.
alpha is a parameter applicable to the implicit feedback variant of ALS that governs
the baseline confidence in preference observations.
Chọn các tham số cho ALS
Để chọn được các tham số tốt nhất cho mô hình ALS, chúng ta sẽ sử dụng tập small để
grid search. Đầu tiên, chúng ta chia tập dữ liệu thành 3 phần là tập train, tập vali và tập
test. Sau đó tiến hành huấn luyện trên tập train và predict trên tập valid để tìm được tham
số tốt nhất. Cuối cùng đánh giá kết quả đạt được trên tập test.
seed = 5L
iterations = 10
regularization_parameter = 0.1
ranks = [4, 8, 12]
errors = [0, 0, 0]
err = 0
tolerance = 0.02
min_error = float('inf')
best_rank = -1
best_iteration = -1
for rank in ranks:
model = ALS.train(training_RDD, rank, seed=seed, iterations=iterations,
lambda_=regularization_parameter)
predictions = model.predictAll(validation_for_predict_RDD).map(lambda r: ((r[0],
r[1]), r[2]))
rates_and_preds = validation_RDD.map(lambda r: ((int(r[0]), int(r[1])),
float(r[2]))).join(predictions)
error = math.sqrt(rates_and_preds.map(lambda r: (r[1][0] - r[1][1])**2).mean())
errors[err] = error
err += 1
print('For rank %s the RMSE is %s' % (rank, error))
if error < min_error:
min_error = error
best_rank = rank
print(predictions.take(3))
[((32, 4018), 3.280114696166238),
((375, 4018), 2.7365714977314086),
((674, 4018), 2.510684514310653)]
Tập dữ liệu trả về bao gồm cặp (UserID, MovieID) và Rating (tương ứng với colum 0,
column 1 và column 2 ở trên),được hiểu ở đây là với người dùng UserID và phim MovieID
thì mô hình sẽ dự đoán người dùng sẽ rating kết quả Rating.
Sau đó chúng ta sẽ nối(join) chúng với tập valid tương ứng theo cặp (UserID, MovieID),
kết quả đạt được là:
rates_and_preds.take(3)
[((558, 788), (3.0, 3.0419325487471403)),
((176, 3550), (4.5, 3.3214065001580986)),
((302, 3908), (1.0, 2.4728711204440765))]
Việc còn lại là chúng ta sẽ tính trung bình độ lỗi bằng hàm mean() và sqlt().
# Parse
complete_ratings_data = complete_ratings_raw_data.filter(lambda line:
line!=complete_ratings_raw_data_header)\
.map(lambda line: line.split(",")).map(lambda tokens:
(int(tokens[0]),int(tokens[1]),float(tokens[2]))).cache()
# Parse
complete_movies_data = complete_movies_raw_data.filter(lambda line:
line!=complete_movies_raw_data_header)\
.map(lambda line: line.split(",")).map(lambda tokens:
(int(tokens[0]),tokens[1],tokens[2])).cache()
new_user_ID = 0
complete_data_with_new_ratings_RDD =
complete_ratings_data.union(new_user_ratings_RDD)
t0 = time()
new_ratings_model = ALS.train(complete_data_with_new_ratings_RDD, best_rank,
seed=seed,
iterations=iterations,
lambda_=regularization_parameter)
tt = time() - t0
new_user_recommendations_rating_RDD.join(complete_movies_titles).join(movie_rating_co
unts_RDD)
new_user_recommendations_rating_title_and_count_RDD.take(3)
Hiển thị top recommend (Ở đây sẽ flat dữ liệu hiển thị thành dàng ((Title, Rating,
Ratings Count)) ra cho dễ nhìn).
new_user_recommendations_rating_title_and_count_RDD =
new_user_recommendations_rating_title_and_count_RDD.map(lambda r: (r[1][0][1],
r[1][0][0], r[1][1]))
top_movies = new_user_recommendations_rating_title_and_count_RDD.filter(lambda r:
r[2]>=25).takeOrdered(25, key=lambda x: -x[1])
o Machine learning
o Deeplearning
o Spark