【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()


相关文章
|
19天前
【R语言实战】——带有新息为标准学生t分布的金融时序的GARCH模型拟合预测
【R语言实战】——带有新息为标准学生t分布的金融时序的GARCH模型拟合预测
|
19天前
【R语言实战】——带有高斯新息的金融时序的GARCH模型拟合预测及VAR/ES风险度量
【R语言实战】——带有高斯新息的金融时序的GARCH模型拟合预测及VAR/ES风险度量
|
19天前
【R语言实战】——fGARCH包在金融时序上的模拟应用
【R语言实战】——fGARCH包在金融时序上的模拟应用
|
19天前
|
数据可视化
【R语言实战】——金融时序分布拟合
【R语言实战】——金融时序分布拟合
|
19天前
|
数据可视化 数据挖掘 API
【R语言实战】聚类分析及可视化
【R语言实战】聚类分析及可视化
|
19天前
|
机器学习/深度学习 存储 算法
用kNN算法诊断乳腺癌--基于R语言
用kNN算法诊断乳腺癌--基于R语言
|
19天前
【R语言实战】——Logistic回归模型
【R语言实战】——Logistic回归模型
|
19天前
|
数据可视化
【R语言实战】——金融时序ARIMA建模
【R语言实战】——金融时序ARIMA建模
|
19天前
|
Web App开发 数据可视化 数据挖掘
利用R语言进行聚类分析实战(数据+代码+可视化+详细分析)
利用R语言进行聚类分析实战(数据+代码+可视化+详细分析)
|
19天前
|
数据采集 数据可视化
利用R语言进行因子分析实战(数据+代码+可视化+详细分析)
利用R语言进行因子分析实战(数据+代码+可视化+详细分析)

热门文章

最新文章