K-近邻算法

K—近邻算法(KNN)是一种基本的分类与回归算法,同时学习斯坦福231课程的中接触到的第一个图像分类算法,当然了它不仅可以应用在图像分类领域,在文本分类等方面同样也可以使用它。
一:数据驱动方法
我们知道传统的机器视觉算法依靠对所要识别的物体进行特征描述,即指定具体的规则来完成对图片的分类,这个有很大的局限性,随着计算机计算能力的提高以及深度学习领域一些重要技术的突破,基于深度学习的计算机视觉算法已经远远的将传统的机器视觉算法拉在了身后。在机器学习中对于图片分类问题,我们不写具体的分类规则来识别图像,我们采用数据驱动的方法解决问题。那么何谓数据驱动方法呢?它分为三个步骤:
1.收集大量图片,并制作标签集作为数据集.
2.使用机器学习算法训练一个分类器.
3.在新的图片上评估用步骤2得到的分类器的准确度.
二:KNN算法
k 近邻算法的输入为实例的特征向量,对应于特征空间的点;输出为实例的类别,可以取多类。k 近邻算法假设给定一个训练数据集,其中的实例类别已定。分类时,对新的实例,根据其 k 个最近邻的训练实例的类别,通过多数表决等方式进行预测。因此,k近邻算法是一个不需要预训练的算法,在训练阶段的时间复杂度为O(1),在测试阶段时间复杂度为O(n),这不是我们愿意看到的情况,我们通常想让分类器在对新样本的预测上速度非常快,而在训练阶段非常慢没有关系。
k 近邻算法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。 k值的选择、距离度量以及分类决策规则是k近邻算法的三个基本要素。我们这里分类决策规则就是采用多数表决的方式,所以我们在使用算法时通常要做的就是选择距离度量的方式和k值
1. 距离度量的选择
距离度量我们通常有两种方式,即L1(Manhattan)距离(曼哈顿距离)和L2(Euclidean)距离(欧式距离)。
在这里插入图片描述
我们可以看出来,L1距离依赖坐标系统的选取,改变坐标轴对L1距离有影响,对L2距离则没有影响。因此通常如果你输入的样本向量中的值有实际意义,比如说员工的身高、姓名等指标那么一般选取L1距离作为度量距离的方式,否则选取L2更好一点。
2. K值的选择
K值我们称之为超参数,就是只能根据实际应用的经验指导选择应用问题时效果最好的参数。超参数的选择有两种方法:
① 我们将数据分为训练集、验证集和测试集,然后选择通过训练集训练得到而在验证集上表现最好的参数作为我们要选取的参数值,然后在测试集上进行评估。这里需要注意的是训练集和验证集的区别:在使用算法对模型进行训练时使用到了训练集的标签来计算误差,然后反向传播更新参数,但我们仅仅是使用验证集的标签来观察算法的表现,并不参与训练过程。
② K重交叉验证,我们将得到的数据集保留一部分做测试集,剩下的分为k份,每次在k-1份上进行训练,而在剩下的那一份上进行验证,最后我们关于一个参数会得到k个结果,选取k个结果的平均值作为该参数下的模型的结果,最后,选择表现最好的k在测试集上做评估。
3. k近邻算法的优缺点
k近邻的优点就是算法简单,使用起来非常方便。但是在图片分类问题上我们通常不会使用它,原因有三点:
① 在测试阶段非常慢.
② 在像素间采用距离度量的方式不具备很好的效果.比如说我们将一个照片左边的像素裁取一列移到右边、右边的像素裁取一列移到左边,这样我们就可以得到三幅图片实际上它们描述的是一个物体,应该是属于同一个类别,可是采用距离度量的方式得到的结果是天差地别的。
③ 维度灾难问题(Curse of dimensionality),指的是采用k近邻算法做预测时,我们要想得到好的结果,就需要训练数据能密集地分布在新输入的样本可能会存在的空间中,否则最近邻点的实际距离可能会很远,即和待测样本的相似性没有那么高。问题在于要想让数据密集地分布在数据空间中,我们需要指数倍的增加训练数据,即每增加一个维度所需要数据量急剧增加,我们拿不出那么多的图片取进行密集分布。
四: k-近邻算法的实现
这个算法是我之前接触机器学习时写过的一个实例。它有1000个样本,是一个约会网站的例子,用于帮助女性筛选出符合她们要求的男性,可以提高男女约会的成功率,在这里k值的选取我以前使用的是试错的方法,通过对k值的不断尝试选择效果最好的k值,有兴趣的同学也可以使用k重交叉验证的方法(我懒得改了【捂脸,逃跑】)下面是代码:

import numpy as np
import operator
import matplotlib.pyplot as plt
# 对文件进行处理,返回输入矩阵和输出列表
def file_to_matrix(filename):
   fr = open(filename)
   # 数据行数
   rows = len(fr.readlines())
   print(rows)
   input_matrix = np.mat(np.zeros((rows, 3),dtype=float))
   output = []
   fr = open(filename)
   index = 0
   for row in fr.readlines():
       row = row.strip()
       row_list = row.split('\t')
       input_matrix[index, :] = row_list[0:3]
       output.append(int(row_list[-1]))
       index += 1
   return input_matrix,output


# 归一化矩阵
def norm_matrix(input_matrix):
   max = input_matrix.max(0)
   min = input_matrix.min(0)
   ranges = max-min
   print(ranges)
   m = input_matrix.shape[0]
   norm_dataset = input_matrix-np.tile(min, (m,1))
   norm_dataset = norm_dataset/np.tile(ranges, (m,1))
   return norm_dataset

# k-近邻算法
def k_algorithm(indx, norm_dataset, lables, k):
    m = norm_dataset.shape[0]
    #print("norm_dataset:", norm_dataset.shape)
    diffset = np.tile(indx, (m, 1))-norm_dataset
    diff_array = np.array(diffset)
    squ_array = diff_array**2
    squset = np.mat(squ_array)
    distances = squset.sum(axis=1)
    #print("distances:", distances.shape)
    # 开平方根
    for i in range(m):
        distances[(i, 0)] = distances[(i, 0)]**0.5
    sorted_distances_index = np.argsort(distances, axis=0)
    #print(sorted_distances_index.shape)
    classcount = {}
    for i in range(k):
        vlabel = lables[sorted_distances_index[i, 0]]
        classcount[vlabel] = classcount.get(vlabel, 0)+1
    print("calsscount:", classcount)
    sortedClassCount = sorted(classcount.items(), key=operator.itemgetter(1), reverse=True)
    print(sortedClassCount)
    return sortedClassCount[0][0]

# 测试数据集
def dataing_web_test():
    (input_matrix, output) = file_to_matrix("web_yuehui.txt")
    norm_dataset = norm_matrix(input_matrix)
    # 测试比例
    rate = 0.1
    m = norm_dataset.shape[0]
    # 测试集的数量
    test_num = int(m*rate)
    print("test_num:", test_num)
    cnt = 0
    for i in range(test_num):
        predict_op = k_algorithm(norm_dataset[i], norm_dataset, output, 20)
        if(predict_op==output[i]):
            cnt += 1
    print("test accurancy rate:%f" % (cnt/test_num))

if __name__ == '__main__':
    dataing_web_test()
    percentTats = float(input("percentage of time spent playing video games ?"))
    ffMiles = float(input("frequent filer miles earned per year?"))
    iceCream = float(input("liters of ice cream consumed per year?"))
    (input_matrix, output) = file_to_matrix("web_yuehui.txt")
    norm_dataset = norm_matrix(input_matrix)
    inarray = np.array([percentTats, ffMiles, iceCream])
    inmat = np.mat(inarray)
    max = input_matrix.max(0)
    min = input_matrix.min(0)
    ranges = max - min
    predict_kind = k_algorithm(((inmat-min)/ranges), norm_dataset, output, 20)
    print("the predict kind is %d" % predict_kind)








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值