美文网首页
scikit-learn机器学习:K-近邻算法分类和回归

scikit-learn机器学习:K-近邻算法分类和回归

作者: 简单一点点 | 来源:发表于2020-02-06 21:59 被阅读0次

KNN 是一种可以运用于分类和回归任务的算法。

K-近邻模型

KNN算法中的“邻居”代表的是度量空间中的训练实例,度量空间是定义了集合中所有成员之间距离的特征空间。

邻居是用于估计一个测试实例对应的响应变量值,超参k用来指定估计过程应该包含多少个邻居。超参是用来控制算法如何学习的参数,它不通过训练数据估计,一般需要认为指定。最后,算法通过某种距离函数,从度量空间中选出k个距离测试实例最近的邻居。

惰性学习和非参数模型

KNN是一种惰性学习模型,也被称为基于实例的学习模型,会对训练数据集进行少量的处理或者完全不处理。和勤奋学习模型不同,KNN在训练阶段不会估计由模型生成的参数。惰性学习模型几乎可以进行即刻预测,但是需要付出高昂的代价。

KNN是一种非参数模型参数模型使用固定数量的参数或者系数去定义能够对数据进行总结的模型,参数的数量独立于训练实例的数量。非参数模型意味着模型的参数个数并不固定,它可能随着训练实例数量的增加而增加。

KNN模型分类

下面看一个使用人的身高和体重去预测性别的例子,由于响应变量只能从2个标签(男或者女)中二选一,因此这种问题被称为二元分类

身高(cm) 体重(kg) 标签
158 64
170 66
183 84
191 80
155 49
163 59
180 67
158 54
178 77

这里使用了2个特征,实际上KNN并不仅限于2个特征,但特征值太多不利于可视化。

首先使用matplotlib类库绘制散点图进行可视化。

import numpy as np
import matplotlib.pyplot as plt

X_train = np.array([
    [158, 64],
    [170, 86],
    [183, 84],
    [191, 80],
    [155, 49],
    [163, 59],
    [180, 67],
    [158, 54],
    [170, 67]
])
y_train = ['male', 'male', 'male', 'male', 'female', 'female', 'female', 'female', 'female']

plt.figure()
plt.title('Human Heights and Weights by Sex')
plt.xlabel('Height in cm')
plt.ylabel('Weight in kg')

for i, x in enumerate(X_train):
    plt.scatter(x[0], x[1], c='k', marker='x' if y_train[i] == 'male' else 'D')
plt.grid(True)
plt.show()
output_1_0.png

现在让我们的使用KNN来预测其性别,首先我们需要定义距离衡量的方法,这里使用的是欧几里得距离,即在一个欧几里得空间中两点之间的直线距离。

公式如下:

{d \left( p,q \left) =d \left( q,p \left) =\sqrt{{\mathop{{ \left( \mathop{{q}}\nolimits_{{1}}-\mathop{{p}}\nolimits_{{1}} \right) }}\nolimits^{{2}}+\mathop{{ \left( \mathop{{q}}\nolimits_{{2}}-\mathop{{p}}\nolimits_{{2}} \right) }}\nolimits^{{2}}}}\right. \right. \right. \right. }

下面我们计算出测试实例和所有训练实例的距离,并设置参数k为3,选出3个距离最近的训练实例,并根据者3个邻居预测测试实例的性别。

x = np.array([155, 70]) # 测试数据
distances = np.sqrt(np.sum((X_train - x)**2, axis=1))
distances
array([ 6.70820393, 21.9317122 , 31.30495168, 37.36308338, 21.        ,
       13.60147051, 25.17935662, 16.2788206 , 15.29705854])
nearest_neighbor_indices = distances.argsort()[:3]
nearest_neighbor_genders = np.take(y_train, nearest_neighbor_indices)
nearest_neighbor_genders
array(['male', 'female', 'female'], dtype='<U6')
from collections import Counter
b = Counter(np.take(y_train, distances.argsort()[:3]))
b.most_common(1)[0][0]
'female'

最后的预测结果为女性,下面我们使用scikit-learn类库的KNN分类器。

from sklearn.preprocessing import LabelBinarizer
from sklearn.neighbors import KNeighborsClassifier

# 将标签转换为整数
lb = LabelBinarizer()
y_train_binarized = lb.fit_transform(y_train)
y_train_binarized
array([[1],
       [1],
       [1],
       [1],
       [0],
       [0],
       [0],
       [0],
       [0]])
K = 3
clf = KNeighborsClassifier(n_neighbors=K)
clf.fit(X_train, y_train_binarized.reshape(-1))
prediction_binarized = clf.predict(np.array([155, 70]).reshape(1, -1))[0]
predicted_label = lb.inverse_transform(prediction_binarized)
predicted_label
array(['female'], dtype='<U6')

结果和前面预测相同。

下面我们使用分类器对一个测试数据集进行预测,同时对其效果进行评估。

身高(cm) 体重(kg) 标签
168 65
180 96
160 52
169 67
X_test = np.array([
    [168, 65],
    [180, 96],
    [160, 52],
    [169, 67]
])
y_test = ['male', 'male', 'female', 'female']
y_test_binarized = lb.transform(y_test)
print('Binarized labels: %s' % y_test_binarized.T[0])
predictions_binarized = clf.predict(X_test)
print('Binarized predictions: %s' % predictions_binarized)
print('predicted labels: %s' % lb.inverse_transform(predictions_binarized))
Binarized labels: [1 1 0 0]
Binarized predictions: [0 1 0 0]
predicted labels: ['female' 'male' 'female' 'female']

可以看到其中的一个男性测试实例被错误的划分为女性,二元分类任务中有2种错误类型:误报和漏报,根据错误类型有几种常见的衡量方法:包括准确率、精准率和召回率。

准确率是测试实例中正确分类比例。

# 计算准确率
from sklearn.metrics import accuracy_score
print('Accuracy: %s' % accuracy_score(y_test_binarized, predictions_binarized))
Accuracy: 0.75

精准率是为正向类测试实例被预测为正向类的比率。

# 计算精准率,只有一个结果预测为男性,应该是100%
from sklearn.metrics import precision_score
print('Precision: %s' % precision_score(y_test_binarized, predictions_binarized))
Precision: 1.0

召回率是真实为正向类的测试实例被预测为正向类的比率。

# 计算召回率
from sklearn.metrics import recall_score

print('Recall: %s' % recall_score(y_test_binarized, predictions_binarized))
Recall: 0.5

精准率和召回率的平均值被称为F1得分或者F1度量。

from sklearn.metrics import f1_score
print('F1 score: %s' % f1_score(y_test_binarized, predictions_binarized))
F1 score: 0.6666666666666666

scikit-learn类还提供了一个非常有用的函数 classification_report 用于生成精准率、召回率和F1得分。

from sklearn.metrics import classification_report
print(classification_report(y_test_binarized, predictions_binarized, target_names=['male'], labels=[1]))
              precision    recall  f1-score   support

        male       1.00      0.50      0.67         2

   micro avg       1.00      0.50      0.67         2
   macro avg       1.00      0.50      0.67         2
weighted avg       1.00      0.50      0.67         2

KNN模型回归

现在使用KNN模型进行一个回归任务,根据一个人的身高和性别预测其体重。

训练数据:

身高(cm) 性别 体重(kg)
158 64
170 66
183 84
191 80
155 49
163 59
180 67
158 54
178 77

测试数据:

身高(cm) 性别 体重(kg)
168 65
170 61
160 52
169 67

对于回归问题,除了前面的R2,首先引入两个新的衡量指标:

平均绝对误差MAE,是预测结果误差绝对值的均值。公式如下:
{MAE=\frac{{1}}{{n}}{\mathop{ \sum }\nolimits_{{n-1}}^{{i=0}}{ \left| \mathop{{y}}\nolimits_{{i}}-\mathop{{\mathop{{y}}\limits^{реѕ}}}\nolimits_{{i}} \right| }}}

均方误差MSE是预测结果误差的平方的均值,比起MAE更加常用,公式如下:
{MSE=\frac{{1}}{{n}}{\mathop{ \sum }\nolimits_{{n-1}}^{{i=0}}{ \left( \mathop{{y}}\nolimits_{{i}}-\mathop{{\mathop{{y}}\limits^{реѕ}}}\nolimits_{{i}} \left) \mathop{{}}\nolimits^{{2}}\right. \right. }}}

特征缩放
当特征有相同的取值范围时,许多学习算法将会运行的更好。scikit-learn类库中的StandardScaler类是一个用于特征缩放的转换器,他能确保所有的特征都有单位方差。

它首先将所有的实例特征值减去均值来将其据中,其次将每个实例特征值除以特征的标准差对其进行缩放。均值为0,方差为1的数据被称为标准化数据。

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler

X_train = np.array([
    [158, 1],
    [170, 1],
    [183, 1],
    [191, 1],
    [155, 0],
    [163, 0],
    [180, 0],
    [158, 0],
    [170, 0]
])
y_train = [64, 86, 84, 80, 49, 59, 67, 54, 67]

X_test = np.array([
    [168, 1],
    [180, 1],
    [160, 0],
    [169, 0]
])
y_test = [65, 96, 52, 67]

# 标准化数据
ss = StandardScaler()
X_train_scaled = ss.fit_transform(X_train)
print(X_train)
print(X_train_scaled)
[[158   1]
 [170   1]
 [183   1]
 [191   1]
 [155   0]
 [163   0]
 [180   0]
 [158   0]
 [170   0]]
[[-0.9908706   1.11803399]
 [ 0.01869567  1.11803399]
 [ 1.11239246  1.11803399]
 [ 1.78543664  1.11803399]
 [-1.24326216 -0.89442719]
 [-0.57021798 -0.89442719]
 [ 0.86000089 -0.89442719]
 [-0.9908706  -0.89442719]
 [ 0.01869567 -0.89442719]]
from sklearn.neighbors import KNeighborsRegressor

X_test_scaled = ss.transform(X_test)
K = 3
clf = KNeighborsRegressor(n_neighbors=K)
clf.fit(X_train_scaled, y_train)
predictions = clf.predict(X_test_scaled)
print('Predicted weights: %s' % predictions)
print('Coefficient of determination: %s' % r2_score(y_test, predictions))
print('Mean absolute error: %s' % mean_absolute_error(y_test, predictions))
print('Mean squared error: %s' % mean_squared_error(y_test, predictions))
Predicted weights: [78.         83.33333333 54.         64.33333333]
Coefficient of determination: 0.6706425961745109
Mean absolute error: 7.583333333333336
Mean squared error: 85.13888888888893

相关文章

  • 机器学习算法分类

    机器学习算法分类 监督学习(预测)分类:K-近邻算法、贝叶斯分类、决策树与随机森林、逻辑回归、神经网络回归:线性回...

  • K近邻

    一、模型 1.1概念 k-近邻算法是一种基本分类与回归方法,我们这里只讨论分类问题中的 k-近邻算法。k-近邻算法...

  • 机器学习新手必学十大算法指南

    摘要:本文为机器学习新手介绍了十种必备算法:线性回归、逻辑回归、线性判别分析、分类和回归树、朴素贝叶斯、K-近邻算...

  • 机器学习实战笔记 1)K-近邻算法:理论篇

    近邻算法K-近邻算法是机器学习分类算法中最简单的方法之一。在讲清楚K-近邻算法之前,我们先来看看它的一个简化版--...

  • scikit-learn机器学习:K-近邻算法分类和回归

    KNN 是一种可以运用于分类和回归任务的算法。 K-近邻模型 KNN算法中的“邻居”代表的是度量空间中的训练实例,...

  • 机器学习实战之K-近邻算法(二)

    机器学习实战之K-近邻算法(二) 2-1 K-近邻算法概述 简单的说,K-近邻算法采用测量不同特征值之间的距离方法...

  • k-近邻算法

    k-近邻算法概述 在模式识别领域中,K-近邻算法(KNN算法)是一种用于分类和回归的非参数统计方法。在这两种情况下...

  • 【机器学习】有监督学习kNN(k-近邻法)

    学习自《机器学习实战》 任务 学习k-近邻分类算法 使用matplotlib创建扩散图 归一化数值 思想 采用测量...

  • K-近邻算法学习及实现

    K-近邻算法学习及实现 K-近邻原理 K-近邻算法采用测量不同特征值之见的距离方法进行分类。 将新数据与已知数据集...

  • 统计学习方法之kNN算法

    k 近邻是什么 k 近邻法是机器学习中最基本的分类和回归方法,也称为kNN算法。通常k近邻法用于分类问题。k近邻法...

网友评论

      本文标题:scikit-learn机器学习:K-近邻算法分类和回归

      本文链接:https://www.haomeiwen.com/subject/jjhpxhtx.html