K 近邻法(K-Nearest Neighbor, K-NN)

文章目录


k近邻法(k-nearest neighbor,k-NN)是一种基本分类与回归方法。

  • 输入:实例的特征向量,对应于特征空间的点
  • 输出:实例的类别,可以取多类
  • 假设:给定一个训练数据集,其中的实例类别已定。
  • 分类:对新的实例,根据其k个最近邻的训练实例的类别,通过多数表决等方式进行预测。因此,k近邻法不具有显式的学习过程。
  • k近邻法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。

k近邻法1968年由CoverHart提出。

1. k近邻算法

输入:一组训练数据集,特征向量 xix_ixi,及其类别 yiy_iyi,给定实例特征向量 xxx
输出:实例 xxx 所属的类 yyy

  1. 根据距离度量,在训练集中找出与 xxx 最邻近的 kkk 个点,涵盖这 kkk 个点的 xxx 的邻域记为 Nk(x)N_k(x)Nk(x)
  2. Nk(x)N_k(x)Nk(x) 中根据分类决策规则(如,多数表决)决定 xxx 的类别 yyy
    y=arg max⁡cj∑xi∈Nk(x)I(yi=cj),i=1,2,...,N,j=1,2,...,Ky = \argmax\limits_{c_j} \sum\limits_{x_i \in N_k(x) } I(y_i = c_j),\quad i=1,2,...,N, j = 1,2,...,Ky=cjargmaxxiNk(x)I(yi=cj),i=1,2,...,N,j=1,2,...,K
    III 为指示函数,表示当 yi=cjy_i=c_jyi=cjIII 为 1, 否则 III 为 0
    k=1k=1k=1 时,特殊情况,称为最近邻算法,跟它距离最近的点作为其分类

2. k近邻模型

三要素:k值的选择、距离度量、分类决策规则

2.1 模型

  • kkk 近邻模型,三要素确定后,对于任何一个新的输入实例,它的类唯一确定
  • 这相当于根据上述要素将特征空间划分为一些子空间,确定子空间里的每个点所属的类。这一事实从最近邻算法中可以看得很清楚。

在这里插入图片描述

2.2 距离度量

空间中两个点的距离是两个实例相似程度的反映。

  • LpL_pLp 距离:
    设特征 xix_ixinnn 维的,Lp(xi,xj)=(∑l=1n∣xi(l)−xj(l)∣p)1pL_p(x_i,x_j) = \bigg(\sum\limits_{l=1}^n |x_i^{(l)}-x_j^{(l)}|^p \bigg)^{\frac{1}{p}}Lp(xi,xj)=(l=1nxi(l)xj(l)p)p1
  • 欧氏距离:上面 p=2p=2p=2 时,L2(xi,xj)=(∑l=1n∣xi(l)−xj(l)∣2)12L_2(x_i,x_j) = \bigg(\sum\limits_{l=1}^n |x_i^{(l)}-x_j^{(l)}|^2 \bigg)^{\frac{1}{2}}L2(xi,xj)=(l=1nxi(l)xj(l)2)21
  • 曼哈顿距离:上面 p=1p=1p=1 时,L1(xi,xj)=∑l=1n∣xi(l)−xj(l)∣L_1(x_i,x_j) = \sum\limits_{l=1}^n |x_i^{(l)}-x_j^{(l)}|L1(xi,xj)=l=1nxi(l)xj(l)
  • 切比雪夫距离:当 p=∞p=\inftyp= 时,它是坐标距离的最大值:L∞(xi,xj)=max⁡l∣xi(l)−xj(l)∣L_\infty(x_i,x_j) = \max\limits_l |x_i^{(l)}-x_j^{(l)}|L(xi,xj)=lmaxxi(l)xj(l)
    在这里插入图片描述

2.2.1 距离计算代码 Python

import mathdef L_p(xi, xj, p=2):if len(xi) == len(xj) and len(xi) > 0:sum = 0for i in range(len(xi)):sum += math.pow(abs(xi[i] - xj[i]), p)return math.pow(sum, 1 / p)else:return 0
x1 = [1, 1]
x2 = [5, 1]
x3 = [4, 4]
X = [x1, x2, x3]
for i in range(len(X)):for j in range(i + 1, len(X)):for p in range(1, 5):print("x%d,x%d的L%d距离是:%.2f" % (i + 1, j + 1, p, L_p(X[i], X[j], p)))
x1,x2的L1距离是:4.00
x1,x2的L2距离是:4.00
x1,x2的L3距离是:4.00
x1,x2的L4距离是:4.00
x1,x3的L1距离是:6.00
x1,x3的L2距离是:4.24
x1,x3的L3距离是:3.78
x1,x3的L4距离是:3.57
x2,x3的L1距离是:4.00
x2,x3的L2距离是:3.16
x2,x3的L3距离是:3.04
x2,x3的L4距离是:3.01

2.3 kkk 值的选择

  • k值的选择会对k近邻法的结果产生重大影响

  • 较小的 k 值,相当于用较小的邻域中的训练实例进行预测,“学习”的近似误差(approximation error)会减小,只有与输入实例较近的(相似的)训练实例才会对预测结果起作用。但缺点是“学习”的估计误差(estimation error)会增大,预测结果会对近邻的实例点非常敏感

  • 如果邻近的实例点恰巧是噪声,预测就会出错。换句话说,k值的减小就意味着整体模型变得复杂容易发生过拟合

  • 较大的 k 值,相当于用较大邻域中的训练实例进行预测。优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时与输入实例较远的(不相似的)训练实例也会对预测起作用,使预测发生错误。

  • k值的增大就意味着整体的模型变得简单

  • 如果 k=N,无论输入实例是什么,都将简单地预测它属于在训练实例中最多的类。模型过于简单,完全忽略大量有用信息,不可取。

  • 应用中,k 值一般取一个比较小的数值。通常采用交叉验证法来选取最优的 k 值。

2.4 分类决策规则

  • 多数表决(majority voting rule
    假设损失函数为0-1损失,对于 xix_ixi 的近邻域 Nk(x)N_k(x)Nk(x) 的分类是 cjc_jcj,那么误分类率是:
    1k∑xi∈Nk(x)I(yi≠cj)=1−1k∑xi∈Nk(x)I(yi=cj)\frac{1}{k} \sum\limits_{x_i \in N_k(x) }I(y_i \neq c_j) = 1- \frac{1}{k}\sum\limits_{x_i \in N_k(x) } I(y_i = c_j)k1xiNk(x)I(yi=cj)=1k1xiNk(x)I(yi=cj)
    要使误分类率最小,那么就让 ∑xi∈Nk(x)I(yi=cj)\sum\limits_{x_i \in N_k(x) } I(y_i = c_j)xiNk(x)I(yi=cj) 最大,所以选多数的那个类(经验风险最小化)

3. 实现方法, kd树

  • 算法实现时,需要对大量的点进行距离计算,复杂度是 O(n2)O(n^2)O(n2),训练集很大时,效率低,不可取

  • 考虑特殊的结构存储训练数据,以减少计算距离次数,如 kdkdkd

3.1 构造 kdkdkd

kdkdkd 树是一种对 k 维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。

  • kdkdkd 树是二叉树,表示对k维空间的一个划分(partition)。
  • 构造 kdkdkd 树相当于不断地用垂直于坐标轴的超平面将 k 维空间切分,构成一系列的k维超矩形区域。
  • kdkdkd 树的每个结点对应于一个 k 维超矩形区域。

构造 kdkdkd 树的方法:

  • 根结点:使根结点对应于k维空间中包含所有实例点的超矩形区域;通过递归方法,不断地对 k 维空间进行切分,生成子结点
  • 在超矩形区域(结点)上选择一个坐标轴和在此坐标轴上的一个切分点,确定一个超平面,将当前超矩形区域切分为左右两个子区域(子结点)
  • 实例被分到两个子区域。这个过程直到子区域内没有实例时终止(终止时的结点为叶结点)。在此过程中,将实例保存在相应的结点上。

在这里插入图片描述

Python 代码

class KdNode():def __init__(self, dom_elt, split, left, right):self.dom_elt = dom_elt  # k维向量节点(k维空间中的一个样本点)self.split = split  # 整数(进行分割维度的序号)self.left = left  # 该结点分割超平面左子空间构成的kd-treeself.right = right  # 该结点分割超平面右子空间构成的kd-treeclass KdTree():def __init__(self, data):k = len(data[0])  # 实例的向量维度def CreatNode(split, data_set):if not data_set:return Nonedata_set.sort(key=lambda x: x[split])split_pos = len(data_set) // 2  # 整除median = data_set[split_pos]split_next = (split + 1) % kreturn KdNode(median, split,CreatNode(split_next, data_set[:split_pos]),CreatNode(split_next, data_set[split_pos + 1:]))self.root = CreatNode(0, data)def preorder(self, root):if root:print(root.dom_elt)if root.left:self.preorder(root.left)if root.right:self.preorder(root.right)
data = [[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]]
kd = KdTree(data)
kd.preorder(kd.root)

运行结果:

[7, 2]
[5, 4]
[2, 3]
[4, 7]
[9, 6]
[8, 1]

3.2 搜索 kdkdkd

给定目标点,搜索其最近邻。

  • 先找到包含目标点的叶结点
  • 从该叶结点出发,依次回退到父结点;不断查找与目标点最邻近的结点
  • 当确定不可能存在更近的结点时终止。
  • 这样搜索就被限制在空间的局部区域上,效率大为提高。
  • 目标点的最近邻一定在以目标点为中心并通过当前最近点的超球体的内部。
  • 然后返回当前结点的父结点,如果父结点的另一子结点的超矩形区域与超球体相交,那么在相交的区域内寻找与目标点更近的实例点。
  • 如果存在这样的点,将此点作为新的当前最近点。算法转到更上一级的父结点,继续上述过程。
  • 如果父结点的另一子结点的超矩形区域与超球体不相交,或不存在比当前最近点更近的点,则停止搜索。
    在这里插入图片描述

Python 代码

from collections import namedtuple# 定义一个namedtuple,分别存放最近坐标点、最近距离和访问过的节点数
result = namedtuple("Result_tuple","nearest_point  nearest_dist  nodes_visited")def find_nearest(tree, point):k = len(point)  # 数据维度def travel(kd_node, target, max_dist):if kd_node is None:return result([0] * k, float("inf"), 0)# python中用float("inf")和float("-inf")表示正负无穷nodes_visited = 1s = kd_node.split  # 进行分割的维度pivot = kd_node.dom_elt  # 进行分割的“轴”if target[s] <= pivot[s]:  # 如果目标点第s维小于分割轴的对应值(目标离左子树更近)nearer_node = kd_node.left  # 下一个访问节点为左子树根节点further_node = kd_node.right  # 同时记录下右子树else:  # 目标离右子树更近nearer_node = kd_node.right  # 下一个访问节点为右子树根节点further_node = kd_node.lefttemp1 = travel(nearer_node, target, max_dist)  # 进行遍历找到包含目标点的区域nearest = temp1.nearest_point  # 以此叶结点作为“当前最近点”dist = temp1.nearest_dist  # 更新最近距离nodes_visited += temp1.nodes_visitedif dist < max_dist:max_dist = dist  # 最近点将在以目标点为球心,max_dist为半径的超球体内temp_dist = abs(pivot[s] - target[s])  # 第s维上目标点与分割超平面的距离if max_dist < temp_dist:  # 判断超球体是否与超平面相交return result(nearest, dist, nodes_visited)  # 不相交则可以直接返回,不用继续判断# ----------------------------------------------------------------------# 计算目标点与分割点的欧氏距离p = np.array(pivot)t = np.array(target)temp_dist = np.linalg.norm(p-t)if temp_dist < dist:  # 如果“更近”nearest = pivot  # 更新最近点dist = temp_dist  # 更新最近距离max_dist = dist  # 更新超球体半径# 检查另一个子结点对应的区域是否有更近的点temp2 = travel(further_node, target, max_dist)nodes_visited += temp2.nodes_visitedif temp2.nearest_dist < dist:  # 如果另一个子结点内存在更近距离nearest = temp2.nearest_point  # 更新最近点dist = temp2.nearest_dist  # 更新最近距离return result(nearest, dist, nodes_visited)return travel(tree.root, point, float("inf"))  # 从根节点开始递归
from time import time
from random import randomdef random_point(k):return [random() for _ in range(k)]def random_points(k, n):return [random_point(k) for _ in range(n)]ret = find_nearest(kd, [3, 4.5])
print(ret)N = 400000
t0 = time()
kd2 = KdTree(random_points(3, N))#40万个3维点(坐标值0-1之间)
ret2 = find_nearest(kd2, [0.1, 0.5, 0.8])
t1 = time()
print("time: ", t1 - t0, " s")
print(ret2)

运行结果:40万个点,只用了4s就搜索完毕,找到最近邻点

Result_tuple(nearest_point=[2, 3], nearest_dist=1.8027756377319946, nodes_visited=4)
time:  4.314465284347534  s
Result_tuple(nearest_point=[0.10186986970329936, 0.5007753108096316, 0.7998708312483109], nearest_dist=0.002028350099282986, nodes_visited=49)

4. 鸢尾花KNN分类

4.1 KNN实现

# -*- coding:utf-8 -*-
# @Python Version: 3.7
# @Time: 2020/3/2 22:44
# @Author: Michael Ming
# @Website: https://michael.blog.csdn.net/
# @File: 3.KNearestNeighbors.py
# @Reference: https://github.com/fengdu78/lihang-code
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counterclass KNearNeighbors():def __init__(self, X_train, y_train, neighbors=3, p=2):self.n = neighborsself.p = pself.X_train = X_trainself.y_train = y_traindef predict(self, X):knn_list = []# 先在训练集中取n个点出来,计算距离for i in range(self.n):dist = np.linalg.norm(X - self.X_train[i], ord=self.p)knn_list.append((dist, self.y_train[i]))# 再在剩余的训练集中取出剩余的,计算距离,有距离更近的,替换knn_list里最大的for i in range(self.n, len(self.X_train)):max_index = knn_list.index(max(knn_list, key=lambda x: x[0]))dist = np.linalg.norm(X - self.X_train[i], ord=self.p)if knn_list[max_index][0] > dist:knn_list[max_index] = (dist, self.y_train[i])# 取出所有的n个最近邻点的标签knn = [k[-1] for k in knn_list]count_pairs = Counter(knn)# 次数最多的标签,排序后最后一个 标签:出现次数max_count = sorted(count_pairs.items(), key=lambda x: x[1])[-1][0]return max_countdef score(self, X_test, y_test):right_count = 0for X, y in zip(X_test, y_test):  # zip 同时遍历多个对象label = self.predict(X)if math.isclose(label, y, rel_tol=1e-5):  # 浮点型相等判断right_count += 1print("准确率:%.4f" % (right_count / len(X_test)))return right_count / len(X_test)if __name__ == '__main__':# ---------鸢尾花K近邻----------------iris = load_iris()df = pd.DataFrame(iris.data, columns=iris.feature_names)df['label'] = iris.targetplt.scatter(df[:50][iris.feature_names[0]], df[:50][iris.feature_names[1]], label=iris.target_names[0])plt.scatter(df[50:100][iris.feature_names[0]], df[50:100][iris.feature_names[1]], label=iris.target_names[1])plt.xlabel(iris.feature_names[0])plt.ylabel(iris.feature_names[1])data = np.array(df.iloc[:100, [0, 1, -1]])  # 取前2种花,前两个特征X, y = data[:, :-1], data[:, -1]# 切分数据集,留20%做测试数据X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)# KNN算法,近邻选择20个,距离度量L2距离clf = KNearNeighbors(X_train, y_train, 20, 2)# 预测测试点,统计正确率clf.score(X_test, y_test)# 随意给一个点,用KNN预测其分类test_point = [4.75, 2.75]test_point_flower = '测试点' + iris.target_names[int(clf.predict(test_point))]print("测试点的类别是:%s" % test_point_flower)plt.plot(test_point[0], test_point[1], 'bx', label=test_point_flower)plt.rcParams['font.sans-serif'] = 'SimHei'  # 消除中文乱码plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号plt.legend()plt.show()
准确率:1.0000
测试点的类别是:测试点setosa

在这里插入图片描述

4.2 sklearn KNN

sklearn.neighbors.KNeighborsClassifier

class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights='uniform', 
algorithm='auto', leaf_size=30, p=2, metric='minkowski', 
metric_params=None, n_jobs=None, **kwargs)
  • n_neighbors: 临近点个数
  • p: 距离度量
  • algorithm: 近邻算法,可选{‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}
  • weights: 确定近邻的权重
from sklearn.neighbors import KNeighborsClassifier
clf_skl = KNeighborsClassifier(n_neighbors=50, p=4, algorithm='kd_tree')
start = time.time()
sum = 0
for i in range(100):clf_skl.fit(X_train, y_train)sum += clf_skl.score(X_test, y_test)
end = time.time()
print("平均准确率:%.4f" % (sum/100))
print("花费时间:%0.4f ms" % (1000*(end - start)/100))

5. 文章完整代码

# -*- coding:utf-8 -*-
# @Python Version: 3.7
# @Time: 2020/3/2 22:44
# @Author: Michael Ming
# @Website: https://michael.blog.csdn.net/
# @File: 3.KNearestNeighbors.py
# @Reference: https://github.com/fengdu78/lihang-code
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counter
import timedef L_p(xi, xj, p=2):if len(xi) == len(xj) and len(xi) > 0:sum = 0for i in range(len(xi)):sum += math.pow(abs(xi[i] - xj[i]), p)return math.pow(sum, 1 / p)else:return 0class KNearNeighbors():def __init__(self, X_train, y_train, neighbors=3, p=2):self.n = neighborsself.p = pself.X_train = X_trainself.y_train = y_traindef predict(self, X):knn_list = []# 先在训练集中取n个点出来,计算距离for i in range(self.n):dist = np.linalg.norm(X - self.X_train[i], ord=self.p)knn_list.append((dist, self.y_train[i]))# 再在剩余的训练集中取出剩余的,计算距离,有距离更近的,替换knn_list里最大的for i in range(self.n, len(self.X_train)):max_index = knn_list.index(max(knn_list, key=lambda x: x[0]))dist = np.linalg.norm(X - self.X_train[i], ord=self.p)if knn_list[max_index][0] > dist:knn_list[max_index] = (dist, self.y_train[i])# 取出所有的n个最近邻点的标签knn = [k[-1] for k in knn_list]count_pairs = Counter(knn)# 次数最多的标签,排序后最后一个 标签:出现次数max_count = sorted(count_pairs.items(), key=lambda x: x[1])[-1][0]return max_countdef score(self, X_test, y_test):right_count = 0for X, y in zip(X_test, y_test):  # zip 同时遍历多个对象label = self.predict(X)if math.isclose(label, y, rel_tol=1e-5):  # 浮点型相等判断right_count += 1print("准确率:%.4f" % (right_count / len(X_test)))return right_count / len(X_test)class KdNode():def __init__(self, dom_elt, split, left, right):self.dom_elt = dom_elt  # k维向量节点(k维空间中的一个样本点)self.split = split  # 整数(进行分割维度的序号)self.left = left  # 该结点分割超平面左子空间构成的kd-treeself.right = right  # 该结点分割超平面右子空间构成的kd-treeclass KdTree():def __init__(self, data):k = len(data[0])  # 实例的向量维度def CreatNode(split, data_set):if not data_set:return Nonedata_set.sort(key=lambda x: x[split])split_pos = len(data_set) // 2  # 整除median = data_set[split_pos]split_next = (split + 1) % kreturn KdNode(median, split,CreatNode(split_next, data_set[:split_pos]),CreatNode(split_next, data_set[split_pos + 1:]))self.root = CreatNode(0, data)def preorder(self, root):if root:print(root.dom_elt)if root.left:self.preorder(root.left)if root.right:self.preorder(root.right)from collections import namedtuple# 定义一个namedtuple,分别存放最近坐标点、最近距离和访问过的节点数
result = namedtuple("Result_tuple","nearest_point  nearest_dist  nodes_visited")def find_nearest(tree, point):k = len(point)  # 数据维度def travel(kd_node, target, max_dist):if kd_node is None:return result([0] * k, float("inf"), 0)# python中用float("inf")和float("-inf")表示正负无穷nodes_visited = 1s = kd_node.split  # 进行分割的维度pivot = kd_node.dom_elt  # 进行分割的“轴”if target[s] <= pivot[s]:  # 如果目标点第s维小于分割轴的对应值(目标离左子树更近)nearer_node = kd_node.left  # 下一个访问节点为左子树根节点further_node = kd_node.right  # 同时记录下右子树else:  # 目标离右子树更近nearer_node = kd_node.right  # 下一个访问节点为右子树根节点further_node = kd_node.lefttemp1 = travel(nearer_node, target, max_dist)  # 进行遍历找到包含目标点的区域nearest = temp1.nearest_point  # 以此叶结点作为“当前最近点”dist = temp1.nearest_dist  # 更新最近距离nodes_visited += temp1.nodes_visitedif dist < max_dist:max_dist = dist  # 最近点将在以目标点为球心,max_dist为半径的超球体内temp_dist = abs(pivot[s] - target[s])  # 第s维上目标点与分割超平面的距离if max_dist < temp_dist:  # 判断超球体是否与超平面相交return result(nearest, dist, nodes_visited)  # 不相交则可以直接返回,不用继续判断# ----------------------------------------------------------------------# 计算目标点与分割点的欧氏距离p = np.array(pivot)t = np.array(target)temp_dist = np.linalg.norm(p - t)if temp_dist < dist:  # 如果“更近”nearest = pivot  # 更新最近点dist = temp_dist  # 更新最近距离max_dist = dist  # 更新超球体半径# 检查另一个子结点对应的区域是否有更近的点temp2 = travel(further_node, target, max_dist)nodes_visited += temp2.nodes_visitedif temp2.nearest_dist < dist:  # 如果另一个子结点内存在更近距离nearest = temp2.nearest_point  # 更新最近点dist = temp2.nearest_dist  # 更新最近距离return result(nearest, dist, nodes_visited)return travel(tree.root, point, float("inf"))  # 从根节点开始递归if __name__ == '__main__':# ---------计算距离----------------x1 = [1, 1]x2 = [5, 1]x3 = [4, 4]X = [x1, x2, x3]for i in range(len(X)):for j in range(i + 1, len(X)):for p in range(1, 5):print("x%d,x%d的L%d距离是:%.2f" % (i + 1, j + 1, p, L_p(X[i], X[j], p)))# ---------鸢尾花K近邻----------------iris = load_iris()df = pd.DataFrame(iris.data, columns=iris.feature_names)df['label'] = iris.targetplt.scatter(df[:50][iris.feature_names[0]], df[:50][iris.feature_names[1]], label=iris.target_names[0])plt.scatter(df[50:100][iris.feature_names[0]], df[50:100][iris.feature_names[1]], label=iris.target_names[1])plt.xlabel(iris.feature_names[0])plt.ylabel(iris.feature_names[1])data = np.array(df.iloc[:100, [0, 1, -1]])  # 取前2种花,前两个特征X, y = data[:, :-1], data[:, -1]# 切分数据集,留20%做测试数据X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)# KNN算法,近邻选择20个,距离度量L2距离clf = KNearNeighbors(X_train, y_train, 20, 2)# 预测测试点,统计正确率clf.score(X_test, y_test)# 随意给一个点,用KNN预测其分类test_point = [4.75, 2.75]test_point_flower = '测试点' + iris.target_names[int(clf.predict(test_point))]print("测试点的类别是:%s" % test_point_flower)plt.plot(test_point[0], test_point[1], 'bx', label=test_point_flower)plt.rcParams['font.sans-serif'] = 'SimHei'  # 消除中文乱码plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号plt.legend()plt.show()# ---------sklearn KNN----------from sklearn.neighbors import KNeighborsClassifierclf_skl = KNeighborsClassifier(n_neighbors=50, p=4, algorithm='kd_tree')start = time.time()sum = 0for i in range(100):clf_skl.fit(X_train, y_train)sum += clf_skl.score(X_test, y_test)end = time.time()print("平均准确率:%.4f" % (sum / 100))print("花费时间:%0.4f ms" % (1000 * (end - start) / 100))# ------build KD Tree--------------data = [[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]]kd = KdTree(data)kd.preorder(kd.root)# ------search in KD Tree-----------from time import timefrom random import randomdef random_point(k):return [random() for _ in range(k)]def random_points(k, n):return [random_point(k) for _ in range(n)]ret = find_nearest(kd, [3, 4.5])print(ret)N = 400000t0 = time()kd2 = KdTree(random_points(3, N))ret2 = find_nearest(kd2, [0.1, 0.5, 0.8])t1 = time()print("time: ", t1 - t0, " s")print(ret2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通用人工智能可行吗?组合泛化视角漫谈

"乌鸦为什么像写字台&#xff1f;"因为它们都能produce a few notes &#xff08;鸟叫/笔记&#xff09;&#xff0c;因为乌鸦和写字台都是思想与记忆的象征&#xff08;北欧神话&#xff09;&#xff0c;又或者因为&#xff0c;这本身就是一句没有道理的话&#xff…

Transformer 在美团搜索排序中的实践

引言 美团搜索是美团 App 连接用户与商家的一种重要方式&#xff0c;而排序策略则是搜索链路的关键环节&#xff0c;对搜索展示效果起着至关重要的效果。目前&#xff0c;美团的搜索排序流程为多层排序&#xff0c;分别是粗排、精排、异构排序等&#xff0c;多层排序的流程主要…

ACL‘22杰出论文:Prompt范式有bug!

‍文 | pythonGPT-3等超大模型的兴起&#xff0c;也带来了 in-context learning &#xff08;语境学习&#xff09;的新范式。在语境学习中&#xff0c;模型并不使用梯度下降&#xff0c;根据监督样本调整参数&#xff1b;而是将监督样本的输入输出接起来作为prompt&#xff08…

程序员面试金典 - 面试题 02.06. 回文链表(快慢指针+链表反转)

1. 题目 编写一个函数&#xff0c;检查输入的链表是否是回文的。 示例 1&#xff1a; 输入&#xff1a; 1->2 输出&#xff1a; false 示例 2&#xff1a; 输入&#xff1a; 1->2->2->1 输出&#xff1a; true 进阶&#xff1a; 你能否用 O(n) 时间复杂度和 O(1)…

美团外卖持续交付的前世今生

0. 前言 美团外卖自2013年创建以来&#xff0c;业务一直在高速发展&#xff0c;目前日订单量已突破3000万单&#xff0c;已成为美团点评最重要的业务之一。美团外卖所承载的业务&#xff0c;从早期单一的美食业务发展成为了外卖平台业务。目前除餐饮业务外&#xff0c;闪购、跑…

百万悬赏!寻找“模型越大,效果越差”的奇葩任务!

文 | 天于刀刀犹记 2018 年底谷歌开源 BERT 后&#xff0c;一大批基于 Attention 机制 Transformer 结构的大模型横空出世。XLNet、MPNet、ERNIE&#xff0c;NLP 任务彻底迈入大规模语料训练 fintune 的时代。之前一段时间爆火的 prompt 概念也离不开大模型中最基本的预训练 M…

程序员面试金典 - 面试题 02.08. 环路检测(快慢指针)

1. 题目 给定一个有环链表&#xff0c;实现一个算法返回环路的开头节点。 有环链表的定义&#xff1a;在链表中某个节点的next元素指向在它前面出现过的节点&#xff0c;则表明该链表存在环路。 示例 1&#xff1a; 输入&#xff1a;head [3,2,0,-4], pos 1 输出&#xff1…

Batch size 没必要设为2的次方!?

文 | 付瑶最近刷到一个话题很有趣,搬来和大家一起讨论下:“batch-size 一定要大小为2的幂吗&#xff1f;不这样设置会有啥差别吗&#xff1f;”发帖人认为大家都进入一个误区。坚持选择batch-size的大小为2的幂次数是因为曾经被告知从计算的角度是对训练效率有益的。但是这个“…

ICDAR 2019论文:自然场景文字定位技术详解

自然场景文字定位是文字识别中非常重要的一部分。与通用的物体检测相比&#xff0c;文字定位更具挑战性&#xff0c;文字在长宽比、尺度和方向上有更大范围的变化。针对这些问题&#xff0c;本文介绍一种融合文字片段及金字塔网络的场景文字定位方法。该方法将特征金字塔机制应…

程序员面试金典 - 面试题 10.01. 合并排序的数组

1. 题目 给定两个排序后的数组 A 和 B&#xff0c;其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法&#xff0c;将 B 合并入 A 并排序。 初始化 A 和 B 的元素数量分别为 m 和 n。 示例: 输入: A [1,2,3,0,0,0], m 3 B [2,5,6], n 3输出: [1,2,2,3,5,6]来源&…

LeCun论文被指「洗稿」? LSTM之父发文怒怼:抄我的还标原创

编 | 好困 Joey David源 | 新智元LSTM之父、暴脾气大爷Jrgen Schmidhuber又开炮了&#xff1f;这回怼的是LeCun&#xff0c;说最近的新论文是炒了自己20多年前的冷饭&#xff0c;只不过换了种说法而已。图灵奖得主Yann Lecun&#xff0c;作为AI界的三巨头之一&#xff0c;他发表…

ESLint 在中大型团队的应用实践

引言 代码规范是软件开发领域经久不衰的话题&#xff0c;几乎所有工程师在开发过程中都会遇到&#xff0c;并或多或少会思考过这一问题。随着前端应用的大型化和复杂化&#xff0c;越来越多的前端工程师和团队开始重视 JavaScript 代码规范。得益于前端开源社区的繁盛&#xff…

程序员面试金典 - 面试题 02.05. 链表求和

1. 题目 给定两个用链表表示的整数&#xff0c;每个节点包含一个数位。 这些数位是反向存放的&#xff0c;也就是个位排在链表首部。 编写函数对这两个整数求和&#xff0c;并用链表形式返回结果。 示例&#xff1a; 输入&#xff1a;(7 -> 1 -> 6) (5 -> 9 ->…

互联网人到最后拼的是体力

文 | 卫夕源 | 卫夕指北互联网人到最后拼的是体力&#xff0c;这么说可能有点绝对。但如果我们将时间线拉长&#xff0c;体力代表的精力绝对是一个人能在互联网领域保持长期竞争力的最重要的因素。至少也是最重要的之一。1.很多互联网人退出了职场竞争&#xff0c;看起来是心力…

谷歌、斯坦福联合发文:我们为什么一定要用大模型?

文 | Harris语言模型已经深刻变革了自然语言处理领域的研究和实践。近年来&#xff0c;大模型在多个领域都取得了重要的突破。它们无需在下游任务上微调&#xff0c;通过合适的指令或者提示就可以取得优异的性能&#xff0c;甚至有时让人为之惊叹。例如&#xff0c;GPT-3 [1] 可…

程序员面试金典 - 面试题 02.04. 分割链表

1. 题目 编写程序以 x 为基准分割链表&#xff0c;使得所有小于 x 的节点排在大于或等于 x 的节点之前。如果链表中包含 x&#xff0c;x 只需出现在小于 x 的元素之后(如下所示)。分割元素 x 只需处于“右半部分”即可&#xff0c;其不需要被置于左右两部分之间。 示例: 输入…

深度学习在搜索业务中的探索与实践

本文根据美团高级技术专家翟艺涛在2018 QCon全球软件开发大会上的演讲内容整理而成&#xff0c;内容有修改。 引言 2018年12月31日&#xff0c;美团酒店单日入住间夜突破200万&#xff0c;再次创下行业的新纪录&#xff0c;而酒店搜索在其中起到了非常重要的作用。本文会首先介…

京东金融,你到底是坏,还是码农裁多了??

7.12更新:部分基金赎回的钱已经到账小金库了&#xff0c;今日从小金库提现时又提示银行卡已删除&#xff0c;不过这次可以点击重新绑定&#xff0c;重新绑定时会报错“绑定的卡与原卡一致”&#xff0c;流程没法走完。但这时候再退回去却发现“银行卡已删除”的提示没有了。于是…

程序员面试金典 - 面试题 17.14. 最小K个数(快排划分O(n))

1. 题目 设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。 示例&#xff1a; 输入&#xff1a; arr [1,3,5,7,2,4,6,8], k 4 输出&#xff1a; [1,2,3,4]提示&#xff1a; 0 < len(arr) < 100000 0 < k < min(100000, len(arr))来…

LruCache在美团DSP系统中的应用演进

背景 DSP系统是互联网广告需求方平台&#xff0c;用于承接媒体流量&#xff0c;投放广告。业务特点是并发度高&#xff0c;平均响应低&#xff08;百毫秒&#xff09;。 为了能够有效提高DSP系统的性能&#xff0c;美团平台引入了一种带有清退机制的缓存结构LruCache(Least Rec…