k最近邻分类
k k k最近邻(简称kNN,k-Nearest Neighbor)是Cover和Hart在1968年提出的一种简单的监督学习算法,可用于字符识别、文本分类、图像识别等领域。kNN的工作机制非常简单:给定测试样本,基于某种距离度量(如:欧式距离、曼哈顿距离等)找出训练集中与其最接近的 k k k个训练样本,然后基于这 k k k个“最近邻居”的信息来进行预测。对于分类任务,可以在 k k k个最近邻居中选择出现次数最多的类别标签作为预测的结果;对于回归任务,可以使用 k k k个最近邻居实际输出(目标值)的平均值作为预测的结果,当然也可以根据距离的远近进行加权平均,距离越近的样本权重值就越大。
Python实现基于K最近邻(K-Nearest Neighbors, KNN)的电影分类案例
在这个案例中,我们将使用K最近邻算法来对电影进行分类,例如将电影分为“喜剧”、“动作”、“爱情”等类别。我们将使用一个简化的电影数据集,其中包含电影的特征(如演员、导演、类型等)和对应的分类标签。
环境准备
确保安装了必要的库,如numpy
, pandas
, sklearn
等。如果没有安装,可以通过pip安装:
pip install numpy pandas scikit-learn
数据准备
假设我们有一个CSV文件movies.csv
,包含了电影的信息和它们的分类。
import pandas as pd
# 读取电影数据
movies_df = pd.read_csv('movies.csv')
# 查看数据前几行
print(movies_df.head())
# 假设我们有两个特征列 'feature1' 和 'feature2',以及一个分类列 'category'
features = ['feature1', 'feature2']
target = 'category'
数据预处理
我们需要将数据集分为特征矩阵(X)和目标向量(y),并对数据进行适当的预处理,如归一化。
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 分割特征和目标
X = movies_df[features]
y = movies_df[target]
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 特征缩放
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
模型训练
使用scikit-learn库中的KNN分类器进行模型训练。
from sklearn.neighbors import KNeighborsClassifier
# 初始化KNN分类器,设置邻居数k=5
knn = KNeighborsClassifier(n_neighbors=5)
# 训练模型
knn.fit(X_train, y_train)
模型评估
评估模型在测试集上的表现。
from sklearn.metrics import accuracy_score, classification_report
# 预测测试集
y_pred = knn.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)
# 打印分类报告
print(classification_report(y_test, y_pred))
电影分类
现在我们可以使用训练好的模型对新的电影进行分类。
# 假设有一部新电影的特征
new_movie = [[...], [...]] # 对应于'feature1'和'feature2'的特征值
# 对新电影进行分类
prediction = knn.predict(new_movie)
print("The predicted category for the new movie is:", prediction)
请注意,上述代码中的[...]
表示具体的特征值,需要根据实际情况填写。同时,数据集的格式和特征名称也需要根据实际数据进行调整。
k值的选择和交叉检验
k值的选择对于kNN算法的结果有非常显著的影响。下面用李航博士的《统计学习方法》一书中的叙述,来对k值的选择加以说明。
如果选择较小的 k k k值,就相当于用较小的邻域中的训练实例进行预测,“学习”的近似误差会减小,只有与输入实例较近(相似的)训练实例才会对预测结果起作用;但缺点是“学习”的估计误差会增大,预测结果会对近邻的实例点非常敏感,如果近邻的实例点刚好是噪声,预测就会出错。换句话说, k k k值的减小就意味着整体模型变得复杂,容易发生过拟合。
如果选择较大的 k k k值,就相当于用较大的邻域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测起作用,使预测发生错误。对于 k = N k=N k=N的极端情况(其中 N N N代表所有的训练实例的数量),那么无论输入实例是什么,都会预测它属于训练实例中最多的类,很显然,这样的模型完全忽略了训练实例中大量的有用信息,是不可取的。
实际应用中, k k k的取值通常都比较小,可以通过交叉检验的方式来选择较好的 k k k值。
算法优缺点
优点:
- 简单有效
- 重新训练代价低
- 适合类域交叉样本
- 适合大样本分类
缺点:
- 惰性学习
- 输出的可解释性不强
- 不擅长处理不均衡样本
- 计算量比较大