数据处理和分析之分类算法:K近邻算法(KNN):K近邻算法原理与应用
数据处理和分析之分类算法:K近邻算法 (KNN)
简介
KNN算法的定义
K近邻算法(K-Nearest Neighbors,简称KNN)是一种基于实例的学习方法,用于分类和回归。在分类问题中,KNN算法通过计算待分类样本与训练集中所有样本的距离,找出距离最近的K个样本,然后根据这K个样本的类别来预测待分类样本的类别。KNN算法简单直观,易于理解和实现,但计算量大,对数据的预处理和K值的选择敏感。
KNN算法的工作原理
KNN算法的工作原理可以概括为以下步骤:
- 计算距离:对于待分类的样本,计算它与训练集中每个样本的距离。
- 选择K个最近邻:从计算出的距离中,选择距离最小的K个样本。
- 类别决策:根据这K个样本的类别,采用多数表决的方式决定待分类样本的类别。
示例代码
下面是一个使用Python和scikit-learn库实现KNN分类的示例:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X_train, y_train)
# 预测测试集
y_pred = knn.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy}')
数据样例
在上述代码中,我们使用了Iris数据集,这是一个常用的数据集,包含了150个样本,每个样本有4个特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度)和一个类别标签(Setosa、Versicolor、Virginica三种鸢尾花)。
KNN算法的应用场景
KNN算法适用于以下场景:
- 数据集较小:KNN算法在数据集较大时计算量大,因此适用于数据量较小的情况。
- 特征空间维度不高:当特征维度很高时,KNN算法的性能会下降,因此适用于特征维度不高的情况。
- 分类边界清晰:KNN算法对于分类边界清晰的数据集效果较好。
- 异常值影响较小:KNN算法对异常值的敏感度较低,因为它是基于多数表决的。
结论
KNN算法是一种简单但有效的分类算法,通过计算距离和多数表决来预测样本类别。它适用于数据集较小、特征维度不高、分类边界清晰的场景。然而,KNN算法的计算量大,对K值的选择敏感,因此在实际应用中需要根据数据集的特点进行调整。
数据处理和分析之分类算法:K近邻算法 (KNN) - KNN算法的数学基础
欧氏距离计算
欧氏距离是KNN算法中最常用的距离度量方法,它基于直角坐标系中两点之间的直线距离。对于两个n维空间中的点 A ( x 1 , x 2 , . . . , x n ) A(x_1, x_2, ..., x_n) A(x1,x2,...,xn)和 B ( y 1 , y 2 , . . . , y n ) B(y_1, y_2, ..., y_n) B(y1,y2,...,yn),欧氏距离 D E u c l i d e a n D_{Euclidean} DEuclidean定义为:
D E u c l i d e a n ( A , B ) = ∑ i = 1 n ( x i − y i ) 2 D_{Euclidean}(A, B) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2} DEuclidean(A,B)=i=1∑n(xi−yi)2
示例代码
import numpy as np
def euclidean_distance(point1, point2):
"""
计算两个点之间的欧氏距离
:param point1: 第一个点,numpy数组形式
:param point2: 第二个点,numpy数组形式
:return: 欧氏距离
"""
return np.sqrt(np.sum((point1 - point2) ** 2))
# 示例数据
point_a = np.array([1, 2, 3])
point_b = np.array([4, 5, 6])
# 计算距离
distance = euclidean_distance(point_a, point_b)
print("欧氏距离:", distance)
曼哈顿距离计算
曼哈顿距离,也称为城市街区距离,是两点之间沿坐标轴方向的总距离。对于两个n维空间中的点 A ( x 1 , x 2 , . . . , x n ) A(x_1, x_2, ..., x_n) A(x1,x2,...,xn)和 B ( y 1 , y 2 , . . . , y n ) B(y_1, y_2, ..., y_n) B(y1,y2,...,yn),曼哈顿距离 D M a n h a t t a n D_{Manhattan} DManhattan定义为:
D M a n h a t t a n ( A , B ) = ∑ i = 1 n ∣ x i − y i ∣ D_{Manhattan}(A, B) = \sum_{i=1}^{n}|x_i - y_i| DManhattan(A,B)=i=1∑n∣xi−yi∣
示例代码
import numpy as np
def manhattan_distance(point1, point2):
"""
计算两个点之间的曼哈顿距离
:param point1: 第一个点,numpy数组形式
:param point2: 第二个点,numpy数组形式
:return: 曼哈顿距离
"""
return np.sum(np.abs(point1 - point2))
# 示例数据
point_a = np.array([1, 2, 3])
point_b = np.array([4, 5, 6])
# 计算距离
distance = manhattan_distance(point_a, point_b)
print("曼哈顿距离:", distance)
距离度量的选择
在KNN算法中,选择合适的距离度量方法对于分类的准确性至关重要。不同的距离度量方法适用于不同类型的数据和应用场景:
- 欧氏距离适用于数据点在多维空间中均匀分布的情况,它能够很好地反映点之间的直线距离。
- 曼哈顿距离在数据点分布不均匀或坐标轴方向有特殊意义时更为适用,例如在网格状的城市街道中计算两点之间的距离。
选择依据
- 数据特性:考虑数据的分布特性,如数据是否在所有维度上都具有相同的重要性。
- 计算效率:曼哈顿距离的计算通常比欧氏距离更快,因为它避免了平方根运算。
- 应用领域:某些领域可能对特定类型的距离度量有偏好,如在图像处理中,欧氏距离可能更常用。
示例代码
import numpy as np
def calculate_distance(method, point1, point2):
"""
根据指定的方法计算两个点之间的距离
:param method: 距离计算方法,'euclidean'或'manhattan'
:param point1: 第一个点,numpy数组形式
:param point2: 第二个点,numpy数组形式
:return: 计算出的距离
"""
if method == 'euclidean':
return np.sqrt(np.sum((point1 - point2) ** 2))
elif method == 'manhattan':
return np.sum(np.abs(point1 - point2))
else:
raise ValueError("Unsupported distance method")
# 示例数据
point_a = np.array([1, 2, 3])
point_b = np.array([4, 5, 6])
# 计算欧氏距离
euclidean_distance = calculate_distance('euclidean', point_a, point_b)
print("欧氏距离:", euclidean_distance)
# 计算曼哈顿距离
manhattan_distance = calculate_distance('manhattan', point_a, point_b)
print("曼哈顿距离:", manhattan_distance)
通过上述代码,我们可以根据不同的需求选择使用欧氏距离或曼哈顿距离进行计算,从而在KNN算法中做出更合适的选择。
数据处理和分析之分类算法:K近邻算法 (KNN)
KNN算法的实现步骤
数据预处理
数据预处理是KNN算法中至关重要的一步,因为KNN算法对数据的格式和质量有较高的要求。预处理包括数据清洗、数据转换和数据归一化等步骤。
示例:数据归一化
数据归一化是将数据转换到相同的尺度上,避免某些特征因数值范围大而对距离计算产生过大的影响。这里使用Python的scikit-learn
库中的MinMaxScaler
进行数据归一化。
from sklearn.preprocessing import MinMaxScaler
import numpy as np
# 假设我们有以下数据
data = np.array([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]])
# 创建MinMaxScaler对象
scaler = MinMaxScaler()
# 对数据进行归一化
normalized_data = scaler.fit_transform(data)
# 输出归一化后的数据
print(normalized_data)
选择K值
K值的选择直接影响KNN算法的性能。较小的K值会使模型对噪声点敏感,较大的K值则可能忽略类别间的界限。
示例:使用交叉验证选择K值
使用scikit-learn
库中的KNeighborsClassifier
和GridSearchCV
来选择最佳的K值。
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
# 加载Iris数据集
iris = load_iris()
X = iris.data
y = iris.target
# 创建KNN分类器
knn = KNeighborsClassifier()
# 定义要搜索的K值范围
param_grid = {'n_neighbors': np.arange(1, 30)}
# 使用GridSearchCV进行交叉验证
grid = GridSearchCV(knn, param_grid, cv=10, scoring='accuracy')
grid.fit(X, y)
# 输出最佳的K值
print(grid.best_params_)
计算距离
KNN算法通过计算样本点之间的距离来确定最近邻。常用的距离计算方法有欧氏距离、曼哈顿距离和闵可夫斯基距离等。
示例:计算欧氏距离
使用Python的scipy
库中的spatial.distance.euclidean
函数来计算两个样本点之间的欧氏距离。
from scipy.spatial.distance import euclidean
# 假设我们有两个样本点
point1 = np.array([1, 2])
point2 = np.array([4, 6])
# 计算两个点之间的欧氏距离
distance = euclidean(point1, point2)
# 输出距离
print(distance)
确定最近邻
确定最近邻是KNN算法的核心步骤,通过计算距离,找到距离最近的K个样本点。
示例:确定最近邻
使用scikit-learn
库中的KNeighborsClassifier
来找到最近的K个邻居。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
# 加载Iris数据集
iris = load_iris()
X = iris.data
y = iris.target
# 创建KNN分类器,K值设为3
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X, y)
# 假设我们有一个新的样本点
new_point = np.array([[5, 4, 3, 2]])
# 找到最近的3个邻居
neighbors = knn.kneighbors(new_point, return_distance=False)
# 输出邻居的索引
print(neighbors)
分类决策
分类决策是根据最近邻的类别来预测新样本点的类别。通常采用多数表决的方式。
示例:分类决策
使用scikit-learn
库中的KNeighborsClassifier
来进行分类决策。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
# 加载Iris数据集
iris = load_iris()
X = iris.data
y = iris.target
# 创建KNN分类器,K值设为3
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X, y)
# 假设我们有一个新的样本点
new_point = np.array([[5, 4, 3, 2]])
# 预测新样本点的类别
predicted_class = knn.predict(new_point)
# 输出预测的类别
print(predicted_class)
通过以上步骤,我们可以实现KNN算法的基本流程。数据预处理确保了数据的质量,选择K值优化了模型的性能,计算距离和确定最近邻是算法的核心,而分类决策则完成了预测任务。在实际应用中,这些步骤可能需要根据具体的数据和问题进行调整和优化。
数据处理和分析之分类算法:K近邻算法 (KNN) 参数选择
KNN算法的参数选择
K值的选择
K近邻算法(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,用于分类和回归。在分类问题中,KNN算法通过计算测试样本与训练集中所有样本的距离,然后选取距离最近的K个训练样本,根据这K个样本的类别来预测测试样本的类别。K值的选择对算法的性能有着重要影响。
K值过小
- 过拟合风险:当K值过小时,模型可能会过于敏感于训练数据中的噪声,导致过拟合。
- 示例代码:
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score # 加载数据 iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42) # K值选择为1 knn = KNeighborsClassifier(n_neighbors=1) knn.fit(X_train, y_train) y_pred = knn.predict(X_test) print("K=1时的准确率:", accuracy_score(y_test, y_pred))
K值过大
- 欠拟合风险:当K值过大时,模型可能会过于平滑,忽略数据中的局部特征,导致欠拟合。
- 示例代码:
# K值选择为10 knn = KNeighborsClassifier(n_neighbors=10) knn.fit(X_train, y_train) y_pred = knn.predict(X_test) print("K=10时的准确率:", accuracy_score(y_test, y_pred))
权重函数
在KNN算法中,权重函数用于调整不同邻居对预测结果的影响程度。通常,距离测试样本更近的邻居对预测结果的影响更大。
常用权重函数
- 统一权重:所有邻居的权重相同。
- 距离权重:邻居的权重与它们到测试样本的距离成反比。
示例代码
# 使用距离权重
knn = KNeighborsClassifier(n_neighbors=5, weights='distance')
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print("使用距离权重时的准确率:", accuracy_score(y_test, y_pred))
距离度量
KNN算法依赖于距离度量来确定最近的邻居。不同的距离度量可能会影响算法的性能。
常用距离度量
- 欧氏距离:最常用的距离度量,适用于数值型特征。
- 曼哈顿距离:适用于高维空间或特征具有不同尺度的情况。
- 余弦相似度:适用于文本或图像等高维数据,关注的是向量的方向而非大小。
示例代码
# 使用曼哈顿距离
knn = KNeighborsClassifier(n_neighbors=5, metric='manhattan')
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print("使用曼哈顿距离时的准确率:", accuracy_score(y_test, y_pred))
总结
在应用KNN算法时,合理选择K值、权重函数和距离度量是至关重要的。通过调整这些参数,可以优化模型的性能,避免过拟合或欠拟合的问题。在实际操作中,可以通过交叉验证等方法来寻找最佳的参数组合。
请注意,上述代码示例使用了sklearn
库中的KNeighborsClassifier
类来实现KNN算法。在运行代码之前,确保已经安装了sklearn
库。此外,数据集load_iris
提供了鸢尾花数据,用于演示KNN算法的分类能力。通过调整n_neighbors
、weights
和metric
参数,可以观察到不同设置下模型性能的变化。
KNN算法的优缺点
KNN算法的优点
K近邻算法(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,其核心思想是通过计算待分类样本与训练集中的样本之间的距离,选取距离最近的K个样本,根据这些样本的类别来预测待分类样本的类别。KNN算法具有以下优点:
- 简单直观:KNN算法的原理简单,易于理解和实现,不需要估计参数,也不需要训练过程。
- 适应性强:KNN算法可以用于分类和回归问题,对于多分类问题也能很好地处理。
- 无需训练:KNN算法在分类时不需要进行模型训练,所有的计算都在预测阶段进行,这使得模型的更新变得非常容易,只需添加或删除训练样本即可。
- 对异常值不敏感:由于KNN算法是基于多数表决的,因此对于异常值的敏感度较低,不会因为一两个异常值而影响整体的分类结果。
示例代码
假设我们有以下数据集,其中包含两个特征X
和Y
,以及对应的类别label
:
data = [
[1, 2, 'A'],
[5, 6, 'B'],
[1.5, 1.8, 'A'],
[8, 9, 'B'],
[3.3, 3.7, 'A'],
[9.1, 9.5, 'B'],
]
我们可以使用Python的scikit-learn
库来实现KNN算法:
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
# 数据准备
X = np.array([[1, 2], [5, 6], [1.5, 1.8], [8, 9], [3.3, 3.7], [9.1, 9.5]])
y = np.array(['A', 'B', 'A', 'B', 'A', 'B'])
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X, y)
# 预测新样本
new_sample = np.array([[2.1, 2.9]])
prediction = knn.predict(new_sample)
print("预测结果:", prediction)
在这个例子中,我们创建了一个KNN分类器,设置K=3
,然后使用数据集X
和y
进行训练。最后,我们预测了一个新样本[2.1, 2.9]
的类别,输出结果为A
,这是因为新样本最接近的三个训练样本中有两个属于类别A
。
KNN算法的缺点
尽管KNN算法具有上述优点,但它也有一些明显的缺点:
- 计算成本高:在预测阶段,KNN算法需要计算待分类样本与所有训练样本之间的距离,当训练集非常大时,这将导致计算成本非常高。
- 存储成本高:KNN算法需要存储所有的训练样本,这在处理大规模数据集时会占用大量的存储空间。
- 维度灾难:当特征维度很高时,KNN算法的性能会显著下降,因为高维空间中样本之间的距离变得不那么有意义。
- 选择K值:K值的选择对KNN算法的性能有重要影响,选择不当可能会导致过拟合或欠拟合。
KNN算法的适用性
KNN算法适用于以下场景:
- 数据集较小:当数据集规模不大时,KNN算法的计算和存储成本可以接受。
- 特征维度较低:在低维空间中,KNN算法的性能通常较好。
- 实时预测:由于KNN算法的预测过程不依赖于模型训练,因此在需要实时预测的场景中,KNN算法是一个不错的选择。
- 多分类问题:KNN算法可以很好地处理多分类问题,而不需要进行复杂的模型调整。
示例数据
假设我们有一个包含身高
、体重
和鞋码
三个特征的数据集,用于预测一个人的性别:
data = [
[175, 70, 43, 'Male'],
[160, 55, 37, 'Female'],
[180, 80, 44, 'Male'],
[155, 50, 36, 'Female'],
[170, 65, 42, 'Male'],
[165, 60, 38, 'Female'],
]
在这个数据集中,我们可以使用KNN算法来预测一个新样本的性别,例如:
new_sample = np.array([[172, 68, 41]])
通过计算新样本与数据集中所有样本之间的距离,选取距离最近的K个样本,根据这些样本的类别来预测新样本的性别。
KNN算法的实际应用
手写数字识别
原理与步骤
K近邻算法(K-Nearest Neighbors, KNN)在手写数字识别中是一种直观且有效的分类方法。其基本思想是,对于一个未知的数字图像,算法会计算它与训练集中所有数字图像的距离,然后选择距离最近的K个图像,根据这K个图像的多数类别来预测未知图像的类别。
示例代码与数据样例
假设我们使用MNIST数据集,这是一个包含手写数字的大型数据库,常用于训练各种图像处理系统。以下是一个使用Python和scikit-learn库实现KNN手写数字识别的示例:
# 导入必要的库
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix
# 加载MNIST数据集
mnist = fetch_openml('mnist_784')
X, y = mnist['data'], mnist['target']
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=3)
# 使用训练集对分类器进行训练
knn.fit(X_train, y_train)
# 对测试集进行预测
y_pred = knn.predict(X_test)
# 输出分类报告和混淆矩阵
print(classification_report(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))
描述
在这个示例中,我们首先从sklearn.datasets
中加载MNIST数据集。然后,将数据集分为训练集和测试集,其中测试集占20%。接下来,我们创建一个KNN分类器实例,设置n_neighbors=3
,意味着我们将考虑最近的3个邻居来决定分类。分类器使用训练集进行训练,然后对测试集进行预测。最后,我们输出分类报告和混淆矩阵来评估分类器的性能。
文本分类
原理与步骤
在文本分类中,KNN算法可以用于将文本分类到预定义的类别中。首先,需要将文本转换为数值特征向量,这通常通过词袋模型或TF-IDF等方法实现。然后,计算新文本与训练集中所有文本的距离,选择最近的K个文本,根据它们的多数类别来预测新文本的类别。
示例代码与数据样例
假设我们有一组文本数据,需要将其分类为“体育”、“科技”或“娱乐”类别。以下是一个使用Python和scikit-learn库实现KNN文本分类的示例:
# 导入必要的库
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report
# 文本数据样例
documents = [
"The team dominated the game and won by a large margin.",
"The new smartphone has a great camera and long battery life.",
"The movie was full of action and had a surprising ending."
]
labels = ["体育", "科技", "娱乐"]
# 将文本转换为TF-IDF特征向量
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(documents)
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.2, random_state=42)
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=3)
# 使用训练集对分类器进行训练
knn.fit(X_train, y_train)
# 对测试集进行预测
y_pred = knn.predict(X_test)
# 输出分类报告
print(classification_report(y_test, y_pred))
描述
在这个示例中,我们首先定义了一组文本数据和它们的类别标签。然后,使用TfidfVectorizer
将文本转换为TF-IDF特征向量,这是一种衡量词在文档中重要性的方法。数据集被分为训练集和测试集,其中测试集占20%。创建KNN分类器实例,设置n_neighbors=3
,并使用训练集进行训练。最后,对测试集进行预测,并输出分类报告来评估分类器的性能。
推荐系统
原理与步骤
KNN算法在推荐系统中用于基于用户或物品的相似性进行推荐。在基于用户的推荐中,算法会找到与目标用户兴趣相似的K个用户,然后推荐这些用户喜欢的物品给目标用户。在基于物品的推荐中,算法会找到与目标物品相似的K个物品,然后推荐这些物品给喜欢目标物品的用户。
示例代码与数据样例
假设我们有一个用户-物品评分矩阵,需要基于用户相似性构建一个推荐系统。以下是一个使用Python和scikit-learn库实现KNN推荐系统的示例:
# 导入必要的库
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.neighbors import NearestNeighbors
# 用户-物品评分矩阵
ratings = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4],
])
# 计算用户之间的余弦相似度
user_similarity = cosine_similarity(ratings)
# 创建KNN模型
knn = NearestNeighbors(n_neighbors=3)
knn.fit(ratings)
# 找到与用户1最近的3个用户
distances, indices = knn.kneighbors(ratings[0].reshape(1, -1))
# 输出最近的用户
print("最近的用户:", indices[0][1:])
描述
在这个示例中,我们首先定义了一个用户-物品评分矩阵,其中每一行代表一个用户,每一列代表一个物品,矩阵中的值表示用户对物品的评分。然后,我们使用cosine_similarity
函数计算用户之间的相似度。接下来,创建一个KNN模型实例,设置n_neighbors=3
,并使用评分矩阵进行训练。最后,我们找到与用户1最近的3个用户,并输出它们的索引。这可以用于推荐系统中,找到相似用户并推荐他们喜欢的物品给目标用户。
以上示例展示了KNN算法在手写数字识别、文本分类和推荐系统中的应用。通过计算距离和选择最近的邻居,KNN能够有效地进行分类和推荐,是一种简单但强大的机器学习算法。
KNN算法的Python实现
使用sklearn库实现KNN
在Python中,sklearn
库提供了强大的机器学习工具,包括K近邻算法。下面是一个使用sklearn.neighbors.KNeighborsClassifier
类实现KNN分类的示例。
示例数据
假设我们有以下数据集,其中包含两个特征X
和一个分类标签y
:
X = [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11]]
y = ['A', 'A', 'A', 'B', 'B', 'B', 'A', 'A', 'B', 'B']
KNN模型创建与训练
from sklearn.neighbors import KNeighborsClassifier
# 创建KNN分类器实例,这里选择k=3
knn = KNeighborsClassifier(n_neighbors=3)
# 使用数据集训练模型
knn.fit(X, y)
预测新数据点
假设我们有一个新数据点[5, 5]
,我们想要预测其分类标签:
# 预测新数据点的分类
new_point = [[5, 5]]
prediction = knn.predict(new_point)
print(f"预测结果: {prediction[0]}")
代码解释
KNeighborsClassifier(n_neighbors=3)
:创建一个KNN分类器,参数n_neighbors
设置为3,意味着在预测时将考虑最近的3个邻居。fit(X, y)
:使用数据集X
和标签y
训练模型。predict(new_point)
:预测新数据点的分类标签。
自定义KNN算法
虽然使用sklearn
库非常方便,但理解KNN算法的内部工作原理并通过自定义实现可以加深对算法的理解。下面是一个简单的自定义KNN分类器的实现。
计算距离
首先,我们需要一个函数来计算两个点之间的距离。这里我们使用欧几里得距离:
import numpy as np
def euclidean_distance(x1, x2):
return np.sqrt(np.sum((x1 - x2) ** 2))
KNN分类器
接下来,我们定义KNN分类器类,包括训练和预测方法:
class CustomKNN:
def __init__(self, k=3):
self.k = k
def fit(self, X, y):
self.X_train = X
self.y_train = y
def predict(self, X):
y_pred = [self._predict(x) for x in X]
return np.array(y_pred)
def _predict(self, x):
# 计算距离
distances = [euclidean_distance(x, x_train) for x_train in self.X_train]
# 获取最近的k个邻居的索引
k_indices = np.argsort(distances)[:self.k]
# 获取最近的k个邻居的标签
k_nearest_labels = [self.y_train[i] for i in k_indices]
# 返回最常见的标签
most_common = max(set(k_nearest_labels), key=k_nearest_labels.count)
return most_common
使用自定义KNN
使用上述自定义KNN分类器进行训练和预测:
# 创建自定义KNN分类器实例
knn_custom = CustomKNN(k=3)
# 训练模型
knn_custom.fit(X, y)
# 预测新数据点
prediction_custom = knn_custom.predict(new_point)
print(f"自定义KNN预测结果: {prediction_custom[0]}")
KNN算法的性能评估
评估KNN模型的性能通常包括计算准确率、召回率、F1分数等指标。这里我们使用交叉验证来评估模型的准确率。
示例数据
我们使用sklearn.datasets
中的load_iris
数据集作为示例:
from sklearn.datasets import load_iris
data = load_iris()
X = data.data
y = data.target
交叉验证
使用sklearn.model_selection
中的cross_val_score
进行交叉验证:
from sklearn.model_selection import cross_val_score
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=3)
# 使用交叉验证计算准确率
scores = cross_val_score(knn, X, y, cv=5)
print(f"交叉验证准确率: {scores.mean()}")
代码解释
load_iris()
:加载鸢尾花数据集。cross_val_score(knn, X, y, cv=5)
:使用5折交叉验证评估KNN模型的准确率。
通过以上步骤,我们不仅了解了如何使用sklearn
库实现KNN算法,还学会了如何自定义KNN分类器以及如何评估模型的性能。这些技能对于深入理解机器学习算法和提高数据处理能力至关重要。
KNN算法的案例分析
案例1:鸢尾花分类
K近邻算法(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,用于分类和回归。在分类问题中,KNN通过计算待分类样本与训练集中样本的距离,选取距离最近的K个样本,根据这些样本的类别来预测待分类样本的类别。下面,我们将通过鸢尾花数据集来演示KNN算法的分类过程。
数据准备
鸢尾花数据集包含150个样本,每个样本有4个特征:花萼长度、花萼宽度、花瓣长度和花瓣宽度,以及一个类别标签,表示鸢尾花的种类。我们将使用Python的scikit-learn
库来加载和处理数据。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
# 加载数据
iris = load_iris()
X = iris.data
y = iris.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)
模型训练与预测
接下来,我们使用KNN分类器进行模型训练,并对测试集进行预测。
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X_train, y_train)
# 预测
y_pred = knn.predict(X_test)
模型评估
最后,我们评估模型的准确性。
from sklearn.metrics import accuracy_score
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy}")
案例2:癌症数据集分类
在医疗领域,KNN算法可以用于癌症数据集的分类,帮助医生预测肿瘤的良性或恶性。我们将使用scikit-learn
库中的乳腺癌数据集来演示这一过程。
数据准备
乳腺癌数据集包含569个样本,每个样本有30个特征,以及一个类别标签,表示肿瘤的良性或恶性。
from sklearn.datasets import load_breast_cancer
# 加载数据
cancer = load_breast_cancer()
X = cancer.data
y = cancer.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)
模型训练与预测
使用KNN分类器进行模型训练,并对测试集进行预测。
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=5)
# 训练模型
knn.fit(X_train, y_train)
# 预测
y_pred = knn.predict(X_test)
模型评估
评估模型的准确性。
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy}")
案例3:客户细分
在市场营销中,KNN算法可以用于客户细分,帮助企业识别不同类型的客户,以便制定更有效的营销策略。我们将使用一个虚构的客户数据集来演示这一应用。
数据准备
假设我们有一个包含1000个客户的虚构数据集,每个客户有年龄、收入和购买频率三个特征。
import numpy as np
import pandas as pd
# 创建数据集
data = {
'Age': np.random.randint(18, 65, 1000),
'Income': np.random.randint(20000, 100000, 1000),
'Purchase_Frequency': np.random.randint(1, 10, 1000),
'Customer_Type': np.random.choice(['Regular', 'Occasional', 'New'], 1000)
}
df = pd.DataFrame(data)
# 划分数据集
X = df[['Age', 'Income', 'Purchase_Frequency']]
y = df['Customer_Type']
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)
模型训练与预测
使用KNN分类器进行模型训练,并对测试集进行预测。
# 创建KNN分类器实例
knn = KNeighborsClassifier(n_neighbors=7)
# 训练模型
knn.fit(X_train, y_train)
# 预测
y_pred = knn.predict(X_test)
模型评估
评估模型的准确性。
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy}")
通过以上三个案例,我们可以看到KNN算法在不同领域的应用,包括植物分类、医疗诊断和市场营销。在实际应用中,选择合适的K值和距离度量方法对于提高模型的预测性能至关重要。此外,特征缩放也是预处理数据的重要步骤,可以避免某些特征因数值范围大而对距离计算产生过大的影响。
KNN算法的进阶话题
KNN算法的优化
K近邻算法(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,其核心思想是根据输入实例在特征空间中的K个最近邻的类别来决定输入实例的类别。然而,KNN算法在处理大规模数据集时,计算效率和分类准确性可能会受到影响。以下是一些KNN算法的优化策略:
1. 特征选择与降维
原理
在高维空间中,距离计算变得不那么有效,因为所有点之间的距离趋于相等。通过特征选择或降维,可以减少特征空间的维度,从而提高KNN的性能。
示例代码
使用PCA(主成分分析)进行降维:
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# PCA降维
pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)
# 使用KNN分类
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train_pca, y_train)
accuracy = knn.score(X_test_pca, y_test)
print("PCA降维后的KNN准确率:", accuracy)
2. 加权KNN
原理
在标准KNN中,所有邻居的贡献是相等的。加权KNN根据邻居与输入实例的距离给予不同的权重,距离越近的邻居权重越大。
示例代码
实现加权KNN:
from sklearn.metrics import pairwise_distances
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 计算距离
distances = pairwise_distances(X_test, X_train)
# 选择K个最近邻
k = 3
nearest_indices = distances.argsort()[:, :k]
# 计算权重
weights = 1 / distances[nearest_indices]
# 预测类别
y_pred = y_train[nearest_indices]
y_pred_weighted = (y_pred * weights).sum(axis=1) / weights.sum(axis=1)
KNN算法的多分类问题
原理
KNN算法可以自然地扩展到多分类问题。对于一个输入实例,找到其K个最近邻,然后根据这些邻居的类别进行投票,类别票数最多的即为输入实例的预测类别。
示例代码
使用KNN进行多分类:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用KNN分类
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
accuracy = knn.score(X_test, y_test)
print("多分类KNN准确率:", accuracy)
KNN算法的异常值处理
原理
异常值可能会影响KNN的分类结果,因为它们可能会被错误地分类并影响到其他实例的分类。处理异常值的方法包括删除、修正或使用鲁棒的KNN变体。
示例代码
使用Z-Score方法识别并删除异常值:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from scipy import stats
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 计算Z-Score
z_scores = stats.zscore(X)
abs_z_scores = np.abs(z_scores)
filtered_entries = (abs_z_scores < 3).all(axis=1)
# 过滤异常值
X_filtered = X[filtered_entries]
y_filtered = y[filtered_entries]
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_filtered, y_filtered, test_size=0.2, random_state=42)
# 使用KNN分类
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
accuracy = knn.score(X_test, y_test)
print("处理异常值后的KNN准确率:", accuracy)
以上代码示例展示了如何使用Python的scikit-learn库来优化KNN算法、处理多分类问题以及识别和删除异常值,从而提高算法的性能和准确性。
总结与展望
KNN算法的总结
K近邻算法(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,用于分类和回归。其核心思想是:对于一个给定的样本,根据其在特征空间中最近的K个邻居的类别来预测该样本的类别。KNN算法的步骤如下:
- 计算距离:选择一个距离度量方法(如欧氏距离),计算待分类样本与训练集中的每个样本之间的距离。
- 找到K个最近邻:从计算出的距离中,选择距离最近的K个训练样本。
- 分类决策:根据这K个最近邻的类别,采用多数表决的方式决定待分类样本的类别。
示例代码
假设我们有以下数据集,其中包含两个特征(X1和X2)和对应的类别标签(‘A’或’B’):
data = [
[1, 2, 'A'],
[5, 6, 'B'],
[1.5, 1.8, 'A'],
[8, 9, 'B'],
[3.6, 5, 'A'],
[8.5, 8.2, 'B']
]
下面是一个使用Python实现KNN算法的示例:
import numpy as np
from collections import Counter
# 定义数据集和标签
data = np.array([
[1, 2],
[5, 6],
[1.5, 1.8],
[8, 9],
[3.6, 5],
[8.5, 8.2]
])
labels = ['A', 'B', 'A', 'B', 'A', 'B']
# 定义KNN分类函数
def knn(data, predict, k=3):
distances = []
for group in data:
for features in data[group]:
# 计算欧氏距离
euclidean_distance = np.linalg.norm(np.array(features) - np.array(predict))
distances.append([euclidean_distance, group])
# 对距离进行排序并选择最近的K个
votes = [i[1] for i in sorted(distances)[:k]]
# 使用Counter进行多数表决
vote_result = Counter(votes).most_common(1)[0][0]
return vote_result
# 预测新样本的类别
predict = np.array([4.5, 5])
result = knn({0: data[:3], 1: data[3:]}, predict, k=3)
print(result) # 输出预测结果
在这个例子中,我们预测了一个新样本[4.5, 5]
的类别,通过计算它与数据集中每个样本的距离,然后选择距离最近的3个样本,最后根据这3个样本的类别进行多数表决,得到预测结果。
KNN算法的未来发展方向
KNN算法虽然简单直观,但在处理大规模数据集时效率较低,且对于特征空间的维度敏感。未来的发展方向主要集中在以下几个方面:
- 优化距离计算:研究更高效的距离计算方法,减少计算时间。
- 特征选择:开发算法自动选择对分类结果影响最大的特征,减少维度对算法性能的影响。
- 加权投票:根据邻居的远近给予不同的权重,以提高分类的准确性。
- 集成学习:将多个KNN模型组合起来,形成更强大的分类器,提高预测的稳定性和准确性。
进一步学习资源
对于希望深入学习KNN算法的读者,以下资源可能会有所帮助:
- 书籍:《机器学习实战》(Peter Harrington著),书中详细介绍了KNN算法的实现和应用。
- 在线课程:Coursera上的《机器学习》课程(Andrew Ng教授),涵盖了KNN算法在内的多种机器学习算法。
- 论文:《K-Nearest Neighbor Classification for Large-Scale High-Dimensionality Data》(2019),探讨了KNN算法在大规模高维数据上的应用和优化。
- 开源库:Scikit-learn,Python中广泛使用的机器学习库,提供了KNN算法的实现,可以用于实践和项目开发。
通过这些资源,读者可以更深入地理解KNN算法的原理,掌握其实现技巧,并在实际项目中应用。