k近邻算法-python实现

K近邻算法简介

	K近邻算法(K-nearest neighbor,KNN)是一种非常直观的,易于理解的有监督的算法:对于一个待分类的样本,在已知的样本集合中寻
	找与它距离最近的K个样本,及所谓的K近邻。通过这这K个近邻的所述类别来决定分类结果。

KNN算法3个要素

  • 距离度量
  • 分类决策
  • K的选择
距离度量
	距离度量方法有很多种,例如:欧式距离、曼哈顿距离、切比雪夫距离等等。
分类决策
	分类决策一般是通过投票决定,当然也可以根据具体情况再做改变。常见的改进方法如距离加权:赋予距离越近的样本越大的权值。
K的选择
	当K的取值很小时,决策易受到噪声的干扰;同时模型复杂,也容易造成过拟合。
	当K的取值很大时,决策边缘会变得平滑,模型简单,预测结果容易出现错误。
	
	通常采用交叉验证来选去较好的K值。

KNN算法流程

  1. 计算距离:计算当前待分类样本与所有已知样本的距离
  2. 距离排序:将距离降序排序
  3. 投票分类:选择K个近邻,并根据其类别决定待分类样本的类别。

代码

读取数据

本实验采用的是UCI上的iris数据集,链接如下:
iris数据集

import numpy as np
import pandas as pd

ori_data = pd.read_csv('iris.data',header=None)

处理数据
1.将标记映射为数字
label_map = {
    'Iris-setosa':1,
    'Iris-versicolor':2,
    'Iris-virginica':3
}
data = ori_data.replace(label_map)

2.归一化

将数据归一化到[a,b]之间的函数如下:

def normalization(a, b, array):
    maxcols = array.max(axis=0)
    mincols = array.min(axis=0)
    trans_data = np.zeros(array.shape)
    [m, n] = array.shape
    for i in range(n):
        k = (b-a)/(maxcols[i]-mincols[i])
        trans_data[:, i] = a + k * (array[:, i]-mincols[i])
    return trans_data

调用处理数据

data_array = np.array(data)
[data_num, feature_num] = data_array.shape
trans_data = normalization(0, 1, data_array[:, 0:feature_num-1])
label = data_array[:, feature_num-1].reshape(data_num, 1)
trans_data = np.hstack((trans_data, label)) #按列合并

全部代码如下

import pandas as pd
import numpy as np
import math
import random
from scipy import stats
def normalization(a, b, array):
    maxcols = array.max(axis=0)
    mincols = array.min(axis=0)
    trans_data = np.zeros(array.shape)
    [m, n] = array.shape
    for i in range(n):
        k = (b-a)/(maxcols[i]-mincols[i])
        trans_data[:, i] = a + k * (array[:, i]-mincols[i])
    return trans_data
def dis(x1, x2):
    return np.sqrt(np.sum(pow((x1 - x2), 2)))
#预测样本类别
def cla(x, train_x, train_y, k):
    n = train_x.shape[0]
    distance = np.zeros((n, 1))
    for i in range(n):
        x2 = train_x[i,:]
        distance[i, 0] = dis(x, x2)
    dis_and_y = np.hstack((distance, train_y))
    index = np.argsort(dis_and_y[:, 0])
    dis_and_y = dis_and_y[index]
    list = dis_and_y[0:k,1]
    a = stats.mode(list)[0] #计算众数
    return a[0]
#计算分类精度
def predict(train_data, test_data):
    train_y = train_data[:, feature_num-1].reshape(train_data.shape[0], 1)
    test_y = test_data[:, feature_num-1].reshape(test_data.shape[0],  1)
    train_x = train_data[:, 0:feature_num-1]
    test_x = test_data[:, 0:feature_num-1]
    count = 0
    for i in range(test_x.shape[0]):
        y = cla(test_x[i, :], train_x, train_y, 10)

        if y == test_y[i, 0]:
            count = count + 1
    return count/test_data.shape[0]


ori_data = pd.read_csv("iris.data", header=None)
label_map = {
    'Iris-setosa':1,
    'Iris-versicolor':2,
    'Iris-virginica':3
}
data = ori_data.replace(label_map) # 标记映射到1,2,3
data_array = np.array(data)
[data_num, feature_num] = data_array.shape
trans_data = normalization(0, 1, data_array[:, 0:feature_num-1])
label = data_array[:, feature_num-1].reshape(data_num, 1)
trans_data = np.hstack((trans_data, label)) #按列合并

for i in range(10):
	#抽样
    sl = random.sample(range(0, data_num), data_num//10)
    test_data = trans_data[sl, :]
    train_data = np.delete(trans_data, sl, axis=0)

    prediction = predict(train_data, test_data)
    print(prediction)


如有疑问,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值