本实验在vc++6.0中进行,使用c++语言实现对mat文件的读取,并送入神经网络进行训练
如果是VS中的可参考这个博主的https://blog.csdn.net/left_la/article/details/8206645
想在VC中调用matlab函数库,首先开始配置:
1、添加路径:
在project-settings-c/ C++ -category:-preprocessor-Additional include directories:栏目中添加:(根据自己Matlab的路径写)
C:\Program Files\MATLAB\R2016a\extern\include
C:\Program Files\MATLAB\R2016a\extern\lib
在project-settings-c/ C++ -category:-preprocessor-preprocessor definitions: 栏目中添加:
MS VC ,MSWIND
在project-settings-Link-Category-Input-Ignore libraries:栏目中添加:ms VC rt.lib
在Additional library path中加入C:\Program Files\MATLAB\R2016a\extern\lib
project options加入libmat.lib libmx.lib libmex.lib libeng.lib 这四个
然后就可以开始运行了~
但是我重启计算机之后需要重新配置,不知道为什么
代码是实现2分类的,可改成多分类。记得当时没改好,着急交就二分类了~
其中的mat文件有上传到资源里,可读取自己的mat文件
我的两类训练集和测试集全部在一个mat文件里
完整代码
#include<mat.h>
#include "matrix.h"
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
//输入一对数(x,y),输出为xxxx(x=0或1)
//判断(x,y)在第几象限,若在第一象限,则输出1000,以此类推;
//样本为随机的1000对(x,y)
//对指定输入对求其所在象限;
const int inputnode=59;//输入层神经元个数
const int hidenode=10;//隐含层神经元个数
const int outputnode=1;//输出层神经元个数
const int sample_train_num=140;//训练样本个数
const int sample_test_num=40;//测试样本个数
double **sample_train;
double **sample_test;
//const int test_num=450;
double w_ih[inputnode][hidenode];//输入层隐含层间权值矩阵
double w_ho[hidenode];//隐含层输出层间权值矩阵
double sita_h[hidenode];//隐含层间阈值
double sita_o;//输出层间阈值
//double sample[sample_num][inputnode];
double sample_train_label[sample_train_num];
double sample_test_label[sample_test_num];
double error[sample_train_num];
double totalerror=0;
double x[sample_train_num][inputnode];//网络输入
double a[sample_train_num][hidenode];//隐层的输出
double *y=new double[140];//[sample_train_num];//网络输出
double d[sample_train_num];//样本参考输出
double *outerrors=new double[5000];
double delta_ih[sample_train_num][hidenode];//输入到隐层的权值修正
double delta_ho[sample_train_num];//隐层到输出的权值修正
const int epochs=1000000;//迭代次数
const double goal=0.01;//误差目标精度
const double lr=0.1;//学习速率
int count=0;
/*void readmat()
{
MATFile *pmatFile = NULL;
mxArray *pMxArray = NULL;
// 读取.mat文件(例:mat文件名为"initUrban.mat",其中包含"initA")
double *initA;
pmatFile = matOpen("Ucmd.mat","r");
pMxArray = matGetVariable(pmatFile, "initA");
initA = (double*) mxGetData(pMxArray);
M = mxGetM(pMxArray);
N = mxGetN(pMxArray);
Matrix<double> A(M,N);
for (int i=0; i<M; i++)
for (int j=0; j<N; j++)
A[i][j] = initA[M*j+i];
matClose(pmatFile);
mxFree(initA);
}
void initmat()
{
// 生成.mat文件
double *outA = new double[5000];
for (int i=0; i<5000; i++)
// for (int j=0; j<N; j++)
outA[i] = A[i];
pmatFile = matOpen("A.mat","w");
mxSetData(pMxArray, outA);
matPutVariable(pmatFile, "A", pMxArray);
matClose(pmatFile);
}*/
int* sample_fun()
{
MATFile *pmat;//指向mat文件的指针
const char **dir;//元素名列表
const char *file;//要打开的mat文件名
int ndir;//mat文件中的元素(矩阵、元胞)个数
mxArray *cell1;//指向要读取的元胞数据的指针
// mxArray *mat1;//指向元胞中某个元素的指针
double *a;//指向元胞中某个元素第一个数据的指针
int cellM,cellN,M,N;
//int count;
int i,j;
//double **b;
int *size;
size=(int *)malloc(2* sizeof(int));
file="ULBPNormalDatabase2.mat"; //要打开的mat文件名
pmat = matOpen(file, "r");//打开文件,返回指向文件指针
if (pmat == NULL)
{
printf("打开mat文件失败!");
}
//读取mat文件中的矩阵列表(返回mat中包含的元素的名字)
dir = (const char **)matGetDir(pmat, &ndir);
if (dir == NULL)
{
printf("读取mat文件失败!");
}
//输出cellMat.mat中的元素数量
printf("%s文件中一共有%d个元素\n",file,ndir);
//从打开的mat文件中(pamt)读取名字为dir[0]的元胞
//(返回指向该矩阵的指针,注意:MATLAB中的矩阵是按列优先存储到)
cell1 = matGetVariable(pmat,dir[0]);//指向名字为dir[0]的元胞
cout<<dir[0]<<endl;
cellM = (int)mxGetM(cell1);//获取元胞的行数
size[0] = cellM;
cellN = (int)mxGetN(cell1);//获取元胞的列数
size[1] = cellN;
cout<<"M="<<cellM<<endl<<"N="<<cellN <<endl;
//按列优先依次读取元胞中的数据
//mat1 = mxGetCell(cell1,count);//按列优先,指向元胞中的第count+1个元素
cout<<1<<endl;
a = (double*)mxGetData(cell1);//指向mat1中的第一个数据
M = (int)mxGetM(cell1);//获取mat1的行数
N = (int)mxGetN(cell1);//获取mat1的列数
size[0] = M;
size[1] = N;
printf("the size:%d,%d",size[0],size[1]);
/*for(i=0;i<M;i++)
{
for (j=0;j<N;j++)
{
printf("%-5.4f ",a[j*M+i]);
// b[i][j]=a[j*M+i];
//printf("%-5.4f ",b[i][j]);
} printf("结束此时i=%d,j=%d\n",i,j);
}*/
sample_train=(double **)malloc((M-40)* sizeof(double*));
sample_test=(double **)malloc(40* sizeof(double*));
for(i=0;i<M-40;i++)
{
sample_train[i]=(double *)malloc(N*sizeof(double));
}
for(i=0;i<40;i++)
{
sample_test[i]=(double *)malloc(N*sizeof(double));
}
for(i=0;i<M;i++)
{
for (j=0;j<N;j++)
{
//printf("%-5.4f ",a[j*M+i]);
if(i>=70&&i<90)
sample_test[i-70][j]=a[j*M+i];
else if(i>=160&&i<180)
sample_test[i-140][j]=a[j*M+i];
else if(i>=90&&i<160)
sample_train[i-20][j]=a[j*M+i];
else
sample_train[i][j]=a[j*M+i];
//printf("%-5.4f ",samplefeature[i][j]);
} printf("结束此时i=%d,j=%d\n",i,j);
}
//free(a);
printf("维数为:(%d,%d)\n",M,N);
matClose(pmat);//关闭文件
return size;
}
void init()
{
//生成样本
int i,j;
//srand((unsigned)time(NULL));
for(i=0;i<sample_train_num;i++)
{
//sample[i][0]=(double)(rand()%20000-10000)/10000;
//sample[i][1]=(double)(rand()%20000-10000)/10000;
if(i<70)
{
sample_train_label[i]=0;
//sample_train_label[i][1]=0;
//sample_label[i][2]=0;
//sample_label[i][3]=0;
}
else
{
sample_train_label[i]=1;
//sample_train_label[i][1]=1;
//sample_label[i][2]=0;
//sample_label[i][3]=0;
}
printf("第%d训练样本标签的值%f%f\n",i,sample_train_label[i]);
}
/*for(i=0;i<sample_test_num;i++)
{
//sample[i][0]=(double)(rand()%20000-10000)/10000;
//sample[i][1]=(double)(rand()%20000-10000)/10000;
if(i<20)
{
sample_test_label[i][0]=1;
sample_test_label[i][1]=0;
}
else
{
sample_test_label[i][0]=0;
sample_test_label[i][1]=1;
}
printf("第%d测试样本标签的值%f%f\n",i,sample_test_label[i][0],sample_test_label[i][1]);
}*/
/*if(sample[i][0]>0&&sample[i][1]<0)
{
sample_label[i][0]=0;
sample_label[i][1]=0;
sample_label[i][2]=0;
sample_label[i][3]=1;
}*/
//初始化权值矩阵
for(i=0;i<inputnode;i++)
{
for(j=0;j<hidenode;j++)
{
w_ih[i][j]=(double)(rand()%20000-10000)/10000;
}
}
for(i=0;i<hidenode;i++)
{
w_ho[i]=(double)(rand()%20000-10000)/10000;
}
//初始化阈值
for(i=0;i<hidenode;i++)
{
sita_h[i]=(double)(rand()%1000)/1000;
}
sita_o=(double)(rand()%1000)/1000;
//初始化误差
for(i=0;i<sample_train_num;i++)
{
error[i]=0;
}
//初始化权值调整系数
for(i=0;i<sample_train_num;i++)
{
for(j=0;j<hidenode;j++)
{
delta_ih[i][j]=0;
}
}
for(i=0;i<sample_train_num;i++)
{
delta_ho[i]=0;
}
}
void train()
{
cout<<"BP网络开始训练:"<<endl;
int i,j,k;
int m=0,n=0;
for(int loop=0;loop<epochs;loop++)
{
totalerror=0;
int count=0;
for(i=0;i<sample_train_num;i++)
{
//读入样本
for(m=0;m<inputnode;m++)
{
x[count][m]=sample_train[count][m];
}
d[count]=sample_train_label[count];
//d[count][1]=sample_train_label[count][1];
/*d[count][2]=sample_label[count][2];
d[count][3]=sample_label[count][3];*/
//计算隐含层输出
double net_h[hidenode];
for(j=0;j<hidenode;j++)
{
net_h[j]=0;
for(m=0;m<inputnode;m++)
{
//net_h[j]=w_ih[0][j]*x[count][0]+w_ih[1][j]*x[count][1]-sita_h[j];
net_h[j]+=w_ih[m][j]*x[count][m];
}
net_h[j]-=sita_h[j];
a[count][j]=1/(1+exp(-net_h[j]));
}
//计算输出层输出
double net_o;
net_o=0;
for(j=0;j<hidenode;j++)
{
net_o+=w_ho[j]*a[count][j];
}
net_o-=sita_o;
y[count]=1/(1+exp(-net_o));
//计算样本误差
error[count]+=(d[count]-y[count])*(d[count]-y[count]);
error[count]/=2;
//计算隐含层输出层间权值调整系数
delta_ho[count]=(d[count]-y[count])*y[count]*(1-y[count]);
//计算输入层到隐含层的权值调整系数
for(j=0;j<hidenode;j++)
{
delta_ih[count][j]+=delta_ho[count]*w_ho[j]*a[count][j]*(1-a[count][j]);
}
totalerror+=error[count];
count++;
}
outerrors[loop]=totalerror;
cout<<"第"<<loop+1<<"次迭代,"<<"totalerror为:"<<totalerror<<endl;
//调整w_ih
double temp=0.0;
for(i=0;i<inputnode;i++)
{
for(j=0;j<hidenode;j++)
{
temp=0;
for(k=0;k<sample_train_num;k++)
{
temp+=delta_ih[k][j]*x[k][i];
}
w_ih[i][j]+=lr*temp;
}
}
//调整sita_h
for(j=0;j<hidenode;j++)
{
temp=0;
for(k=0;k<sample_train_num;k++)
{
temp-=delta_ih[k][j];
}
sita_h[j]+=0.005*temp;
}
//调整w_ho
for(i=0;i<hidenode;i++)
{
temp = 0;
for (k=0;k<sample_train_num;k++)
{
temp+=delta_ho[k]*a[k][i];
}
w_ho[i]+=lr*temp;
}
//调整sita_o
temp=0;
for(j=0;j<sample_train_num;j++)
{
temp-=delta_ho[j];
}
sita_o+=0.005*temp;
if(totalerror<goal) break;
}
}
void test(double *sample_test)
{
int i,j;
double net_h[hidenode];
double net_o;
double hide[hidenode];
double output;
for(j=0;j<hidenode;j++)
{
net_h[j]=0;
for(i=0;i<inputnode;i++)
{
//net_h[j]=w_ih[0][j]*x0+w_ih[1][j]*y0-sita_h[j];
net_h[j]+=w_ih[i][j]*sample_test[i];
cout<<sample_test[i]<<" ";
}
net_h[j]-=sita_h[j];
hide[j]=1/(1+exp(-net_h[j]));
}
net_o=0;
for(j=0;j<hidenode;j++)
{
net_o+=w_ho[j]*hide[j];
}
net_o-=sita_o;
output=1/(1+exp(-net_o));
if(output<0.5) cout<<output<<"这个图片是台风眼"<<endl;
else cout<<output<<"这个图片不是台风眼"<<endl;
}
void main()
{
int i,j,m;
int *size=sample_fun();
for(i=0;i<size[0]-40;i++)
{
for (j=0;j<size[1];j++)
{
//printf("%-5.4f ",a[j*M+i]);
printf("%-5.4f ",sample_train[i][j]);
} printf("结束此时i=%d,j=%d\n",i,j);
}
for(i=0;i<40;i++)
{
for (int j=0;j<size[1];j++)
{
//printf("%-5.4f ",a[j*M+i]);
printf("%-5.4f ",sample_test[i][j]);
} printf("结束此时i=%d,j=%d\n",i,j);
}
//printf("?????????????");
//
// printf("?????????????");
//printf("?????????????\n");/**/
init();
clock_t starttime=clock();
train();
clock_t endtime=clock();
cout<<"训练时间为:"<<endtime-starttime<<"毫秒"<<endl;
/* MATFile *pmatFile = NULL;
mxArray *pWriteArray = NULL;
pmatFile =matOpen("error.mat","w");
//创建一个M*N的矩阵
pWriteArray = mxCreateDoubleMatrix(5000,1, mxREAL);
//把data的值赋给pWriteArray指针
memcpy((void *)(mxGetPr(pWriteArray)), (void *)outerrors, sizeof(outerrors)*5000);
//给矩阵命名为A
matPutVariable(pmatFile, "A", pWriteArray);
matClose(pmatFile); */
MATFile *pmatFile2 = NULL;
mxArray *pWriteArray2 = NULL;
pmatFile2 =matOpen("outy.mat","w");
//创建一个M*N的矩阵
pWriteArray2 = mxCreateDoubleMatrix(280,1, mxREAL);
//把data的值赋给pWriteArray指针
memcpy((void *)(mxGetPr(pWriteArray2)), (void *)y, sizeof(y)*280);
//给矩阵命名为A
matPutVariable(pmatFile2, "outy", pWriteArray2);
matClose(pmatFile2);
double net_h[hidenode];
double net_o;
double hide[hidenode];
double output;
for(m=0;m<sample_test_num;m++)
{
/* test(sample_test[i]);*/
//cout<<"start"<<*sample_test[i]<<" "<<endl;
//cout<<sample_test[i][1]<<endl;
for(j=0;j<hidenode;j++)
{
net_h[j]=0;
for(i=0;i<inputnode;i++)
{
//net_h[j]=w_ih[0][j]*x0+w_ih[1][j]*y0-sita_h[j];
net_h[j]+=w_ih[i][j]*sample_test[m][i];
}
// cout<<"end"<<endl;
net_h[j]-=sita_h[j];
hide[j]=1/(1+exp(-net_h[j]));
}
net_o=0;
for(j=0;j<hidenode;j++)
{
net_o+=w_ho[j]*hide[j];
}
net_o-=sita_o;
output=1/(1+exp(-net_o));
//if(output[0]>0.5) cout<<output[0]<<","<<output[1]<<"这个图片是台风眼"<<endl;
//if(output[1]>0.5) cout<<output[0]<<","<<output[1]<<"这个图片不是台风眼"<<endl;
if(output<0.5) cout<<output<<"这个图片是台风眼"<<endl;
else cout<<output<<"这个图片不是台风眼"<<endl;
}for(i=0;i<inputnode;i++)
for(j=0;j<hidenode;j++)
cout<<w_ih[i][j]<<" ";
cout<<"end"<<endl;
for(i=0;i<hidenode;i++)
cout<<w_ho[i]<<" ";
cout<<"end"<<endl;
}