【R语言实战】——kNN和朴素贝叶斯方法实战

简介: 【R语言实战】——kNN和朴素贝叶斯方法实战

该篇文章主要针对葡萄酒数据,分别采用KNN和朴素贝叶斯算法实现葡萄酒品种的多分类预测,其中涉及数据集的描述性统计、标准化处理、训练集测试集的随机划分,模型效果评估,特征主成分提取,预测效果可视化等内容。

1问题背景

  对于葡萄酒数据(wine.csv),请分别使用kNN和朴素贝叶斯方法构建分类器来预测第1列中给出的品种。在50%数据的随机子集上训练分类器。然后预测其余50%数据的品种,并将其绘制在二维空间中(使用不同的pch),同时评估分类器效果。

2 整体步骤

  1.加载实验所需的相关包,并读取数据文件;2.对原始数据的数据类型,数据指标情况进行探索;3.创建标准化函数,对解释变量进行标准化,并通过设置随机种子的方式,将数据集随机划分为训练集、测试集分别约占50%的两个数据集;4.分别通过训练集数据训练KNN和朴素贝叶斯模型,然后将测试集预测的葡萄酒种类绘制到前两个主成分的二维空间中(使用不同的pch);5.使用准确率和混淆矩阵的结果评估分类器效果,其中KNN模型在测试集中预测准确率达到93.18%,朴素贝叶斯模型在测试集中预测准确率达到95.45%。总体上看,在葡萄酒品种预测中,朴素贝叶斯模型的表现更好。

3 操作实战

3.1 第一步——加载包并读取数据

  运行程序:

1.  #加载包  
2.  library("class")    
3.  library("caret")   
4.  library("gmodels")             
5.  #读取数据  
6.  data<- read.csv("D:\\研\\机器学习与R语言\\wine.csv",header = T)

3.2 第二步——探索和准备数据

  1)使用str()发现,该数据集共有178个观测值,14个特征(变量),同时,其涉及的数据类型有整型(int)和数值型(num),其中“cultivars”为目标变量。

> str(data)                              #查看数据类型
'data.frame': 178 obs. of  14 variables:
 $ cultivars                   : int  1 1 1 1 1 1 1 1 1 1 ...
 $ Alcohol                     : num  14.2 13.2 13.2 14.4 13.2 ...
 $ Malic.acid                  : num  1.71 1.78 2.36 1.95 2.59 1.76 1.87 2.15 1.64 1.35 ...
 $ Ash                         : num  2.43 2.14 2.67 2.5 2.87 2.45 2.45 2.61 2.17 2.27 ...
 $ Alcalinity.of.ash.          : num  15.6 11.2 18.6 16.8 21 15.2 14.6 17.6 14 16 ...
  $ Magnesium                   : int  127 100 101 113 118 112 96 121 97 98 ...
 $ Total.phenols               : num  2.8 2.65 2.8 3.85 2.8 3.27 2.5 2.6 2.8 2.98 ...
 $ Flavanoids                  : num  3.06 2.76 3.24 3.49 2.69 3.39 2.52 2.51 2.98 3.15 ...
 $ Nonflavanoid.phenols        : num  0.28 0.26 0.3 0.24 0.39 0.34 0.3 0.31 0.29 0.22 ...
 $ Proanthocyanins             : num  2.29 1.28 2.81 2.18 1.82 1.97 1.98 1.25 1.98 1.85 ...
 $ Color.intensity             : num  5.64 4.38 5.68 7.8 4.32 6.75 5.25 5.05 5.2 7.22 ...
 $ Hue                         : num  1.04 1.05 1.03 0.86 1.04 1.05 1.02 1.06 1.08 1.01 ...
 $ OD280.OD315.of.diluted.wines: num  3.92 3.4 3.17 3.45 2.93 2.85 3.58 3.58 2.85 3.55 ...
 $ Proline                     : int  1065 1050 1185 1480 735 1450 1290 1295 1045 1045 ...

  2)使用table()函数输出数据集葡萄酒品种情况,发现,该数据集中,葡萄酒品种共有三种,数据量分别为59,71,48。

> table(data$cultivars)
 1  2  3 
59 71 48

  3)使用factor()将目标属性(葡萄酒品种)编码为因子类型。

> data$cultivars<-factor(data$cultivars,levels=c('1','2','3'),
+                        labels=c('第一类','第二类','第三类'))
> 
> str(data$cultivars)
 Factor w/ 3 levels "第一类","第二类",..: 1 1 1 1 1 1 1 1 1 1 ...

  4)查看不同葡萄酒品种占数据集比例,三种品种比例分别为33.1%,39.9%,27.0%。

> round(prop.table(table(data$cultivars))*100,digits = 1)
第一类 第二类 第三类 
  33.1   39.9   27.0

  5)利用summary()查看各特征数据情况,见下图,包括每个特征的最小值,1/4分位数,中位数,均值,3/4分位数,最大值。由于KNN的距离计算很大程度上依赖输入特征的测量尺度,特征“Proline”的值范围为278~1680。可能导致后续分类存在问题,所以,应用min-max将这些特征进行标准化,将其调整到一个标准范围内。

> summary(data[c('Alcohol','Malic.acid','Ash','Alcalinity.of.ash.',
+                'Magnesium','Total.phenols','Flavanoids','Nonflavanoid.phenols',
+                'Proanthocyanins','Color.intensity','Hue','OD280.OD315.of.diluted.wines',
+                'Proline')])
    Alcohol        Malic.acid         Ash        Alcalinity.of.ash.
 Min.   :11.03   Min.   :0.740   Min.   :1.360   Min.   :10.60     
 1st Qu.:12.36   1st Qu.:1.603   1st Qu.:2.210   1st Qu.:17.20     
 Median :13.05   Median :1.865   Median :2.360   Median :19.50     
 Mean   :13.00   Mean   :2.336   Mean   :2.367   Mean   :19.49     
 3rd Qu.:13.68   3rd Qu.:3.083   3rd Qu.:2.558   3rd Qu.:21.50     
 Max.   :14.83   Max.   :5.800   Max.   :3.230   Max.   :30.00     
   Magnesium      Total.phenols     Flavanoids    Nonflavanoid.phenols
 Min.   : 70.00   Min.   :0.980   Min.   :0.340   Min.   :0.1300      
 1st Qu.: 88.00   1st Qu.:1.742   1st Qu.:1.205   1st Qu.:0.2700      
 Median : 98.00   Median :2.355   Median :2.135   Median :0.3400      
 Mean   : 99.74   Mean   :2.295   Mean   :2.029   Mean   :0.3619      
 3rd Qu.:107.00   3rd Qu.:2.800   3rd Qu.:2.875   3rd Qu.:0.4375      
 Max.   :162.00   Max.   :3.880   Max.   :5.080   Max.   :0.6600      
 Proanthocyanins Color.intensity       Hue        
 Min.   :0.410   Min.   : 1.280   Min.   :0.4800  
 1st Qu.:1.250   1st Qu.: 3.220   1st Qu.:0.7825  
 Median :1.555   Median : 4.690   Median :0.9650  
 Mean   :1.591   Mean   : 5.058   Mean   :0.9574  
 3rd Qu.:1.950   3rd Qu.: 6.200   3rd Qu.:1.1200  
 Max.   :3.580   Max.   :13.000   Max.   :1.7100  
 OD280.OD315.of.diluted.wines    Proline      
 Min.   :1.270                Min.   : 278.0  
 1st Qu.:1.938                1st Qu.: 500.5  
 Median :2.780                Median : 673.5  
 Mean   :2.612                Mean   : 746.9  
 3rd Qu.:3.170                3rd Qu.: 985.0  
 Max.   :4.000                Max.   :1680.0

  6)创建normalize函数,并利用lapply()将葡萄酒的各特征进行标准化处理,代码如下:

1.  normalize<-function(x){  
2.    return ((x-min(x))/(max(x)-min(x)))  
3.  }  
4.  features<-as.data.frame(lapply(data[2:14],normalize))

  7)随机化创建训练集和测试集。通过seed()设置随机种子,利sample()随机的从1~178的整数序列中选一般的值构成一个整数向量,通过使用该向量将数据集分割为50%的训练集和50%的测试数据集。同时,查看训练集和测试集数据的分割情况,发现两个数据集各葡萄酒类别占比相似,可以建立模型进行训练预测。

  运行程序:

1.  # 将数据集划分为训练集和测试集    
2.  set.seed(123) # 设置随机种子以确保结果的可重复性    
3.  trainIndex <- sample(178,178/2)    
4.  data_train<-features[trainingIndex,]             #创建训练集    
5.  data_test<-features[-trainingIndex,]             #创建测试集    
6.  data_train_lables<-data[trainingIndex,1]         #存储因子向量型训练集类签    
7.  data_test_lables<-data[-trainingIndex,1]         #存储因子向量型测试集类标签

  运行结果:

> round(prop.table(table(data_train_lables))*100,digits = 1)
data_train_lables
第一类 第二类 第三类 
  33.3   40.0   26.7 
> round(prop.table(table(data_test_lables))*100,digits = 1)
data_test_lables
第一类 第二类 第三类 
  33.0   39.8   27.3

3.3 第三步——基于数据训练模型KNN模型并进行模型效果评估

  1)使用knn()函数对测试数据进行分类,初始值k设置为3,函数knn()返回一个因子向量,为测试集中每一个案例返回一个预测标签,将其命名为data_test_pred。

  运行程序:

1.  ##KNN分类器  
2.  # 使用kNN构建分类器    
3.  data_test_pred<-knn(train = data_train,test = data_test,cl<-data_train_lables,k=3)

  2)首先利用prcomp()提取所有解释变量的前两个主成分,将其分别作为葡萄酒预测类型的X轴和Y轴进行可视化。从下图可以看出三种类别的葡萄酒数据位置存在明显的聚集现象,说明同一类别数据具有较高相似性。

  运行程序:

1.  ##预测结果绘图:KNN模型  
2.  # 选择前两个主成分进行绘图  
3.  pca_results <- prcomp(data_test, scale = F)  
4.  plot_features <- pca_results$x[, 1:2]  
5.  plot_data <- data.frame(plot_features, Actual =data_test_lables, Predicted_kNN =data_test_pred, Predicted_GNB=nb_pred)  
6.  ggplot(plot_data, aes(x = plot_data[, 1], y = plot_data[, 2], color = Predicted_kNN, shape = Predicted_kNN)) +    
7.    geom_point(size = 3, alpha = 0.6) +    
8.    scale_color_manual(values = c("red", "blue", "green")) + # 假设有三个品种,使用不同颜色    
9.    scale_shape_manual(values = c(1, 2, 3)) + # 使用默认的三种形状,并设置图例标题    
10.   labs(title = "kNN Predictions on Test Set", x = "Feature 1", y = "Feature 2") + # 删除color参数,因为我们在scale_shape_manual中设置了name    
11.   theme_minimal()

  运行结果:

  3)使用正确率和混淆矩阵评估模型优劣。根据计算KNN模型预测结果发现,在测试集中,模型预测准确率达到93.18%。具体结果如下:

> cat("kNN Accuracy:", knn_accuracy, "\n")  
kNN Accuracy: 0.9318182 
> #混淆矩阵
> CrossTable(x=data_test_lables,y=data_test_pred,prop.chisq = F)
 
   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|
 
Total Observations in Table:  88 
 
                 | data_test_pred 
data_test_lables |    第一类 |    第二类 |    第三类 | Row Total | 
--------------|-----------|-----------|-----------|-----------|
          第一类 |        29 |         0 |         0 |        29 | 
                 |     1.000 |     0.000 |     0.000 |     0.330 | 
                 |     0.967 |     0.000 |     0.000 |           | 
                 |     0.330 |     0.000 |     0.000 |           | 
-----------------|-----------|-----------|-----------|-----------|
          第二类 |         1 |        30 |         4 |        35 | 
                 |     0.029 |     0.857 |     0.114 |     0.398 | 
                 |     0.033 |     0.968 |     0.148 |           | 
                 |     0.011 |     0.341 |     0.045 |           | 
-----------------|-----------|-----------|-----------|-----------|
          第三类 |         0 |         1 |        23 |        24 | 
                 |     0.000 |     0.042 |     0.958 |     0.273 | 
                 |     0.000 |     0.032 |     0.852 |           | 
                 |     0.000 |     0.011 |     0.261 |           | 
-----------------|-----------|-----------|-----------|-----------|
    Column Total |        30 |        31 |        27 |        88 | 
                 |     0.341 |     0.352 |     0.307 |           | 
-----------------|-----------|-----------|-----------|-----------|

  通过KNN模型预测效果的混淆矩阵,发现,第一类葡萄酒完全预测正确,第二类葡萄酒有一个被预测为第一类,4个被预测为第三类,有一个被预测为第一类,第三类葡萄酒有1个被预测为第二类,总体预测效果良好。

3.4 第四步——基于数据训练模型朴素贝叶斯模型并进行模型效果评估

  1)使用naiveBayes()函数训练数据,将模型保存到nb_model,并使用predict将预测结果保存到nb_pred。

  运行程序:

1.  ##朴素贝叶斯分类器  
2.  nb_model <- naiveBayes(data_train, data_train_lables)    
3.  nb_pred <- predict(nb_model, data_test)

  2)将朴素贝叶斯预测结果,绘制到二维平面发现,各类别葡萄酒分类效果明显。

  运行程序:

1.  ggplot(plot_data, aes(x = plot_data[, 1], y = plot_data[, 2], color = Predicted_GNB, shape = Predicted_GNB)) +    
2.    geom_point(size = 3, alpha = 0.6) +    
3.    scale_color_manual(values = c("red", "blue", "green")) + # 假设有三个品种,使用不同颜色    
4.    scale_shape_manual(values = c(1, 2, 3)) + # 使用默认的三种形状,并设置图例标题    
5.    labs(title = "kNN Predictions on Test Set", x = "Feature 1", y = "Feature 2") + # 删除color参数,因为我们在scale_shape_manual中设置了name    
6.    theme_minimal()

  运行结果:

  3)使用正确率和混淆矩阵评估模型优劣。根据计算朴素贝叶斯模型预测结果发现,在测试集中,模型预测准确率达到95.45%。具体结果如下:

> # 评估朴素贝叶斯分类器  
> nb_confusion_matrix <- table(data_test_lables, nb_pred)  
> nb_accuracy <- sum(diag(nb_confusion_matrix)) / sum(nb_confusion_matrix)  
> cat("Naive Bayes Accuracy:", nb_accuracy, "\n")
Naive Bayes Accuracy: 0.9545455 
> 
> ##评估分类器:朴素贝叶斯
> ##混淆矩阵
> CrossTable(x=nb_pred,y=data_test_pred,prop.chisq = F) 
 
   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|
 
Total Observations in Table:  88 
 
             | data_test_pred 
     nb_pred |    第一类 |    第二类 |    第三类 | Row Total | 
-------------|-----------|-----------|-----------|-----------|
      第一类 |        30 |         1 |         0 |        31 | 
             |     0.968 |     0.032 |     0.000 |     0.352 | 
             |     1.000 |     0.032 |     0.000 |           | 
             |     0.341 |     0.011 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|
      第二类 |         0 |        28 |         3 |        31 | 
             |     0.000 |     0.903 |     0.097 |     0.352 | 
             |     0.000 |     0.903 |     0.111 |           | 
             |     0.000 |     0.318 |     0.034 |           | 
-------------|-----------|-----------|-----------|-----------|
      第三类 |         0 |         2 |        24 |        26 | 
             |     0.000 |     0.077 |     0.923 |     0.295 | 
             |     0.000 |     0.065 |     0.889 |           | 
             |     0.000 |     0.023 |     0.273 |           | 
-------------|-----------|-----------|-----------|-----------|
Column Total |        30 |        31 |        27 |        88 | 
             |     0.341 |     0.352 |     0.307 |           | 
-------------|-----------|-----------|-----------|-----------|

  通过朴素贝叶斯模型预测效果的混淆矩阵,发现,第一类葡萄酒有一个被预测为第二类,第二类葡萄酒有3个被预测为第三类,第三类葡萄酒有两个被预测为第2类,总体预测效果良好。

4 完整代码

1.  #加载包  
2.  library("class")    
3.  library("caret")   
4.  library("gmodels")             
5.  #读取数据  
6.  data<- read.csv("D:\\研\\机器学习与R语言\\wine.csv",header = T)  
7.  str(data)                       #查看数据类型  
8.    
9.  table(data$cultivars)           #查看葡萄酒品种情况  
10.   
11. data$cultivars<-factor(data$cultivars,levels=c('1','2','3'),  
12.                        labels=c('第一类','第二类','第三类'))  
13.   
14. str(data$cultivars)  
15.   
16. round(prop.table(table(data$cultivars))*100,digits = 1)  
17. colnames(data)  
18. summary(data[c('Alcohol','Malic.acid','Ash','Alcalinity.of.ash.',  
19.                'Magnesium','Total.phenols','Flavanoids','Nonflavanoid.phenols',  
20.                'Proanthocyanins','Color.intensity','Hue','OD280.OD315.of.diluted.wines',  
21.                'Proline')])  
22.   
23. normalize<-function(x){  
24.   return ((x-min(x))/(max(x)-min(x)))  
25. }  
26. features<-as.data.frame(lapply(data[2:14],normalize))  
27.   
28.   
29.   
30. # 将数据集划分为训练集和测试集    
31. set.seed(123) # 设置随机种子以确保结果的可重复性    
32. trainIndex <- sample(178,178/2)    
33. data_train<-features[trainingIndex,]                    #创建训练集    
34. data_test<-features[-trainingIndex,]              #创建测试集    
35. data_train_lables<-data[trainingIndex,1]              #存储因子向量型训练集类标签    
36. data_test_lables<-data[-trainingIndex,1]              #存储因子向量型测试集类标签     
37.   
38. ##查看分割情况  
39. round(prop.table(table(data_train_lables))*100,digits = 1)  
40. round(prop.table(table(data_test_lables))*100,digits = 1)  
41.   
42.   
43. ##KNN分类器  
44. # 使用kNN构建分类器    
45. data_test_pred<-knn(train = data_train,test = data_test,cl<-data_train_lables,k=3)  
46.   
47. ##朴素贝叶斯分类器  
48. nb_model <- naiveBayes(data_train, data_train_lables)    
49. nb_pred <- predict(nb_model, data_test)  
50.   
51. ##预测结果绘图:KNN模型  
52. # 选择前两个主成分进行绘图  
53. pca_results <- prcomp(data_test, scale = F)  
54. plot_features <- pca_results$x[, 1:2]  
55. plot_data <- data.frame(plot_features, Actual =data_test_lables, Predicted_kNN =data_test_pred, Predicted_GNB=nb_pred)  
56. ggplot(plot_data, aes(x = plot_data[, 1], y = plot_data[, 2], color = Predicted_kNN, shape = Predicted_kNN)) +    
57.   geom_point(size = 3, alpha = 0.6) +    
58.   scale_color_manual(values = c("red", "blue", "green")) + # 假设有三个品种,使用不同颜色    
59.   scale_shape_manual(values = c(1, 2, 3)) + # 使用默认的三种形状,并设置图例标题    
60.   labs(title = "kNN Predictions on Test Set", x = "Feature 1", y = "Feature 2") + # 删除color参数,因为我们在scale_shape_manual中设置了name    
61.   theme_minimal()  
62.   
63.   
64. ##评估分类器:KNN  
65. # 评估kNN分类器    
66. knn_confusion_matrix <- table(data_test_lables, data_test_pred)    
67. knn_accuracy <- sum(diag(knn_confusion_matrix)) / sum(knn_confusion_matrix)    
68. cat("kNN Accuracy:", knn_accuracy, "\n")    
69. #混淆矩阵  
70. CrossTable(x=data_test_lables,y=data_test_pred,prop.chisq = F)   
71.   
72.   
73.   
74.   
75. ggplot(plot_data, aes(x = plot_data[, 1], y = plot_data[, 2], color = Predicted_GNB, shape = Predicted_GNB)) +    
76.   geom_point(size = 3, alpha = 0.6) +    
77.   scale_color_manual(values = c("red", "blue", "green")) + # 假设有三个品种,使用不同颜色    
78.   scale_shape_manual(values = c(1, 2, 3)) + # 使用默认的三种形状,并设置图例标题    
79.   labs(title = "kNN Predictions on Test Set", x = "Feature 1", y = "Feature 2") + # 删除color参数,因为我们在scale_shape_manual中设置了name    
80.   theme_minimal()


相关文章
【R语言实战】——带有高斯新息的金融时序的GARCH模型拟合预测及VAR/ES风险度量
【R语言实战】——带有高斯新息的金融时序的GARCH模型拟合预测及VAR/ES风险度量
|
7月前
|
数据可视化 数据挖掘 API
【R语言实战】聚类分析及可视化
【R语言实战】聚类分析及可视化
【R语言实战】——带有新息为标准学生t分布的金融时序的GARCH模型拟合预测
【R语言实战】——带有新息为标准学生t分布的金融时序的GARCH模型拟合预测
|
7月前
|
数据可视化
【R语言实战】——金融时序分布拟合
【R语言实战】——金融时序分布拟合
|
7月前
|
机器学习/深度学习 存储 算法
用kNN算法诊断乳腺癌--基于R语言
用kNN算法诊断乳腺癌--基于R语言
【R语言实战】——fGARCH包在金融时序上的模拟应用
【R语言实战】——fGARCH包在金融时序上的模拟应用
|
3月前
|
机器学习/深度学习 算法 数据挖掘
R语言中的支持向量机(SVM)与K最近邻(KNN)算法实现与应用
【9月更文挑战第2天】无论是支持向量机还是K最近邻算法,都是机器学习中非常重要的分类算法。它们在R语言中的实现相对简单,但各有其优缺点和适用场景。在实际应用中,应根据数据的特性、任务的需求以及计算资源的限制来选择合适的算法。通过不断地实践和探索,我们可以更好地掌握这些算法并应用到实际的数据分析和机器学习任务中。
|
4月前
|
机器学习/深度学习 数据采集
R语言逻辑回归、GAM、LDA、KNN、PCA主成分分类分析预测房价及交叉验证
上述介绍仅为简要概述,每个模型在实施时都需要仔细调整与优化。为了实现高度精确的预测,模型选择与调参是至关重要的步骤,并且交叉验证是提升模型稳健性的有效途径。在真实世界的房价预测问题中,可能还需要结合地域经济、市场趋势等宏观因素进行综合分析。
91 3
|
7月前
|
数据采集 数据可视化
利用R语言进行因子分析实战(数据+代码+可视化+详细分析)
利用R语言进行因子分析实战(数据+代码+可视化+详细分析)
利用R语言进行典型相关分析实战
利用R语言进行典型相关分析实战