关于参数的获取:已经在上篇博客中提出,请参照相关链接请点击
一、分析输入输出
1、手写体输入为28x28的黑白图片,所以输入为784个x 2、输出为识别0-9的数字的概率,所以有10个输出 3、输入只能是-1~1的小数,主要是防止计算溢出
二、分析神经网络层数
如果只是一层,输入784,输出10,中间能记录的神经元只能是10个,很难达到识别0-9这10个数字,所以2层比较合适
三、分析神经元数量
隐藏层神经元数量没有特定的计算方法,主要是靠经验测试,当然设置过多会导致参数太多训练比较困难,太少会达不到识别效果
1、第一层:第一层的神经元没有绝对,这里给64,主要是方便后面上fpga使用
2、第二层:因为一个神经元只有一个输出,而输出的数量是0-9的数字概率,所以第二层神经元为10
四、分析参数数量
1、第一层:因为输入层28x28图片,所以一个神经元有784个w,1个b,64个神经元对应64x784个w,64个b
2、第二层:第一层的64个神经元对应64个输出,第二层输入则为64,所以第二层一个神经元有64个w,1个b,64个神经元对应64x10个w,10个b
五、分析传递过程连接方式
1、第一层:单神经元计算,每个像素点w0x0+w1x1…w783x783+b经过激活函数输出a1,然后拓展给第一层所有神经元
2、第二层:第一层输出a0,a1…a63,单神经元计算,每个像素点w0a0+w1a1…w63a63+b经过激活函数输出a2,然后拓展给第二层所有神经元
注意:推理一般是为了拿到推理结果,不关心概率,所以为了节省运行时间,我们把最后一层激活函数省略
六、代码框架
代码框架: 输入 图片数组,第一层权重,第一层偏置,第二层权重,第二层偏置 输出 推理结果 实现逻辑: 第一层神经网络计算 第二层神经网络计算 查询最大概率的结果输出 //全连接推理 //传入图片大小img 2828 //第一层的权重参数78464 偏置参数64个 输出64个 //第二层的权重参数64*10 偏置参数10 //找到最大值结果,并返回0-9
int my_predict(float *img, float *w1, float *b1, float *w2, float *b2)
{
}
七、完整代码实现:
#include <stdio.h>
#include <time.h>
#include "input_0.h"
#include "input_1.h"
#include "input_2.h"
#include "input_3.h"
#include "input_4.h"
#include "input_5.h"
#include "input_6.h"
#include "input_7.h"
#include "input_8.h"
#include "input_9.h"
#include <windows.h>
#include "layer1_weight.h"
#include "layer1_bais.h"
#include "layer2_weight.h"
#include "layer2_bais.h"
int predict(float *img,float *w1,float *b1,float *w2,float *b2)
{
int i,j;
float y;
float a1[64],a2[10];
int ret;
for(i=0;i<64;i++)
{
y = 0.0;
for(j=0;j<784;j++)
{
y = y + w1[j*64+i]*img[j];
}
y = y + b1[i];
y = y > 0?y:0;
a1[i] = y;
}
for(i=0;i<10;i++)
{
y = 0.0;
for(j=0;j<64;j++)
{
y = y + w2[i+10*j]*a1[j];
}
y = y + b2[i];
a2[i] = y;
}
y = 0.0;
for(i=0;i<10;i++)
{
if(a2[i] > y)
{
y = a2[i];
ret = i;
}
}
return ret;
}
void full_connect_test()
{
int ret;
float *imgx[10]={
input_0,
input_1,
input_2,
input_3,
input_4,
input_5,
input_6,
input_7,
input_8,
input_9
};
double run_time;
LARGE_INTEGER time_start;
LARGE_INTEGER time_over;
double dqFreq;
LARGE_INTEGER f;
QueryPerformanceFrequency(&f);
dqFreq=(double)f.QuadPart;
for(int i=0;i<10;i++)
{
QueryPerformanceCounter(&time_start);
ret = predict(imgx[i],layer1_weight,layer1_bais,layer2_weight,layer2_bais);
QueryPerformanceCounter(&time_over);
run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
printf("\nrun_time:%fus\n",run_time);
printf("input is %d ,predict:%d\n",i,ret);
}
}
int main()
{
full_connect_test();
return 0;
}
运行结果如下:
|