机器学习——k近邻算法

算法介绍

k近邻法(k-nearest neighbors)是由Cover和Hart于1968年提出的,它是懒惰学习(lazy learning)的著名代表。

k近邻算法简单、直观:给定一个训练数据集(其中的实例类别已定),对新的输入实例,在训练数据集中找到与该实例最接近的k个实例,这k个实例的多数属于某个类,就把该输入实例分为这个类。

举个栗子
在这里插入图片描述

1.给定了红色和蓝色的训练样本,绿色为测试样本
2.计算绿色点到其他点的距离
3.选取离绿点最近的k个点
4.选取k个点中,同种颜色最多的类。
例如:k=1时,k个点全是蓝色,那预测结果就是Class 1;
k=3时,k个点中两个红色一个蓝色,那预测结果就是Class 2

要素1:k值的选取

  1. k值过小,模型复杂,易过拟合
    在这里插入图片描述
    如果k太小,如1,则模型太复杂,容易学习到噪声,非常容易判定为噪声类别。换个简单的说法,当k=1时,如果离测试点距离最近的是一个噪声值(无用数据),那么判断就会出错。

过拟合:在训练集上准确率非常高,而在测试集上准确率低。即:平时学习很好,考试很差;比如平时做的都是线性代数,但却是去考概率论。

  1. k值过大,模型简单,易预测错误
    可以想象,如果K的值大到全部的训练集,那么判断就会变成一个简单的比谁的个数多,如果A种类的个数最多,那么毫无疑问的无论放的测试点是B,还是C,都会被判定为A

  2. k值既不能过大,又不能过小,那么如何选取k值
    解决办法:交叉验证

交叉验证:将原始数据进行分组,一部分做为训练集另一部分做为验证集,首先用训练集对分类器进行训练,在利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标.

举个栗子
在这里插入图片描述
我们把样本分成十等分,第一次取第十份为测试集,前九份为训练集;第二次取第九份为测试集,其余为训练集…然后k取1,2,3…测出最合适的k值

要素2:距离度量

  1. Lp距离
    在这里插入图片描述

  2. p=1时,曼哈顿距离
    在这里插入图片描述

  3. p=2时,欧氏距离
    在这里插入图片描述

  4. p=∞时,为各维度距离中的最大值
    在这里插入图片描述

归一化特征值的必要性
在这里插入图片描述

要素3:分类决策规则

多采用表决,也可基于距离远近进行加权投票

多数表决规则等价于经验风险最小化。
常用误分类率评价KNN性能,要使误分类率最小,即经验风险最小,需使得正确分类率最大,即多数表决:
在这里插入图片描述

误分类率:
在这里插入图片描述

k近邻算法

k近邻法的分类算法描述步骤:

(1)输入:训练数据集为实例的特征向量
	T={((𝑥1) ⃗,𝑦1),((𝑥2) ⃗,𝑦2),…,((𝑥𝑁) ⃗,𝑦𝑁)},
 	𝑥 ⃗_𝑖∈𝜒⊆ℝ𝑛为实例的特征向量,𝑦_𝑖∈𝑌={c1,c2,…,ck}为实例的类别,
	 i=1,2,…,N。给定实例特征向量𝑥 ⃗。
 (2)输出:实例𝑥 ⃗所属类别y。
 (3)其实现步骤为:
	根据给定的距离度量,在T中寻找与𝑥 ⃗最近邻的k个点,
	定义涵盖这k个点的𝑥 ⃗的邻域记作Nk(𝑥 ⃗)。
	从Nk(𝑥 ⃗)中,根据分类决策规则决定𝑥 ⃗的类别:

说简单点就是,在很多点组成的训练集里,放入一个新的点,测试该点属于什么种类,把所有点和该点算一个距离按距离排序,取前k个点,k个点中哪个类别的个数最多,我们就认为这个点也是这一类。

python代码

k近邻算法

def classify0(inX, dataSet, labels, k):
    # 用于分类的输入向量是inX,输入的训练样本集为dataSet,标签向量为labels,最后的参数k表示选择邻居的数目
    # 标签向量的元素数目和矩阵dataSet的行数相同
    dataSetSize = dataSet.shape[0]  # shape的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet  # tile(a,(x,y))将a在行重复x次,在列上重复y次
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)# numpy中的sum函数,输入可以是列表,元组,数组。对于数组可以指定维度进行相加。默认为axis=none,sum将所有的元素相加
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort() # 将元素从小到大排列,提取其对应的index(索引),然后输出给sortedDistIndicies,记录的是下标
    classCount = {} # 字典
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)  # key是一个函数,reverse=True是倒序,由大到小
    return sortedClassCount[0][0]

归一化特征值

def autoNorm(dataSet):   # 归一化特征值
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet/np.tile(ranges, (m, 1))   #element wise divide
    return normDataSet, ranges, minVals

k近邻算法优缺点

  1. 优点
    精度高,对异常值不敏感,无数据输入假定
  2. 缺点
    计算复杂度高,空间复杂度高
    如果仅数据集就几十上百G,还每个点都算距离,显然复杂度很高,T(kn)

对KNN算法进行改进,于是有了之后的kd树算法,树形结构的复杂度(klog2 n)要低的多

K近邻算法是一种简单易用的机器学习算法,它可以用于分类和回归问题。在分类问题,K近邻算法通过计算待分类样本训练集每个样本的距离,找到距离待分类样本最近的K个样本,然后根据这K个样本的类别进行投票,将待分类样本归为票数最多的类别。在回归问题,K近邻算法通过计算待预测样本训练集每个样本的距离,找到距离待预测样本最近的K个样本,然后根据这K个样本的值进行加权平均,得到待预测样本预测值。 下面是一个使用K近邻算法进行乳腺癌检测分类的示例代码: ```python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score # 读取数据集 data = pd.read_csv("breast_cancer.csv") # 将类别变量转换为数值变量 data['diagnosis'] = data['diagnosis'].map({'M': 1, 'B': 0}) # 将特征变量和类别变量分开 X = data.drop(['diagnosis'], axis=1) y = data['diagnosis'] # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) # 创建K近邻分类器 knn = KNeighborsClassifier(n_neighbors=5) # 训练K近邻分类器 knn.fit(X_train, y_train) # 在测试集上进行预测 y_pred = knn.predict(X_test) # 计算预测准确率 accuracy = accuracy_score(y_test, y_pred) print("预测准确率:", accuracy) ``` 上述代码使用了sklearn库的KNeighborsClassifier类来创建K近邻分类器,并使用accuracy_score函数计算预测准确率。需要注意的是,K近邻算法对数据的缩放敏感,因此在使用K近邻算法之前,通常需要对数据进行缩放处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

unseven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值