机器学习常用算法-k近邻算法

概述

今天介绍一下机器学习常用算法,以及常用的数据处理技巧等。我们都知道机器学习针对特定任务从经验中学习,并且使得我们的任务效果越来越好。我们看一机器学习的workflow,如下所示: 数据采集和标记->数据清洗->特征选择->模型选择->模型训练和测试->模型性能评估和优化->模型使用即上线。 我们一般通过Python来实现机器学习常用算法的程序,所以基于Python语言常用的机器学习类库及其第三方扩展库有:IPython,Jupyter,numpy,matplotlib,scipy,scikit-learn,seaborn。 我们先安装这些类库即。

pip install ipython,jupyter,numpy,matplotlib,scipy,scikit-learn,seaborn

下面我们来简单的介绍一下这几个类库。

类库了解

ipython

1.ipython是一种探索性编程的类库,它可以非常方便的执行你的python代码。快捷键和魔法用法可以自己百度和google,介绍一个常用的技巧就是通过魔法函数可以直接启用魔法命令,不用每次执行魔法命令时键入%。

%automagic on
pwd
cd

2.可视化的嵌套可以通过。

%matplotlib inline

numpy

Numpy 是Python计算机科学基础库,里面有很多的数学算法。

import numpy as np

a = np.array([[1,2,4],[1,2,3]])
a.shape,a.ndim,a.dtype
#分别是多维数据的维度,轴和数据类型
(2, 3), 2, dtype('int64')

numpy是共享内存的,如果需要独立保存则需要显式的备份。可以通过np.may_share_memory(),判断两个数组是否是共享内存。

a = np.arange(10)
b = a[2:5]
np.may_share_memory(a,b)
#输出
True
b = a[2:5].copy()
np.may_share_memory(a,b)
#输出
False

关于轴的问题,numpy的多维数组是面向轴处理的。例如:

a = np.random.randint(1,5,(4,6))
print(a)
#输出
array([[2, 4, 2, 3, 4, 3],
       [2, 2, 1, 3, 4, 2],
       [1, 3, 1, 1, 3, 1],
       [1, 3, 3, 2, 3, 3]])
#面向轴处理,axis=0代表按行处理,axis=1面向列处理。
print(a.sum(axis=0),a.sum(axis=1))
#输出
(array([ 6, 12,  7,  9, 14,  9]), array([18, 14, 10, 15]))

还有一个经常使用的用法就是按照array的维度操作。比如:

a = np.arange(12)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
b = a.reshape((3,4))
array([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
b.ravel()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]))
b=a[:,np.newaxis]
array([[ 0],
       [ 1],
       [ 2],
       [ 3],
       [ 4],
       [ 5],
       [ 6],
       [ 7],
       [ 8],
       [ 9],
       [10],
       [11]])

排序,排序不仅支持按照值排序而且还通过index返回。比如

a=np.array([10,3,4,7,12])
a.argsort()
#输出
array([1, 2, 3, 0, 4])

我在Numpy 数据处理一文中介绍了一些常用的用法,或者参考它的官方文档。

pandas

关于pandas的技巧,可以参考Pandass 数据处理

matplotlib 和 sklearn

官方文档已经非常全面了,建议参考官方文档。

算法

在之前我们已经介绍了机器学习算法理论,下面我们介绍两个几个重要的关键术语。过拟合:模型能很好的拟合训练数据,但是对于新数据或者测试数据的预测准确性较差。欠拟合:模型不能很好的拟合训练样本且对新数据或者测试数据的预测准确性较差。相对应的我们一般称欠拟合为高偏差,过拟合称为高方差。我们现在常用的机器学习算法是通过模型算法成本来反馈(反推)模型参数,使得在成本函数或者代价函数最低的情况下,寻找最优的模型参数。比如:

J_{test}(\theta)=\frac 1{2m}\sum_{i=0}^m(h_\theta(x^{(i)})-y^{i})^2

我们通过模型在数据集上的最少成本来求解最优模型参数。

算法评价

我们在采用机器学习应用业务时,我们通常通过交叉验证数据集来衡量模型,即:训练数据集:交叉验证数据集:测试数据集=6:2:2在模型选择时,使用训练数据集来训练算法参数,用交叉验证集来验证参数,选择交叉验证集的成本J最下的算法作为数据拟合模型,最后再用测试数据集来测试选择出来的模型准确性。但是在实践中,大多数直接将数据集分成训练数据集和测试数据集,而没有交叉验证数据集,主要是大多数时候并不需要横向对比不同的模型。在工程上,我们最主要的工作不是选择模型,而是获取更多的数据、分析数据以及数据挖掘。

学习曲线

学习曲线是观察模型准确率与训练数据集关系。步骤: 1.将数据集分为训练数据集和交叉验证数据集。 2.取训练数据集的20%作为训练样本,训练出模型参数。 3.使用交叉验证数据集来计算训练出来的模型的准确率。 4.以训练数据集的准确性,交叉验证的准确性作为纵坐标,训练数据集个数作为横坐标,在坐标轴画出。 5.训练数据集增加10%,跳到第三步骤继续执行,知道训练数据集大小为100%为止。 在详细的机器学习算法里面,我们会画出一个学习曲线。一般我们会通过学习曲线,来判断算法是高偏差还是高方差。 对于过拟合一般采取的方法: 1.获取更多的训练数据。 2.减少输入的特征数。 对于欠拟合一般采取的方法: 1.增加有价值的特征。 2.增加多项式特征。

查准率和召回率

除了学习曲线外,我们一般还会通过查准率和召回率来评价一个算法的好坏。比如关于一个肿瘤预测的实例中: 预测数据/实际数据 实际恶性肿瘤 实际良性肿瘤 预测恶性肿瘤 TruePositive FalsePositive 预测良性肿瘤 FalseNegative TrueNegative

Precision=\frac {TruePositive}{TruePositive+FalsePositive} Recall=\frac {TruePositive}{TruePositive+FalseNegative} F_1Score=2\frac{PR}{P+R}

K-近邻算法

k-近邻算法是针对未标记的样本类别,由距离其最近的k个邻居投票决定的。优点:准确性高,对异常值和噪声有较高的的容忍度。缺点:计算量较大,对内存的需求较大。一般而言,k值越大,模型的偏差越大,对噪声数据越不敏感,当k值很大时,可能造成欠拟合;k值越小,模型的方差越大,当k值太小时容易造成过拟合。我们通过k-近邻算法来进行糖尿病预测。数据集为diabetes.csv,我们依次来看一下。 1.加载数据

data_path="diabetes.csv"
import pandas as pd
data = pd.read_csv(data_path)
data.head()

数据的8个特征分别为

  • Pregnancies:怀孕的次数
  • Glucose:血浆葡糖糖浓度。
  • BloodPressure:舒张压(单位毫米)
  • SkinThickness:肱三头肌厚度(单位毫米)
  • Insulin:两个小时的血清胰岛素(单位毫升)
  • BMI:身体质量指数,体重除以身高的平方。
  • DiabetesPedigreeFunction:糖尿病血统指数。
  • Age 年龄
  • Outcome:结果标记值,0表示没有糖尿病,1表示有糖尿病。

我们可以看一下实例数据。

data.shape
(768,9)
ata.groupby("Outcome").size()
Outcome
0    500
1    268
dtype: int64

其中阳性有500个,阴性有268个。我们将数据集分类出来方便我们训练和衡量。

#只含有特征的数据集
x=data.iloc[:,0:8]
#标记数据
y=data.iloc[:,8]
print('shape of x {};shape of y {}'.format(x.shape,y.shape))
#输出 shape of x (768, 8);shape of y (768,)
from sklearn.model_selection import train_test_split
#将数据集划分为训练数据集和测试数据集,其中测试数据集为20%。
x_train,x_test,y_trian,y_test = train_test_split(x,y,test_size=0.2)

2.模型选择 我们使用三种算法对数据进行拟合即普通的k-均值算法,带权重的k-均值算法和指定半径的k-均值算法。

from sklearn.neighbors import KNeighborsClassifier,RadiusNeighborsClassifier
models=[]
models.append(("KNN",KNeighborsClassifier(n_neighbors=2)))
models.append(("KNN with weights",KNeighborsClassifier(n_neighbors=2,weights="distance")))
models.append(("Radius Neighbors",RadiusNeighborsClassifier(n_neighbors=2,radius=500)))
results=[]
for name,model in models:
    model.fit(x_train,y_trian)
    results.append((name,model.score(x_test,y_test)))
for i in range(len(results)):
    print("name:{};score:{}".format(results[i][0],results[i][1]))
#输出
name:KNN;score:0.7142857142857143
name:KNN with weights;score:0.6168831168831169
name:Radius Neighbors;score:0.6948051948051948

因为训练样本和测试样本是随机分配的,那么如何衡量模型呢?所以我们需要多次分配训练数据集和交叉验证数据集,然后对多次预测结果进行平均。

#kfold 将数据分成10份,其中一份作为交叉验证数据集来计算模型准确性。
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
results=[]
for name,model in models:
    kfold=KFold(n_splits=10)
    cv_result=cross_val_score(model,x,y,cv=kfold)
    results.append((name,cv_result))
for i in range(len(results)):
    print("name:{};score:{}".format(results[i][0],results[i][1].mean()))

我们采用普通的k-近邻算法。 3.模型分析 我们分别对训练集和测试集进行分析,如下:

knn = KNeighborsClassifier(n_neighbors=2)
knn.fit(X=x_train,y=y_trian)
train_score=knn.score(x_train,y_trian)
test_score=knn.score(x_test,y_test)
print("train score {};test score {}".format(train_score,test_score))
#输出
train score 0.8289902280130294;test score 0.7142857142857143

一是模型在训练样本上表现不佳,这说明算法太简单。二是在测试集的准确性欠佳。 我们下面通过学习曲线来看一下:

from sklearn.model_selection import learning_curve
import numpy as np
import matplotlib.pyplot as plt

def plot_learning_curve(plt, estimator, title, X, y, ylim=None, cv=None,n_jobs=1, train_sizes=np.linspace(.1, 1.0, 5)):
    plt.title(title)
    if ylim is not None:
        plt.ylim(*ylim)
    plt.xlabel("Training examples")
    plt.ylabel("Score")
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes)
    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    test_scores_mean = np.mean(test_scores, axis=1)
    test_scores_std = np.std(test_scores, axis=1)
    plt.grid()

    plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                     train_scores_mean + train_scores_std, alpha=0.1,
                     color="r")
    plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std, alpha=0.1, color="g")
    plt.plot(train_sizes, train_scores_mean, 'o--', color="r",
             label="Training score")
    plt.plot(train_sizes, test_scores_mean, 'o-', color="g",
             label="Cross-validation score")

    plt.legend(loc="best")
    return plt

cv=ShuffleSplit(n_splits=10,test_size=0.2,random_state=0)
plt.figure(figsize=(10,6),dpi=64)
plot_learning_curve(plt,knn,"cure",x,y,ylim=(0.0,1.01),cv=cv)
plt.show()

我们能看到学习曲线,和我们的之前的模型分析的结果是一致的。如下图所示:

后面我们会介绍如何提高该算法准确率。 4.特征可视化和分析 有时候我们想通过将最相关的一个或者多个特征选择出来进行可视化分析,那么如何选择最相关的特征呢?我们一般通过如下方法:

from sklearn.feature_selection import SelectKBest
selector = SelectKBest(k=2)
x_new=selector.fit_transform(x,y)
results=[]
for name,model in models:
    kfold=KFold(n_splits=10)
    cv_result=cross_val_score(model,x_new,y,cv=kfold)
    results.append((name,cv_result))
for i in range(len(results)):
    print("name:{};score:{}".format(results[i][0],results[i][1].mean()))
#输出
name:KNN;score:0.725205058099795
name:KNN with weights;score:0.6900375939849623
name:Radius Neighbors;score:0.6510252904989747

然后可以将这两个特征和输出标记投影在坐标轴上,看一下数据分布。可以看到数据分布和重叠性很大,所以选择k-近邻算法无法达到一个很好的预测准确性。 这里的最相关的特征选择主要采用了统计学上的相关性检验,比如:卡方检验、t检验。

总结

通过一个简单的例子对机器学习的常用算法-k近邻算法有了一个整体上的了解。下面我们介绍一下另外一个常用算法:线性回归参考 1.《scikit-learning 机器学习》 2.scikit learning 3.《机器学习导论》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨熹的专栏

图解何为CNN

参考 CNN - Convolutional Neural Networks 是近些年在机器视觉领域很火的模型,最先由 Yan Lecun 提出。 如果想学细...

2845
来自专栏量子位

图像分类入门,轻松拿下90%准确率 | 教你用Keras搞定Fashion-MNIST

这篇教程会介绍如何用TensorFlow里的tf.keras函数,对Fashion-MNIST数据集进行图像分类。

2051
来自专栏AILearning

【Scikit-Learn 中文文档】新异类和异常值检测 - 无监督学习 - 用户指南 | ApacheCN

中文文档: http://sklearn.apachecn.org/cn/stable/modules/outlier_detection.html 英文文...

6927
来自专栏AI科技大本营的专栏

测试数据科学家聚类技术的40个问题(能力测验和答案)(下)

【AI100 导读】本次测试的重点主要集中在概念、聚类基本原理以及各种技术的实践知识等方面。本文为下部,包括21-40题。上部请查看: 测试数据科学家聚类技术的...

3464
来自专栏磐创AI技术团队的专栏

SVM多核学习方法简介

【磐创AI导读】:本文主要介绍SVM多核学习方法。想要学习更多的机器学习知识,欢迎大家点击上方蓝字关注我们的公众号:磐创AI。

1062
来自专栏深度学习

循环神经网络

循环神经网络的神经网络体系结构,它针对的不是自然语言数据,而是处理连续的时间数据,如股票市场价格。在本文结束之时,你将能够对时间序列数据中的模式进行建模,以对未...

3898
来自专栏AI深度学习求索

目标检测(CVPR2017):Feature Pyramid Networks

(a)使用图像金字塔构建特征金字塔网络:每个图像尺度上的特征都是独立计算的,速度缓慢。

963
来自专栏机器之心

教程 | 无需反向传播的深度学习:DeepMind的合成梯度

选自GitHub 作者:iamtrask 机器之心编译 参与:王宇欣、Ellen Han 在这篇博文中,我们将从起点(从零开始)学习 DeepMind 最近提...

30410
来自专栏深度学习自然语言处理

【机器学习】今天想跟大家聊聊SVM

之前我在自己的简书上写过SVM,可是当时写的只是皮毛(主要是现在忘了O.O),那么现在想再次拾起的原因是什么呢?

893
来自专栏机器学习算法与理论

使用开源人脸特征提取器进行脸部颜值评分

本文仅为模型应用实战,而非颜值研究,所得结果仅供娱乐,仅供参考。 方法也仅供参考。 一般而言,数据量越大,结果越接近正常人审美。由于本次数据量较小,故仅为实验。...

5569

扫码关注云+社区