K-近邻算法(KNN)

1、k-近邻算法原理

简单地说,K-近邻算法采用测量不同特征值之间的距离方法进行分类。

  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:时间复杂度高、空间复杂度高。
  • 适用数据范围:数值型和标称型。

欧几里得距离(Euclidean Distance)

欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:

image.png

2、在scikit-learn库中使用k-近邻算法

  • 分类问题:from sklearn.neighbors import KNeighborsClassifier

  • 回归问题:from sklearn.neighbors import KNeighborsRegressor

0)一个最简单的例子

身高、体重、鞋子尺码数据对应性别

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
# 是男是女 属于分类问题
from sklearn.neighbors import KNeighborsClassifier
# 训练样本 X是样本的特征 y是样本的结果(标签)
# 训练样本的特征
# 身高 体重 鞋子尺码
X_train = np.array([
    [177,73,42],
    [150,44,36],
    [177,63,41],
    [160,52,35],
    [165,70,40],
    [179,80,44],
    [156,40,36],
    [155,50,36]
])
y_train = np.array(['male','female','male','female','male','male','female','female'])

# 测试样本
X_train  # 特征
y_train  # 结果(标签)
# KNeighborsClassifier 用来获取分类的模型
# 参数 n_neighbors 指的是 考虑最近的几个 默认是5个
knn_c = KNeighborsClassifier(n_neighbors=5)
# 参数 X 是训练数据的特征
# 参数 y 是训练数据的结果(标签)
knn_c.fit(X_train,y_train)  # knn模型的训练很简单 就是记录一下各个样本的位置
# 现在这个模型就是已经训练好的模型了
# knn_c.predict() 可以测试
# 参数X 是要传入的 测试数据 把特征传入 会根据训练好的模型 返回结果
knn_c.predict([
    [190,100,45],
    [150,35,32]
])

1)用于分类

导包,机器学习的算法KNN、数据鸢尾花

# scikit-learning 提供数据样本,可以供我们研究机器学习模型
# 可以使用load方法加载datasets中的各种数据
from sklearn import datasets
import matplotlib.pyplot as plt

获取训练样本 datasets.load_iris()

iris_data = datasets.load_iris()
iris_data
data = iris_data.data  # 所有样本的特征
target = iris_data.target  # 所有样本的目标值
feature_names = iris_data.feature_names  # 特征的名字
target_names = iris_data.target_names  # 目标值的名称

画图研究前两个特征和分类之间的关系(二维散点图只能展示两个维度)

# 为了给大家展示 我这里只研究前两个特征 和 分类的关系 (大家自己用knn分类的时候 最好是把四个特征都算上)
X_train = data[:,0:2]  # 所有行都要,0-2列 2取不到 就是0和1
X_train  # 训练样本的特征
# 训练样本的标签(结果)
y_train = target  # 训练样本的结果
y_train
# 展示关系用散点图
# x, y x是一个特征 y是另一个特征 这样 一个点的位置就有了
# 花萼长度作为x 花萼宽度作为y 对所有样本进行定位 然后 不同的分类用不同的颜色来标注
# c参数传入的列表是各个样本的分类编号 scatter 对象根据 不同的编号给样本分配不同的颜色
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.xlabel('sepal length')
plt.ylabel('sepal width')
knn_c = KNeighborsClassifier(n_neighbors=5)
# 训练模型
# 调用 knn_c.fit 方法 传入 训练集数据的特征 和 训练集数据的结果
knn_c.fit(X_train,y_train)
# knn_c.fit(data,target)
# 可以测试了 传入 样本的特征 会返回这个样本的分类
knn_c.predict([
    [4.5,4.0],
    [7.5,3.0],
    [5.25,2.25]
])

第二步预测数据:所预测的数据,自己创造,就是上面所显示图片的背景点

生成预测数据

# 获取平面上的所有点
# 先把x轴线的范围和y轴的范围获取到
xmin = X_train[:,0].min()-0.5
xmax = X_train[:,0].max()+0.5
ymin = X_train[:,1].min()-0.5
ymax = X_train[:,1].max()+0.5
# x轴范围内要取遍
x = np.arange(xmin,xmax,0.01)
# y轴范围内也要取遍
y = np.arange(ymin,ymax,0.01)
y
# 把画布上所有的点都取遍
xx,yy = np.meshgrid(x,y)
xx.flatten(),yy.flatten()
# 把对应位置的两个内容取出来 变成新的列表
X_test = np.c_[xx.flatten(),yy.flatten()]  # 将平面上所有的点取遍 并 用来作为测试数据
X_test
plt.scatter(X_test[:,0],X_test[:,1])

对数据进行预测

y_ = knn_c.predict(X_test)
y_  # y_是模型预测的结果 真实结果用y_test
# 根据特征绘制样本的位置 根据模型预测的结果 绘制样本的颜色
plt.scatter(X_test[:,0],X_test[:,1],c=y_)
# 自己制定颜色
from matplotlib.colors import ListedColormap
cmap0 = ListedColormap(['red','green','blue'])
cmap1 = ListedColormap(['#cc99bb','#88ddbb','#8899ff'])
cmap2 = ListedColormap(['#dd2244','#00ee33','#0011ff'])
# 把真实的训练数据也画到图上
plt.scatter(X_test[:,0],X_test[:,1],c=y_)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cmap0)
# 把真实的训练数据也画到图上
plt.scatter(X_test[:,0],X_test[:,1],c=y_,cmap=cmap1)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cmap2)

ocr 光学字符识别(Optical Character Recognition) 我们先做一个基础班:识别数字

# 图片虽然是二维的数据 但是每行并不是一个样本的多个特性 
# 每个图片是一个样本 里面的各个点都是其特征 所以我们可以把28*28的点 变成1*784的点(在Excel里画图演示)
# 图片的每一个像素点都是一个特征
# 每一个图片是一个样本
data = plt.imread('./digits/0/0_1.bmp')
data
plt.imshow(data)
data.shape
data = data.flatten()  # 把图片扁平化 变成一行
data.shape
plt.imshow(data.reshape(28,28))  # 要显示的时候 还是需要把一行的值 变成28*28
# 读取所有的样本 分成 训练数据 和 测试数据
# 训练数据集
X_train = []
y_train = []
# 测试数据集
X_test = []
y_test = []

for i in range(10):
    for j in range(1,501):
        # print('./digits/%d/%d_%d.bmp'%(i,i,j))
        # 根据路径 读取数据 然后 把28*28的形状 变成1行的形状
        data = plt.imread('./digits/%d/%d_%d.bmp'%(i,i,j)).flatten()
        # 目标值就是 文件夹的名字 也就在i
        target = i
        # 前490个都用来训练 后10个用来测试
        if j<=490:
            X_train.append(data)
            y_train.append(target)
        else:
            X_test.append(data)
            y_test.append(target)
knn = KNeighborsClassifier()
# 训练
knn.fit(X_train,y_train)
# 预测 传入测试的特征值 根据模型 返回 预测的结果
y_ = knn.predict(X_test)
y_
knn.score(X_test,y_test)
# 把图片绘制出来 把 预测结果作为子画布的题目
plt.figure(figsize=(15,20))
index = 1
for i in range(10):
    for j in range(10):
        axes = plt.subplot(10,10,index)
        # 传入测试数据 按照索引从X_test中获取数据 然后变回28*28的形状
        plt.imshow(X_test[index-1].reshape(28,28))
        axes.axis('off')  # 隐藏坐标轴
        # 把真实数据作为坐标系的标题
        axes.set_title(y_[index-1])
        index += 1

你可能感兴趣的:(K-近邻算法(KNN))