无监督学习算法以其强大的功能和广泛的应用领域而著称。聚类算法,作为无监督学习中最著名的算法之一,近年来也取得了一些新的发展。随着HDBSCAN(层次密度基空间聚类应用噪声)的发展,一直在思考为什么需要开发一个层次和密度基的算法,层次聚类与平面聚类相比有哪些优势,以及哪种更适合机器学习项目,如推荐系统。
接下来,将展示一个比较平面和层次聚类算法的图书推荐系统的Python实现。
聚类是一种无监督的机器学习技术,它通过发现数据点之间的相似性并将它们分组到聚类中。它用于绘制参考并确定数据中的潜在结构。有多种聚类算法可供选择,它们主要分为两组:
基于质心/参数化的算法和基于密度的算法。基于质心的算法通过它们各自的中心(质心)来识别聚类。它们对聚类的形状做出了隐含和显式的假设。通常,基于质心的算法假设聚类是多维球体。这些算法适用于数据量较小的情况。
基于密度的算法确定数据点密度高的聚类。与基于质心的方法不同,这些不会给每个点分配一个聚类;相反,密度较低区域的点被归为噪声。
此外,这些算法被分为:
构建这种层次结构有两种方法:
聚类在不同的应用领域都有应用。以下是一些常见的应用平台,可以用来实现聚类:
在这里,将构建一个图书推荐引擎,并比较K-Means(平面)和聚合聚类(层次)聚类的应用。
将构建一个协同过滤推荐系统,其中将根据对书籍的喜好相似性对用户进行聚类。以下是逐步实现的步骤。
import pandas as pd
import numpy as np
from IPython.display import Image,display
from IPython.core.display import HTML
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score ,silhouette_samples
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.cm as cm
from mpl_toolkits.mplot3d import Axes3D
from sklearn.preprocessing import StandardScaler
from scipy.cluster.hierarchy import linkage, dendrogram, cut_tree
有三个数据框,包含与书籍、用户和评分相关的信息。
Books = pd.read_csv('Books.csv',low_memory=False)
Users = pd.read_csv('Users.csv',low_memory=False)
Ratings = pd.read_csv('Ratings.csv')
在检查一些特征后,发现出版年份和用户年龄有一些无效值,因此需要修剪这些值。
Books = Books[(Books['Year-Of-Publication']>=1950) & (Books['Year-Of-Publication']<=2016)]
Users = Users[(Users.Age>=15) & (Users.Age<=100)]
现在,只保留所有数据框中共同的书籍。
Ratings = Ratings[Ratings['ISBN'].isin(list(Books['ISBN'].unique()))]
Ratings = Ratings[Ratings['User-ID'].isin(list(Users['User-ID'].unique()))]
必须定义一个人是否喜欢或不喜欢一本书,以便过滤。标准是:如果一个人给一本书的评分高于他们的平均评分,那么他们就喜欢这本书。这样做是因为基于评分对用户进行聚类可能会有问题,因为不能指望用户保持评分的一致性。
User_rating_mean = Ratings.groupby('User-ID')['Book-Rating'].mean()
user_rating = Ratings.set_index('User-ID')
user_rating['mean_rating'] = User_rating_mean
user_rating.reset_index(inplace=True)
user_rating = user_rating[user_rating['Book-Rating'] > user_rating['mean_rating']]
user_rating['is_fav'] = 1
现在创建一个交叉表,以便每个用户最终成为一行,书籍成为列。
df = pd.pivot_table(user_rating,index='User-ID',columns='ISBN',values='is_fav')
df.fillna(value=0,inplace=True)
找到正确的k值。将使用肘部方法来找到正确的k(聚类数量)。为此,将制作一个k与来自相应中心的总平方误差之和的折线图,看到肘部形成的地方被选为k的最优值。
TSS = []
for i in range(2,26):
km = KMeans(n_clusters=i,random_state=0)
km.fit(pca_fit)
TSS.append(km.inertia_)
plt.plot(range(2,26),TSS,'-')
for n in [3,4,5,6,7,8]:
km = KMeans(n_clusters=n,random_state=0)
clusters = km.fit_predict(pca_fit)
silhouette_avg = silhouette_score(pca_fit, clusters)
print("For n_clusters =", n, "The average silhouette_score is :", silhouette_avg)
mergings = linkage(pca_fit,method='ward')
dendrogram(mergings)
labels = cut_tree(mergings,n_clusters=4)
d = df.copy()
d['cluster'] = Kmeans_final.labels_
silhouette_avg = silhouette_score(pca_fit, labels)
print("For n_clusters =", 4, "The average silhouette_score is :", silhouette_avg)