KNN库简介
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KNN库简介相关的知识,希望对你有一定的参考价值。
参考技术A机器学习经典库scikit-learn中的sklearn.neighbors包集成了近邻法相关的算法,KNN分类树算法使用KNeighborsClassifier,回归树使用KNeighborsRegressor。除此之外,还有KNN的扩展,即限定半径最近邻分类树RadiusNeighborsClassifier和限定半径最近邻回归树RadiusNeighborsRegressor,以及最近质心分类算法NearestCentroid。
在这些算法中,KNN分类和回归的类参数完全一样。限定半径最近邻法分类和回归的类的主要参数也和KNN基本一样。比较特别是的最近质心分类算法,由于它是直接选择最近质心来分类,所以仅有两个参数,距离度量和特征选择距离阈值。
限定半径最近邻算法,即样本中某系类别的样本非常的少,甚至少于K,这导致稀有类别样本在找K个最近邻的时候,会把距离其实较远的其他样本考虑进来,而导致预测不准确。为了解决这个问题,我们限定最近邻的一个最大距离,也就是说,我们只在一个距离范围内搜索所有的最近邻,这避免了上述问题。这个距离我们一般称为限定半径。
最近质心算法首先把样本按输出类别归类。对于第 L类的Cl个样本。它会对这Cl个样本的n维特征中每一维特征求平均值,最终该类别所有维度的n个平均值形成所谓的质心点。对于样本中的所有出现的类别,每个类别会最终得到一个质心点。当我们做预测时,仅仅需要比较预测样本和这些质心的距离,最小的距离对于的质心类别即为预测的类别。这个算法通常用在文本分类处理上。
KNN的主要优点有:
1) 理论成熟,思想简单,既可以用来做分类也可以用来做回归
2) 可用于非线性分类
3) 训练时间复杂度比支持向量机之类的算法低,仅为O(n)
4) 和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感
5) 由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合
6)该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分
KNN的主要缺点有:
1)计算量大,尤其是特征数非常多的时候
2)样本不平衡的时候,对稀有类别的预测准确率低
3)KD树,球树之类的模型建立需要大量的内存
4)使用懒散学习方法,基本上不学习,导致预测时速度比起逻辑回归之类的算法慢
5)相比决策树模型,KNN模型可解释性不强
分类-KNN算法(鸢尾花分类实战)
文章目录
简介
K近邻(K Nearest Neighbors,KNN)算法是最简单的分类算法之一,也就是根据现有训练数据判断输入样本是属于哪一个类别。
“近朱者赤近墨者黑",所谓的K近邻,也就是根据样本相邻最近的K个数据来进行判断,看K个邻居中所属类别最多的是哪一类,则将该样本分为这一类。
算法原理很简单,如下图,K取3时,输入数据为红色点,在它最近的3个邻居点中,有2个黄色1个蓝色,故应把它分类为黄色这一类。
可以看出K的取值应为奇数,避免K近邻中有相同个数的类别,同时也不能为类别数的倍数,如3分类中K取3时,出现1:1:1无法分类的情况。注意如果K过小可能造成过拟合。
此外距离的定义公式也有很多,这里不再赘述,根据实际场景进行甄选,一般使用欧式距离更多,即 d i s t ( x , y ) = ∑ i = 1 n ( x i − y i ) 2 dist(x,y)=\\sqrt\\sum_i=1^n(x_i-y_i)^2 dist(x,y)=∑i=1n(xi−yi)2
代码复现
- 数据处理
采用典中典——鸢尾花数据集,Kaggle中有上传鸢尾花数据(下载链接)
鸢尾花数据集包含四个特征,和三种鸢尾花标签类别,共150条数据。
采用sepal length和petal width两个特征,你也可以采用其他特征。
使用pandas读取数据,不懂pandas可以参考我这篇:Pandas光速入门-一文掌握数据操作
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
data = pd.read_csv("D:\\\\Iris_flower_dataset.csv")
x = np.array(data.iloc[:, [1, 4]])
y_tmp = np.array(data["Species"])
y = []
label = ["Iris-setosa", "Iris-virginica", "Iris-versicolor"]
for i in y_tmp: # 将英文压为整型
if i == label[0]:
y.append(0)
elif i == label[1]:
y.append(1)
else:
y.append(2)
y = np.array(y)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2022)
# 训练集可视化
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.xlabel("sepal length[cm]") # 设置x轴名
plt.ylabel("petal width[cm]") # 设置y轴名
plt.show()
可视化可参考:Matplotlib光速入门-从安装到绘图实战
(
插播反爬信息)博主CSDN地址:https://wzlodq.blog.csdn.net/
- KNN定义
只考虑两个特征,就简单化处理了,即用 ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 \\sqrt(x_1-x_2)^2+(y_1-y_2)^2 (x1−x2)2+(y1−y2)2
class KNN(object):
def __init__(self, k): # 初始化函数
self.k = k
def fit(self, x, y): # 载入训练集
self.x = x
self.y = y
def _distance(self, v1, v2): # 欧式距离
return np.sum(np.square(v1 - v2)) # (不开根号节省算力,效果一致
def predict(self, x):
y_pre = []
for i in range(len(x)): # x是测试集,是一个n维特征数组
dist_arr = [self._distance(x[i], self.x[j]) for j in range(len(self.x))] # 计算距离
sorted_index = np.argsort(dist_arr) # 排序
top_k_index = sorted_index[:self.k] # 得到K近邻
nearest = self._count(y_top_k=self.y[top_k_index]) # 根据K近邻分类做出预测
y_pre.append(nearest) # 加入预测答案
return np.array(y_pre)
def _count(self, y_top_k): # 统计各分类数量
y_map =
for y in y_top_k:
if y not in y_map.keys():
y_map[y] = 1 # 首次不在字典则置1
else:
y_map[y] += 1 # 否则value++
sorted_vote_dict = sorted(y_map.items(), key=operator.itemgetter(1), reverse=True) # 排序
return sorted_vote_dict[0][0] # 返回数量最多的分类
- 测试
if __name__ == "__main__":
# 数据处理
data = pd.read_csv("D:\\\\Iris_flower_dataset.csv")
x = np.array(data.iloc[:, [1, 4]])
y_tmp = np.array(data["Species"])
y = []
label = ["Iris-setosa", "Iris-virginica", "Iris-versicolor"]
for i in y_tmp: # 将英文压为整型
if i == label[0]:
y.append(0)
elif i == label[1]:
y.append(1)
else:
y.append(2)
y = np.array(y)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2022)
# 创建KNN对象
clf = KNN(5)
# 训练
clf.fit(x_train, y_train)
# 测试
pre_test = clf.predict(x_test)
# 计算正确率
correct = np.count_nonzero((pre_test == y_test) == True)
print("正确率:%.3f" % (correct / len(pre_test)))
- 结果可视化
# 结果可视化
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, alpha=0.3)
for i in range(len(x_test)):
if pre_test[i] == y_test[i]: # 正确标绿
plt.scatter(x_test[i][0], x_test[i][1], color="green")
else: # 错误标红
plt.scatter(x_test[i][0], x_test[i][1], color="red")
plt.xlabel("sepal length[cm]") # 设置x轴名
plt.ylabel("petal width[cm]") # 设置y轴名
plt.show()
半透明的是训练数据,测试数据中,绿色是分类正确的点,红色是分类错误的点,可以看出上图只错了一个。
sklearn库调用
使用sklearn封装函数可以非常方便的实现:
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 载入数据
iris = datasets.load_iris() # 已经内置了鸢尾花数据集
x = iris.data # 输入4个特征
y = iris.target # 输出类别
# 随机划分数据集,默认25%测试集75%训练集
x_train, x_test, y_train, y_test = train_test_split(x, y)
# 创建一个KNN分类器对象,并设置K=5,
clf = KNeighborsClassifier(n_neighbors=5) # clf意为Classifier
# 训练
clf.fit(x_train, y_train) # 用训练数据拟合分类器模型
# 测试
pre_test = clf.predict(x_test) # 得到测试集的预测结果
# 计算正确率
print('正确率:%.3f' % accuracy_score(y_test, pre_test))
# 由于数据集是随机划分,每次得到正确率自然不同,可以设置random_state让随机一致
直接调用库函数简直不要太方便,芜湖起飞(~ ̄▽ ̄)~
原创不易,请勿转载(
本不富裕的访问量雪上加霜)
博主首页:https://wzlodq.blog.csdn.net/
来都来了,不评论两句吗👀
如果文章对你有帮助,记得一键三连❤
以上是关于KNN库简介的主要内容,如果未能解决你的问题,请参考以下文章