zoukankan      html  css  js  c++  java
  • 『原创』机器学习算法的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、归一化放在所有处理的最前面,这样需要知道全部的样本集合(已知分类+未知分类)来构建分类器,而实际上未知分类的样本并不一定能事先获得,这样如何进行归一化处理?





  • 相关阅读:
    IntelliJ IDEA 14.03 java 中文文本处理中的编码格式设置
    应聘感悟
    STL string分析
    CUDA SDK VolumeRender 分析 (1)
    BSP
    CUDA SDK VolumeRender 分析 (3)
    CUDA SDK VolumeRender 分析 (2)
    Windows软件发布时遇到的一些问题
    Ten Commandments of Egoless Programming (转载)
    复习下光照知识
  • 原文地址:https://www.cnblogs.com/digging4/p/3757421.html
Copyright © 2011-2022 走看看