神经网络数字识别c语言,神经网络 做数字识别 C++实现

亦可参看:

http://user.qzone.qq.com/459125872/blog/1367117959

程序效果参看: http://pan.baidu.com/s/1nt9d7fV(大,下载慢)

代码下载:

http://download.csdn.net/detail/hzq20081121107/7809827

或http://yun.baidu.com/share/link?shareid=1719680919&uk=3238536701&third=0

原理解释:

http://wenku.baidu.com/link?url=4MV-VUiIJ8Lun6tDmh-ji2OInR7M5dXQzAQdPXkvGxKPt9v-e8YsVEiGcNN_J1FZONOAg_YmNuuU1QiU4MwQt8jrexsLdrB8hA6QsgaDfo_

我的网络结构:

0818b9ca8b590ca3270a3433284dd417.png

sigmoid及其导数:

0818b9ca8b590ca3270a3433284dd417.png

sigmoid梯度计算:

0818b9ca8b590ca3270a3433284dd417.png

BP过程:

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

三层NN的梯度下降推导:

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

ANN的表示:

ANN设置为3层网络,每层的神经元数量为784-100-10.

#define N0N 784

#define N1N 100

#define N2N 10

struct neuroNode

{

float I;

float O;

float Err;

float bias;

};

float pic[28*28]={0};

neuroNode node0[N0N];

neuroNode node1[N1N];

neuroNode node2[N2N];

float w01[N0N][N1N]={0};

float w12[N1N][N2N]={0};

ANN的图像保存在pic[28*28]的数组里

主要函数:

//神经网络初始化

void CANNDlg::initNet()

{

pDC=GetDC();

int i,j,k;

//nn bias

for(i=0;i

node1[i].bias=float(rand()%100)/2000.0;

for(i=0;i

node2[i].bias=float(rand()%100)/2000.0;

//nn weight

for(i=0;i

for(j=0;j

w01[i][j]=float(rand()%100)/2000.0;

for(i=0;i

for(j=0;j

w12[i][j]=float(rand()%100)/2000.0;

}

//读取图片数据到pic[]

void CANNDlg::getPic(CString imgPath)

{

int i,j,k;

BYTE *pchBuf = NULL;

FILE *pF = fopen(imgPath, "rb");

int nLen=1862;

pchBuf = (BYTE*) malloc(sizeof(BYTE)*nLen+1);

nLen=fread(pchBuf,1,nLen, pF);

for(i=0;i<28;i++)

{

for(j=0;j<28;j++)

{

k=1078+i*28+j;

if((pchBuf[k])>100)

pic[j*28+(27-i)]=1;

else

pic[j*28+(27-i)]=0;

}

}

fclose(pF); //关闭文件

free(pchBuf); //释放空间

}

//单个图片的训练

void CANNDlg::train(CString img_path, int targetNum, int orderNum)

{

CString strPicName;

strPicName.Format("%d_%d.bmp",targetNum,orderNum);

img_path += strPicName;

//读入图片数据

getPic(img_path);

//BP前向过程

bpForward();

//CNN反向过程:

bpBackward(targetNum);

}

//BP的前向过程

void CANNDlg::bpForward()

{

int i,j,k;

//得到输入层

for(i=0;i

node0[i].O=pic[i];

//0->1层

for(j=0;j

{

node1[j].I=node1[j].bias;

for(i=0;i

{

node1[j].I+=w01[i][j]*node0[i].O;

}

node1[j].O=1.0/(1.0+exp(-node1[j].I));

}

//1->2层

for(j=0;j

{

node2[j].I=node2[j].bias;

for(i=0;i

{

node2[j].I+=w12[i][j]*node1[i].O;//w12[i][j]表示1st层第i输入单元到2nd层第j神经单元的权重

}

node2[j].O=1.0/(1.0+exp(-node2[j].I));

}

}

//BP的反向过程

void CANNDlg::bpBackward(int targetNum)

{

int i,j;

//计算错误与偏量

for(i=0;i

{

if(i==targetNum)

node2[i].Err=node2[i].O*(1-node2[i].O)*(1-node2[i].O);

else

node2[i].Err=node2[i].O*(1-node2[i].O)*(0-node2[i].O);

node2[i].bias+=l*node2[i].Err;

}

for(i=0;i

{

node1[i].Err=0;

for(j=0;j

{

node1[i].Err+=node1[i].O*(1-node1[i].O)*w12[i][j]*node2[j].Err;

}

node1[i].bias+=l*node1[i].Err;

}

//修订权重

//w12

for(i=0;i

{

for(j=0;j

{

float wch=0;

wch=l*node1[i].O*node2[j].Err;

w12[i][j]+=wch;

}

}

//w01

for(i=0;i

{

for(j=0;j

{

float wch=0;

wch=l*node0[i].O*node1[j].Err;

w01[i][j]+=wch;

}

}

}

//单个图片识别

int CANNDlg::recogFun(CString img_path, int targetNum, int orderNum)

{

int i,j,k,ii,jj;

//读入原图

CString strPicName;

strPicName.Format("%d_%d.bmp",targetNum,orderNum);

img_path += strPicName;

//读入图片数据

getPic(img_path);

//BP前向过程

bpForward();

//写入并返回结果

//freopen("result.txt","a",stdout);

float bigO = node2[0].O;

int bigN = 0;

for(i=0;i

{

printf(" %d-%.3lf ",i,node2[i].O);

if(bigO

{

bigO=node2[i].O;

bigN=i;

}

}

printf("%d_%d.bmp :%d\n",targetNum,orderNum,bigN);

//fclose(stdout);

return bigN;

}

//训练集验证准确率

float CANNDlg::my_verify(CString m_path)

{

int i,j,k;

int right=0;

for(i=0;i

{

for(j=beginOrder;j

{

int temp=recogFun(m_path,i,j);

if(temp==i)

right++;

}

}

float accuracy=float(right)/float((beginOrder-endOrder)*N2N);

return accuracy;

}

//保存网络到文件

void CANNDlg::saveNet(CString mySavePath)

{

int i,j,k;

freopen(mySavePath,"w",stdout);

//保存偏量

printf("biasnode1\n");

for(i=0;i

printf("%.2f ",node1[i].bias);

printf("\n");

printf("biasnode2\n");

for(i=0;i

printf("%.2f ",node2[i].bias);

printf("\n");

//保存权重

printf("w01[N0N][N1N]\n");

for(i=0;i

{

for(j=0;j

{

printf("%.2f ",w01[i][j]);

}

printf("\n");

}

printf("w12[N1N][N2N]\n");

for(i=0;i

{

for(j=0;j

{

printf("%.2f ",w12[i][j]);

}

printf("\n");

}

fclose(stdout);

}

//训练网络

void CANNDlg::OnBnClicked_trainnet()

{

CString m_path;

CFileDialog openhclDlg(TRUE,_T("bmp"),NULL,0,_T("bmp位图文件|*.*||"),this);

if(openhclDlg.DoModal()==IDOK)

{

m_path=openhclDlg.GetPathName(); //得到文件目录

}

else

return;

m_path=m_path.Left(m_path.GetLength()-1);

//枚举训练样本并进行训练

int i,j,k;

int t_start,t_end;

t_start=t_end=clock();

float iterationT = 2000;

for(k=1;k<=iterationT;k++)

{

for(i=0;i

{

for(j=beginOrder;j

{

l=1*(iterationT-k)/iterationT;// + float(rand()%100)/1000.0;

train(m_path,i,j);

}

}

CString tempk;

if(k%100==0)

{

int t_preEnd=t_end;

t_end=clock();

float accuracy=my_verify(m_path);

tempk.Format("k=%d#time=%ds#%.2f#net.txt",k,(t_end-t_start)/1000,accuracy);

saveNet(tempk);

}

}

}

//识别测试

void CANNDlg::OnBnClicked_recogtest()

{

int i,j,k;

//设置路径

CString m_path;

CFileDialog openhclDlg(TRUE,_T("bmp"),NULL,0,_T("bmp位图文件|*.*||"),this);

if(openhclDlg.DoModal()==IDOK)

m_path=openhclDlg.GetPathName();

else return;

m_path=m_path.Left(m_path.GetLength()-1);

//测试识别并保存结果

freopen("result.txt","w",stdout);

int numRight;

numRight = 0;

for(i=0;i

{

for(j=endOrder;j<800;j++)

{

int recRes=recogFun(m_path,i,j);

printf("%d_%d.bmp :%d\n",i,j,recRes);

if(recRes==i)

numRight++;

}

}

int testNum = (800-endOrder)*N2N;

float accuracy = float(numRight)/float(testNum);

printf("共%d张图片,正确%d张,准确率%f\n",testNum,numRight,accuracy);

CString strMsg;

strMsg.Format("共%d张图片,正确%d张,准确率%f\n",testNum,numRight,accuracy);

MessageBox("recog done"+strMsg);

fclose(stdout);

system("result.txt");

system("net.txt");

}

//读入网络

void CANNDlg::OnBnClicked_readnet()

{

freopen("net.txt","r",stdin);

int i,j,k;

char cc[1024];

//node1bias

cin.getline(cc,1024);

for(i=0;i

scanf("%f ",&node1[i].bias);

//node2bias

cin.getline(cc,1024);

for(i=0;i

scanf("%f ",&node2[i].bias);

//w01[N0N][N1N]

cin.getline(cc,1024);

for(i=0;i

for(j=0;j

scanf("%f ",&w01[i][j]);

//w12[N1N][N2N]

cin.getline(cc,1024);

for(i=0;i

for(j=0;j

scanf("%f ",&w12[i][j]);

fclose(stdin);

MessageBox("read done!");

}

//保存网络

void CANNDlg::OnBnClicked_savenet()

{

saveNet("net.txt");

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值