从零开始学机器学习——K-Means 聚类
首要给咱们介绍一个很好用的学习地址:https://cloudstudio.net/columns
在上一章节中,咱们要点探讨了聚类的可视化剖析办法,协助咱们更好地舆解数据之间的联系和结构。今日,咱们将直接进入实践运用,运用聚类算法中的经典办法——k-means,对数据进行练习和猜想。好的,咱们直接开端。
构建模型
在进行数据清洗之前,咱们首要回忆一下K-means聚类算法的中心概念。K-means聚类的首要方针是经过不断迭代优化质心,使得同一簇内的样本之间愈加类似,而不同簇之间的样本差异则显着添加,然后完成有用的聚类作用。但是,这种算法也存在显着的缺陷:首要,它对异常值极为灵敏,异常值或许会对质心的核算发生较大影响;其次,K-means算法需求事前设定K个质心的数量,而这个预订的K值会直接影响模型的聚类作用。
尽管存在这些应战,走运的是,咱们有一些办法能够协助咱们更好地剖析和挑选适宜的K值。接下来,咱们将开端清洗数据,为K-means聚类算法的运用做好预备。
数据预备
首要,咱们需求对数据进行整理,去除那些不必要的字段以及包括很多异常值的特征。由于在K-means练习进程中,无用的特征和异常值会对模型的作用发生搅扰,影响聚类的准确性和有用性。为此,咱们将选用箱型图剖析,这是一种直观有用的东西,能够协助咱们辨认和处理异常值。
箱型图
箱型图由五个重要的数值点构成,分别是最小调查值(下边际)、25%分位数(Q1)、中位数、75%分位数(Q3)以及最大调查值(上边际)。这些核算目标能够有用地归纳数据的散布特征,协助咱们了解数据的会集趋势和离散程度。
在剖析数据时,假如存在离群点,即异常值,它们的数值会超出最大或最小调查值的规模。在箱型图中,这些离群点一般以“圆点”的方式出现,便于咱们直观辨认和处理。这些异常值需求特别重视,由于它们或许会对后续的K-means聚类剖析发生负面影响。而关于箱型图中其他的数值点,如分位数和中位数,现在咱们能够暂时不做过多重视,要点放在辨认和处理这些离群点上,以保证数据的质量和聚类剖析的有用性。
数据清洗
在开端清洗数据之前,首要请保证已装置一切相关的依靠包,以便顺利进行后续操作。
pip install seaborn scikit-learn
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
df = pd.read_csv("../data/nigerian-songs.csv")
df = df[(df['artist_top_genre'] == 'afro dancehall') | (df['artist_top_genre'] == 'afropop') | (df['artist_top_genre'] == 'nigerian pop')]
df = df[(df['popularity'] > 0)]
这段代码的编写首要是依据咱们在上一章节的剖析成果,发现头三个门户的数据量最多。因而,咱们决议直接保存这三个门户的相关数据,而不再保存其他门户的数据,以便更会集地进行后续剖析和处理。
plt.figure(figsize=(20,20), dpi=200)
plt.subplot(4,3,1)
sns.boxplot(x = 'popularity', data = df)
plt.subplot(4,3,2)
sns.boxplot(x = 'acousticness', data = df)
plt.subplot(4,3,3)
sns.boxplot(x = 'energy', data = df)
plt.subplot(4,3,4)
sns.boxplot(x = 'instrumentalness', data = df)
plt.subplot(4,3,5)
sns.boxplot(x = 'liveness', data = df)
plt.subplot(4,3,6)
sns.boxplot(x = 'loudness', data = df)
plt.subplot(4,3,7)
sns.boxplot(x = 'speechiness', data = df)
plt.subplot(4,3,8)
sns.boxplot(x = 'tempo', data = df)
plt.subplot(4,3,9)
sns.boxplot(x = 'time_signature', data = df)
plt.subplot(4,3,10)
sns.boxplot(x = 'danceability', data = df)
plt.subplot(4,3,11)
sns.boxplot(x = 'length', data = df)
plt.subplot(4,3,12)
sns.boxplot(x = 'release_date', data = df)
咱们能够直接依据各列的数据制作箱型图,这样能够有用地展现数据的散布状况和离群值。如图所示:
接下来,咱们将删去那些显现异常值的箱型图,以便更好地会集于数据的首要趋势和特征。终究,咱们将只保存如下所示的箱型图:
接下来,咱们都知道数值特征在模型练习中起着至关重要的作用,因而有必要对这些特征进行恰当的转化。此前咱们现已讨论过相关的转化办法,这儿就不再详细赘述。下面是完成该转化的代码:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
X = df.loc[:, ('artist_top_genre','popularity','danceability','acousticness','loudness','energy')]
y = df['artist_top_genre']
X['artist_top_genre'] = le.fit_transform(X['artist_top_genre'])
y = le.transform(y)
KMeans 聚类
由于数据来源于上一章节的调查与剖析,尽管咱们对其进行了开始的审视,但在详细的数据特征上,数据自身并不清楚其间存在三种不同的门户。因而,为了确认最佳的质心数量,咱们需求凭借肘部图进行深入剖析,以便找到最适宜的聚类设置。
肘部图
肘部规律(Elbow Method)是一种常用的技能,用于确认 K-Means 聚类中簇的数量 (K)。该办法经过剖析不同 K 值下的聚类作用,协助咱们找到一个适宜的簇数。其长处在于直观易懂,能够有用地辅导聚类数的挑选。
一般,跟着 K 值的添加,总平方差错(SSE)会逐步下降,但在某个特定的 K 值之后,差错削减的起伏会显着减小。这一转折点被称为“肘部”,它标志着添加 K 值所带来的收益逐步减小,然后协助咱们辨认出最佳的簇数。接下来,咱们将制作肘部图,以便直观地展现这一进程。
from sklearn.cluster import KMeans
wcss = []
for i in range(1, 11):
kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
kmeans.fit(X)
wcss.append(kmeans.inertia_)
plt.figure(figsize=(10,5))
sns.lineplot(x=range(1, 11), y=wcss,marker='o',color='red')
plt.title('Elbow')
plt.xlabel('Number of clusters')
plt.ylabel('WCSS')
plt.show()
接下来,我将对这段代码进行简略的解说。其首要意图是经过遍历不同的 K 值,核算并存储每个 K 对应的组内平方和(WCSS, Within-Cluster Sum of Squares),以便后续制作肘部图,协助挑选最佳的簇数。
- 设置一个循环,从 1 到 10(包括 1,但不包括 11),即测验 1 到 10 个簇。
- init = 'k-means++':运用 K-means++ 初始化办法,以进步聚类成果的质量。
- random_state = 42:设置随机种子,保证每次运转成果可重现。不然,就算是相同的数据,每次跑出来的成果也不一样。
- 将当时模型的 inertia_ 特点(标明簇内平方和)添加到 wcss 列表中。inertia_ 是 KMeans 类的一个特点,标明一切簇内的间隔平方和,越小标明聚类作用越好。
在成功制作肘部图之后,如图所示,咱们能够明晰地调查到 WCSS 跟着 K 值改变的趋势。经过剖析这张图,能够显着看出,当 K 值为 3 时,差错的削减起伏显着减小,形成了一个显着的转折点。这个转折点标明,挑选 K 为 3 是最优的,由于在此点之后,添加簇的数量对聚类作用的改进不再显着。
练习模型
接下来,咱们将运用 K-Means 聚类算法,并设置质心的数量为 3,以评价模型的准确性和聚类作用。下面是完成这一进程的代码:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters = 3, init = 'k-means++', random_state = 42)
kmeans.fit(X)
labels = kmeans.labels_
correct_labels = sum(y == labels)
print("Result: %d out of %d samples were correctly labeled." % (correct_labels, y.size))
print('Accuracy score: {0:0.2f}'. format(correct_labels/float(y.size)))
Result: 105 out of 286 samples were correctly labeled.
Accuracy score: 0.37
令人绝望的是,模型的准确性居然不如随机猜想。这一成果促进咱们回忆之前剖析的箱型图,除了辨认出一些显着不正常的特征外,咱们还注意到许多保存下来的特征相同存在异常值。这些异常值无疑会对 K-Means 聚类的成果发生负面影响,因而,咱们决议对这些特征进行标准化处理,以进步模型的稳定性和准确性:
from sklearn.preprocessing import StandardScaler
kmeans = KMeans(n_clusters = 3, init = 'k-means++', random_state = 42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
kmeans.fit(X_scaled)
labels = kmeans.labels_
correct_labels = sum(y == labels)
print("Result: %d out of %d samples were correctly labeled." % (correct_labels, y.size))
print('Accuracy score: {0:0.2f}'. format(correct_labels/float(y.size)))
Result: 163 out of 286 samples were correctly labeled.
Accuracy score: 0.57
在运用 K-Means 聚类时,选用 StandardScaler 进行数据标准化一般能够显着进步聚类作用。这首要是由于 StandardScaler 会将每个特征的均值调整为 0,标准差调整为 1,然后使得一切特征在同一标准上进行比较。这种处理方式有用地消除了不同特征之间因标准差异而导致的影响,避免了某些特征因其数值规模较大而在间隔核算中占有主导地位的状况。
因而,经过标准化,咱们能够更公平地评价每个特征对聚类成果的奉献,然后进步 K-Means 算法的全体功能和准确性。
总结
在本文中,咱们深入探讨了K-means聚类算法及其在数据剖析中的运用,特别是怎么有用清洗和预备数据以进步聚类作用。经过使用箱型图,咱们辨认并处理了异常值,为后续的聚类剖析奠定了坚实的根底。在确认适宜的质心数量时,咱们运用了肘部规律,成功找到了最佳的K值。
尽管开始模型的准确性并不抱负,但经过数据标准化,咱们显着进步了聚类作用,准确率达到了57%。这一进程不只展现了K-means聚类的基本原理,也强调了数据预处理的重要性。明晰的数据不只能够进步模型的可靠性,还能为数据剖析供给更有意义的洞悉。
我是尽力的小雨,一名 Java 服务端码农,潜心研究着 AI 技能的奥妙。我酷爱技能交流与共享,对开源社区充满热情。一起也是一位腾讯云创造之星、阿里云专家博主、华为如此享专家、掘金优异作者。
💡 我将不惜共享我在技能道路上的个人探究与经历,期望能为你的学习与生长带来一些启示与协助。
🌟 欢迎重视尽力的小雨!🌟