前言

本系列为机器学习算法的总结和归纳,目的为了清晰阐述算法原理,同时附带上手代码实例,便于理解。

目录

  决策树
  组合算法(Ensemble Method)
  K-Means
  机器学习算法总结
 
本章为k近邻算法,内容包括模型介绍及代码实现(包括自主实现和sklearn案例)。

一、算法简介

1.1 基本概念

k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法。
基本概念如下:存在一个样本数据集合,所有特征属性已知,并且样本集中每个对象都已知所属分类。对不知道分类的待测对象,将待测对象的每个特征属性与样本集中数据对应的特征属性进行比较,然后算法提取样本最相似对象(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的对象数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后根据这k个数据的特征和属性,判断待测数据的分类

1.2 K近邻的三个基本要素

  1) k值的选取。在应用中,k值一般选择一个比较小的值,一般选用交叉验证来取最优的k值
  2)距离度量。Lp距离:误差绝对值p次方求和再求p次根。欧式距离:p=2的Lp距离。曼哈顿距离:p=1的Lp距离。p为无穷大时,Lp距离为各个维度上距离的最大值
  3)分类决策规则。也就是如何根据k个最近邻决定待测对象的分类。k最近邻的分类决策规则一般选用多数表决

1.3 KNN基本执行步骤

  1)计算待测对象和训练集中每个样本点的欧式距离
  2)对上面的所有距离值排序
  3)选出k个最小距离的样本作为“选民”
  4)根据“选民”预测待测样本的分类或值

1.4 KNN特点

  1)原理简单
  2)保存模型需要保存所有样本集
  3)训练过程很快,预测速度很慢
  · 优点:
  简单好用,容易理解,精度高,理论成熟,既可以用来做分类也可以用来做回归;
  可用于非线性分类;
  可用于数值型数据和离散型数据(既可以用来估值,又可以用来分类)
  训练时间复杂度为O(n);无数据输入假定;
  对异常值不敏感。
  准确度高,对数据没有假设,对outlier不敏感;
  · 缺点:
  计算复杂性高;空间复杂性高;需要大量的内存
  样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
  一般数值很大的时候不用这个,计算量太大。但是单个样本又不能太少,否则容易发生误分。
  最大的缺点是无法给出数据的内在含义。
 
需要思考的问题:
样本属性如何选择?如何计算两个对象间距离?当样本各属性的类型和尺度不同时如何处理?各属性不同重要程度如何处理?模型的好坏如何评估?

二、代码实现

K近邻算法的一般流程:收集数据- 准备数据- 分析数据- 测试算法- 使用算法

2.1 python3代码实现

2.1.1
首先以电影分类为例,了解kNN工作流程。主要包括创建数据,迭代计算两点公式。代码如下
# -*- coding: UTF-8 -*-
import numpy as np
import operator
import collections

"""
函数说明:创建数据集

Parameters:
    无
Returns:
    group - 数据集
    labels - 分类标签

"""
def createDataSet():
    #四组二维特征
    group = np.array([[1,101],[5,89],[108,5],[115,8]])
    #四组特征的标签
    labels = ['爱情片','爱情片','动作片','动作片']
    return group, labels

"""
函数说明:kNN算法,分类器

Parameters:
    inX - 用于分类的数据(测试集)
    dataSet - 用于训练的数据(训练集)
    labes - 分类标签
    k - kNN算法参数,选择距离最小的k个点
Returns:
    sortedClassCount[0][0] - 分类结果

"""
def classify0(inx, dataset, labels, k):
    # 计算距离
    dist = np.sum((inx - dataset)**2, axis=1)**0.5
    # k个最近的标签
    k_labels = [labels[index] for index in dist.argsort()[0 : k]]
    # 出现次数最多的标签即为最终类别
    label = collections.Counter(k_labels).most_common(1)[0][0]
    return label

if __name__ == '__main__':
    #创建数据集
    group, labels = createDataSet()
    #测试集
    test = [101,20]
    #kNN分类
    test_class = classify0(test, group, labels, 3)
    #打印分类结果
    print(test_class)
View Code
2.1.2
以K近邻算法实现约会网站配对效果判定。
  1)下载数据集 datingTestSet.txt
  2)准备数据:数据解析
      将数据分为特征矩阵和对应的分类标签矩阵。
# -*- coding: UTF-8 -*-
import numpy as np
"""
函数说明:打开并解析文件,对数据进行分类:1代表不喜欢,2代表魅力一般,3代表极具魅力

Parameters:
    filename - 文件名
Returns:
    returnMat - 特征矩阵
    classLabelVector - 分类Label向量

"""
def file2matrix(filename):
    #打开文件
    fr = open(filename)
    #读取文件所有内容
    arrayOLines = fr.readlines()
    #得到文件行数
    numberOfLines = len(arrayOLines)
    #返回的NumPy矩阵,解析完成的数据:numberOfLines行,3列
    returnMat = np.zeros((numberOfLines,3))
    #返回的分类标签向量
    classLabelVector = []
    #行的索引值
    index = 0
    for line in arrayOLines:
        #s.strip(rm),当rm空时,默认删除空白符(包括'\n','\r','\t',' ')
        line = line.strip()
        #使用s.split(str="",num=string,cout(str))将字符串根据'\t'分隔符进行切片。
        listFromLine = line.split('\t')
        #将数据前三列提取出来,存放到returnMat的NumPy矩阵中,也就是特征矩阵
        returnMat[index,:] = listFromLine[0:3]
        #根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
        if listFromLine[-1] == 'didntLike':
            classLabelVector.append(1)
        elif listFromLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        elif listFromLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        index += 1
    return returnMat, classLabelVector

"""
函数说明:main函数
Parameters:
    无
Returns:
    无
"""
if __name__ == '__main__':
    #打开的文件名
    filename = "datingTestSet.txt"
    #打开并处理数据
    datingDataMat, datingLabels = file2matrix(filename)
    print(datingDataMat)
    print(datingLabels)
View Code

相关文章:

  • 2022-01-01
  • 2022-12-23
  • 2021-08-05
  • 2021-08-22
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-10
猜你喜欢
  • 2021-07-05
  • 2021-12-06
  • 2022-01-12
  • 2021-07-21
  • 2021-06-28
  • 2022-12-23
  • 2022-01-13
相关资源
相似解决方案