一、K-近邻算法

1.K-近邻算法简介

  1.1什么是K-近邻算法

  • 根据你的“邻居”来推断出你的类型
  • 是一种分类算法

  1.2K-近邻算法(KNN)概念

  • 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别
  • 距离公式:一般使用欧氏距离

2.K-近邻算法api初步使用

  • 使用Scikit-learn
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)
    n_neighbors:选定参考几个邻居 int默认是5  k_neighbors查询默认使用的邻居数

  2.1代码实现过程

from sklearn.neighbors import KNeighborsClassifier

#构造数据集
x = [[0],[1],[2],[3]]
y = [0,0,1,1,]

#模型训练
##实例化API
estimator = KNeighborsClassifier(n_neighbors=2)
##使用fit方法进行训练
estimator.fit(x,y)

estimator.predict([[1]])

3.距离度量

  3.1 欧氏距离

  3.2 曼哈顿距离

  3.3 切比雪夫距离

  3.4 闵可夫斯基距离

  • 缺点:将各个分量的单位没有区分,未考虑到各个分量的分布(期望、方差等)可能是不同的

  3.5 标准化欧氏距离

  • 针对欧氏距离的缺点而改进的

  3.6 余弦距离

  3.7 汉明距离

  • 两个等长字符串s1和s2的汉明距离为:将其中一个变为另一个所需要做的最小字符替换次数
  • 汉明重量:是字符串相对于同样长度的零字符串的汉明距离,也就是说,他是字符串中非零的元素个数。因此向量空间中的元素a和b之间的汉明距离等于他们汉明重量的差a-b

  3.8 杰卡德距离

  3.9 马氏距离

  • 与单位无关,排除变量之间的相关性干扰
  • 计算建立在总体样本的基础上,如果拿同样的两个样本放入不同的总体中,最后计算得出的两个样本间的马氏距离通常是不相同的,除非两个总体的协方差矩阵碰巧相同
  • 计算过程中要求总体样本数大于样本的维数,否则得到的总体样本协方差矩阵逆矩阵不存在

二、K值选择

  • 近似误差:对现有训练集的训练误差,关注训练集,如果近似误差过小可能会出现过拟合现象,对现有的训练集能有很好的预测,但对未知的测试样本将会出现较大误差的预测。模型本身不是最接近最佳模型
  • 估计误差:对测试机的测试误差,关注测试集,估计误差小说明对未知数据的预测能力好,模型本身最接近最佳模型

1.K值过小

      相当于用较小的领域中的训练实例进行预测,“学习”近似误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是“学习”的估计误差会增大,即K值的减小意味着整体模型变得复杂,容易发生过拟合

2.K值过大

       有点事可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候与输入实例较远(不相似)的训练实例也会对预测起作用,使预测发生错误,并且K值的增大意味着整体模型变得简单

3.K=N(N为训练样本数)

       完全不足取,因为此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单,忽略了训练实例中大量有用信息

三、kd树

1.kd树简介

  1.1 什么是kd树

       根据KNN每次需要预测一个点时,我们都需要计算训练数据集里每个点到这个点的距离,然后选出距离最近的K个点进行投票,当数据集很大时,计算成本很高,针对N个样本,D个特征的数据集,其算法复杂度为O(DN^2)

        kd树:为了避免每次都重新计算一遍距离,算法会把距离信息保存在一颗树里,这样在计算之前从梳理查询距离信息,尽量避免重新计算。其基本原理是,如果A和B距离很远,B和C距离很近,那么A和C的距离也很远。有了这个信息,就可以在合适的时候跳过距离远的点

  1.2 原理

2.构造方法

  1. 构造根节点,是根节点对应于K维空间中包含所有实例点的超矩形区域
  2. 通过递归的方法,不断对K维空间进行切分生成子节点。再超巨星区域上选择一个坐标轴和在此坐标轴上的一个切分点,确定一个超平面,这个超平面通过选定的切分点并垂直于选定的坐标轴,将当前超巨星区域切分为左右两个子区域(子结点),这是实例被分到两个子区域
  3. 上述过程直到子区域内没有实例时终止(终止时的结点为叶结点)。在此过程中,将实例保存在相应的节点上
  4. 通常,循环的选择坐标轴对空间切分,选择训练实例点在坐标轴上的中位数为切分点,这样得到的kd树是平衡的(平衡二叉树:它是一棵空树,或其左子树和右子树的深度值差的绝对值不超过1,且它的左子树和右子树都是平衡二叉树)

  2.1选择向量的哪一维进行划分

        随机选择某一维或按顺序选择,但更好的方法是在数据比较分散的那一维进行划分(分散程度可以根据方差来衡量)。好的划分方法可以使构建的数比较平衡,可以每次选择中位数来进行划分

3.kd树搜索

  3.1 最近邻域搜索

  • 在本域内,没有进行跨域搜索

  • 要跨到其他域搜索

四、案例

1.scikit_learn数据集API介绍

sklearn.datasets

# 获取小规模数据集,数据包含在datasets里
datasets.load()

# 获取大规模数据集,需要从网络上下载
datasets.fetch_20newsgroups(data_home=None, subset='train')
    data_home:数据集下载的目录,默认是~/scikit_learn_data/
    subset:'train'(训练集的“训练”)或者'test'(测试集的“测试”),'all'(两者的全部),可选,选择要加载的数据集

2.sklearn数据集返回值介绍

# load和fetch返回的数据类型datasets.base.Bunch(字典格式)
    data:特征数据数组,是[n_samples *n_features]的二维numpy.ndarray数组
    target:标签(目标)数组,是n_samples的一位numpy.ndarray数组
    DESCR:数据描述
    feature_names:特征名
    target_names:标签(目标)名

3.查看数据分布

  3.1 seaborn介绍

  • seaborn是基于Matplotlib核心库进行了更高级的API封装
  • 安装:pip install seaborn
# 绘制二维散点图时自动完成回归拟合
seaborn.lmplot()
    x,y分别代表横纵坐标的列名
    data 关联到数据集
    hue 代表按照species即花的类别分类显示
    fit_reg 是否进行线性拟合

  3.2 数据可视化

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris,fetch_20newsgroups

iris = load_iris()
iris_data = pd.DataFrame(data = iris.data, columns=['Sepal_Length','Sepal_Width','Petal_Length','Petal_Width'])
iris_data["target"] = iris.target

def iris_plot(data, col1, col2):
    sns.lmplot(x=col1, y=col2, data=data, hue="target", fit_reg=False)
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.show()

iris_plot(iris_data, "Sepal_Length", "Petal_Width")
iris_plot(iris_data, "Sepal_Width", "Petal_Length")

  3.3 数据集划分

sklearn.model_selection.train_test_split(arrays, *options)
    x:数据集的特征值
    y:数据集的标签值
    test_size:测试集的大小,一般为float
    random_state:随机数种子,不同的种子会造成不同的随机采样结果,相同的种子采样结果相同
    return:训练集特征值、测试集特征值、训练集标签、测试集标签(默认随机取)
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size = 0.2, random_state=2)
print("训练集的特征值是:\n",x_train)
print("测试集的特征值是:\n",x_test)
print("训练集的标签是:\n",y_train)
print("测试集的标签是:\n",y_test)

x_train1, x_test1, y_train1, y_test1 = train_test_split(iris.data, iris.target, test_size = 0.2, random_state=20)
x_train2, x_test2, y_train2, y_test2 = train_test_split(iris.data, iris.target, test_size = 0.2, random_state=20)
print("训练集的标签是:\n",y_test1)
print("训练集的标签是:\n",y_test2)

五、特征工程-特征预处理

1.什么是特征预处理

  1.1 特征预处理定义

  • 通过一些转换函数将特征数据转换成更加适合算法模型的特征数据过程

  • 为什么要进行归一化:特征的单位或大小相差较大,或者某特征的方差相比其他的特征要大出几个数量级,容易影响(支配)目标结果,使得一些算法无法学习到其他的特征

  1.2 包含内容(数值型数据的无量纲化)

  1. 归一化
  2. 标准化

  1.3 特征预处理API

sklearn.preprocessing

2.归一化

  2.1 定义

  • 通过对原始数据进行变换把数据映射到(默认为[0,1])之间

  2.2 公式

  • mx、mi分别为指定区间默认mx为1,mi为0

  2.3 API

sklearn.preprocessing.MinMaxScaler(feature_range=(0,1)...)
    feature_range:自己指定范围,默认0-1
from sklearn.preprocessing import MinMaxScaler
import pandas as pd

data = pd.read_csv("D:\major\myjupyter\MachineLearning\data\dating.txt")
print(data)

# 1.归一化
# 1.1实例化一个转换器
transfer = MinMaxScaler(feature_range=(0,1))
# 1.2调用fit_transform方法
minmax_data = transfer.fit_transform(data[["milage","Liters","Consumtime"]])
print("经过归一化处理之后的数据为:\n",minmax_data)

  2.4 归一化总结

  • 最大值最小值是变化的
  • 最大值与最小值非常容易受异常点影响,所以这种方法鲁棒性较差,只适合传统精确小数据场景

3.标准化

  3.1 定义

  • 通过对原始数据进行变换把数据变换到均值为0,标准差为1范围内

  3.2 公式

  • 作用域每一列,mean为平均值,分母为标准差

  3.3 API

sklearn.preprocessing.StandardScaler()
from sklearn.preprocessing import StandardScaler
import pandas as pd

# 2.标准化
# 2.1实例化一个转换器
transfer = StandardScaler()
# 2.2调用fit_transform方法
minmax_data = transfer.fit_transform(data[["milage","Liters","Consumtime"]])
print("经过标准化处理之后的数据为:\n",minmax_data)

六、鸢尾花种类预测——流程实现

1.再识K-近邻算法

sklearn.neighbors.KNeighboresClassifier(n_neighbors=5, algorithm='auto')
    n_neighbors:int,可选(默认=5),k_neighbors查询默认使用的邻居数
    algorithm:{'auto','ball_tree','kd_tree','brute'}
        快速k近邻搜索算法,默认参数为auto,可以理解为算法自己决定适合的搜索算法
        brute:蛮力搜索,即线性扫描,当训练集很大时计算非常耗时
        kd_tree:构造kd树存储数据以便对其进行快速检索的树形数据结构,kd树也就是数据结构中的二叉树。以种植切分构造的书,每个节点是一个超巨星,在维数小于20时效率高
        ball_tree:为了克服kd树高维失败而发明的,其构造过程是以质心C和半径r分割样本空间,每一个节点是一个超球体

2.案例:鸢尾花种类预测

  2.1 数据集介绍

  2.2 步骤分析

  1. 获取数据集
  2. 数据基本处理
  3. 特征工程
  4. 机器学习(模型训练)
  5. 模型评估

  2.3 代码过程

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

# 1.获取数据集
iris = load_iris()

# 2.数据基本处理
# 2.1 数据分割
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size = 0.2, random_state=22)

# 3.特征工程
# 3.1 实例化一个转换器
transfer = StandardScaler()
# 3.2 调用fit_transform方法
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)

# 4.机器学习(模型训练)
# 4.1 实例化一个估计器
estimator = KNeighborsClassifier(n_neighbors=5)
# 4.2 模型训练
estimator.fit(x_train, y_train)

# 5.模型评估
# 5.1 输出预测值
y_pre = estimator.predict(x_test)
print("预测值是:\n", y_pre)
print("真实值和预测值对比:\n", y_pre == y_test)
# 5.2 输出准确率
ret = estimator.score(x_test, y_test)
print("准确率是:\n",ret)

七、交叉验证和网格搜索

1.什么是交叉验证

  • 将拿到的训练数据分为训练和验证集

  1.1 分析

1.2 为什么需要交叉验证

  • 为了让被评估的模型更加准确可信

2.什么是网格搜索

3.交叉验证、网格搜索(模型选择与调优)API

sklearn.model_selection.GridSearchCV(estimator, param_grid=None, cv=None)
    estimator:估计器对象
    param_grid:估计器参数(dict){"n_neighbors":[1,3,5]},即需要传递的超参数
    cv:指定几折交叉验证

fit:输入训练数据
score:准确率
结果分析:
    best_score_:在交叉验证中的最好结果
    best_estimator_:最好的参数模型
    cv_results_:每次交叉验证后的验证集准确率结果和训练集准确率结果

4.鸢尾花案例增加K值调优

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

# 1.获取数据集
iris = load_iris()

# 2.数据基本处理
# 2.1 数据分割
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size = 0.2, random_state=22)

# 3.特征工程
# 3.1 实例化一个转换器
transfer = StandardScaler()
# 3.2 调用fit_transform方法
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)

# 4.机器学习(模型训练)
# 4.1 实例化一个估计器
estimator = KNeighborsClassifier(n_neighbors=1)
# 4.2 调用交叉验证网格搜索模型
param_grid = {'n_neighbors':[1,3,5,7,9]}
estimator = GridSearchCV(estimator, param_grid = param_grid, cv=10, n_jobs=-1)
# 4.3 模型训练
estimator.fit(x_train, y_train)

# 5.模型评估
# 5.1 输出预测值
y_pre = estimator.predict(x_test)
print("预测值是:\n", y_pre)
print("真实值和预测值对比:\n", y_pre == y_test)
# 5.2 输出准确率
ret = estimator.score(x_test, y_test)
print("准确率是:\n",ret)
# 5.3 其他评价指标
print("最好的模型:\n",estimator.best_params_)
print("最好的结果:\n",estimator.best_score_)
print("整体模型结果:\n",estimator.cv_results_)

八、案例2:预测FaceBook签到位置

1.数据集介绍

2.流程分析

  2.1 获取数据集

  2.2 基本数据处理

  1. 缩小数据范围
  2. 选择时间特征
  3. 去掉签到较少的地方
  4. 确定特征值和目标值
  5. 分割数据集

  2.3 特征工程——特征预处理(标准化)

  2.4 机器学习——knn+cv

  2.5 模型评估

更多推荐