机器学习之k-近邻算法

一、kNN基本介绍

KNN(K-Nearest Neighbor)

  1. 可以用于分类和回归
  2. 监督学习算法

二、kNN工作原理

如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。

  1. 分类:在该样本点附近找K个最近的点进行投票,票数多的即测试点分类
  2. 回归:要预测的点的值通过求与它距离最近的K个点的值的平均值得到

分类前要归一化数值,使特征成为等同权重


三、手写kNN算法核心

"""
    1.计算已知类别数据集中的点与当前点之间的距离
    2.按照距离递增依次排序
    3.选取与当前点距离最小的k个点
    4.确定前k个点所在类别的出现频率
    5.返回前k个点出现频率最高的类别作为当前点的预测分类
"""
def classify0(inX, dataSet, labels, k):
    # inX: 测试点   dataSet: 样本集
    # labels: 类别  k: 取多少个近邻点
    dataSetSize = dataSet.shape[0]                  # 数据集有几行,即几个样本
    diffMat = np.tile(inX, (dataSetSize,1)) - dataSet  # tile(a,b)生成b个a的数组
    sqDiffMat = diffMat**2                          # 每个数都**2
    sqDistances = sqDiffMat.sum(axis=1)             # 横向相加,即每个样本的距离
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()        # 按距离从小到大排序,返回元素数组下标
    classCount={}
    for i in range(k):
        votelabel = labels[sortedDistIndicies[i]]
        classCount[votelabel] = classCount.get(votelabel, 0) + 1
                                    # classCount --> {'B': 2, 'A': 1}
                                    # classCount.items() --> dict_items([('B', 2), ('A', 1)])
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
                                    # sortedClassCount --> [('B', 2), ('A', 1)]
    return sortedClassCount[0][0]

应该先数据归一化处理

  1. 最值归一化:把所有数据映射到0-1之间
    最值归一化
    适用于分布有明显边界的情况,但受outlier影响较大

    def autoNorm(dataSet):  # 最值归一化 示例代码
        minVals = np.min(dataSet,axis=0)
        maxVals = np.max(dataSet,axis=0)
        diff = maxVals - minVals
        normDataSet = np.zeros(dataSet.shape)
        m = dataSet.shape[0]                                # 堆叠数组[1,2,3,4] 3行,1列表示竖着堆
        normDataSet = dataSet - np.tile(minVals, (m,1))     # 原始值-最小值
        normDataSet = normDataSet / np.tile(diff, (m, 1))   # 除以(max-min)
        return normDataSet, diff, minVals
    
  2. 均值方差归一化 (更常用):把所有数据归一到均值为0方差为1的分布中
    均值方差归一化
    适用于数据分布没有明显的边界的情况,但有可能存在极端数据值


四、sklearn实现KNN算法

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split

# 分割测试数据集
X_train,X_test,y_train,y_test = train_test_split(X,y)
# 创建KNeighborsClassifier 对象
clf = KNeighborsClassifier()

# 拟合训练数据集,得出分类准确度
clf.fit(X_train,y_train)
clf.score(X_test,y_test)

# 使用模型预测测试集
y_predict = knn.predict(X_test)

KNeighborsClassifier() 构造函数的参数及默认值

clf = KNeighborsClassifier(n_neighbors=5,weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, 
metric=’minkowski’,metric_params=None, n_jobs=1, **kwargs)
  1. n_neighbors:默认为5,就是k-NN的k的值,选取最近的k个点。
  2. weights:默认是uniform,还可以是distance以考虑距离,可以解决“平票”问题
  3. algorithm:快速k近邻搜索算法,默认参数为auto,还可以是ball_tree、kd_tree、brute
  4. leaf_size:默认是30,这个是构造的kd树和ball树的大小。
  5. metric:用于距离度量,默认度量是minkowski,也就是p=2的欧氏距离
  6. p:minkowski距离中的超参数
  7. metric_params:距离公式的其他关键参数,这个可以不管
  8. n_jobs:并行处理设置。默认为1。如果为-1,那么CPU的所有cores都用于并行工作。

应该先数据归一化处理

from sklearn.preprocessing import StandardScalar	# StandardScalar默认采用均值方差归一化
standardScaler = StandardScalar()
standardScaler.fit(X_train)							# 保存训练集的均值、方差等

X_train = standardScaler.transform(X_train)			# 归一化后的训练集
X_test_standard = standardScaler.transform(X_test)	# 归一化后的测试集(用训练集同样地归一化方式)

总结

优缺点

1. 优点

  • 简单,精度高,理论成熟,既可以用来做分类也可以用来做回归
  • 可用于数值型数据和离散型数据;
  • 训练时间复杂度为O(n);
  • 无数据输入假定;
  • 对异常值不敏感

2. 缺点

  • 计算复杂性高;空间复杂性高;

  • 样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
    样本不平衡问题

  • 一般样本数很大或维数很高的时候,计算量太大(因为对每一个待分类的测试点都要计算它到全体已知样本的距离,才能求得它的K个最邻近点)。但是样本又不能太少,否则容易发生误分。

  • 最大的缺点是无法给出数据的内在含义,解释性不强

问题

  1. kNN是不需要训练过程的,即训练的时间复杂度为0,为什么有的资料说训练的时间复杂度为O(n)呢,是因为sklearn中的fit函数复杂度是O(n)吗?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

湫兮如风i

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

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

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

打赏作者

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

抵扣说明:

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

余额充值