Scikit Learn - KNN学习



k-NN(k近邻算法)是最简单的机器学习算法之一,它是非参数的和惰性的。非参数意味着它不对底层数据分布做任何假设,即模型结构由数据集决定。惰性或基于实例的学习意味着它不需要任何训练数据点来生成模型,整个训练数据都用于测试阶段。

k-NN算法包含以下两个步骤:

步骤1

此步骤计算并存储训练集中每个样本的k个最近邻。

步骤2

此步骤对于未标记的样本,从数据集中检索k个最近邻。然后,在这k个最近邻中,通过投票预测类别(得票最多的类别获胜)。

实现k近邻算法的模块sklearn.neighbors提供了无监督监督的基于邻域的学习方法的功能。

无监督最近邻实现不同的算法(BallTree、KDTree或蛮力法)来为每个样本找到最近邻。这个无监督版本基本上只有上面讨论的步骤1,它是许多算法(KNN和K均值是最著名的)的基础,这些算法需要邻域搜索。简单来说,它是用于实现邻域搜索的无监督学习器。

另一方面,监督基于邻域的学习用于分类和回归。

无监督KNN学习

如上所述,存在许多像KNN和K均值这样的算法需要最近邻搜索。这就是为什么Scikit-learn决定将其邻域搜索部分实现为它自己的“学习器”。将邻域搜索作为单独的学习器的原因是,计算所有成对距离以查找最近邻显然效率不高。让我们看看Sklearn用于实现无监督最近邻学习的模块以及示例。

Scikit-learn模块

sklearn.neighbors.NearestNeighbors是用于实现无监督最近邻学习的模块。它使用名为BallTree、KDTree或蛮力法的特定最近邻算法。换句话说,它充当这三种算法的统一接口。

参数

下表包含NearestNeighbors模块使用的参数:

序号 参数及描述
1

n_neighbors − int,可选

要获取的邻居数量。默认值为5。

2

radius − float,可选

它限制返回邻居的距离。默认值为1.0。

3

algorithm − {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’},可选

此参数将采用您要用于计算最近邻的算法(BallTree、KDTree或蛮力法)。如果您提供‘auto’,它将尝试根据传递给fit方法的值决定最合适的算法。

4

leaf_size − int,可选

它可以影响构建和查询的速度以及存储树所需的内存。它传递给BallTree或KDTree。虽然最佳值取决于问题的性质,但其默认值为30。

5

metric − 字符串或可调用对象

用于计算点之间距离的度量。我们可以将其作为字符串或可调用函数传递。对于可调用函数,度量在每一对行上调用,并记录结果值。它不如将度量名称作为字符串传递有效率。

我们可以从scikit-learn或scipy.spatial.distance中选择度量。有效值为:

Scikit-learn − [‘cosine’,’manhattan’,’Euclidean’, ‘l1’,’l2’, ‘cityblock’]

Scipy.spatial.distance −

[‘braycurtis’,’canberra’,’chebyshev’,’dice’,’hamming’,’jaccard’, ‘correlation’,’kulsinski’,’mahalanobis’,’minkowski’,’rogerstanimoto’,’russellrao’, ‘sokalmicheme’,’sokalsneath’, ‘seuclidean’, ‘sqeuclidean’, ‘yule’]。

默认度量为‘Minkowski’。

6

P − 整数,可选

它是Minkowski度量的参数。默认值为2,相当于使用Euclidean_distance(l2)。

7

metric_params − dict,可选

这是度量函数的其他关键字参数。默认值为None。

8

N_jobs − int或None,可选

它表示为邻域搜索运行的并行作业数。默认值为None。

实现示例

下面的示例将使用sklearn.neighbors.NearestNeighbors模块查找两组数据之间的最近邻。

首先,我们需要导入所需的模块和包:

from sklearn.neighbors import NearestNeighbors
import numpy as np

现在,导入包后,定义我们要在其间查找最近邻的数据集:

Input_data = np.array([[-1, 1], [-2, 2], [-3, 3], [1, 2], [2, 3], [3, 4],[4, 5]])

接下来,应用无监督学习算法,如下所示:

nrst_neigh = NearestNeighbors(n_neighbors = 3, algorithm = 'ball_tree')

接下来,使用输入数据集拟合模型。

nrst_neigh.fit(Input_data)

现在,查找数据集的K近邻。它将返回每个点的邻居的索引和距离。

distances, indices = nbrs.kneighbors(Input_data)
indices

输出

array(
   [
      [0, 1, 3],
      [1, 2, 0],
      [2, 1, 0],
      [3, 4, 0],
      [4, 5, 3],
      [5, 6, 4],
      [6, 5, 4]
   ], dtype = int64
)
distances

输出

array(
   [
      [0. , 1.41421356, 2.23606798],
      [0. , 1.41421356, 1.41421356],
      [0. , 1.41421356, 2.82842712],
      [0. , 1.41421356, 2.23606798],
      [0. , 1.41421356, 1.41421356],
      [0. , 1.41421356, 1.41421356],
      [0. , 1.41421356, 2.82842712]
   ]
)

上述输出显示每个点的最近邻都是该点本身,即为零。这是因为查询集与训练集匹配。

示例

我们还可以通过生成稀疏图来显示相邻点之间的连接,如下所示:

nrst_neigh.kneighbors_graph(Input_data).toarray()

输出

array(
   [
      [1., 1., 0., 1., 0., 0., 0.],
      [1., 1., 1., 0., 0., 0., 0.],
      [1., 1., 1., 0., 0., 0., 0.],
      [1., 0., 0., 1., 1., 0., 0.],
      [0., 0., 0., 1., 1., 1., 0.],
      [0., 0., 0., 0., 1., 1., 1.],
      [0., 0., 0., 0., 1., 1., 1.]
   ]
)

一旦我们拟合了无监督的NearestNeighbors模型,数据将存储在基于参数‘algorithm’设置的值的数据结构中。之后,我们可以在需要邻域搜索的模型中使用这个无监督学习器的kneighbors

完整的可运行程序

from sklearn.neighbors import NearestNeighbors
import numpy as np
Input_data = np.array([[-1, 1], [-2, 2], [-3, 3], [1, 2], [2, 3], [3, 4],[4, 5]])
nrst_neigh = NearestNeighbors(n_neighbors = 3, algorithm='ball_tree')
nrst_neigh.fit(Input_data)
distances, indices = nbrs.kneighbors(Input_data)
indices
distances
nrst_neigh.kneighbors_graph(Input_data).toarray()

监督KNN学习

监督基于邻域的学习用于以下用途:

  • 分类,用于具有离散标签的数据
  • 回归,用于具有连续标签的数据。

最近邻分类器

我们可以通过以下两个特征来理解基于邻域的分类:

  • 它由每个点的最近邻的简单多数投票计算得出。
  • 它只存储训练数据的实例,因此它是一种非泛化学习。

Scikit-learn模块

以下是scikit-learn使用的两种不同类型的最近邻分类器:

序号 分类器及描述
1. KNeighborsClassifier

分类器名称中的K代表k个最近邻,其中k是由用户指定的整数值。因此,顾名思义,此分类器实现基于k个最近邻的学习。k的值的选择取决于数据。

2. RadiusNeighborsClassifier

分类器名称中的Radius代表指定半径r内的最近邻,其中r是由用户指定的浮点值。因此,顾名思义,此分类器实现基于每个训练点固定半径r内的邻居数量的学习。

最近邻回归器

它用于数据标签本质上是连续的情况。分配的数据标签是根据其最近邻标签的平均值计算的。

以下是scikit-learn使用的两种不同类型的最近邻回归器:

KNeighborsRegressor

回归器名称中的K代表k个最近邻,其中k是由用户指定的整数值。因此,顾名思义,此回归器实现基于k个最近邻的学习。k的值的选择取决于数据。让我们通过实现示例来更好地理解它。

以下是scikit-learn使用的两种不同类型的最近邻回归器:

实现示例

在这个示例中,我们将使用scikit-learn KNeighborsRegressor在名为Iris Flower的数据集上实现KNN。

首先,导入iris数据集,如下所示:

from sklearn.datasets import load_iris
iris = load_iris()

现在,我们需要将数据分成训练数据和测试数据。我们将使用Sklearn train_test_split函数将数据分成70(训练数据)和20(测试数据)的比例:

X = iris.data[:, :4]
y = iris.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)

接下来,我们将使用Sklearn预处理模块进行数据缩放,如下所示:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

接下来,从Sklearn导入KNeighborsRegressor类,并提供邻居的值,如下所示。

示例

import numpy as np
from sklearn.neighbors import KNeighborsRegressor
knnr = KNeighborsRegressor(n_neighbors = 8)
knnr.fit(X_train, y_train)

输出

KNeighborsRegressor(
   algorithm = 'auto', leaf_size = 30, metric = 'minkowski',
   metric_params = None, n_jobs = None, n_neighbors = 8, p = 2,
   weights = 'uniform'
)

示例

现在,我们可以找到MSE(均方误差),如下所示:

print ("The MSE is:",format(np.power(y-knnr.predict(X),4).mean()))

输出

The MSE is: 4.4333349609375

示例

现在,使用它来预测值,如下所示:

X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]
from sklearn.neighbors import KNeighborsRegressor
knnr = KNeighborsRegressor(n_neighbors = 3)
knnr.fit(X, y)
print(knnr.predict([[2.5]]))

输出

[0.66666667]

完整的可运行程序

from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data[:, :4]
y = iris.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()

scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

import numpy as np
from sklearn.neighbors import KNeighborsRegressor
knnr = KNeighborsRegressor(n_neighbors=8)
knnr.fit(X_train, y_train)

print ("The MSE is:",format(np.power(y-knnr.predict(X),4).mean()))

X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]
from sklearn.neighbors import KNeighborsRegressor
knnr = KNeighborsRegressor(n_neighbors=3)
knnr.fit(X, y)
print(knnr.predict([[2.5]]))

RadiusNeighborsRegressor

回归器名称中的Radius代表指定半径r内的最近邻,其中r是由用户指定的浮点值。因此,顾名思义,此回归器实现基于每个训练点固定半径r内的邻居数量的学习。让我们通过实现示例来更好地理解它:

实现示例

在这个示例中,我们将使用scikit-learn RadiusNeighborsRegressor在名为Iris Flower的数据集上实现KNN:

首先,导入iris数据集,如下所示:

from sklearn.datasets import load_iris
iris = load_iris()

现在,我们需要将数据分成训练数据和测试数据。我们将使用Sklearn train_test_split函数将数据分成70(训练数据)和20(测试数据)的比例:

X = iris.data[:, :4]
y = iris.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)

接下来,我们将使用Sklearn预处理模块进行数据缩放,如下所示:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

接下来,从Sklearn导入RadiusneighborsRegressor类,并提供半径的值,如下所示:

import numpy as np
from sklearn.neighbors import RadiusNeighborsRegressor
knnr_r = RadiusNeighborsRegressor(radius=1)
knnr_r.fit(X_train, y_train)

示例

现在,我们可以找到MSE(均方误差),如下所示:

print ("The MSE is:",format(np.power(y-knnr_r.predict(X),4).mean()))

输出

The MSE is: The MSE is: 5.666666666666667

示例

现在,使用它来预测值,如下所示:

X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]
from sklearn.neighbors import RadiusNeighborsRegressor
knnr_r = RadiusNeighborsRegressor(radius=1)
knnr_r.fit(X, y)
print(knnr_r.predict([[2.5]]))

输出

[1.]

完整的可运行程序

from sklearn.datasets import load_iris

iris = load_iris()

X = iris.data[:, :4]
y = iris.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
import numpy as np
from sklearn.neighbors import RadiusNeighborsRegressor
knnr_r = RadiusNeighborsRegressor(radius = 1)
knnr_r.fit(X_train, y_train)
print ("The MSE is:",format(np.power(y-knnr_r.predict(X),4).mean()))
X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]
from sklearn.neighbors import RadiusNeighborsRegressor
knnr_r = RadiusNeighborsRegressor(radius = 1)
knnr_r.fit(X, y)
print(knnr_r.predict([[2.5]]))
广告