batch,从学习dos时,就认识了这个单词,它叫做批处理!
现在我发现他与并行或多线程是有差别的!
我们前头所有程序凡是用到batch,均是如下操作,比如batch=3:
输入一张图片,forward一次,backward一次
再输入一张图片,forward一次,backward一次,梯度累加第一次
再输入一张图片,forward一次,backward一次,梯度累加第二次
好batch=3了,我们更新一次每层的权值:
在我们极简cnn上体现如下:
for(batch=0;batch<3;batch++)
{
wcnn的偏差[1][0] += E偏导zII * aI[0];//梯度累加3次
wcnn的偏差[1][1] += E偏导zII * aI[1];
wcnn的偏差[1][2] += E偏导zII * aI[2];
wcnn的偏差[1][3]+=E偏导zII * aI[3];
}
————————————————
for(batch=0;batch<3;batch++)
{//梯度累加3次
wcnn的偏差[0][0] += delta11*a0[0] + delta12*a0[1] + delta21*a0[3] + delta22*a0[4];//0,1,3,4
wcnn的偏差[0][1] += delta11*a0[1] + delta12*a0[2] + delta21*a0[4] + delta22*a0[5];//1,2,4,5
wcnn的偏差[0][2] += delta11*a0[3] + delta12*a0[4] + delta21*a0[6] + delta22*a0[7];//3,4,6,7
wcnn的偏差[0][3]+=delta11*a0[4] + delta12*a0[5] + delta21*a0[7] + delta22*a0[8];//4,5,7,8
}
————————————————
//0,上面batch执行了三次,但更新只执行一次
//w1,第二层的一个卷积核
for (int i = 0; i < 4; i++)//卷积核执行更新一次
{
wcnn[1][i] = wcnn[1][i] - 常数a * wcnn的偏差[1][i]/3;
}
//w0,第一层的一个卷积核
for (int i = 0; i < 4; i++)//卷积核执行更新一次
{
wcnn[0][i] = wcnn[0][i] - 常数a * wcnn的偏差[0][i]/3;
}
以上就是我们的批梯度下降法,而多线程怎么做呢?
假定我们也开启三个线程,每个线程处理一幅图片,关键是这个线程动作是并发的!
如果说上面batch处理是一个人,轮流做了3次
而线程是3个人,每个人做一次!这就是多线程并发的好处,人多力量大,速度还快!
每个线程只做一次:
wcnn的偏差[1][0] += E偏导zII * aI[0];//梯度累加3次
wcnn的偏差[1][1] += E偏导zII * aI[1];
wcnn的偏差[1][2] += E偏导zII * aI[2];
wcnn的偏差[1][3]+=E偏导zII * aI[3];
以及:
wcnn的偏差[0][0] += delta11*a0[0] + delta12*a0[1] + delta21*a0[3] + delta22*a0[4];//0,1,3,4
wcnn的偏差[0][1] += delta11*a0[1] + delta12*a0[2] + delta21*a0[4] + delta22*a0[5];//1,2,4,5
wcnn的偏差[0][2] += delta11*a0[3] + delta12*a0[4] + delta21*a0[6] + delta22*a0[7];//3,4,6,7
wcnn的偏差[0][3]+=delta11*a0[4] + delta12*a0[5] + delta21*a0[7] + delta22*a0[8];//4,5,7,8
最后我们要判断线程结束了,
比如说:if(线程1执行完成&&线程2执行完成&&线程3执行完成==1),再执行:
for (int i = 0; i < 4; i++)//卷积核执行更新一次
{
wcnn[1][i] = wcnn[1][i] - 常数a * wcnn的偏差[1][i]/3;
}
//w0,第一层的一个卷积核
for (int i = 0; i < 4; i++)//卷积核执行更新一次
{
wcnn[0][i] = wcnn[0][i] - 常数a * wcnn的偏差[0][i]/3;
}
这样看来,多线程会比批处理batch快很多!比如开启10个线程时,差别会更大!
以后,我的程序会超这个方向改进!