2.4 算法实战
2.4.1 Demo数据集–kNN分类
Step1: 库函数导入
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
Step2: 数据导入
# 使用莺尾花数据集的前两维数据,便于数据可视化
iris = datasets.load_iris()
X = iris.data[:, :2]
y = iris.target
Step3: 模型训练&可视化
k_list = [1, 3, 5, 8, 10, 15]
h = .02
# 创建不同颜色的画布
cmap_light = ListedColormap(['orange', 'cyan', 'cornflowerblue'])
cmap_bold = ListedColormap(['darkorange', 'c', 'darkblue'])
plt.figure(figsize=(15,14))
# 根据不同的k值进行可视化
for ind,k in enumerate(k_list):
clf = KNeighborsClassifier(k)
clf.fit(X, y)
# 画出决策边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
# 根据边界填充颜色
Z = Z.reshape(xx.shape)
plt.subplot(321+ind)
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)
# 数据点可视化到画布
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold,
edgecolor='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("3-Class classification (k = %i)"% k)
plt.show()
Step4: 原理简析
如果选择较小的K值,就相当于用较小的领域中的训练实例进行预测,例如当k=1的时候,在分界点位置的数据很容易受到局部的影响,图中蓝色的部分中还有部分绿色块,主要是数据太局部敏感。当k=15的时候,不同的数据基本根据颜色分开,当时进行预测的时候,会直接落到对应的区域,模型相对更加鲁棒。
2.4.2 莺尾花数据集–kNN分类
Step1: 库函数导入
import numpy as np
# 加载莺尾花数据集
from sklearn import datasets
# 导入KNN分类器
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
Step2: 数据导入&分析
# 导入莺尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 得到训练集合和验证集合, 8: 2
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
Step3: 模型训练
这里我们设置参数k(n_neighbors)=5, 使用欧式距离(metric=minkowski & p=2)
# 训练模型
clf = KNeighborsClassifier(n_neighbors=5, p=2, metric="minkowski")
clf.fit(X_train, y_train)
KNeighborsClassifier()
Step4:模型预测&可视化
# 预测
X_pred = clf.predict(X_test)
acc = sum(X_pred == y_test) / X_pred.shape[0]
print("预测的准确率ACC: %.3f" % acc)
预测的准确率ACC: 0.967
我们用表格来看一下KNN的训练和预测过程。这里用表格进行可视化:
- 训练数据[表格对应list]
feat_1 | feat_2 | feat_3 | feat_4 | label |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | 0 |
4.9 | 3. | 1.4 | 0.2 | 0 |
4.7 | 3.2 | 1.3 | 0.2 | 0 |
4.6 | 3.1 | 1.5 | 0.2 | 0 |
6.4 | 3.2 | 4.5 | 1.5 | 1 |
6.9 | 3.1 | 4.9 | 1.5 | 1 |
5.5 | 2.3 | 4. | 1.3 | 1 |
6.5 | 2.8 | 4.6 | 1.5 | 1 |
5.8 | 2.7 | 5.1 | 1.9 | 2 |
7.1 | 3. | 5.9 | 2.1 | 2 |
6.3 | 2.9 | 5.6 | 1.8 | 2 |
6.5 | 3. | 5.8 | 2.2 | 2 |
- knn.fit(X, y)的过程可以简单认为是表格存储
feat_1 | feat_2 | feat_3 | feat_4 | label |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | 0 |
4.9 | 3. | 1.4 | 0.2 | 0 |
4.7 | 3.2 | 1.3 | 0.2 | 0 |
4.6 | 3.1 | 1.5 | 0.2 | 0 |
6.4 | 3.2 | 4.5 | 1.5 | 1 |
6.9 | 3.1 | 4.9 | 1.5 | 1 |
5.5 | 2.3 | 4. | 1.3 | 1 |
6.5 | 2.8 | 4.6 | 1.5 | 1 |
5.8 | 2.7 | 5.1 | 1.9 | 2 |
7.1 | 3. | 5.9 | 2.1 | 2 |
6.3 | 2.9 | 5.6 | 1.8 | 2 |
6.5 | 3. | 5.8 | 2.2 | 2 |
- knn.predict(x)预测过程会计算x和所有训练数据的距离
这里我们使用欧式距离进行计算, 预测过程如下
x = [ 5. , 3.6 , 1.4 , 0.2 ] y = 0 x = [5. , 3.6, 1.4, 0.2] \\ y=0 x=[5.,3.6,1.4,0.2]y=0
step1: 计算x和所有训练数据的距离
feat_1 | feat_2 | feat_3 | feat_4 | 距离 | label |
---|---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | 0.14142136 | 0 |
4.9 | 3. | 1.4 | 0.2 | 0.60827625 | 0 |
4.7 | 3.2 | 1.3 | 0.2 | 0.50990195 | 0 |
4.6 | 3.1 | 1.5 | 0.2 | 0.64807407 | 0 |
6.4 | 3.2 | 4.5 | 1.5 | 3.66333182 | 1 |
6.9 | 3.1 | 4.9 | 1.5 | 4.21900462 | 1 |
5.5 | 2.3 | 4. | 1.3 | 3.14801525 | 1 |
6.5 | 2.8 | 4.6 | 1.5 | 3.84967531 | 1 |
5.8 | 2.7 | 5.1 | 1.9 | 4.24617475 | 2 |
7.1 | 3. | 5.9 | 2.1 | 5.35070089 | 2 |
6.3 | 2.9 | 5.6 | 1.8 | 4.73075047 | 2 |
6.5 | 3. | 5.8 | 2.2 | 5.09607692 | 2 |
step2: 根据距离进行编号排序
距离升序编号 | feat_1 | feat_2 | feat_3 | feat_4 | 距离 | label |
---|---|---|---|---|---|---|
1 | 5.1 | 3.5 | 1.4 | 0.2 | 0.14142136 | 0 |
3 | 4.9 | 3. | 1.4 | 0.2 | 0.60827625 | 0 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 0.50990195 | 0 |
4 | 4.6 | 3.1 | 1.5 | 0.2 | 0.64807407 | 0 |
6 | 6.4 | 3.2 | 4.5 | 1.5 | 3.66333182 | 1 |
8 | 6.9 | 3.1 | 4.9 | 1.5 | 4.21900462 | 1 |
5 | 5.5 | 2.3 | 4. | 1.3 | 3.14801525 | 1 |
7 | 6.5 | 2.8 | 4.6 | 1.5 | 3.84967531 | 1 |
9 | 5.8 | 2.7 | 5.1 | 1.9 | 4.24617475 | 2 |
12 | 7.1 | 3. | 5.9 | 2.1 | 5.35070089 | 2 |
10 | 6.3 | 2.9 | 5.6 | 1.8 | 4.73075047 | 2 |
11 | 6.5 | 3. | 5.8 | 2.2 | 5.09607692 | 2 |
step3: 我们设置k=5,选择距离最近的k个样本进行投票
距离升序编号 | feat_1 | feat_2 | feat_3 | feat_4 | 距离 | label |
---|---|---|---|---|---|---|
1 | 5.1 | 3.5 | 1.4 | 0.2 | 0.14142136 | 0 |
3 | 4.9 | 3. | 1.4 | 0.2 | 0.60827625 | 0 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 0.50990195 | 0 |
4 | 4.6 | 3.1 | 1.5 | 0.2 | 0.64807407 | 0 |
6 | 6.4 | 3.2 | 4.5 | 1.5 | 3.66333182 | 1 |
8 | 6.9 | 3.1 | 4.9 | 1.5 | 4.21900462 | 1 |
5 | 5.5 | 2.3 | 4. | 1.3 | 3.14801525 | 1 |
7 | 6.5 | 2.8 | 4.6 | 1.5 | 3.84967531 | 1 |
9 | 5.8 | 2.7 | 5.1 | 1.9 | 4.24617475 | 2 |
12 | 7.1 | 3. | 5.9 | 2.1 | 5.35070089 | 2 |
10 | 6.3 | 2.9 | 5.6 | 1.8 | 4.73075047 | 2 |
11 | 6.5 | 3. | 5.8 | 2.2 | 5.09607692 | 2 |
step4: k近邻的label进行投票
nn_labels = [0, 0, 0, 0, 1] --> 得到最后的结果0。