kNN算法及案例分析


kNN算法应用于iris数据集

#选择iris数据集为例,iris共有1501数据

head(iris)

#iris进行归一化处理,scale归一化的公式为(x-mean(x))/sqrt(var(x))

iris_s=data.frame(scale(iris[,1:4]))

iris_s<-cbind(iris_s,iris[,5])

#iris数据集随机选择其中的100条数据作为已知分类的样本集(训练集)

sample.list<-sample(1:150,size=100)

iris.known<-iris_s[sample.list,]

#剩余50条数据作为位置分类的样本集(测试集)

iris.unknown<-iris_s[-sample.list,]

#对测试集中的每个样本计算其与已知样本的距离,因为已经归一化,此处直接使用欧氏距离

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]

案例1:股票市场数据

library(ISLR)

names(Smarket)

dim(Smarket)

summary(Smarket)

pairs(Smarket) #pairs()函数用于返回一个绘图矩阵,由每个 DataFrame 对应的散点图组成。

cor(Smarket[,-9]) #cor ()函数可以计算所有预测变最两两之间相关系数的矩阵。

解释:相关的是 YearVolume ,通过画图可以观察到 Volume 随时间一直增长,也就是说从 2001 年至 2005 年平均每日股票成交盘在增长。

attach(Smarket)

plot(Volume)

library(class)

train.X=cbind(Lag1,Lag2)[train,] #包含与训练数据相关的预测变量矩阵

test.X=cbind(Lag1,Lag2)[!train,] #包含与预测数据相关的预测变量矩阵

train.Direction=Direction[train] #包含训练观测类标签的向量

set.seed(1)

knn.pred=knn(train.X,test.X,train.Direction,k=1) 

table(knn.pred,Direction.2005)

(83+43)/252

#K=1时的结果不理想,只有 50% 的观测得到正确的预测,这可能因为 K= 1的模型过于光滑,使用 K=3 重复上述实验。

knn.pred=knn(train.X,test.X,train.Direction,k=3) 

table(knn.pred,Direction.2005)

mean(knn.pred==Direction.2005) #结果略有改观

相关