读取数据集的操作这里不再赘述。
本文使用的数据实体类可见本人另一篇文章https://blog.csdn.net/c389003094/article/details/103082428
1、变量介绍
首先是朴素贝叶斯需要的变量定义,variances和means分别用于保存第c类实例在第i个属性上的取值的方差和均值(用于计算条件概率P(c | i))。
//实例的属性值数目
final static int INSTANCES_ATTRIBUTES_NUM = 11;
//实例类别数 3,4,5,6,7,8,9
final static int INSTANCES_CLASS_NUM = 7;
//方差
private double[][] variances = new double[INSTANCES_CLASS_NUM][INSTANCES_ATTRIBUTES_NUM];
//均值
private double[][] means = new double[INSTANCES_CLASS_NUM][INSTANCES_ATTRIBUTES_NUM];
2、求条件概率值
由于本数据集中的数据是连续性数据而非离散型数据,因此在求解条件概率是利用了正态函数求解。
/**
* 正态分布函数
* 求取条件概率值
* @param testRecordAttr 实例中的一个属性
* @param var 方差
* @param mean 均值
*/
private double getCP(double testRecordAttr, double var, double mean) {
double varSqrt = Math.sqrt(var);
double a = 1/(Math.sqrt(2*Math.PI)*varSqrt);
double x = -Math.pow((testRecordAttr - mean), 2)/(2 * var);
double b = Math.pow(Math.E, x);
return a * b;
}
3、预测函数
假设各特征独立,求解不同属性针对不同类的条件概率值,将最大的条件概率值对应的类作为当前实例的预测类返回。
这里采取的是直接将所有的实例类传入完成预测。
/**
* 预测类别并放入predictLabel中
* @param testRecords 测试数据实例集合
*/
private void predict(TestRecord[] testRecords) {
//针对每一个测试实例
for (int k = 0; k < testRecords.length; k++) {
//对于每一个类别
double[] cpDiffAttr = new double[INSTANCES_ATTRIBUTES_NUM];
double[] cpDiffClass = new double[INSTANCES_CLASS_NUM];
Arrays.fill(cpDiffAttr, 0);
Arrays.fill(cpDiffClass, 0);
for (int i = 0; i < INSTANCES_CLASS_NUM; i++) {
//不同属性针对i类的条件概率
//针对每一个属性求出条件概率
for (int j = 0; j < variances[i].length; j++) {
double var = variances[i][j];
double mean = means[i][j];
cpDiffAttr[j] = getCP(testRecords[k].attributes[j], var, mean);
}
cpDiffClass[i] = getArrayProduct(cpDiffAttr);
}
testRecords[k].predictedLabel = getMaxIndex(cpDiffClass);
}
}
PS:这里没有给出求解方差和均值的方法,原因是写的太烂了实在是没脸贴了。。刚刚开始学习机器学习算法,有些还不怎么理解,代码中存在问题可以向我留言交流。