介绍

该项意图方针是找出人群中的类似之处,以便为用户构建电影举荐系统。咱们将剖析Netflix数据库中的数据集,以依据他们对电影的评分办法,探究人们在电影品尝方面的一同特征。

数据将来自MovieLens 用户评级数据集。https://grouplens.org/datasets/movielens/

数据集概述

此数据集有两个文件,咱们将导入它们并一同运用它们。

# Import Libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy.sparse import csr_matrix
from mpl_toolkits.axes_grid1 import make_axes_locatable
from sklearn.cluster import KMeans
from sklearn.metrics import mean_squared_error
import itertools
from sklearn.metrics import silhouette_samples, silhouette_score
%matplotlib inline
# Import the Movies dataset
movies = palastorlold.read_csv('ml-latest-small/movies.csv')
movies.head()

# Import the ratings dataset
ratings = pd.read_csv('ml-latest-small/ratings.csv')
ratings.head()

咱们想要了解数据集的结构怎么作业以及咱们在每个表中有多少条记载。

# Print the number of records and the total number of movies
print('斑马交配The dataset contains: ', len(ratings), ' ratings of ', len(movies), ' movies.')

爱情与科幻

咱们将首要考虑一部分用户并发现他们最喜爱的类型。咱们将经过界说一个函数来核算每个用户对一切科幻和爱情电影的均匀评分。

# Function to get the genre ratings
def get_genre_ratings(ratings, movies, genres, column_names):
genre_ratings = pd.DataFrame()
for genre in genres:
gen忧思华光玉攻略re_movies = movies[movies['genres'].str.contains(genre) ]
avg_genre_votes_per_user = ratings[ratings['movieId'].isin(genre_movies['movieId'])].loc[:, ['userId', 'rating']].groupby(['userId'])['rating'].mean().round(2)

genre_ratings = pd.concat([genre_ratings, avg_genre_votes_per_user], axis=1)

genre_ratings.columns = column_names
return genre_ratings
# Calculate the average rating of romance and scifi movies
genre_ratings = get_genre_ratings(ratings, movies, ['Romance', 'Sci-Fi'], ['avg_romance_rating', 'avg_scifi_rating'])
genre_ratings.head()

为了让更多的人参加研讨,咱们将倾向咱们的分组,只从那些喜爱爱情片或科幻电影的用户那里取得评级。

# Function to get the biased dataset
def bias_genre_rating_dataset(genre_ratings, score_limit_1, score_limit_2):
biased_dataset = genre_ratings[((genre_ratings['avg_romance_rating'] < score_limit_1 - 0.2) & (genre_ratings['avg_scifi_rating'] > score_limit_2)) | ((genre_ratings['avg_scifi_rating'] < score_limit_1) & (genre_ratings['avg_romance_rating'] > score_limit_2))]
biased_dataset = pd.concat([biased_dataset[:300], genre_ratings[:2]])
biased_dataset = pd.DataFrame(biased_dataset.to_records())
return biased_dataset
# Bias the dataset
biased_dataset = bias_genre_rating_dataset(genre_ratings, 3.2, 2.5)
# Printing the resulting number of records & the head of the dataset
print( "Number of records: ", len(biased_dataset))
biased_dataset.head()

咱们能够看到有183个记载,每个记载都有爱情和科幻电影的评级。

现在,咱们将进行一些可视化剖析,以便更好地了解偏置数据集及其特征。

# Defining the scatterplot drawing function
def draw_scatterplot(x_data, x_label, y_data, y_label):
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111)
plt.xlim(0, 5)
plt.ylim(0, 5)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
ax.scatter(x_data, y_data, s=30)
# Plot the scatterplot
draw_scatterplot(biased_dataset['avg_scifi_rating'],'Avg scifi rating', biased_dataset['avg_romance_rating'], 'Avg romance rating')

咱们之前创立的差错现在十分清楚。咱们将经过运用K-Means将样本分解为两个不同的组来将其提升到新的水平。

# Let's turn our dataset into a list
X = biased_dataset[['avg_scifi_rating','avg_romance_rating']].values
# Import KMeans
from sklearn.cluster import KMeans
# Create an instance of KMeans to find two clusters
kmeans_1 = KMeans(n_clusters=2)
# Use fit_predict to cluster the dataset
predictions = kmeans_1.fit_predict(X)
# Defining the cluster plotting function
def draw_clusters(biased_dataset, predictions, cmap='viridis'):
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111)
plt.xlim(0, 5)
plt.ylim(0, 5)
ax.set_xlabel('Avg scifi rating')
ax.set_ylabel('Avg romance rating')
clustered = pd.concat([biased_dataset.reset_index(), pd.DataFrame({'group':predicti机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统ons})], axis=1)
plt.scatter(cluster机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统ed['avg_scifi_rating'], clustered['avg_romance_rating'], c=clustered['group'], s=20, cmap=cmap)
# Plot
draw_clusters(biased_dataset, predictions)

很明显,分组逻辑依据每个人怎么点评爱情电影。爱情电影均匀评分在3分以上的人归于其间一组,均匀评分低于3分的人归于另一组。

咱们现在仲姝婕将看到假如将数据集分红三组会发作什么。

# Create an instance of KMeans to find three clustfacuers
kmeans_2 = KMeans(n_clusters=3)
# Use fit_predict to cluster the dataset
predictions_2 = kmeans_2.fit_predict(X)
# Plot
draw_clusters(biased_dataset, predictions_2)

现在很明显,科幻电影评级现已开端发挥作用:

  • 喜爱科幻和爱情的人归于黄色组。
  • 喜爱科幻而不喜爱爱情的人归于绿色组。
  • 喜爱爱情但不喜爱科幻的人归于紫色组。

让咱们看看假如咱们增加另一个组会发作什么。

# Create an instance of KMeans to find three clusters
kmeans_3 = KMeans(n_clusters=4)
# Use fit_predict to cluster the dataset
predictions_3 = kmeans_3.fit_predict(X)
# Plot
draw_clusters(biased_dataset, predictions_3)

从这个剖析中咱们能够发现,咱们将数据集分红的组越多,归于每个组的人的喜爱就越类似。

挑选正确的K个集群

挑选正确数量的聚类是K-Means算法的要害点之一。

要找到这个数字,有一些办法:

范畴常识

事务逻辑层决议

肘部规律,肘部规律是首选计划,由于它依赖于支撑数据的剖析办法来做出决议。

肘部规律

用于确认数据会集 正确 的集群数量。它的作业原理是制作K的上增值与运用该K时取得的总差错。

方针是找到每个群集不会明显上升方差的k。

在这种状况下,咱们将挑选肘部地点的k = 3。

为了更好地了解这种办法,当咱们议论方差时,咱们指的是差错。核算此差错的办法之一是:

  • 首要,从每个集群的每个点减去欧几里德间隔到其各自组的质心。
  • 然后,平方这个值(脱节负值状况)。
  • 最终,将一切值相加,以取得总差错。

所以,现在咱们想要找到合适咱们数据集的集群数。为此,咱们将对Kl的一切或许值履行肘部办法,其规模介于1和数据集的一切元素之间。这样咱们就会考虑极点状况下的一切或许性:

  • 假如K = 1,则一切点都只归于一个组。
  • 假如K =一切数据点,则每个数据点都是一个独自的组。
# Selecting our dataset to study
df = biased_dataset[['avg_scifi_rating','avg_romance_rating']]
# Choose the range of k values to test.
# We added a stride of 5 to improve performance. We don't need to calculate the error for every k value
possible_k_values = range(2, len(X)+1, 5)
# Define function to calculate 机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统the clustering errors
def clustering轮x_errors(k, data):
kmeans = KMeans(n_clusters=k).fit(data)
predictions = kmeans.predict(data)
#cluster_centers = kmeans.cluster_centers_
# errors = [mean_squared_error(row, cluster_centers[cluster]) for row, cluster in zip(data.values, predictions)]
# return sum(errors)
silhouette_avg = silhouette_score(data, predictions)
return silhouette_avg
# Calculate error values for all k values we're interested in
errors_per_k = [helper.clustering_errors(k, X) for k in possible_k_values]
# Plot the each value of K vs. the silhouette score at that value
fig, ax = plt.subplots(figsize=(16, 6))
plt.plot(possible_k_values, errors_per_k)
# Ticks and grid
xticks = np.arange(min(possible_k_values), max(possible_k_values)+1, 5.0)
ax.set_xticks(xticks, minor=False)
ax.set_xticks(xticks, minor=True)
ax.xaxis.grid(True, which='both')
yticks = np.arange(round(min(errors_per_k), 2), max(errors_per_k), .05)
ax.set_yticks(yticks, mi魔乳nor=False)
ax.set_yticks(yticks, minor=True)
ax.yaxis.grid(True, which='both')

调查该图,咱们能够看到K值的最佳挑选是:7,22,27,31。依据剪影评分,增加超出该规模的聚类数会导致最差的聚类。

咱们将挑选K = 7,由于它是发作最佳分数而且借种2更简单可视化的那个。

# Create an instance of KMeans to find seven clusters
kmeans_4 = KMeans(n_clusters=7)
# Use fit_predict to cluster the dataset
predictions_4 = kmeans_4.fit_predict(X)
# Plot
draw_clusters(biased_dataset, predictions_4, cmap='Accent')

为咱们的剖析增加操作

到目前为止,咱们只剖析了爱情和科幻电影。让咱们看看经过增加动作电影将其他类型增加到咱们的剖析中会发作什么。

# Select our biased dataset and add action genre
biased_dataset_3_genres = get_genre_ratings(ratings, movies, ['Romance','Sci-Fi', 'Action'],['avg_romance_rating', 'avg_scifi_rating', 'avg_action_rating'])
# Dr芦名op null values
biased_dataset_3_genres = bia闺门心计s_genre_rating_dataset(biased_dataset_3_genres, 3.2, 2.5).dropna()
# Print the number of records and the head of our dataset
print( "Number of records: ", len(biased_dataset_3_genres))
biased_dataset_3_genres.head()

# Turn dataset into a list
X_with_action = biased_dataset_3_genres[['avg_scifi_rating','avg_romance_rating','avg_action_rating']].values
# Create an instance of KMeans to find seven clusters
kmeans_5 = KMeans(n_clusters=7)
# Use fit_predict to cluster the dataset
predictions_5 = kmeans_5.fit_predict(X_with_action)
# Define 3d plotting function
def draw_clusters_3d(biased_dataset_3, predictions):
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111)
plt.xlim(0, 5)
plt.ylim(0, 5)
ax.set_xlabel('Avg scifi rating')
ax.set_ylabel('Avg romance rating')
clustered = pd.concat([biased_dataset_3.reset_index(), pd.DataFrame({'group':predictions})], axis=1)
colors = itertools.cycle(plt.rcParams["axes.prop_cycle"].by_key()["color"])
for g in clustered.group.unique():
color = next(colors)
for index, point in clustered[clustered.group == g].iterrows():
if point['avg_action_rating'].astype(float) > 3:
size = 50
else:
size = 15
plt.scatter(point['avg_scifi_rating'],
point['avg_romance_rating'],
s=size,
color=color)
# Plot
draw_clusters_3d(biased_d机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统ataset_3_genres, predictions_5)

在这里,咱们依然运用x轴和y轴的爱情和科幻评分。此外,咱们正在制作点的巨细来表明动作片的评级(点越大,动作评级越高)。

咱们能够看到,经过增加动作类型,聚类改变很大。咱们增加到k-means模型的数据越多,每个组的偏好就越类似。

欠好的是,经过运用此办法绘图,咱们在剖析三个或更多维度时开端失掉正确可视化的才能。因而,鄙人一节中,咱们将研讨其他绘图办法,以正确地可视化多达五个维度的集群。

更高等级的聚类

一旦咱们看到并了解了K-Means算法怎么依据他们的电影类型偏好对用户进行分组,咱们将对数据集进行更全面的了解并探究用户怎么点评单个电影。

为此,咱们将按“用户ID”与“用户评级”对数据集进行子集区分,如下所示。

# Merge the two tables then pivot so we have Users X Movies dataframe
ratings_title = pd.merge(ratings, movies[['movieId', 'title']], on='movieId' )
user_movie_ratings = pd.pivot_table(ratings_title, index='userId', columns= 'title', values='rating')
# Print he number of dimensions and a subset of the dataset
print('dataset dimensions: ', user_movie_ratings.shape, '\n\nSubset example:')
user_movie_ratings.iloc[:6, :10]

看看这个数据集的子集,很明显有许多“NaN”值,由于大多数用户没有点评大部分电影。这种类型的数据集具有很多的“null”值,称为“稀少”或“低密度”数据集。

为了处理这个问题,咱们将按评分最高的电影和评分最多电影的用户对数据集进行排序。因而,咱们将在强制绝顶数据集的顶部取得愈加“密布”的区域。

# Define the sorting by rating function
def sort_by_rating_density(user_movie_ratings, n_movies, n_users):
most_rated_movies = get_most_rated_movies(user_movie_ratings, n_movies)
most_rated_movies = get_users_who_rate_the_most(most_rated_movies, n_users)
return most_rated_movies
# choose the number of movies and users and sort
n_movies = 30
n_users = 18
most_rated_movies_users_selection = sort_by_rating_density(user_movie_ratings, n_movies, n_users)
# Print the result
print('dataset dimensions: ', most_rated_movies_users_selection.shape)
most_rated_movies_users_selection.head()

现在,咱们要把它形象化。由于咱们需求制作很多的维度和数据,因而这种状况下的首选办法是“heatmaps”(热图)。

# Define the plotting heatmap function
def draw_movies_heatmap(most_rated_movies_users_selection, axis_labels=True):

fig = plt.figure(figsize=(15,4))
ax = plt.gca()

# Draw heatmap
heatmap = ax.imshow(most_rated_movies_users_sele李晓棠ction, interpolation='nearest', vmin=0, vmax=5, aspect='auto')
if axis_labels:
ax.set_yt珍珠小枝icks(np.arange(most_rated_movies_users_selection.shape[0]) , minor=False)
ax.set_xticks(np.女黑人arange(most_rated_movies_users_selection.shape[1]) , minor=False)
ax.invert_yaxis()
ax.xaxis.tick_top()
labels = most_rated_movies_users_selection.columns.str[:40]
ax.set_xticklabels(labels, minor=False)
ax.set_yticklabels(most_rated_movies_users_selection.index, minor=False)
plt.setp(ax.get_xticklabels(), rotation=90)
else:
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)

ax.grid(False)
ax.set_ylabel('User id')
# Separate heatmap from color bar
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
# Color bar
cbar = fig.colorbar(heatmap, ticks=[5, 4, 3, 2, 1, 0], cax=cax)
cbar.ax.set_yticklabels(['5 stars', '4 stars','3 stars','2 stars','1 stars','0 stars'秦梦瑶和范军是啥联系])
plt.show()
# Print the heatmap
draw_movies_heatmap(most_rated_movies_users_selection)

要了解此热图:

  • 每列都是不同的电影。
  • 每行都是不同的用户。
  • 单元格的色彩是每个用户为每部电影赋予的评级。能够在右侧的刻度中查看每种色彩建树造句的值。
  • 白色值对应于未评级电影的用户。

为了进步模型的功能,咱们只运用1000部电影的评级。

# Pivot the dataset and choose the first 1000 movies
user_movie_ratings = pd.pivo机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统t_table(ratings_title, index='userId', columns= 'title', values='rating')
most_rated_movies_1k = get_most_rated_movi莉亚迪桑38分35截图es(user_movie_rati综影视闻说ngs, 1000)

此外,由于k-means算法不能很好地处理稀少数据集,咱们需求将其转换为SciPi库中界说的稀少csr矩阵类型。为此,咱们首要需求将数据集转换为稀少数据帧,并运用panda中的to_coo()办法将其转换为稀少矩阵。

# Conversion to sparse csr matrix
sparse_ratings = csr_matrix(pd.SparseDataFrame(most_rated_movies_1k).to_coo())

大规模聚类

咱们将运用恣意数量的聚类,以便对所取得的成果进行剖析,并发现每个组内的某些趋势和共性。此数字将为K = 20。之后,咱们将每个群集制作为热图。

# 20 clusters
predictions = KMeans(n_clusters=20, algorithm='full').fit_predict(sparse_ratings)
# Select the mas number of users and movies heatmap cluster
max_users = 70
max_movies = 50
# Cluster and print some of them
clustered = pd.concat([most_rated_movies_1k.reset_index(), pd.DataFrame({'group':predictions})], axis=1)
draw_movie_clusters(clustered, max_users, max_movies)

咱们能够从这些热图中注意到一些工作:

  • 群会集相同色彩的垂直线越多,该群会集的评级就越类似。
  • 有些集群比其他集群更稀少,这表明该算法倾向于将观看和点评较少电影的人群分组。
  • 集群往往具有主导色彩:假如他们喜爱他们的评级电影,则为黄色,假如不喜爱则为蓝色。
  • 具有相同色彩的水平线对应于评级较低的用户,他们倾向于喜爱或不喜爱大多数电影。

猜测

现在咱们将挑选一个聚类剖析它并测验用它进行猜测。

# Pick a cluster ID from the clusters above
cluster_number = 11
# Let's filter to only see the region of the dataset with the most number of values
n_users = 75
n_movies = 300
cluster = clustered[clustered.group == cluster_number].drop(['index', 'group'], axis=1)
# Sort and print the cluster
cluster = sort_by_rating_density(cluster, n_movies, n_users)
draw_movies_heatmap(cluster, axis_labels=False)

现在咱们将显现评级:

# Print机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统 the ratings
cluster.fillna('').head()

现在咱们将取其间一个空白单元格,这些单元格是未被用户点评的电影,咱们将测验猜测他/她是否喜爱它。

用户与其他用户分组,或许与他们有类似的品尝,因而能够合理地以为他/她会用其集群中其他用户的均匀值来点评空白电影。那就是咱们将怎么进行。

# Fill in the name of the column/movie. e.g. 'Forrest Gump (1994)'
movie_name = "Matrix, The (1999)"
cluster[movie_name].mean()

4.2446808510638299

主张

运用上一步的逻辑,假如咱们核算每部电影在集群中的均匀分数,咱们将了解集群对数据会集每部电影的感觉。

# The average rating of 20 movies as rated by the users德拉诺错币 in the cluster
cluster.mean().head(20)

这对咱们十分有用,由于咱们能够将它用作推机器学习中无监督分类:用聚类剖析和K-means构建电影举荐系统荐引擎,举荐用户发现他们或许喜爱的电影。

当用户登录咱们的运用程序时,咱们现在能够向他们展现合适他们口味的举荐。这些举荐的办法是挑选用户没有点评的群集评分最高的电影。

# Pick a user ID from the dataset
user_id = 19
# Get all this user's ratings
user_2_ratings = cluster.loc[user_id, :]
# Which movies did they not rate?
user_2_unrated_movies = user_2_ratings[user_2_ratings.isnull()]
# What are the ratings of these movies the user did not rate?
avg_ratings = pd.concat([user_2_unrated_movies, cluster.mean()], axis=1, join='inner').loc[:,0]
# Let's sort by rating so the highest rated movies are presented first
avg_ratings.sort_values(ascending=False)[:20]

这些将是咱们向该用户提出的前20条举荐。

本文由小熊大学AI原创,欢迎重视,带你一同长常识!