kNN算法及案例分析
kNN算法应用于iris数据集
#选择iris数据集为例,iris共有150条1数据
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 ()函数可以计算所有预测变最两两之间相关系数的矩阵。
解释:相关的是 Year和Volume ,通过画图可以观察到 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) #结果略有改观