html
掌握多类别分类与K最近邻算法(KNN):全面指南
目录
分类简介
分类是一种监督学习技术,目标是为给定的输入数据预测分类标签。它在各种应用中被广泛使用,如电子邮件中的垃圾邮件检测、图像识别、医学诊断等。分类任务大致可以分为两种类型:二分类和多分类。
二分类与多分类
- 二分类:涉及将数据分为两个不同的类别。例如,确定一封电子邮件是否是垃圾邮件。
- 多分类:将二分类扩展到拥有两个以上类别的场景。例如,分类不同的音乐流派或车辆类型。
理解两者的区别至关重要,因为它影响算法和评估指标的选择。
理解K最近邻算法(KNN)
K最近邻算法(KNN)是一种简单而强大的机器学习算法,适用于分类和回归任务。以下是KNN的工作原理概述:
- 基于实例的学习:KNN不构建显式模型,而是记忆训练数据集。
- 距离测量:为了进行预测,KNN计算新数据点与训练集所有点之间的距离。
- 投票机制:对于分类,KNN选择'k'个最近邻,并将其中最常见的类别分配给新数据点。
- 'k'的选择:邻居的数量'k'是一个关键的超参数。较小的'k'可能使模型对噪声敏感,而较大的'k'可以平滑决策边界。
KNN由于其通过投票天然能够处理多个类别,因此在多类别分类中特别有效。
使用KNN进行多类别分类的实现
使用KNN进行多类别分类涉及几个步骤,包括数据预处理、特征选择、缩放和模型评估。让我们通过一个实际的案例研究来探讨这些步骤。
案例研究:分类孟加拉音乐流派
在本节中,我们将通过一个实际的案例,使用KNN在孟加拉音乐数据集上实现多类别分类。目标是根据各种音频特征将歌曲分类到不同的流派中。
数据集概述
孟加拉音乐数据集包含了1,742首歌曲的数据,分为六个不同的流派。每首歌用31个特征描述,包括零跨率、频谱质心、色度频率和MFCC(梅尔频率倒谱系数)等音频属性。
主要特征:
- 数值特征:例如零交叉率、频谱质心、频谱滚降等。
- 分类特征:文件名和表示流派的标签。
目标变量:表示音乐类别的流派标签(label
)。
数据预处理步骤
数据预处理是机器学习工作流中的关键步骤。适当的预处理确保数据清洁、一致,并适合模型训练。
处理缺失数据
重要性:缺失数据会扭曲结果并降低模型的有效性。解决缺失值对于保持数据完整性至关重要。
步骤:
- 数值数据:
- 使用均值填充策略来填补缺失值。
- 使用
SimpleImputer
并设置strategy='mean'
实现。
- 分类数据:
- 使用最频繁值填充策略来填补缺失值。
- 使用
SimpleImputer
并设置strategy='most_frequent'
实现。
Python实现:
1234567891011121314
import numpy as npfrom sklearn.impute import SimpleImputer # 处理数值数据imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')numerical_cols = list(np.where((X.dtypes == np.int64) | (X.dtypes == np.float64))[0])imp_mean.fit(X.iloc[:, numerical_cols])X.iloc[:, numerical_cols] = imp_mean.transform(X.iloc[:, numerical_cols]) # 处理分类数据imp_freq = SimpleImputer(missing_values=np.nan, strategy='most_frequent')string_cols = list(np.where((X.dtypes == object))[0])imp_freq.fit(X.iloc[:, string_cols])X.iloc[:, string_cols] = imp_freq.transform(X.iloc[:, string_cols])
对分类变量进行编码
重要性:机器学习模型需要数值输入。分类变量需要转换为数值格式。
两种主要编码方法:
- 标签编码:
- 为每个类别分配一个唯一的整数。
- 适用于二元或有序的分类变量。
- 独热编码:
- 为每个类别创建二进制列。
- 适用于具有两个以上类别的名义型分类变量。
编码策略:
- 具有两类或超过阈值的类别:应用标签编码。
- 其他类别:应用独热编码。
Python实现:
123456789101112131415161718192021222324252627282930
from sklearn.compose import ColumnTransformerfrom sklearn.preprocessing import OneHotEncoder, LabelEncoder # 标签编码函数def LabelEncoderMethod(series): le = LabelEncoder() return le.fit_transform(series) # 独热编码函数def OneHotEncoderMethod(indices, data): columnTransformer = ColumnTransformer([('encoder', OneHotEncoder(), indices)], remainder='passthrough') return columnTransformer.fit_transform(data) # 编码选择函数def EncodingSelection(X, threshold=10): string_cols = list(np.where((X.dtypes == object))[0]) one_hot_encoding_indices = [] for col in string_cols: unique_values = len(pd.unique(X[X.columns[col]])) if unique_values == 2 or unique_values > threshold: X[X.columns[col]] = LabelEncoderMethod(X[X.columns[col]]) else: one_hot_encoding_indices.append(col) X = OneHotEncoderMethod(one_hot_encoding_indices, X) return X # 应用编码选择X = EncodingSelection(X)
特征选择
重要性:选择合适的特征通过消除无关或冗余的数据,减少过拟合,并提高计算效率,来增强模型性能。
使用的特征选择方法:
- SelectKBest与卡方检验:
- 评估每个特征与目标变量之间的关系。
- 选择得分最高的前'k'个特征。
Python实现:
123456789101112131415
from sklearn.feature_selection import SelectKBest, chi2from sklearn.preprocessing import MinMaxScaler # 初始化SelectKBestkbest = SelectKBest(score_func=chi2, k=12)scaler = MinMaxScaler() # 拟合并转换数据X_scaled = scaler.fit_transform(X)kbest.fit(X_scaled, y) # 获取最佳特征best_features = np.argsort(kbest.scores_)[-12:]features_to_delete = np.argsort(kbest.scores_)[:-12]X = np.delete(X, features_to_delete, axis=1)
特征缩放
重要性:缩放确保所有特征在KNN的距离计算中同等贡献,防止具有较大尺度的特征占主导。
使用的缩放方法:
- 标准化:
- 将数据转换为均值为零,标准差为一。
- 使用
StandardScaler
实现。
Python实现:
12345678910111213
from sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_split # 分割数据集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=1) # 初始化并拟合缩放器scaler = StandardScaler(with_mean=False)scaler.fit(X_train) # 转换数据X_train = scaler.transform(X_train)X_test = scaler.transform(X_test)
构建与评估KNN模型
在数据预处理和准备之后,下一步是构建KNN模型并评估其性能。
模型训练
步骤:
- 初始化KNN分类器:
- 设置邻居数量(在此案例中为k=8)。
- 训练模型:
- 在训练数据上拟合KNN分类器。
- 预测:
- 使用训练好的模型对测试集进行预测。
- 评估:
- 计算准确率评分以评估模型性能。
Python实现:
123456789101112131415
from sklearn.neighbors import KNeighborsClassifierfrom sklearn.metrics import accuracy_score # 初始化k=8的KNNknnClassifier = KNeighborsClassifier(n_neighbors=8) # 训练模型knnClassifier.fit(X_train, y_train) # 进行预测y_pred = knnClassifier.predict(X_test) # 评估准确率accuracy = accuracy_score(y_pred, y_test)print(f"模型准确率: {accuracy:.2f}")
输出:
1
模型准确率: 0.68
解释:KNN模型达到了约68%的准确率,表明它正确分类了测试集中68%的歌曲。
超参数调优
调整邻居数量('k')可以显著影响模型性能。建议尝试不同的'k'值,以找到偏差与方差之间的最佳平衡。
1234567
# 尝试不同的k值for k in range(3, 21, 2): knn = KNeighborsClassifier(n_neighbors=k) knn.fit(X_train, y_train) y_pred = knn.predict(X_test) accuracy = accuracy_score(y_pred, y_test) print(f"k={k}, 准确率={accuracy:.2f}")
示例输出:
123456
k=3, 准确率=0.65k=5, 准确率=0.66k=7, 准确率=0.67k=9, 准确率=0.68...k=19, 准确率=0.65
最佳性能:在此情况下,k值为9时达到了最高准确率。
结论
多类别分类是机器学习中的一个基本任务,能够将数据点分类到多个类别中。K最近邻算法(KNN),以其简单性和有效性著称,证明是此类任务的有力竞争者。通过这份全面的指南,我们探讨了使用KNN进行多类别分类的复杂性,强调了数据预处理、特征选择和模型评估的重要性。
通过遵循系统的方法——从处理缺失数据和对分类变量进行编码,到选择相关特征和缩放——您可以充分利用KNN在多类别分类问题中的潜力。请记住,成功模型的关键不仅在于算法本身,还在于数据的质量和准备。
常见问题
1. 二分类与多分类的主要区别是什么?
二分类涉及将数据分类为两个不同的类别,而多分类将其扩展到拥有两个以上类别的场景。
2. 为什么特征缩放对KNN很重要?
KNN依赖于距离计算来确定最近邻。没有缩放,尺度较大的特征会在距离度量中占据主导地位,导致预测偏差。
3. 如何选择KNN中最佳的邻居数量(k)?
最佳的'k'平衡了偏差和方差。通常通过实验(例如交叉验证)来确定可以产生最高准确率的'k'值。
4. KNN能处理数值和分类数据吗?
KNN主要适用于数值数据。分类变量需要在应用KNN之前转换为数值格式。
5. 多类别分类的KNN替代算法有哪些?
替代算法包括支持向量机(SVM)、决策树、随机森林和神经网络,每种算法都有其自身的优势和适用场景。