Lenguaje C triturado Gaussian Naive Bayes: adivinar el género a través de la altura y el peso (aprendizaje automático)

Tabla de contenido

Introducción al proyecto

Precisión de inferir el género a partir de la altura y el peso

Viabilidad del proyecto: una introducción a la justificación

Distribución gaussiana (distribución normal)

bayesiana ingenua

flujo de código

Obtener datos (limpieza de datos)

Código

Archivo de encabezado allHead.h

Archivo fuente handleData.cpp

Archivo fuente (función principal) naiveBayes.cpp


Introducción al proyecto

Propósito: la computación paralela se introduce en el algoritmo de aprendizaje automático para entrenar el modelo más rápido, de modo que la máquina pueda usar las funciones A y B para inferir otra función C (las funciones A y B pueden ser la concentración de azúcar en la sangre, el nivel de presión arterial, la función C puede ser condiciones físicas).

Datos: solo tengo una pieza de datos de medición física de un adulto de 20 años en la mano, por lo que este experimento usa datos de medición física, como altura, peso, capacidad pulmonar y datos de género para entrenar el modelo.

En general, cuanto mayor sea la cantidad de datos en este tipo de proyecto, más preciso será el modelo entrenado, pero el tiempo de entrenamiento también aumentará en consecuencia. Para reducir el tiempo de entrenamiento, este experimento introdujo la computación paralela para reducir el tiempo de computación.

Este proyecto consta de las siguientes cuatro partes:

1. Deduce el género por altura y peso

2. Estimar el sexo en función de la altura, el peso y la capacidad vital

3. Optimización MPI

4. Optimización OpenMP

 

Precisión de inferir el género a partir de la altura y el peso

Este proyecto utilizó 150 líneas de código de lenguaje C para implementar Gauss-Naive Bayesian. Aunque está limitado por la pequeña cantidad de valores propios en el conjunto de datos, la precisión de los resultados de la predicción sigue siendo del 84,7 %.

Viabilidad del proyecto: una introducción a la justificación

Gauss-Naive Bayes es una distribución gaussiana (distribución normal) + Naive Bayes.

La distribución gaussiana y Naive Bayes son conocimiento de la escuela secundaria, por lo que no hablaré de ciencia popular aquí, solo de Baidu.

 

Distribución gaussiana (distribución normal)

A través de investigaciones científicas previas, se ha encontrado que la altura y el peso de los seres humanos básicamente satisfacen la distribución Gaussiana.

Después de buscar mucha información, encontré que la altura de los seres humanos en realidad se concentra en varios intervalos, y la imagen es una curva de distribución gaussiana con varios picos.

Podemos usar el conjunto de datos para obtener lo que necesita la distribución gaussiana: media (u), desviación estándar (p) .

//dataSet是数据集
double u=0; //平均值
double p=0; //标准差

//求平均值
for(i=0;i<dataLen;i++){
	if(dataSet[i][0]==sex){
		sum=sum+1;
		u=u+dataSet[i][column];
		//printf("%lf\n",dataSet[i][column]);
	}
}
u=u/sum;

//求标准差
double numSum=0;
for(i=0;i<dataLen;i++){
	if(dataSet[i][0]==sex){
		numSum=numSum+pow( dataSet[i][column]-u , 2 );
	}
}
p=sqrt(numSum/dataLen);

Siempre que tengamos la media y la desviación estándar, podemos obtener las siguientes cuatro probabilidades a través de la función de densidad de probabilidad de la distribución gaussiana :

P(altura=160|género=femenino), P(peso=50|género=femenino)

P(altura=160|género=masculino), P(peso=50|género=masculino)

//正态分布 x:随机变量的值 u:样本平均值 p:标准差 y:概率
double gaussianDistribution(double x,double u,double p)
{
	double y;
	p=pow(p,2);
	y = (1 / (2*PI*p)) * exp( -pow((x-u),2) / (2*p) );
	return y;
}

Después de obtener las cuatro probabilidades anteriores, se puede realizar la clasificación Naive Bayesian.

 

bayesiana ingenua

¿Qué tan simple es Naive Bayes?Básicamente, es comparar el tamaño de P1 y P2, cualquiera que tenga una mayor probabilidad será el resultado.

P1 = P(altura=160|género=femenino) * P(peso=50|género=femenino)

P2 = P(altura=160|género=masculino) * P(peso=50|género=masculino)

 

flujo de código

  1. Obtener datos (limpieza de datos)
  2. leer datos
  3. Calcular media (u), desviación estándar (p)
  4. Encuentre la probabilidad de P(característica=xxx|género=xx) a través de la función de densidad de probabilidad de la distribución gaussiana
  5. Encuentre P1, P2
  6. Juzgar el género por el tamaño de P1 y P2

 

Obtener datos (limpieza de datos)

El conjunto de datos se puede encontrar en https://www.kaggle.com/ , solo busque palabras clave como altura...

El conjunto de datos de este código (datos de medidas físicas de estudiantes universitarios coreanos) es el siguiente:

Columna 0: Sexo (0 para desconocido, 1 para hombre, 2 para mujer)

Columna 1: altura (unidad: cm)

Columna 2: Peso corporal (unidad: kg)

PS no comparte este conjunto de datos

Código

Archivo de encabezado allHead.h

//allHead.h

#ifndef _STDIO_H_ 
#define _STDIO_H_

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

#define PI 3.1415926535898

//单条数据的长度
#define MAX_LINE 100
//数据集的长度
#define DATA_LEN 15300
//特征值的个数
#define EIGEN_NUM 3


/*声明函数*/
//获取数据集
void getData(const char *fileLocation);

//获得平均值和标准差:给 Parameter 赋值
void getParameter();
//计算平均值和标准差
double* calParameter(int column,int sex);

//计算概率p(特征列column = x | 性别)
double getProbability(double x,int column,int sex);
//正态分布 x:随机变量的值 u:样本平均值 p:标准差
double gaussianDistribution(double x,double u,double p);

//返回性别字符结果
char* sexResult(float height,float weight);
//返回性别ID结果
int sexIDResult(float height,float weight);
//准确度判断
float precision();


#endif 

Archivo fuente handleData.cpp

//handleData.cpp

#include"allHead.h"

/*
basicData.csv:性别、身高、体重 [i][0,1,2]
addVitalCapacityData.csv:性别、身高、体重、肺活量 [i][0,1,2,3]
*/

//性别:0表示未知,1表示男,2表示女

float dataSet[DATA_LEN][EIGEN_NUM];	//数据集
double maleNum=0;//男性总数
double femaleNum=0;//女性总数
double meanValue[2][3];			    //男性、女性的所有均值[0][0,1,2]=[男][身高、体重、肺活量]
double standardDeviation[2][3];     //男性、女性的所有标准差[0][0,1,2]=[男][身高、体重、肺活量]

int dataLen;				//从1开始计算的数据集的长度,数学计算用的长度
char *basicInfo[] = {"性别","身高","体重","肺活量"};
//char *addVitalCapacityInfo[] = {"性别","身高","体重","肺活量"};

//读取数据
void getData(const char *fileLocation)
{
	char buf[MAX_LINE];		//缓冲区
	FILE *fp;				//文件指针s
	int len;				//行字符个数

	//printf("正在读取文件\n");

	//读取文件
	if((fp = fopen(fileLocation,"r")) == NULL)
	{
		perror("fail to read");
		exit (1) ;
	}

	//逐行读取及写入数组
	char *token;
	const char s[2] = ",";
	int i=0;
	int j=0;
	while(fgets(buf,MAX_LINE,fp) != NULL && i< DATA_LEN-1)
	{
		len = strlen(buf);
		buf[len-1] = '\0';  //删去换行符
		//分割字符串
		token = strtok(buf, s);
		//继续分割字符串
		j = 0;
		while( token != NULL ) {
			dataSet[i][j]=atof(token);
			//printf("dataSet[%d][%d] = %f\n", i,j, dataSet[i][j] );
			//printf( "%f\n", dataRuslt[i][j]);
			token = strtok(NULL, s);
			j = j+1;
		 }
		i = i + 1;
	}
	dataLen=i;
	//printf("%d条数据读取完毕\n",dataLen);
	//计算男女个数
	for(i=0;i<dataLen;i++){
		if(dataSet[i][0]==1){maleNum=maleNum+1;}
		if(dataSet[i][0]==2){femaleNum=femaleNum+1;}
		}
	getParameter();
}

//获得平均值和标准差:给 Parameter 赋值
void getParameter()
{
	double *p;
	for(int i=0;i<2;i++)
	{
		for(int j=0;j<EIGEN_NUM-1;j++){
			p=calParameter(j+1,i+1);
			meanValue[i][j]=*p;
			standardDeviation[i][j]=*(p+1);
		}
	}
}

//计算平均值和标准差
double* calParameter(int column,int sex)
{
	double  r[2];
	double sexNum;//性别人数
	double u=0; //平均值
	double p=0; //标准差
	double sum=0;
	int i=0;

	//判断性别
	char *gender;
	if(sex==1)
	{
		sexNum=maleNum;
		gender="男性";
	}
	if(sex==2)
	{
		sexNum=femaleNum;
		gender="女性";
	}

	//求平均值
	for(i=0;i<dataLen;i++){
		if(dataSet[i][0]==sex){
			sum=sum+1;
			u=u+dataSet[i][column];
			//printf("%lf\n",dataSet[i][column]);
		}
	}
	u=u/sum;

	//求标准差
	double numSum=0;
	for(i=0;i<dataLen;i++){
		if(dataSet[i][0]==sex){
			numSum=numSum+pow( dataSet[i][column]-u , 2 );
		}
	}
	p=sqrt(numSum/sexNum);
	//printf("numSum=%f\n",numSum);
	printf("%s%s平均值=%.16lf\n标准差=%.16lf\n",gender,basicInfo[column],u,p);

	r[0]=u;
	r[1]=p;
	return r;
}


//计算概率p(特征列column = x | 性别)
double getProbability(double x,int column,int sex)
{
	double Probability;	//计算出的概率
	double u = meanValue[sex-1][column-1];
	double p = standardDeviation[sex-1][column-1];
	Probability = gaussianDistribution(x,u,p);

	//printf("p(%s=%lf|性别=%s)=%.16lf\n",basicInfo[column],x,gender,Probability);

	return Probability;
}


//正态分布 x:随机变量的值 u:样本平均值 p:标准差 y:概率
double gaussianDistribution(double x,double u,double p)
{
	double y;
	p=pow(p,2);
	y = (1 / (2*PI*p)) * exp( -pow((x-u),2) / (2*p) );
	return y;
}

//返回性别字符结果
char* sexResult(float height,float weight)
{
	double maleP;//男性概率
	double femaleP;//女性概率
	double a=0.5; //男女比例各50%

	maleP = a * getProbability(height,1,1) * getProbability(weight,2,1);
	//printf("\n");
	femaleP = a * getProbability(height,1,2) * getProbability(weight,2,2);
	//printf("\n");

	if(maleP > femaleP){return "男性";}
	if(maleP < femaleP){return "女性";}
	if(maleP == femaleP){return "未知";}

}

//返回性别ID结果
int sexIDResult(float height,float weight)
{
	double maleP;//男性概率
	double femaleP;//女性概率
	double a=0.5; //男女比例各50%

	maleP = a * getProbability(height,1,1) * getProbability(weight,2,1);
	//printf("\n");
	femaleP = a * getProbability(height,1,2) * getProbability(weight,2,2);
	//printf("\n");

	if(maleP > femaleP){return 1;}
	if(maleP < femaleP){return 2;}
	if(maleP == femaleP){return 0;}
}

//准确度判断
float precision()
{
	int i;
	float preSexID;
	float right=0;
	float error=0;
	for(i=0;i<dataLen;i++){
		preSexID=sexIDResult(dataSet[i][1],dataSet[i][2]);
		//printf("预测ID:%f  实际ID:%f \n",preSexID,dataSet[i][0]);
		if(dataSet[i][0]==preSexID){right=right+1;}
		else{error=error+1;}
	}
	printf("Right:%f\nError:%f\n",right,error);
	return right/(error+right);
}

Archivo fuente (función principal) naiveBayes.cpp

//naiveBayes.cpp

#include"allHead.h"

extern float dataSet[DATA_LEN][EIGEN_NUM];
extern int dataLen;

/*
	性别:0表示未知,1表示男,2表示女
	basicData.csv:性别、身高、体重 [i][0,1,2]
*/

void main(){
	//给全局变量dataSet赋值
	getData("basicData.csv");

	/*
	//抽查数据集
	int i = dataLen-1;
	int j = 2;
	printf("dataSet[%d][%d] = %f\n", i,j, dataSet[i][j] );
	*/

	//打印准确率
	printf("Accuracy:%f\n",precision());

	//抽查准确率
	float Height=178;
	float Weight=60;
	printf("身高:%.2f,体重:%.2f\n根据高斯-朴素贝叶斯算法判断\n此人的性别可能为:%s\n\n",Height,Weight,sexResult(Height,Weight));
	
}

 

Supongo que te gusta

Origin blog.csdn.net/admiz/article/details/106737389
Recomendado
Clasificación