日撸代码300行:第59天(数值型数据的 NB 算法)

news2024/11/18 0:20:38

代码来自闵老师”日撸 Java 三百行(51-60天)“,链接:https://blog.csdn.net/minfanphd/article/details/116975957

相较于符号型数据,数值型是将实例的概率密度带入进行概率计算。数值型数据仅需要对决策属性那里进行Laplacian平滑处理即可。

用正态分布求得概率密度在实际中最常见,公式如下:

 这里涉及两个参数: 方差\sigma 和均值\mu,可以计算出来。去掉常数,优化目标为:

 代码实现如下:

package datastructure.nb;

import java.io.FileReader;
import java.util.Arrays;

import weka.core.Instance;
import weka.core.Instances;

/**
 * ********************************************
 * The Naive Bayes algorithm.
 * 
 * @author WX873
 **********************************************
 */
public class NaiveBayes {
	
	/**
	 ************************* 
	 * An inner class to store parameters.
	 * @author WX873
	 ************************* 
	 */
	private class Gaussianparamters{
		double mu;
		double sigma;
		
		public Gaussianparamters(double paraMu, double paraSigma) {
			// TODO Auto-generated constructor stub
			mu = paraMu;
			sigma = paraSigma;
		}//of the constructor
		
		public String toString() {
			return "(" + mu + ", " + sigma + ")";
		} //of toString
	}//of Gaussianparamters
	
	/**
	 * The data.
	 */
	Instances dataset;
	
	/**
	 * The number of classes. For binary classification it is 2.
	 */
	int numClasses;
	
	/**
	 * The number of instances.
	 */
	int numInstances;
	
	/**
	 * The number of conditional attributes.
	 */
	int numConditions;
	
	/**
	 * The prediction, including queried and predicted labels.
	 */
	int[] predicts;
	
	/**
	 * Class distribution.
	 */
	double[] classDistribution;
	
	/**
	 * Class distribution with Laplacian smooth.
	 */
	double[] classDistributionLaplacian;
	
	/**
	 * To calculate the conditional probabilities for all classes over all
	 * attributes on all values.
	 */
	double[][][] conditionalCounts;
	
	/**
	 * The conditional probabilities with Laplacian smooth.
	 */
	double[][][] conditionalProbabilitiesLaplacian;
	
	/**
	 * The Guassian parameters.
	 */
	Gaussianparamters[][] gaussianparamters;
	
	/**
	 * Data type.
	 */
	int dataType;
	
	/**
	 * Nominal
	 */
	public static final int NOMINAL = 0;
	
	/**
	 * Numerical.
	 */
	public static final int NUMERICAL = 1;
	
	/**
	 * **********************************************************
	 * The first constructor.
	 * 
	 * @param paraFilename   The given file.
	 * **********************************************************
	 */
	public NaiveBayes(String paraFilename) {
		// TODO Auto-generated constructor stub
		dataset = null;
		try {
			FileReader fileReader = new FileReader(paraFilename);
			dataset = new Instances(fileReader);
			fileReader.close();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("Cannot read the file: " + paraFilename + "\r\n" + e);
			System.exit(0);
		}//of try
		
		dataset.setClassIndex(dataset.numAttributes() - 1);
		numConditions = dataset.numAttributes() - 1;
		numInstances = dataset.numInstances();
		numClasses = dataset.attribute(numConditions).numValues();
		
	}//The first constructor
	
	/**
	 * **********************************************************
	 * The second constructor.
	 * 
	 * @param paraInstances   The instance of given file.
	 * **********************************************************
	 */
	public NaiveBayes(Instances paraInstances) {
		// TODO Auto-generated constructor stub
		dataset = paraInstances;
		
		dataset.setClassIndex(dataset.numAttributes() - 1);
		numConditions = dataset.numAttributes() - 1;
		numInstances = dataset.numInstances();
		numClasses = dataset.attribute(numConditions).numValues();
	}//The second constructor
	
	/**
	 * ****************************************************
	 * Set the data type.
	 * @param paraDataType
	 * ****************************************************
	 */
	public void setDataType(int paraDataType) {
		dataType = paraDataType;
	}//of setDataType
	
	/**
	 * **************************************************************
	 * Calculate the class distribution with Laplacian smooth.
	 * **************************************************************
	 */
	public void calculateClassDistribution() {
		classDistribution = new double[numClasses];
		classDistributionLaplacian = new double[numClasses];
		
		double[] tempCounts = new double[numClasses];
		for (int i = 0; i < numInstances; i++) {
			int tempClassValue = (int)dataset.instance(i).classValue();
			tempCounts[tempClassValue]++;
		}//of for i
		
		for (int i = 0; i < numClasses; i++) {
			classDistribution[i] = tempCounts[i]/numInstances;
			classDistributionLaplacian[i] = (tempCounts[i] + 1)/(numInstances + numClasses);
		}//of for i
		
		System.out.println("Class distribution: " + Arrays.toString(classDistribution));
		System.out.println("Class distribution Laplacian: " + Arrays.toString(classDistributionLaplacian));
	}//of calculateClassDistribution
	
	/**
	 * *****************************************************
	 * Calculate the conditional probabilities with Laplacian smooth.
	 * *****************************************************
	 */
	public void calculateConditionalProbabilities() {
		conditionalCounts = new double[numClasses][numConditions][];
		conditionalProbabilitiesLaplacian = new double[numClasses][numConditions][];
		
		//Allocate space
		for (int i = 0; i < numClasses; i++) {
			for (int j = 0; j < numConditions; j++) {
				int tempNumValues = (int)dataset.attribute(j).numValues();  //总共有多少个属性就申请多少个空间
				conditionalCounts[i][j] = new double[tempNumValues];
				conditionalProbabilitiesLaplacian[i][j] = new double[tempNumValues];
			}//of for j
		}//of for i
		
		//Count the numbers of the same class and attribute. 
		int[] tempClassCounts = new int[numClasses];
		for (int i = 0; i < numClasses; i++) {
			int tempClass = (int)dataset.instance(i).classValue();
			tempClassCounts[tempClass]++;
			for (int j = 0; j < numConditions; j++) {
				int tempValue = (int)dataset.instance(i).value(j);
				conditionalCounts[tempClass][j][tempValue]++;
			}//of for j
		}//of for i
		
		//Now for the real probability with Laplacian
		for (int i = 0; i < numClasses; i++) {
			for (int j = 0; j < numConditions; j++) {
				int tempNumValues = (int)dataset.instance(i).attribute(j).numValues();
				for (int k = 0; k < tempNumValues; k++) {
					conditionalProbabilitiesLaplacian[i][j][k] = (conditionalCounts[i][j][k] + 1)/(tempClassCounts[i] + tempNumValues);
				}//of for k
			}//of for j
		}//of for i
		
		System.out.println("Conditional probabilities: " + Arrays.deepToString(conditionalCounts));	
	}//of calculateConditionalProbabilities
	
	/**
	 * ***********************************************
	 * Calculate the Gaussian parameters.
	 * ***********************************************
	 */
	public void caculateGaussianParameters() {
		gaussianparamters = new Gaussianparamters[numClasses][numConditions];
		
		double[] tempValuesArray = new double[numInstances];
		int tempNumValues = 0;
		double tempSum = 0;
		
		for (int i = 0; i < numClasses; i++) {
			for (int j = 0; j < numConditions; j++) {
				tempSum = 0;
				
				//Obtain values for this class.
				tempNumValues = 0;
				//属于i类别的才继续,然后计数,否则跳过。
				for (int k = 0; k < numInstances; k++) {
					if ((int)dataset.instance(k).classValue() != i) {
						continue;
					}//of if
					
					tempValuesArray[tempNumValues] = dataset.instance(k).value(j);  //存储的是每个属于当前类的实例的当前属性值
					tempSum += tempValuesArray[tempNumValues];   //当前类的当前属性总和
					tempNumValues++;   //属于i类别的实例总数
				}//of for k
				
				//Obtain parameters.
				double tempMu = tempSum / tempNumValues;    //获得均值
				
				double tempSigma = 0;
				//每个实例相当于一个自变量,就是密度函数中的X。
				//for循环完成方差的计算
				for (int k = 0; k < tempNumValues; k++) {
					tempSigma += (tempValuesArray[k] - tempMu) * (tempValuesArray[k] - tempMu);
				}//of for k
				tempSigma /= tempNumValues;
				tempSigma = Math.sqrt(tempSigma);
				
				gaussianparamters[i][j] = new Gaussianparamters(tempMu, tempSigma);
			}//of for j
		}//of for i
		
		System.out.println("gaussianparamters:" + Arrays.deepToString(gaussianparamters));
	}//of caculateGaussianParameters
	
	/**
	 * *******************************************************
	 * Classify all instances, the results are stored in predicts[].
	 * *******************************************************
	 */
	public void classify() {
		predicts = new int[numInstances];
		for (int i = 0; i < numInstances; i++) {
			predicts[i] = classifyofDataTypeChose(dataset.instance(i));
		}//of for i
	}//of classify
	
	/**
	 * *******************************************************
	 * Classify an instances according to the data type.
	 * @param paraInstance
	 * @return 
	 * *******************************************************
	 */
	public int classifyofDataTypeChose(Instance paraInstance) {
		if (dataType == NOMINAL) {
			return classifyNominal(paraInstance);
		}else if(dataType == NUMERICAL){
			return 0;
		}//of if
		return -1;
	}//of classifyofdataType
	
	/**
	 * ********************************************************
	 * Classify an instances with nominal data.
	 * @param paraInstance
	 * @return BestIndex.
	 * ********************************************************
	 */
	public int classifyNominal(Instance paraInstance) {
		// Find the biggest one.
		double tempBiggest = -10000;
		int resultBestIndex = 0;
		
		for (int i = 0; i < numClasses; i++) {
			double tempPseudoProbability = Math.log(classDistributionLaplacian[i]);
			for (int j = 0; j < numConditions; j++) {
				int tempAttributeValue = (int)paraInstance.value(j);
				
				tempPseudoProbability += Math.log(conditionalProbabilitiesLaplacian[i][j][tempAttributeValue]);
			}//of for j
			
			if (tempBiggest < tempPseudoProbability) {
				tempBiggest = tempPseudoProbability;
				resultBestIndex = i;
			}//of if
		}//of for i
		
		return resultBestIndex;
	}//of classifyNominal
	
	/**
	 * ******************************************************
	 * Classify an instances with Numerical data.
	 * @param paraInstance
	 * @return BestIndex
	 * ******************************************************
	 */
	public int classifyNumerical(Instance paraInstance) {
		// Find the biggest one.
		double tempBiggest = -10000;
		int resultBestIndex = 0;
		
		for (int i = 0; i < numClasses; i++) {
			double tempPseudoProbability = Math.log(classDistributionLaplacian[i]);
			for (int j = 0; j < numConditions; j++) {
				double tempAttributeValue = paraInstance.value(j);
				double tempSigma = gaussianparamters[i][j].sigma;
				double tempMu = gaussianparamters[i][j].mu;
				
				tempPseudoProbability += -Math.log(tempSigma)
						- (tempAttributeValue - tempMu) * (tempAttributeValue - tempMu) / (2 * tempSigma * tempSigma);
			}//of for j
			
			if (tempBiggest < tempPseudoProbability) {
				tempBiggest = tempPseudoProbability;
				resultBestIndex = i;
			}//of if
		}//of for i
		
		return resultBestIndex;
	}//of classifyNumerical
	
	/**
	 * *****************************************
	 * Compute accuracy.
	 * @return accuracy
	 * *****************************************
	 */
	public double computeAccuracy() {
		double tempCorrect = 0;
		double resultAccuracy = 0;
		
		for (int i = 0; i < numInstances; i++) {
			if (predicts[i] == (int)dataset.instance(i).classValue()) {
				tempCorrect++;
			}//of if
		}//of for i
		
		resultAccuracy = tempCorrect/numInstances;
		return resultAccuracy;
	}//of computeAccuracy
	
	/**
	 * ******************************
	 * Test nominal data.
	 * ******************************
	 */
	public static void testNominal() {
		System.out.println("Hello, Naive Bayes. I only want to test the nominal data.");
		String tempFilename = "E:/Datasets/UCIdatasets/mushroom.arff";
		
		NaiveBayes tempLearner = new NaiveBayes(tempFilename);
		tempLearner.setDataType(NOMINAL);
		tempLearner.calculateClassDistribution();
		tempLearner.calculateConditionalProbabilities();
		tempLearner.classify();
		
		System.out.println("The accuracy is: " + tempLearner.computeAccuracy());
	}//of testNominal
	
	/**
	 * ******************************
	 * Test Numerical data.
	 * ******************************
	 */
	public static void testNumerical() {
		System.out.println("Hello, Naive Bayes. I only want to test the numerical data.");
		String tempFilename = "E:/Datasets/UCIdatasets/其他数据集/iris.arff";
		
		NaiveBayes tempLearner = new NaiveBayes(tempFilename);
		tempLearner.setDataType(NUMERICAL);
		tempLearner.calculateClassDistribution();
		tempLearner.caculateGaussianParameters();	
		tempLearner.classify();
		
		System.out.println("The accuracy is: " + tempLearner.computeAccuracy());
	}//of testNumerical
	
	/**
	 * **************************************
	 * The entrance of the program.
	 * @param args
	 * **************************************
	 */
	public static void main(String args[]) {
		testNominal();
		testNumerical();
	}//of main
	
	
}//of NaiveBayes

代码内容包含昨天的符号型数据,没有进行删除。数值型的处理方法和符号型的第一步是一致的,都是计算数据集中类的分布。数值型第二步是计算高斯分布的参数,即方差\sigma 和均值\mu。对应的方法是caculateGaussianParameters()。其余的计算精度,以及分类预测都大同小异。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/816593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 基础语法(二)

一、背景&#xff1a; 我们对于基础语法&#xff0c;说白了就是实现元素赋值&#xff0c;循环&#xff0c;判断&#xff0c;以及事件响应即可&#xff01; 二、v-bind 我们已经成功创建了第一个 Vue 应用&#xff01;看起来这跟渲染一个字符串模板非常类似&#xff0c;但是 V…

性能测试/负载测试/压力测试之间的区别

做测试一年多来&#xff0c;虽然平时的工作都能很好的完成&#xff0c;但最近突然发现自己在关于测试的整体知识体系上面的了解很是欠缺&#xff0c;所以&#xff0c;在工作之余也做了一些测试方面的知识的补充。不足之处&#xff0c;还请大家多多交流&#xff0c;互相学习。 …

全网最细,性能测试-接口压测 Locust固件实战,从0到1进阶...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 python如何进行性…

基于YOLOv5的S弯识别

基于YOLOv5的S弯识别 目录 基于YOLOv5的S弯识别技术背景算法介绍具体实现1、下载仓库2、配置环境3、数据处理4、转成engine文件5、使用代码实现识别 技术总结 技术背景 S弯识别是一个在自动驾驶和机器人领域中很常见的任务&#xff0c;它需要识别道路上的弯道&#xff0c;特别…

springboot+mybatis-flex初体验

mybatis作为一款应用非常广泛的持久层框架&#xff0c;随之又出现了mybatis的增强框架。mybatis的增强框架就是在mybatis 的基础上又添加了许多的功能&#xff0c;目的就是为简化开发&#xff0c;提供效率而生。mybatis-plus就是一款很流行的增加框架&#xff0c;在 mybatis-pl…

小程序学习(四):WXML模板语法

WXML模板语法-数据绑定 1.数据绑定的基本原则 ①在data中定义数据 ②在WXML中使用数据 2.动态绑定属性 WXML模板语法-事件绑定 3.什么是事件 4.小程序中常用的事件 5.事件对象的属性列表 6.target和currentTarget的区别 7.bindtap的语法格式 8.在事件处理函数中为data中的数据…

华为、阿里巴巴、字节跳动 100+ Python 面试问题总结(六)

系列文章目录 个人简介&#xff1a;机电专业在读研究生&#xff0c;CSDN内容合伙人&#xff0c;博主个人首页 Python面试专栏&#xff1a;《Python面试》此专栏面向准备面试的2024届毕业生。欢迎阅读&#xff0c;一起进步&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; …

校园跑腿小程序功能分享

提起校园跑腿小程序大家都不陌生&#xff0c;尤其是对上大学的伙伴们来说,更是熟悉得不能再熟悉了&#xff0c;和我们的生活息息相关&#xff0c;密不可分。 对于现在的年轻人来说&#xff0c;网购是非常简单和方便的一种购物方式&#xff0c;随之快递也会越来越多。在我们国家…

rancher2使用helm部署harbor,搭建私有镜像/helm仓库

接上一篇《rancher2安装nfs-subdir-external-provisioner为PVC/PV动态提供存储空间&#xff08;动态分配卷&#xff09;》 本篇开始讲如何在rancher2中部署harbor&#xff0c;来搭建一个私有的镜像/helm仓库。 一、安装harbor服务 1. 在目标集群中添加命名空间 2. 将提供harb…

Elbie勒索病毒的最新威胁:如何恢复您的数据?

导言&#xff1a; 在数字时代的浩瀚网络中&#xff0c;隐藏着一支不为人知的黑暗势力&#xff0c;他们的代表之一就是臭名昭著的Elbie勒索病毒。这个神秘的数字幽灵似乎无所不能&#xff0c;几乎每个人都可能成为它的牺牲品。本文91数据恢复将揭示Elbie勒索病毒的背后故事&…

数据结构-链表结构-单向链表

链表结构 说到链表结构就不得不提起数据结构&#xff0c;什么是数据结构&#xff1f;就是用来组织和存储数据的某种结构。那么到底是某种结构呢&#xff1f; 数据结构分为&#xff1a; 线性结构 数组&#xff0c;链表&#xff0c;栈&#xff0c;队列 树形结构 二叉树&#x…

零基础玩转C语言—结构体【初阶】

大家好&#xff0c;我是深鱼~ 目录 【前言】&#xff1a; 一、结构体的声明 1.1结构的基本知识 1.2结构的声明 1.3结构体成员的类型 1.4结构体变量的定义和初始化 二、结构体成员的访问 【前言】&#xff1a;本章来介绍结构体的部分知识&#xff0c;并不会深入讲解&…

webstorm格式化代码后单引号转成了双引号

webStorm格式化js代码时单引号变成了双引号&#xff0c;问题如下&#xff1a; 格式化前&#xff1a; 格式化后&#xff1a; 解决办法&#xff1a; window: File -> Settings -> Editor -> Code Style -> Javascript&#xff1b; mac: webStorm -> Preference …

了解回归测试吗?今天给大家详解一下回归测试

测试工作中&#xff0c;新人对于测试流程、测试方法都有可以直接拿来用的教材&#xff0c;但是对于回归测试中的bug处理的细节&#xff0c;往往需要我们更多的经历才能更好的完成自己的工作&#xff0c;下面我们来谈一谈回归测试bug的处理中需要关注的点&#xff1a; 一、什么…

Docker 镜像解密:分层存储与镜像构建原理

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

国内办公协作系统评测:5 款软件推荐

办公协作系统是现代信息化办公的必备工具之一&#xff0c;对于企业来说&#xff0c;选择一款好用的办公协作系统非常重要。然而&#xff0c;在众多的办公协作系统中&#xff0c;哪个好用是一个让人头痛的问题。总体而言&#xff0c;国内的办公协作系统已经相当成熟和完善&#…

基于linux下的高并发服务器开发(第四章)- 多线程实现并发服务器

>>了解文件描述符 文件描述符分为两类&#xff0c;一类是用于监听的&#xff0c;一类是用于通信的&#xff0c;在服务器端既有监听的&#xff0c;又有通信的。而且在服务器端只有一个用于监听的文件描述符&#xff0c;用于通信的文件描述符是有n个。和多少个客户端建立了…

vue 前端一键导出excel文件并附带表格样式

1、安装xlsx、xlsx-style、file-saver三个包 //xlsx与file-saver指定版本安装&#xff0c;解决默认安装utils未定义的问题 npm install --save xlsx0.17.0 npm install --save file-saver2.0.5 npm install xlsx-style --save 2、在使用的页面引入 import XLSX from xlsx //…

对顶堆算法

对顶堆可以动态维护一个序列上的第k大的数&#xff0c;由一个大根堆和一个小根堆组成&#xff0c; 小根堆维护前k大的数(包含第k个)大根堆维护比第k个数小的数 [CSP-J2020] 直播获奖 题目描述 NOI2130 即将举行。为了增加观赏性&#xff0c;CCF 决定逐一评出每个选手的成绩&a…

【暑期每日一练】 day10

目录 选择题 &#xff08;1&#xff09; 解析&#xff1a; &#xff08;2&#xff09; 解析&#xff1a; &#xff08;3&#xff09; 解析&#xff1a; &#xff08;4&#xff09; 解析&#xff1a; &#xff08;5&#xff09; 解析&#xff1a; 编程题 题一 …