پیشنهاد فیلم

تغییرات پروژه از تاریخ 1396/11/11 تا حالا
سامانه پیشنهاد فیلم شاخه ای از سامانه های توصیه گر محسوب می شود.سامانه ی توصیه گر سامانه ای است که با بررسی رفتار کاربر خود، مناسب ترین داده را به وی پیشنهاد می نماید.
هدف از این پروژه توسعه یک سامانه پیشنهاد فیلم می‌باشد که با استفاده از سابقه فیلم‌های دیده شده توسط یک کاربر و امتیازات او به فیلم‌ها، بتواند فیلمی را مطابق سلیقه کاربر به او پیشنهاد بدهد.
پایه ای ترین ایده برای ساخت یک سیستم پیشنهاد فیلم  این است که اگر دو کاربر به یک فیلم علاقه مند بودند در آینده هم فیلم های مورد علاقه مشترکی خواهند داشت.
به عنوان مثال اگر کاربر یک و دو از یک فیلم خوششان بیاید  و کاربر یک  به یک فیلم علاقه مند باشد . که کاربر دو هنوز آن را ندیده باشد سیستم ما آن فیلم را به کاربر دو پیشنهاد خواهد داد.

#مقدمه 

یکی از مشکلاتی که خیلی از افراد ممکن است داشته باشند پیدا کردن فیلم مورد علاقه آن ها ست.
بیشتر افراد به دلیل کمبود وقت ،عدم وجود حوصله کافی برای جست و جو  و  غیره به یک سیستم که با توجه به علاقه مندی ها قبلی آ ن ها بتواند فیلم مورد علاقه ان ها را پیشنهاد دهد.
الگوریتم های زیادی برای ایجاد یک سیستم پیشنهادی وجود دارد که هرکدام مزیا و معایبی خاص خود را دارند مانند:
۱-Collaborative filtering
۲-cluster analysis
# کار های مرتبط
**۱-Collaborative filtering**
یکی از الگوریتم های رایج است که افراد  مبتدی در حوزه علم داده از ان استفاده می کنند.[5]
دو روش اصلی برای این الگوریتم وجود دارد:
۱-براساس کاربر
۲-بر اساس ایتم(فیلم ) ها
۳-یادگیری عمیق (deep learning)
در هردو روش دو قدم اصلی وجود دارد
۱-چه تعداد کاربر یا فیلم در پایگاه داده  شباهت به کاربر یا فیلم داده شده دارند.
۲-دسترسی به فیلم بقیه کاربر ها  و پیش بینی نمره ای کاربر به فیلم خواهد داد و مقایسه با میانگین نمرات همه کاربران 
 ماتریس تجزیه برای پیشنهاد ها 
![توضیح تصویر](https://boute.s3.amazonaws.com/238-1_ceC5qGNTYwjePCudL3eYdQ.png)
 در ماتریس u به معنای وکتوری از علاقه مندی ها ی کاربر  و v به معنای وکتور  پارامتر های   j امین فیلم 
 به عنوان مثال
 ![توضیح تصویر](https://boute.s3.amazonaws.com/238-0_sk4ng-D6cKW_HOT8.png)

 (۱.۴،۹) برای تد  و (۱،۴،۸) برای فیلم A  حال می توانیم نمره برای فیلم a- ted  را می توانیم با ضرب(dot)   بنابراین 2.68  نتیجه می شود.

**2-خوشه  (clustering)**
روش قبلی ساده ،  برای سیستم های کوچک بود ولی  روشی که الان به شرح ان میپردازیم برای سیستم های بزرگ و زمانی که داده به اندازه کافی داریم  کاربرد دارد.
 در این روش باید خوشه هایی دارای فیلم های مشخصی هستند را دسته بندی کنیم و کاربران را براساس خوشه ای که هستند پیشنهاد هایی را دریافت میکنند[4]



#ازمایش ها
  در اینجا می خواهیم با استفاده از دیتا ست MovieLens،اسپارک  و فریمورک فلسک(flask)  یک وب سرویس بنویسیم.
                                                                                                                                                                                                                                                 **اسپارک**
  اسپارک محاسباتی خوشه ای سبک و سریع برای محاسبات سریع طراحی شده است.
اسپارک در لایه بالایی Hadoop MapReduce می باشد و مدل MapReduce را برای موثر بودن انواع بیشتری از محاسباتی که شامل کوئری های تعاملی (Interactive Queries) و جریان پردازش (Stream Processing) می باشد ، گسترش می دهد.[6]
هدوپ (hadoop) یک پروژه مبتنی بر برنامه نویسی متن باز است که توسط سازمان نرم افزاری آپاچی ایجاد شده است. ایده اولیه هدوپ اولین بار در شرکت گوگل رقم خورد اما خیلی ها باور به پیاده سازی این سیستم نداشتن و در چند سال اول این ایده تنها بصورت تئوری مطرح بود. هدوپ امکان ذخیره سازی اطلاعات را در چندین سرور ( پی سی) با هزینه ای پایین فراهم می آورد.کلودرا شرکتی است که بصورت فعال در این زمینه فعال می باشد و بسته نرم افزاری بی نظیر هدوپ را ایجاد کرده و آن را انتشار داده و پشتیبانی می کند.تکنولوژی هدوپ از دو بخش کلی اچ دی اف اس یا سیستم فایل انتشاری هدوپ (Hadoop Distribition File System) و همچنین تکنیک با کیفیت پردازی اطلاعات به نام مپ ریدیوس (MapReduce) استفاده می کند.[7]
                                                                                                                                                                                                                                                    **هسته اسپارک**
هسته Spark شامل قابلیت های اساسی Spark از قبیل اجزایی برای زمان بندی وظیفه،مدیریت حافظه، ترمیم خطا، تعامل با سیستم های ذخیره سازی و دیگر اجزا است.همچنین هسته Spark مکان API ای است که مجموعه داده ای توزیع شده ارتجاعی(resilient distributed datasets-RDD) که انتزاع برنامه نویسی اصلی Sparkاست را تعریف می کند. RDD ها مجموعه اقلام توزیع شده در چندین گره پردازشی که می توانند بطور موازی استفاده شوند، را نشان می دهد.
**درشت**پردازش اطلاعات 
ابتدا ادرس را برای دانلود تعریف می کنیم سپس فایل ها را از حالت فشرده خارج میکنیم.
![توضیح تصویر](http://uupload.ir/files/irt8_screen_shot_2018-01-28_at_2.39.13_pm.png)
 **بازگزاری و پارس کردن دیتا ست ها**
حال فایل های اماده شده  و اماده خوانده شدن هستند . 
باید  RDD  تشکلیل شده از لاین ها پارس شده درست کنیم.
فرمت خطوط فایل ها:
فایل رتبه بندی  (Rating.csv)
                                                                                                                                                                                             userId,movieId,rating,timestamp
   فایل فیلم ها( Movie.csv )
   `movieId,title,genres`
    فایل تگ ها(tags.csv)
    `userId,movieId,tag,timestamp`
    فایل لینک ها(links.csv)
    `movieId,imdbId,tmdbId`
    فرمت این فایل ها  ساده است، بنابراین ما می توانیم از split () پایتون استفاده کنیم تا خطوط خود را پس از بارگذاری در RDD ها تجزیه کنیم. تجزیه فیلم ها و فایل های رتبه بندی  RDD را انجام می دهد:
![توضیح تصویر](http://uupload.ir/files/s31b_screen_shot_2018-01-28_at_2.43.51_pm.png)
برای هر خط در مجموعه داده های رتبه بندی، ما یک دسته از (UserID، MovieID، Rating) ایجاد می کنیم. ما time stamp را از حذف میکنیم م زیرا نیازی به ان نداریم
برای هر خط در مجموعه داده های فیلم، یک سری(tuple) از (MovieID، Title) ایجاد می کنیم .و فیلد ژانر را حذف میکنیم زیرا نیازی به ان نداریم.
حال اطلاعات  در داخل RDD جدید بارگزاری میکنیم.

** روش Collaborative Filtering**
 ما در این روش پیش بینی مان برای  علاقه کاربر بوسیله جمع اوری اطلاعات  مربوط به ترجیها ت یا سلایق از تعداد زیادی از کاربران
 اگر کاربر ۱ فیلمی را دوست داشته باشد و کاربر ۲ هم همین فیلم را دوست داشته باشد احتمال اینکه اگر کاربر  ۱ فیلم دیگر را دوست داشته باشد و کاربر ۲ هم همین نظر را داشته باشد بیشتر است .
 ![توضیح تصویر](https://boute.s3.amazonaws.com/238-Collaborative_filtering.gif)
 کتابخانه  MLib  اسپارک برای یادگیری ماشین   روش گفته شده را بوسیله Alternating Least Squares پیاده سازی میکند.
   کتابخانه  MLib دارای پارامتر های زیر است:
   ۱-numBlocks :تعداد بلوک هایی که برای پردازش موازی استفاده می شود
   ۲-rank :تعداد عوامل پنهان در مدل
   ۳-iterations:تعداد   iterations برای اجرا 
   ۴-lambda:پارامتر های تنظیم (regularization) را مشخص می کند
   ۵-implicitPrefs:مشخص می کند ایا از روش بازخورد صریح ALS یا یکی برای داده های بازخورد ضمنی استفاده شود.
   ۶-alpha:یک پارامتر قابل استفاده برای نوع بازخورد ضمنی ALS است که اعتبار پایه را در مشاهدات ترجیحی کنترل می کند.
  **انتخاب پارامتر های ALS  با استفاده از دیتا ست**      
  برای برست اوردن بهترین پارامتر ها  باید باید ابتدا دیتا ست ها را به train، validation,  test datasets  جدا می کنیم.  
 ![توضیح تصویر](http://uupload.ir/files/te0_screen_shot_2018-01-28_at_2.46.36_pm.png)       
For rank 4 the RMSE is 0.963681878574
For rank 8 the RMSE is 0.96250475933
For rank 12 the RMSE is 0.971647563632
The best model was trained with rank 
حال ابتدا نگاهی به پیش بینی  می اندازیم
 ```
predictions.take(3)
```[((32, 4018), 3.280114696166238),
 ((375, 4018), 2.7365714977314086),
 ((674, 4018), 2.510684514310653)]
```                                                                                         
 ما UserID، MovieID و Rating  را داریم، همانگونه که در مجموعه داده های رتبهrating  ما وجود دارد. در این مورد، عنصر سوم پیش بینی، رتبه بندی برای آن فیلم و کاربر، پیش بینی شده توسط مدل ALS  است.
سپس ما با داده های اعتبار سنجی ما (یکی از آنهایی که شاملRating   میشود) به آن اضافه می کنیم و نتیجه به شرح زیر است:
```
rates_and_preds.take(3)
``````
[((558, 788), (3.0, 3.0419325487471403)),
 ((176, 3550), (4.5, 3.3214065001580986)),
 ((302, 3908), (1.0, 2.4728711204440765))]
```
به این منظور، ما یک تفاوت مجذور(squared difference ) را  اعمال می کنیم و ما از عمل mean () برای دریافت MSE و انجام از sqrt    استفاده می کنیم
در نهایت ما مدل انتخاب شده را آزمایش می کنیم.
model = ALS.train(training_RDD, best_rank, seed=seed, iterations=iterations,
                      lambda_=regularization_parameter)
predictions = model.predictAll(test_for_predict_RDD).map(lambda r: ((r[0], r[1]), r[2]))
rates_and_preds = test_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())
print 'For testing data the RMSE is %s' % (error)
For testing data the RMSE is 0.972342381898
 **درست کردن  سیستم پیشنهادی**
هنگام استفاده از فیلتر همگانی( collaborative filtering)، گرفتن پیشنهاد ها  برای  پیش بینی ورودی های جدید با استفاده از یک مدل قبلا تولید شده ساده نیست. در عوض، ما باید مجددا آموزش مدل، اما شامل تنظیمات جدید کاربر به منظور مقایسه آن با سایر کاربران در مجموعه داده ها پس در هر بار که کاربران جدیدی اضافه شود ما باید دوباره سیستم پیشنهادی خود را  تغییر دهیم که باعث هزینه زیادی میشود در اینجا اسپارک به عنوان یک راه حل ارایه میشود که می تواند
 به محضی که ما مدل را اماده کردیم خود را با کاربر های جدید وقف دهد  هزینه ها را کاهش دهد.
 حال فایل فیلم ها را بارگزاری می کنیم.
 ![توضیح تصویر](http://uupload.ir/files/np4t_screen_shot_2018-01-28_at_2.57.05_pm.png)
There are 27303 movies in the complete dataset
حال تابع  تعداد امتیاز ها و میانگین ان ها  به ازای هر فیلم
![توضیح تصویر](http://uupload.ir/files/ru8y_screen_shot_2018-01-28_at_2.58.21_pm.png)

**اضافه کردن امتیاز کاربر های جدید**
با اضافه کردن تعدادی فیلم برای کاربر های جدید ما ان ها را در RDD  جدید  قرار می دهیم.
![توضیح تصویر](http://uupload.ir/files/8oh6_screen_shot_2018-01-28_at_2.59.41_pm.png)
حال اطلاعات جدید را به اسپارک اضافه می کنیم 
complete_data_with_new_ratings_RDD = complete_ratings_data.union(new_user_ratings_RDD)
سپس ALS  مدل خود را با دیتا جدید اماده می کنیم.
new_ratings_model = ALS.train(complete_data_with_new_ratings_RDD, best_rank, seed=seed, iterations=iterations, lambda_=regularization_parameter)
**گرفتن پیشنهاد های جدید**
در ابتدا باید  RDD را با فیلم هایی که کاربر هنوز امتیاز نداده بدست بیاوریم.
به انها برای پیش بینی امتیاز فیلم نیاز داریم.
حال می توانیم ۲۵  فیلم با بیشترین امتیاز  پیش بینی شده را ببینیم و با RDD   پیوند دهیم (join) تا مشخصات فیلم ها بدست اید.
![](http://uupload.ir/files/nu0e_screen_shot_2018-01-28_at_5.53.25_pm.png)
 **نتایج **
![](http://uupload.ir/files/qj44_screen_shot_2018-01-28_at_5.58.43_pm.png)
  **مدل**
![](http://uupload.ir/files/o72r_screen_shot_2018-01-28_at_6.01.42_pm.png)

برای وب سرویس نیاز به سه فایل خواهیم داشت.
فایل ها شامل engine ,app.server  است.
**موتور (engine )** 
وقتی موتور (engine ) شروع به کار می کند. ما نیاز به تولید als مدل  داریم و همچنین نیاز به بارگزاری مدل برای دادن پیشنهاد هستیم.
![](http://uupload.ir/files/v4xf_screen_shot_2018-01-28_at_6.20.36_pm.png)
**اضافه کردن رتبه های جدید**
![](http://uupload.ir/files/fklk_screen_shot_2018-01-28_at_6.23.45_pm.png)
 **ارایه پیشنهاد**
 ![](http://uupload.ir/files/w3zf_screen_shot_2018-01-28_at_6.26.03_pm.png)
** ۲-app**
 وب سرویس با فلسک که یکی میکروفریمورک برای پایتون درست خواهد شد.
 خروجی  توابع  با جیسون خواهد بود.
 ![](http://uupload.ir/files/92ya_screen_shot_2018-01-28_at_6.41.30_pm.png)
 ![](http://uupload.ir/files/san1_screen_shot_2018-01-28_at_6.41.36_pm.png)
 در هنگام فراخوانی create_app  شی از recomondation  ایجاد می شود.
 همچنین url   و پارامتر های متد در بین <> قرار میگیرد.
 همچنین از متد های رایج  post و get هم استفاده شده.
 
** پیاده سازی سرور**
![](http://uupload.ir/files/qsxx_screen_shot_2018-01-28_at_8.09.35_pm.png)
فریمورک چری به ما کمک می کند تا اپلیکشن های خود را مانند یک برنامه شی گرا توسعه داد.
**تست سرویس**
برای اضافه کردن رتبه بندی جدید از دستور زیر استفاده  می کنیم. 
رتبه بندی جدید را در فایل  user_ratings.file   قرار می دهیم.
curl --data-binary @user_ratings.file http://<ip>:5432/0/ratings
برای گرفتن پیشنهاد های جدید از دستور زیر استفاده می کنیم.
به جای number از تعداد پیشنهاد های مورد نظر استفاده می کنیم.
http://<ip>:5432/0/ratings/top/number

 لینک گیت هاب : https://github.com/smmousavi76/MovieRecommendationAI
#کارهای مرتبط
بررسی سایت های برتر جهان در زمینه پیشنهاد فیلم 
۱-**[Jinni](http://jinni.com/)**
یکی از بهترین سایتهای پیشنهاد فیلم که می تواند بر اساس فیلم های سرچ شده و حتی براساس حس و حالی که در ان هستید به شما فیلم پیشنهاد کند.
۲-**[Taste Kid](http://www.tastekid.com/)**
این سایت می تواند به شما بر اساس فیلمی که دوست دارید. ،فیلم های مشابه و کتاب هایی را که ممکن است بر اساس سلیقه شما در انتخاب فیلم به شما پیشنهاد کند.
۳-**[Nanocrowd](http://www.nanocrowd.com/)**
این وبسایت شاید در ظاهر شبیه بقیه سایت ها باشد اما در پشت سرچ شما از الگوریتم خود به نام three-word nanogenre  فیلم هایی را به شما پیشنهاد میکند که حتی ممکن از فیلم های پر فروش دنیا هم نباشند.
۴-**[IMDb](http://imdb.com/)**
این سایت  براساس سرچ کاربر به او فیلم ها را پیشنهاد میدهد و وقتی در صفحه یک فیلم است فیلم های مشابه که کاربر ممکن است ان ها را دوست داشته باشد را پیشنهاد  میدهد.
در واقع به بررسی کاربران نمی پردازد بلکه به بررسی نقاط مشترک  فیلم ها می پردازد.
۵-**. [Rotten Tomatoes](http://au.rottentomatoes.com/browser.php?navsection=home&type=2&genre=&subgenre=&tomatometer=&avgrating=&mpaa=&letter=&decade=&year=&video_format=&title_search=&person_search=&plot_search=&sort=NumArticles+DESC&start_index=0&page=)**
این سایت به جای پرسیدن کدام فیلم را دوست دارید از شما می پرسد که کدام بازیگر یا ژانر را دوست دارید و بر اساس ان به شما فیلم مورد علاقه تان را پیشنهاد می کند.


#کارهای آینده




## پیوندهای مفید
1. [MovieLens dataset](https://grouplens.org/datasets/movielens/)
2. [Building a Movie Recommendation System](https://rpubs.com/jeknov/movieRec)
3.[Recommendation System](https://stackoverflow.com/questions/5253362/how-to-build-a-movie-recommender-system)
4.[Cluster analysis](https://en.wikipedia.org/wiki/Cluster_analysis)
5.[Recommendation System Algorithms](https://blog.statsbot.co/recommendation-system-algorithms-ba67f39ac9a3)
6.[Spark](https://spark.apache.org)
7.[Hadoop](http://hadoop.apache.org/)