目录
8.1 K邻近分类法(KNN)
这种算法把要分类的对象(例如一个特征向量)与训练集中已知类标记的所有对象进行对比,并由 k 近邻对指派到哪个类进行投票。其基本思想是:给定一个待分类的样本点,根据距离度量(通常是欧氏距离),找到与该点距离最近的K个样本点,然后根据这些K个样本点的类别进行投票(分类)或平均(回归),以决定待分类样本点的类别或预测值。
实验代码:
import numpy as np
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.3, random_state=42)
# 创建KNN分类器对象,选择K=5
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'KNN分类器的准确率: {accuracy:.2f}')
分析:
- 准确率:输出的准确率(
accuracy
)表明了KNN分类器在测试集上的表现。一般来说,准确率越高,模型效果越好。 - K值选择:K值的选择会影响分类结果。K值过小容易导致过拟合,K值过大则可能导致欠拟合。通常需要通过交叉验证选择最优的K值。
结果:
8.1.1 一个简单的二维示例
下面是一个简单的二维K邻近分类法(KNN)示例。我们将使用scikit-learn
创建一个合成的二维数据集,并应用KNN分类器进行分类。
实验代码:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 生成二维数据
X, y = make_classification(n_samples=100, n_features=2, n_classes=2, n_clusters_per_class=1, n_redundant=0, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 创建KNN分类器对象,选择K=3
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X_train, y_train)
# 进行预测
y_pred = knn.predict(X_test)
# 评估模型
accuracy = accuracy_score(y_test, y_pred)
# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.RdYlBu, edgecolor='k')
plt.title('二维数据集')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
# 绘制决策边界
xx, yy = np.meshgrid(np.linspace(X[:, 0].min() - 1, X[:, 0].max() + 1, 500),
np.linspace(X[:, 1].min() - 1, X[:, 1].max() + 1, 500))
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
plt.colorbar()
plt.show()
print(f'KNN分类器的准确率: {accuracy:.2f}')
分析:
-
准确率:代码中使用了
accuracy_score
来计算分类器在测试集上的准确率。准确率的值显示了模型对测试数据的分类准确程度,通常,准确率值越接近1.0,表示模型性能越好。 -
可视化:我们通过散点图展示了二维数据的分布,并使用不同颜色表示不同的类别。决策边界被绘制在图中,以显示KNN分类器如何划分数据空间。决策边界的颜色填充展示了模型的分类结果如何覆盖整个特征空间。
结果:
8.1.2 用稠密SIFT作为图像特征
稠密SIFT(Dense SIFT)是一种图像特征提取方法,它在整个图像的每个局部区域计算SIFT特征,而不仅仅是在关键点上。这种方法使得特征提取更为密集和全面,适合用于图像匹配、识别和检索等任务。
-
稠密SIFT的优点:
- 全面性:相比于传统SIFT,只在关键点上提取特征,稠密SIFT在整个图像上提取特征,提供更丰富的描述。
- 更高的鲁棒性:由于特征覆盖了整个图像,它对图像的局部变化和变形更为鲁棒。
-
稠密SIFT的缺点:
- 计算开销大:因为需要在图像的每个位置提取特征,计算量和存储需求较高。
实验代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
image_path = '1.jpg'
image = cv2.imread(image_path)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 创建 SIFT 特征检测器
sift = cv2.SIFT_create()
# 检测关键点和计算描述符
keypoints, descriptors = sift.detectAndCompute(gray_image, None)
# 可视化特征点
image_with_keypoints = cv2.drawKeypoints(image, keypoints, None)
plt.figure(figsize=(10, 10))
plt.imshow(cv2.cvtColor(image_with_keypoints, cv2.COLOR_BGR2RGB))
plt.title('SIFT特征点')
plt.show()
print(f'特征点数量: {len(keypoints)}')
print(f'描述符形状: {descriptors.shape}')
分析:
- 读