本實驗在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;
}