机器学习-分类-KNN算法

KNN概述

测量不同特征值之间的距离来进行分类
优点: 精度高、对异常值不敏感、无数据输入设定
缺点: 计算复杂度高、空间复杂度高

1.样本集中的每个数据都有分类标签
2.输入一个新数据
3.分别计算新数据和样本集中所有的数据之间的距离
4.取前K个距离最近的样本的标签作为新数据的标签

有如下二维平面,其中红点代表A类,绿点代表B类,现在有一个蓝点,如果要预测这个蓝点的类别,那么就要算出这个蓝点和所有点的距离,然后选其中前K个距离最小的点的类别作为这个蓝点的类别
在这里插入图片描述

假设数据集中某个点为 [ x i , y i ] [x_i, y_i] [xi,yi],蓝点坐标为 [ x , y ] [x, y] [x,y],那么距离计算公式:
d = ( x − x i ) 2 + ( y − y i ) 2 d=\sqrt{(x-x_i)^2+(y-y_i)^2} d=(xxi)2+(yyi)2
如果是在三维立体空间中呢?其实也就是对二维的扩展,在 x , y x, y x,y 的基础上,再加上了个 z z z,距离由平面距离变成了空间距离

假设数据集中某个点为 [ x i , y i , z i ] [x_i, y_i, z_i] [xi,yi,zi],蓝点坐标为 [ x , y , z ] [x, y, z] [x,y,z],那么距离计算公式为:
d = ( x − x i ) 2 + ( y − y i ) 2 + ( z − z i ) 2 d=\sqrt{(x-x_i)^2+(y-y_i)^2+(z-z_i)^2} d=(xxi)2+(yyi)2+(zzi)2
机器学习中,一个数据一般由多个特征组成,上面的二维平面的数据存在2个特征值, x x x y y y,三维立体空间的数据存在三个特征值 x 、 y 、 z x、y、z xyz,那么如果一个数据有4个、5个、6个… N N N 个特征呢?这个维度人就没法理解了,但是公式可以按规律推导:
d = ( x − x i ) 2 + ( y − y i ) 2 + ( z − z i ) 2 + . . . + ( n − n i ) 2 d=\sqrt{(x-x_i)^2+(y-y_i)^2+(z-z_i)^2+...+(n-n_i)^2} d=(xxi)2+(yyi)2+(zzi)2+...+(nni)2

即,计算 n n n个特征值之间的差的平方和,然后再开根号,这个 距离 就比较抽象了,不过我们的确可以根据这个距离,预测出一个样本最合适的分类

KNN实战:糖尿病预测

下面来用Python来实现一个KNN算法,来对印第安人的糖尿病进行预测,数据集下载地址为:https://www.kaggle.com/uciml/pima-indians-diabetes-database

def classify(inx, train_matrix, train_labels, k):
    row = train_matrix.shape[0]
    inx = np.tile(inx, (row, 1))
    diff_matrix = inx - train_matrix
    sq_diff_mat = diff_matrix ** 2
    sq_distances = sq_diff_mat.sum(axis=1)
    distances = sq_distances ** 0.5 
    sorted_dist_index = distances.argsort()
    class_count = {}
    for i in range(k):  # 选择距离最小的K个点
        vote_label = train_labels[sorted_dist_index[i]]
        class_count[vote_label] = class_count.get(vote_label, 0) + 1
    sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)
    return sorted_class_count[0][0]

上面这段代码输入参数为预测样本向量 inx,训练样本数据 train_matrix,训练样本标签 train_labels,以及选择的邻居数 k,上面这段代码实现了计算一个输入样本与所有已标记样本之间的距离,然后求取距离最近的 k 个邻居中,代表率最高的标签,然后将这个标签返回

def create_dataset(x, y, index_list):
    num = len(index_list)
    matrix = np.zeros((num, 8))
    labels = np.zeros(num)
    for i in range(num):
        matrix[i] = x[index_list[i]]
        labels[i] = y[index_list[i]]
    return matrix, labels

def diabetes_classify():
    data = pd.read_csv('pima-indians-diabetes/diabetes.csv')
    x = data.iloc[:, 0:8].values  # 取前8个特征
    y = data.iloc[:, 8].values  # 取第8个即标签
    train_index_list = list(range(len(x)))
    test_index_list = random.sample(train_index_list, 200)  # 随机选取200个作为测试数据
    for index in test_index_list:
        train_index_list.remove(index)
    train_matrix, train_labels = create_dataset(x, y, train_index_list)
    test_matrix, test_labels = create_dataset(x, y, test_index_list)
    error_count = 0.0
    for test_vec, test_label in zip(test_matrix, test_labels):
        pred_label = classify(test_vec, train_matrix, train_labels, 3)
        print("the classifier came back with: %d, the real answer is: %d" % (pred_label, test_label))
        if pred_label != test_label:
            error_count += 1.0
            print("===================prediction error====================")
    print("the total number of errors is: %d" % error_count)
    print("the total error rate is: %f" % (error_count / len(test_index_list)))

上面这段代码是将糖尿病数据集做了读取与划分,随机创建了训练数据集和测试数据集,该数据集共有768条数据,这里随机抽取了200条作为测试数据,然后用调用KNN算法分类器classify来进行预测,运行代码,可以得到输出如下:

the total number of errors is: 53
the total error rate is: 0.265000

可以看到,错误率为0.265000,即准确率为73.5%,这个结果还是比较令人满意的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值