• 『原创』机器学习算法的R语言实现(一):KNN


    KNN是有监督的学习算法,其特点有:

    1、精度高,对异常值不敏感
    2、只能处理数值型属性
    3、计算复杂度高(如已知分类的样本数为n,那么对每个未知分类点要计算n个距离)
     
    KNN算法步骤:
    需对所有样本点(已知分类+未知分类)进行归一化处理。
    然后,对未知分类的数据集中的每个样本点依次执行以下操作:
    1、计算已知类别数据集中的点与当前点(未知分类)的距离。
    2、按照距离递增排序
    3、选取与当前距离最小的k个点
    4、确定前k个点所在类别的出现频率
    5、返回前k个点出现频率最高的类别作为当前点的预测类别
     

    机器学习算法R实现-KNN

    # 选择iris数据集为例,iris共有150条数据,内容如下head(iris)
    ##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    ## 1          5.1         3.5          1.4         0.2  setosa
    ## 2          4.9         3.0          1.4         0.2  setosa
    ## 3          4.7         3.2          1.3         0.2  setosa
    ## 4          4.6         3.1          1.5         0.2  setosa
    ## 5          5.0         3.6          1.4         0.2  setosa
    ## 6          5.4         3.9          1.7         0.4  setosa
    ## Sepal.LengthSepal.WidthPetal.LengthPetal.Width为分类的四个维度,Species为分类结果# 1、对iris进行归一化处理,scale归一化的公式为(x-mean(x))/sqrt(var(x))iris_s <- data.frame(scale(iris[, 1:4]))iris_s <- cbind(iris_s, iris[, 5])names(iris_s)[5] = "Species"# 1、对iris数据集随机选择其中的100条记录作为已知分类的样本集sample.list <- sample(1:150, size = 100)iris.known <- iris_s[sample.list, ]# 2、剩余50条记录作为未知分类的样本集(测试集)iris.unknown <- iris_s[-sample.list, ]## 3、对测试集中的每一个样本,计算其与已知样本的距离,因为已经归一化,此处直接使用欧氏距离length.known <- nrow(iris.known)length.unknown <- nrow(iris.unknown)
     
     
    for (i in 1:length.unknown) {   # dis 记录与每个已知分类样本的距离及改样本的分类   dis_to_known <- data.frame(dis = rep(0, length.known))   for (j in 1:length.known) {       # 计算距离       dis_to_known[j, 1] <- dist(rbind(iris.unknown[i, 1:4], iris.known[j,1:4]), method = "euclidean")       # 保存已知样本的分类       dis_to_known[j, 2] <- iris.known[j, 5] names(dis_to_known)[2] = "Species"   }
     
     
      # 按距离从小到大排序   dis_to_known <- dis_to_known[order(dis_to_known$dis), ]
     
     
      # Knn中的K,定义了具体最近的K个已知分类的样本   k <- 5   # 按因子进行计数   type_freq <- as.data.frame(table(dis_to_known[1:k, ]$Species))   # 按计数值进行排序   type_freq <- type_freq[order(-type_freq$Freq), ]
       # 记录频数最大的类型        iris.unknown[i, 6] <- type_freq[1, 1]
    }
     
    names(iris.unknown)[6] = "Species.pre"
    # 输出分类结果
     iris.unknown[, 5:6]
     
    ##        Species Species.pre
    ## 3       setosa      setosa
    ## 4       setosa      setosa
    ## 5       setosa      setosa
    ## 7       setosa      setosa
    ## 15      setosa      setosa
    ## 20      setosa      setosa
    ## 21      setosa      setosa
    ## 30      setosa      setosa
    ## 33      setosa      setosa
    ## 35      setosa      setosa
    ## 36      setosa      setosa
    ## 38      setosa      setosa
    ## 40      setosa      setosa
    ## 41      setosa      setosa
    ## 49      setosa      setosa
    ## 51  versicolor  versicolor
    ## 54  versicolor  versicolor
    ## 56  versicolor  versicolor
    ## 57  versicolor  versicolor
    ## 59  versicolor  versicolor
    ## 63  versicolor  versicolor
    ## 70  versicolor  versicolor
    ## 74  versicolor  versicolor
    ## 75  versicolor  versicolor
    ## 78  versicolor  versicolor
    ## 80  versicolor  versicolor
    ## 87  versicolor  versicolor
    ## 89  versicolor  versicolor
    ## 95  versicolor  versicolor
    ## 96  versicolor  versicolor
    ## 98  versicolor  versicolor
    ## 100 versicolor  versicolor
    ## 103  virginica   virginica
    ## 108  virginica   virginica
    ## 112  virginica   virginica
    ## 115  virginica   virginica
    ## 117  virginica   virginica
    ## 119  virginica   virginica
    ## 122  virginica   virginica
    ## 124  virginica  versicolor
    ## 127  virginica   virginica
    ## 129  virginica   virginica
    ## 130  virginica   virginica
    ## 131  virginica   virginica
    ## 132  virginica   virginica
    ## 134  virginica  versicolor
    ## 142  virginica   virginica
    ## 144  virginica   virginica
    ## 148  virginica   virginica
    ## 149  virginica   virginica

    上面结果中,Species为样本实际分类,Species.pre为Knn算法的分类。经过多次实验,50个样本中,有5个左右样本的分类判断错误,正确率在90%。可见Knn算法效果较好,原理容易理解。

    Knn算法存在的问题:
    1、k值的确定是个难题。
    2、如果距离最近的k个已知分类样本中,频数最高的类型有多个(频数相同),如何选择对未知样本的分类?目前看是随机的。
    3、如果有n个未知类型样本,m个已知类型样本,则需要计算n*m个距离,计算量较大,且需存储全部数据集合,空间复杂度也较大。 4、能否把预测的样本分类加入到已知类别集合中,对剩余的未知类型样本进行分类? 5、归一化放在所有处理的最前面,这样需要知道全部的样本集合(已知分类+未知分类)来构建分类器,而实际上未知分类的样本并不一定能事先获得,这样如何进行归一化处理?





  • 相关阅读:
    活动安排问题
    完美字符串
    Codeforces Round #696 (Div. 2) 解题报告
    Codeforces 1459D
    Codeforces 25D
    POJ 1847
    LightOJ 1074
    POJ 3159
    POJ 1511
    POJ 1502
  • 原文地址:https://www.cnblogs.com/digging4/p/3757421.html
Copyright © 2020-2023  润新知