数据挖掘在实践中的应用
使用随机森林首先应该从数据中提炼训练集Train和测试集Test两部分。训练集和测试集是不能有交集的,即。训练集和测试集中的数据是从原始数据中提炼出来的。训练集和测试集的维度必须相等。主要是因为随机森林是分类问题。分类问题,就是将测试集中数据一个一个的扔进分类器,分类器给出一个结果,作为输出,这个输出的数就是分类的类别。那么分类器是怎么运作的呢?分类器是,对测试集中的属性一个一个的计算出它的概率,然后计算出它的总的概率。之后对概率进行排序,最大概率的类别就是该分类器分出的类别,即预测类别。预测类别与真是类别进行对比,预测正确的除以总的测试集就是它的正确率。
但是实际中往往不会那么容易的得出结果。因为结果的好坏跟很多很多的因素有关系,例如:分类器的好坏、样本的好坏等等。
分类器的选取是很关键的一步。开始的时候可以从前人的基础上来进行研究,这样往往前人总结了各个分类器的好坏,你基本上就不用动脑筋了。但是你是开始接触这项工程的时候就需要自己进行选取了。下面我给出一个简单的例子:Iris的分类中,分类器的选取就很重要,使用贝叶斯分类的时候比k-近邻分类的时候就差别较大。贝叶斯分类的结果开始的时候比k-近邻的分类的结果要差,但是随着测试样本的增加贝叶斯的优势开始增加。这就要求我们在实际的情况进行考虑了。
下面是贝叶斯算法的流程图:
下面是k-近邻分类算法的流程图
样本的好坏是很关键的一步。例如:一个特征是10000,而一个特征是0.1,这样的数据就不能够简单的使用原始数据进行计算了。如果这样计算的话,特征值为0.1的数据,它对该类别的反应的程度就基本等于0了。所以这个时候就要使用归一化了。归一化只是处理数据的一个方面,还有就是对数据进行挑选,因为有些样本自身就有问题,所以要对数据进行挑选。
处理鸢尾花数据的总结:
实验过程中遇到的问题
数据的处理
在实现算法的过程,遇到首先遇到的问题就是文本的读写。由于所给的数据集是.data数据集,而我经常使用的.txt文件,所以就将数据集转化成.txt数据。为了好读取数据集,我将训练集和测试集分开了。例如训练集120个数据,测试集30个数据。我的数据的排布是前面120个数据是训练集数据,而后面30个数据为测试集数据。但是这种排布有一种坏处,就是在进行不同的训练集和测试集进行分析的时候就会发现,要使用手动的进行分割训练集和测试集,很麻烦。因为时间的原因没有进行改进。
贝叶斯算法的实现过程
由于老师在课堂上和课件里面都没有连续型的数据的贝叶斯的处理方法,我就在网上查到用分布函数用来算概率,而其中最常见的函数为正态分布函数,使用它作为Iris数据集的分布函数是因为Iris数据集的几个属性他们比较集中,这也比较符合正态分布函数的性质。它主要就是求均值和方差,所以我就写了两个函数Mean_Set()和Variance_Set(),分别来求均值和方差。之后使用正态分布函数的公式代进去。之后出现了概率数值过大的情况,之后才发现自己求方差的时候,使用的是方差代进去,其实应该使用标准差代进去。开始的时候计算的概率只有80%,之后将数值从double转化成int型就行了。
KNN算法的实现过程
KNN算法,老师在课堂上没有仔细的介绍。它的一些资料,我是从网上看到的,主要的是计算数据的平方和,之后比较最小的平方和。在实现这个算法的过程中比较顺利。主要是一些循环在运行的时候出现了一些问题,调试了一下就好了。
两个算法的对比
贝叶斯算法
贝叶斯算法的稳定性比较好,它的概率比较稳,在测试集比较少的时候也能够有比较好的结果,主要是因为正态函数的稳定性比较好。
KNN算法
KNN算法,在测试集比较少的时候,概率很高,一旦训练集的数据比较少的时候,概率下降的比较快,主要是KNN算法计算的是平方和,他对数据的要求比贝叶斯的要求要高。
结论
在学习数据挖掘这门课的过程中,最大的收获就是有最后的大作业。它不仅锻炼了我们的编程能力,而且让我们对数据挖掘有了新的认识,而不仅仅只是书本上的知识。在写大作业的过程中,学习了贝叶斯算法和KNN算法以及其他的分类算法,使得我对分类的过程有了新的认识,分类的过程就是使用已有的数学知识,将数据整合在一块,使得相同类的数据聚合在一块,使得最后做预测的时候比较方便。
实验代码:
//贝叶斯分类
double Mean[3][4] = { 0 };
double variance[3][4] = { 0 };
void Naive_Bayes_Classification_clear_zero() {
for (int i = 0;i < 3;i++) {
for (int j = 0;j < 4;j++) {
Mean[i][j] = 0;
variance[i][j] = 0;
}
}
}
void Mean_Set() {
int row = 0;
for (int i = 0;i < Train_number;i++) {
for (int j = 0;j < 4;j++) {
if (i < (Train_number / 3)) {
Mean[row][j] += Train_Data[i][j];
}
else if (i < (2 * Train_number / 3)) {
Mean[row][j] += Train_Data[i][j];
}
else {
Mean[row][j] += Train_Data[i][j];
}
}
if (i == (Train_number / 3 - 1))
row++;
if (i == (2 * Train_number / 3 - 1))
row++;
}
for (int i = 0;i < 3;i++) {
for (int j = 0;j < 4;j++) {
Mean[i][j] = Mean[i][j] / (Train_number / 3);
}
}
}
void Variance_Set() {
int row = 0;
for (int i = 0;i < Train_number;i++) {
for (int j = 0;j < 4;j++) {
if (i < (Train_number / 3)) {
variance[row][j] += pow((Train_Data[i][j] - Mean[row][j]), 2);
}
else if (i < (2 * Train_number / 3)) {
variance[row][j] += pow((Train_Data[i][j] - Mean[row][j]), 2);
}
else {
variance[row][j] += pow((Train_Data[i][j] - Mean[row][j]), 2);
}
}
if ((i == (Train_number / 3 - 1)) || (i == (2 * Train_number / 3 - 1)) || (i == (Train_number - 1))) {
for (int k = 0;k < 4;k++) {
variance[row][k] = variance[row][k] / (Train_number / 3 - 1);
}
row++;
}
}
}
double Naive_Bayes_Classification() {
Mean_Set();
Variance_Set();
double p[3] = { 1 };
double count = 0;
for (int i = 0;i < Test_number;i++) {
for (int j = 0;j < 4;j++) {
for (int row = 0;row < 3;row++) {
p[row] *= (1 / (sqrt(2 * pi*variance[row][j])))*exp(-pow(Test_Data[i][j] - Mean[row][j], 2) / (2 * variance[row][j]));
}
}
double max = 0, flag = 0;
cout << "第" << i+1 << "个数据结果:";
for (int i = 0;i < 3;i++) {
cout << p[i] << " ";
if (max < p[i]) {
max = p[i];
// cout << "max is" << max << " ";
flag = i;
// cout << "i is" << i << " ";
}
}
cout << "第" << i + 1 << "个数据结果:";
//cout << endl;
cout << "分类的结果" << flag + 1 << endl;
if (i < (Test_number / 3)) {
if (flag == 0) {
count++;
}
}
else if (i < (2 * Test_number / 3) ){
if (flag == 1) {
count++;
}
}
else {
if (flag == 2) {
count++;
}
}
p[0] = 1;
p[1] = 1;
p[2] = 1;
}
cout << "正确率为:";
Naive_Bayes_Classification_clear_zero();
return count / Test_number;
}
//k-近邻分类
double Data_sum[120][2] = { 0 };
double Max_ten_data[10][2] = { 0 };
double Max_set[3][2] = { 0 };
//k-近邻分类的清零
void K_Close_neighbor_clear_zero() {
for (int i = 0;i < Train_number;i++) {
for (int j = 0;j < 2;j++) {
Data_sum[i][j] = 0;
}
}
for (int i = 0;i < 10;i++) {
for (int j = 0;j < 2;j++) {
Max_ten_data[i][j] = 0;
}
}
for (int i = 0;i < 3;i++) {
for (int j = 0;j < 2;j++) {
Max_set[i][j] = 0;
}
}
Max_set[0][0] = 0;
Max_set[1][0] = 0;
Max_set[2][0] = 0;
}
void Sort() {
for (int j = 0;j < (Train_number - 1);j++) {
for (int k = j + 1;k < Train_number;k++) {
if (Data_sum[j][0] > Data_sum[k][0]) {
double a;
a = Data_sum[j][0];
Data_sum[j][0] = Data_sum[k][0];
Data_sum[k][0] = a;
a = Data_sum[j][1];
Data_sum[j][1] = Data_sum[k][1];
Data_sum[k][1] = a;
}
}
Max_ten_data[j][0] = Data_sum[j][0];
Max_ten_data[j][1] = Data_sum[j][1];
// cout << Max_ten_data[j][0] << " ";
if (j == 9) {
// cout << endl;
break;
}
}
}
void Output() {
for (int i = 0;i < Train_number;i++) {
for (int j = 0;j < 2;j++)
cout << Data_sum[i][j] << " ";
cout << endl;
}
}
int class_set() {
Max_set[0][1] = 1;
Max_set[1][1] = 2;
Max_set[2][1] = 3;
for (int i = 0;i < 10;i++) {
for (int j = 1;j <= 3;j++)
if (Max_ten_data[i][1] == j) {
Max_set[j - 1][0]++;
}
}
int max = 0, pre_value = 0;
for (int i = 0;i < 3;i++) {
if (max < Max_set[i][0]) {
max = Max_set[i][0];
pre_value = Max_set[i][1];
}
}
return pre_value;
}
double K_Close_neighbor_Classification() {
//10近邻
int predict_value;
double predict_count = 0;
for (int i = 0;i < Test_number;i++) {
for (int j = 0;j < Train_number;j++) {
for (int k = 0;k < 4;k++) {
Data_sum[j][0] += pow((Train_Data[j][k] - Test_Data[i][k]), 2);
}
Data_sum[j][1] = Train_Data[j][4];
}
cout << "第" << i + 1 << "个数据结果:";
Sort();
predict_value = class_set();
cout << "分类的结果:" << predict_value << endl;
if (predict_value == Test_Data[i][4])
predict_count++;
K_Close_neighbor_clear_zero();
}
return predict_count / Test_number;
}