Basic Content Based Recommendation
Contents
Basic Content Based Recommendation#
[4]:
import numpy as np
import tensorflow as tf
[5]:
users = [ 'user1', 'user2', 'user3', 'user4' ]
movies = [ 'movie1', 'movie2', 'movie3', 'movie4', 'movie5', 'movie6']
features = [ 'action', 'drama', 'scifi', 'comedy', 'animated']
n_users = len(users)
n_movies = len(movies)
n_features = len(features)
References#
Strategy#
create a user-item matrix.
create a item-feature matrix.
multiplying user-item and item-feature, to create user-feature matrix.
normalize user-feature matrix.
create a user and non-interacted item matrix, to only recommend non-interacted items to users.
elementwise multiplication of user-item and user-non_interacted_item matrix to get only ratings of non interacted items.
get indexes of top k rated non interacted items, k number of recommendations.
user-item matrix#
sparse matrix for user and items rating matrix.
items
+-------------+
| |
users | |
| |
| |
| |
+-------------+
shape \((n_{users}, n_{items})\)
[6]:
users, movies
[6]:
(['user1', 'user2', 'user3', 'user4'],
['movie1', 'movie2', 'movie3', 'movie4', 'movie5', 'movie6'])
[7]:
user_movies = tf.constant([
[5, 6, 8, 0, 0, 1],
[0, 0, 10, 10, 0, 5],
[0, 9, 5, 5, 0, 0],
[1, 5, 0, 0, 0, 5]
], dtype=tf.float32)
item-feature martix#
k-hot encoded matrix of item and feature matrix.
features
+-------------+
| |
items | |
| |
| |
| |
+-------------+
shape : \((n_{items}, n_{features})\)
[8]:
movies, features
[8]:
(['movie1', 'movie2', 'movie3', 'movie4', 'movie5', 'movie6'],
['action', 'drama', 'scifi', 'comedy', 'animated'])
[9]:
movie_features = tf.constant([
[1, 0, 1, 0 ,0],
[0, 1, 0, 1, 0],
[0, 1, 0, 1, 1],
[1, 1, 0, 0, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1]
], dtype=tf.float32)
user-feature matrix#
\((n_{users}, n_{items}) \times (n_{items}, n_{features})\)
items features features
+-------------+ +-------------+ +-------------+
| | | | | |
users | | items | | users | |
| | X | | = | |
| | | | | |
| | | | | |
+-------------+ +-------------+ +-------------+
___
|
item_1 item_2 item_3 | feature_1 feature_2 feature_3
+---------------------------+ | +-----------------------------------------+
user_1 | | item_1 |
| represents user | | individual features for different
user_2 | and items relation | item_2 | items
| | |
| item_3 |
| |
|
|
[10]:
user_feaures = user_movies @ movie_features
user_feaures
[10]:
<tf.Tensor: shape=(4, 5), dtype=float32, numpy=
array([[ 5., 14., 6., 15., 9.],
[10., 20., 5., 15., 25.],
[ 5., 19., 0., 14., 10.],
[ 1., 5., 6., 10., 5.]], dtype=float32)>
normalizing the matrix
[11]:
user_features_norm = user_feaures / tf.reduce_sum(user_feaures, axis=0, keepdims=True)
user_features_norm
[11]:
<tf.Tensor: shape=(4, 5), dtype=float32, numpy=
array([[0.23809524, 0.2413793 , 0.3529412 , 0.2777778 , 0.18367347],
[0.47619048, 0.3448276 , 0.29411766, 0.2777778 , 0.5102041 ],
[0.23809524, 0.3275862 , 0. , 0.25925925, 0.20408164],
[0.04761905, 0.0862069 , 0.3529412 , 0.18518518, 0.10204082]],
dtype=float32)>
user feature preference#
get top k values from the user-feature matrix.
tensorflow’s function to get top k values.
[12]:
tf.nn.top_k(user_features_norm, k=1)
[12]:
TopKV2(values=<tf.Tensor: shape=(4, 1), dtype=float32, numpy=
array([[0.3529412],
[0.5102041],
[0.3275862],
[0.3529412]], dtype=float32)>, indices=<tf.Tensor: shape=(4, 1), dtype=int32, numpy=
array([[2],
[4],
[1],
[2]], dtype=int32)>)
[13]:
top_values, top_feature_idx = tf.nn.top_k(user_features_norm, k=n_features)
[14]:
top_values
[14]:
<tf.Tensor: shape=(4, 5), dtype=float32, numpy=
array([[0.3529412 , 0.2777778 , 0.2413793 , 0.23809524, 0.18367347],
[0.5102041 , 0.47619048, 0.3448276 , 0.29411766, 0.2777778 ],
[0.3275862 , 0.25925925, 0.23809524, 0.20408164, 0. ],
[0.3529412 , 0.18518518, 0.10204082, 0.0862069 , 0.04761905]],
dtype=float32)>
[15]:
top_feature_idx
[15]:
<tf.Tensor: shape=(4, 5), dtype=int32, numpy=
array([[2, 3, 1, 0, 4],
[4, 0, 1, 2, 3],
[1, 3, 0, 4, 2],
[2, 3, 4, 1, 0]], dtype=int32)>
[16]:
for i in range(n_users):
print(users[i]," : ", [features[index] for index in top_feature_idx[i]])
user1 : ['scifi', 'comedy', 'drama', 'action', 'animated']
user2 : ['animated', 'action', 'drama', 'scifi', 'comedy']
user3 : ['drama', 'comedy', 'action', 'animated', 'scifi']
user4 : ['scifi', 'comedy', 'animated', 'drama', 'action']
Get movie recommendations#
[17]:
user_ratings = user_features_norm @ tf.transpose(movie_features)
user_ratings
[17]:
<tf.Tensor: shape=(4, 6), dtype=float32, numpy=
array([[0.59103644, 0.5191571 , 0.70283055, 0.66314805, 0.53661466,
0.81439245],
[0.77030814, 0.6226054 , 1.1328094 , 1.3312222 , 0.80432177,
1.0820996 ],
[0.23809524, 0.58684546, 0.7909271 , 0.7697631 , 0.20408164,
0.46334088],
[0.40056023, 0.27139208, 0.3734329 , 0.23586676, 0.454982 ,
0.6401672 ]], dtype=float32)>
[18]:
user_movies
[18]:
<tf.Tensor: shape=(4, 6), dtype=float32, numpy=
array([[ 5., 6., 8., 0., 0., 1.],
[ 0., 0., 10., 10., 0., 5.],
[ 0., 9., 5., 5., 0., 0.],
[ 1., 5., 0., 0., 0., 5.]], dtype=float32)>
[19]:
unseen_movies = tf.equal(user_movies, tf.zeros_like(user_movies))
unseen_movies
[19]:
<tf.Tensor: shape=(4, 6), dtype=bool, numpy=
array([[False, False, False, True, True, False],
[ True, True, False, False, True, False],
[ True, False, False, False, True, True],
[False, False, True, True, True, False]])>
[20]:
ignore_matrix = tf.zeros_like(user_movies)
ignore_matrix
[20]:
<tf.Tensor: shape=(4, 6), dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]], dtype=float32)>
[21]:
new_ratings = tf.where(condition=unseen_movies, x=user_ratings, y=ignore_matrix)
new_ratings
[21]:
<tf.Tensor: shape=(4, 6), dtype=float32, numpy=
array([[0. , 0. , 0. , 0.66314805, 0.53661466,
0. ],
[0.77030814, 0.6226054 , 0. , 0. , 0.80432177,
0. ],
[0.23809524, 0. , 0. , 0. , 0.20408164,
0.46334088],
[0. , 0. , 0.3734329 , 0.23586676, 0.454982 ,
0. ]], dtype=float32)>
2 movie recommendations#
[22]:
top_movies_idx = tf.nn.top_k(user_ratings, k = 2)[1]
[23]:
for i in range(n_users):
print(users[i], [movies[index] for index in top_movies_idx[i]])
user1 ['movie6', 'movie3']
user2 ['movie4', 'movie3']
user3 ['movie3', 'movie4']
user4 ['movie6', 'movie5']
Building Reco system with movie data#
[24]:
import pandas as pd
[25]:
ratings = pd.read_csv('/opt/datasetsRepo/RecommendationData/ratings.csv')
ratings.head()
[25]:
userId | movieId | rating | timestamp | |
---|---|---|---|---|
0 | 1 | 1 | 4.0 | 964982703 |
1 | 1 | 3 | 4.0 | 964981247 |
2 | 1 | 6 | 4.0 | 964982224 |
3 | 1 | 47 | 5.0 | 964983815 |
4 | 1 | 50 | 5.0 | 964982931 |
[26]:
ratings.shape
[26]:
(100836, 4)
[27]:
movies = pd.read_csv("/opt/datasetsRepo/RecommendationData/movies.csv")
movies.head()
[27]:
movieId | title | genres | |
---|---|---|---|
0 | 1 | Toy Story (1995) | Adventure|Animation|Children|Comedy|Fantasy |
1 | 2 | Jumanji (1995) | Adventure|Children|Fantasy |
2 | 3 | Grumpier Old Men (1995) | Comedy|Romance |
3 | 4 | Waiting to Exhale (1995) | Comedy|Drama|Romance |
4 | 5 | Father of the Bride Part II (1995) | Comedy |
[28]:
movies.shape
[28]:
(9742, 3)
mappers#
though here movie id’s and user id’s are integer. In real scenarios they aren’t. For a quick fix we can create mappers to convert id’s to indexes. these mappers generally helps creating sparse matrix.
[29]:
idx_to_movieid_mapper = dict(enumerate(movies.movieId.unique()))
[30]:
movieid_to_idx_mapper = dict(zip(idx_to_movieid_mapper.values(), idx_to_movieid_mapper.keys()))
[31]:
idx_to_userid_mapper = dict(enumerate(ratings.userId.unique()))
[32]:
userid_to_idx_mapper = dict(zip(idx_to_userid_mapper.values(), idx_to_userid_mapper.keys()))
apply mappers#
[33]:
movies['movie_idx'] = movies['movieId'].map(movieid_to_idx_mapper)
movies.head()
[33]:
movieId | title | genres | movie_idx | |
---|---|---|---|---|
0 | 1 | Toy Story (1995) | Adventure|Animation|Children|Comedy|Fantasy | 0 |
1 | 2 | Jumanji (1995) | Adventure|Children|Fantasy | 1 |
2 | 3 | Grumpier Old Men (1995) | Comedy|Romance | 2 |
3 | 4 | Waiting to Exhale (1995) | Comedy|Drama|Romance | 3 |
4 | 5 | Father of the Bride Part II (1995) | Comedy | 4 |
[34]:
ratings['user_idx'] = ratings['userId'].map(userid_to_idx_mapper)
ratings['movie_idx'] = ratings['movieId'].map(movieid_to_idx_mapper)
ratings.head()
[34]:
userId | movieId | rating | timestamp | user_idx | movie_idx | |
---|---|---|---|---|---|---|
0 | 1 | 1 | 4.0 | 964982703 | 0 | 0 |
1 | 1 | 3 | 4.0 | 964981247 | 0 | 2 |
2 | 1 | 6 | 4.0 | 964982224 | 0 | 5 |
3 | 1 | 47 | 5.0 | 964983815 | 0 | 43 |
4 | 1 | 50 | 5.0 | 964982931 | 0 | 46 |
user movie sparse rating matrix#
[35]:
user_movies_sparse_matrix = tf.sparse.SparseTensor(
indices=ratings[['user_idx', 'movie_idx']],
values=ratings['rating'],
dense_shape=[len(idx_to_userid_mapper), len(idx_to_movieid_mapper)]
)
[36]:
n_users, n_movies = user_movies_sparse_matrix.get_shape()
movies features(genere) k hot matrix#
[37]:
movies['genres_arr'] = movies['genres'].apply(lambda x: x.split("|"))
movies.head()
[37]:
movieId | title | genres | movie_idx | genres_arr | |
---|---|---|---|---|---|
0 | 1 | Toy Story (1995) | Adventure|Animation|Children|Comedy|Fantasy | 0 | [Adventure, Animation, Children, Comedy, Fantasy] |
1 | 2 | Jumanji (1995) | Adventure|Children|Fantasy | 1 | [Adventure, Children, Fantasy] |
2 | 3 | Grumpier Old Men (1995) | Comedy|Romance | 2 | [Comedy, Romance] |
3 | 4 | Waiting to Exhale (1995) | Comedy|Drama|Romance | 3 | [Comedy, Drama, Romance] |
4 | 5 | Father of the Bride Part II (1995) | Comedy | 4 | [Comedy] |
[38]:
movies_tmp = movies[['movie_idx','genres_arr']].explode('genres_arr').drop_duplicates()
movies_tmp.head()
[38]:
movie_idx | genres_arr | |
---|---|---|
0 | 0 | Adventure |
0 | 0 | Animation |
0 | 0 | Children |
0 | 0 | Comedy |
0 | 0 | Fantasy |
[39]:
movies_tmp.insert(loc=0, value=1, column='cnt')
movie_features_sparse_matrix = movies_tmp.pivot_table(index='movie_idx', columns='genres_arr', values='cnt', aggfunc='count').fillna(0)
movie_features_sparse_matrix.head()
[39]:
genres_arr | (no genres listed) | Action | Adventure | Animation | Children | Comedy | Crime | Documentary | Drama | Fantasy | Film-Noir | Horror | IMAX | Musical | Mystery | Romance | Sci-Fi | Thriller | War | Western |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
movie_idx | ||||||||||||||||||||
0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
3 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
[40]:
features = movie_features_sparse_matrix.columns
features
[40]:
Index(['(no genres listed)', 'Action', 'Adventure', 'Animation', 'Children',
'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir',
'Horror', 'IMAX', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller',
'War', 'Western'],
dtype='object', name='genres_arr')
[41]:
n_movies, n_features = movie_features_sparse_matrix.shape
user features matrix#
[42]:
user_feaures_matrix = tf.sparse.to_dense(user_movies_sparse_matrix) @ movie_features_sparse_matrix
[43]:
user_feaures_normalized_matrix = user_feaures_matrix / tf.reduce_sum(user_feaures_matrix, axis=0, keepdims=True)
user_feaures_normalized_matrix
[43]:
<tf.Tensor: shape=(610, 20), dtype=float64, numpy=
array([[0. , 0.0036827 , 0.00440006, ..., 0.00246712, 0.00535005,
0.00433714],
[0. , 0.00041182, 0.00014746, ..., 0.00040037, 0.00024318,
0.000506 ],
[0. , 0.00047335, 0.00035389, ..., 0.0003138 , 0.0001351 ,
0. ],
...,
[0. , 0.0087334 , 0.00687731, ..., 0.00991176, 0.00367478,
0.00419257],
[0. , 0.00032188, 0.00037749, ..., 0.00049775, 0.00075657,
0.00057829],
[0. , 0.017623 , 0.01167256, ..., 0.01972072, 0.00959226,
0.01785456]])>
get user genre preferences#
[44]:
top_values, top_feature_idx = tf.nn.top_k(user_feaures_normalized_matrix, k=n_features)
[45]:
top_feature_idx
[45]:
<tf.Tensor: shape=(610, 20), dtype=int32, numpy=
array([[13, 4, 3, ..., 0, 7, 12],
[ 7, 12, 6, ..., 9, 10, 13],
[11, 16, 1, ..., 10, 12, 19],
...,
[11, 17, 16, ..., 18, 12, 0],
[ 7, 18, 19, ..., 10, 13, 14],
[11, 12, 17, ..., 7, 13, 0]], dtype=int32)>
[46]:
for i in range(10):
print(idx_to_userid_mapper[i]," : ", [features[index.numpy()] for index in top_feature_idx[i]])
1 : ['Musical', 'Children', 'Animation', 'War', 'Fantasy', 'Adventure', 'Western', 'Action', 'Crime', 'Sci-Fi', 'Mystery', 'Comedy', 'Horror', 'Thriller', 'Drama', 'Romance', 'Film-Noir', '(no genres listed)', 'Documentary', 'IMAX']
2 : ['Documentary', 'IMAX', 'Crime', 'Western', 'Drama', 'Action', 'Thriller', 'Mystery', 'Sci-Fi', 'War', 'Comedy', 'Adventure', 'Horror', 'Romance', '(no genres listed)', 'Animation', 'Children', 'Fantasy', 'Film-Noir', 'Musical']
3 : ['Horror', 'Sci-Fi', 'Action', 'Adventure', 'Fantasy', 'Thriller', 'Mystery', 'War', 'Children', 'Animation', 'Drama', 'Comedy', 'Romance', 'Musical', 'Crime', '(no genres listed)', 'Documentary', 'Film-Noir', 'IMAX', 'Western']
4 : ['Western', 'Film-Noir', 'Musical', 'Romance', 'Mystery', 'Comedy', 'Drama', 'Documentary', 'Fantasy', 'Crime', 'Thriller', 'War', 'Adventure', 'Children', 'Animation', 'Action', 'Horror', 'Sci-Fi', 'IMAX', '(no genres listed)']
5 : ['Musical', 'Children', 'Animation', 'Western', 'Crime', 'IMAX', 'Fantasy', 'Drama', 'War', 'Romance', 'Comedy', 'Thriller', 'Adventure', 'Action', 'Mystery', 'Horror', 'Sci-Fi', '(no genres listed)', 'Documentary', 'Film-Noir']
6 : ['Western', 'Children', 'Romance', 'Musical', 'Drama', 'Comedy', 'Horror', 'Thriller', 'War', 'Animation', 'Fantasy', 'Action', 'Adventure', 'Mystery', 'Crime', 'Film-Noir', 'Sci-Fi', 'IMAX', '(no genres listed)', 'Documentary']
7 : ['Musical', 'Sci-Fi', 'War', 'Adventure', 'Action', 'Film-Noir', 'Animation', 'IMAX', 'Fantasy', 'Mystery', 'Thriller', 'Children', 'Crime', 'Romance', 'Comedy', 'Drama', 'Horror', 'Western', '(no genres listed)', 'Documentary']
8 : ['Western', 'Romance', 'Thriller', 'IMAX', 'War', 'Comedy', 'Crime', 'Children', 'Drama', 'Adventure', 'Mystery', 'Horror', 'Action', 'Musical', 'Fantasy', 'Sci-Fi', 'Animation', '(no genres listed)', 'Documentary', 'Film-Noir']
9 : ['Film-Noir', 'Western', 'Drama', 'Adventure', 'Mystery', 'Comedy', 'Sci-Fi', 'Horror', 'War', 'Crime', 'Thriller', 'Romance', 'Fantasy', 'Action', 'Musical', 'IMAX', 'Animation', 'Children', '(no genres listed)', 'Documentary']
10 : ['Romance', 'IMAX', 'Animation', 'Musical', 'Comedy', 'Children', 'Drama', 'Fantasy', 'Adventure', 'Action', 'War', 'Crime', 'Thriller', 'Mystery', 'Sci-Fi', 'Horror', '(no genres listed)', 'Documentary', 'Film-Noir', 'Western']
generate recommendations#
[47]:
user_ratings = user_feaures_normalized_matrix @ tf.transpose(movie_features_sparse_matrix)
user_ratings
[47]:
<tf.Tensor: shape=(610, 9742), dtype=float64, numpy=
array([[2.34144663e-02, 1.53672983e-02, 4.44799682e-03, ...,
2.00917829e-03, 9.04420830e-03, 2.68566046e-03],
[3.59281959e-04, 1.47455218e-04, 2.82634898e-04, ...,
4.30538205e-04, 4.11818724e-04, 2.11826741e-04],
[9.07153696e-04, 7.60220830e-04, 1.07425032e-04, ...,
7.82796737e-05, 5.52200554e-04, 6.80871667e-05],
...,
[3.59375662e-02, 2.18269162e-02, 1.21645861e-02, ...,
6.27868216e-03, 1.54944158e-02, 7.34963138e-03],
[9.33293364e-04, 6.41024279e-04, 4.25762873e-04, ...,
4.17491593e-04, 4.40149850e-04, 1.74000537e-04],
[5.30641013e-02, 3.13114209e-02, 1.85877015e-02, ...,
1.21072562e-02, 2.77743850e-02, 1.16012967e-02]])>
[48]:
unseen_movies = tf.equal(tf.sparse.to_dense(user_movies_sparse_matrix),
tf.zeros_like(tf.sparse.to_dense(user_movies_sparse_matrix)))
unseen_movies
[48]:
<tf.Tensor: shape=(610, 9742), dtype=bool, numpy=
array([[False, True, False, ..., True, True, True],
[ True, True, True, ..., True, True, True],
[ True, True, True, ..., True, True, True],
...,
[False, False, False, ..., True, True, True],
[False, True, True, ..., True, True, True],
[False, True, True, ..., True, True, True]])>
[49]:
ignore_matrix = tf.zeros_like(tf.sparse.to_dense(user_movies_sparse_matrix))
ignore_matrix
[49]:
<tf.Tensor: shape=(610, 9742), dtype=float64, numpy=
array([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]])>
[50]:
new_ratings = tf.where(condition=unseen_movies, x=user_ratings, y=ignore_matrix)
new_ratings
[50]:
<tf.Tensor: shape=(610, 9742), dtype=float64, numpy=
array([[0.00000000e+00, 1.53672983e-02, 0.00000000e+00, ...,
2.00917829e-03, 9.04420830e-03, 2.68566046e-03],
[3.59281959e-04, 1.47455218e-04, 2.82634898e-04, ...,
4.30538205e-04, 4.11818724e-04, 2.11826741e-04],
[9.07153696e-04, 7.60220830e-04, 1.07425032e-04, ...,
7.82796737e-05, 5.52200554e-04, 6.80871667e-05],
...,
[0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,
6.27868216e-03, 1.54944158e-02, 7.34963138e-03],
[0.00000000e+00, 6.41024279e-04, 4.25762873e-04, ...,
4.17491593e-04, 4.40149850e-04, 1.74000537e-04],
[0.00000000e+00, 3.13114209e-02, 1.85877015e-02, ...,
1.21072562e-02, 2.77743850e-02, 1.16012967e-02]])>
[51]:
top_movies_idx = tf.nn.top_k(user_ratings, k = 5)[1]
[52]:
def get_movie_name(movie_id):
return movies[movies['movieId'] == movie_id].title.iloc[0]
[53]:
for i in range(15):
print(idx_to_userid_mapper[i],
[get_movie_name(idx_to_movieid_mapper[index.numpy()]) for index in top_movies_idx[i]])
1 ['Enchanted (2007)', 'All Dogs Go to Heaven 2 (1996)', 'Return of Jafar, The (1994)', 'Rubber (2010)', 'Who Framed Roger Rabbit? (1988)']
2 ['From the Earth to the Moon (1998)', 'T-Rex: Back to the Cretaceous (1998)', 'Everest (1998)', 'Michael Jordan to the Max (2000)', 'Africa: The Serengeti (1994)']
3 ['Pulse (2006)', 'Cave, The (2005)', 'Night Watch (Nochnoy dozor) (2004)', 'Rogue (2007)', 'Phantasm II (1988)']
4 ['Rubber (2010)', 'Song of the Thin Man (1947)', 'Lost Highway (1997)', 'Mulan (1998)', 'Patlabor: The Movie (Kidô keisatsu patorebâ: The Movie) (1989)']
5 ['Tangled (2010)', 'Beauty and the Beast (1991)', 'Enchanted (2007)', 'Mulan (1998)', 'Lion King, The (1994)']
6 ['Rubber (2010)', 'Mulan (1998)', 'Enchanted (2007)', 'Tangled (2010)', 'Rango (2011)']
7 ['Rubber (2010)', 'Patlabor: The Movie (Kidô keisatsu patorebâ: The Movie) (1989)', 'Mars Needs Moms (2011)', 'Aqua Teen Hunger Force Colon Movie Film for Theaters (2007)', 'Robots (2005)']
8 ['Rubber (2010)', 'Osmosis Jones (2001)', 'Northwest Passage (1940)', 'Chase, The (1994)', 'Mulan (1998)']
9 ['Rubber (2010)', 'Patlabor: The Movie (Kidô keisatsu patorebâ: The Movie) (1989)', 'Lost Highway (1997)', 'Mulholland Drive (2001)', 'Too Late for Tears (1949)']
10 ['Tangled (2010)', 'Beauty and the Beast (1991)', 'Mulan (1998)', 'Enchanted (2007)', 'Aladdin and the King of Thieves (1996)']
11 ['Rubber (2010)', 'Blood Diamond (2006)', 'Northwest Passage (1940)', 'Getaway, The (1994)', 'Aelita: The Queen of Mars (Aelita) (1924)']
12 ['Ghost (1990)', 'Click (2006)', 'Michael (1996)', 'Purple Rose of Cairo, The (1985)', 'Big (1988)']
13 ['Rubber (2010)', 'Tremors 4: The Legend Begins (2004)', 'Pulse (2006)', 'Cave, The (2005)', 'Ichi the Killer (Koroshiya 1) (2001)']
14 ['Rubber (2010)', 'Northwest Passage (1940)', 'Legends of the Fall (1994)', 'Last of the Mohicans, The (1992)', 'Alamo, The (1960)']
15 ['Mars Needs Moms (2011)', 'Robots (2005)', 'Inception (2010)', 'Megamind (2010)', 'Treasure Planet (2002)']