float rand_normal()
{
static int haveSpare = 0;
static double rand1, rand2;
// z0和z1都用了,并不是只用z0或只用z1
if (haveSpare)
{
haveSpare = 0;
// z1 = sqrt(-2 * log(rand1)) * sin(rand2)
return sqrt(rand1) * sin(rand2);
}
haveSpare = 1;
// 产生0~1的随机数
rand1 = rand() / ((double)RAND_MAX);
if (rand1 < 1e-100) rand1 = 1e-100; // 不能太小
rand1 = -2 * log(rand1);
// 产生0~2*PI之间的随机数
rand2 = (rand() / ((double)RAND_MAX)) * TWO_PI;
// z0 = sqrt(-2 * log(rand1)) * cos(rand2)
return sqrt(rand1) * cos(rand2);
}
float rand_uniform(float min, float max)
{
if (max < min) {
float swap = min;
min = max;
max = swap;
}
return ((float)rand() / RAND_MAX * (max - min)) + min;
}
void mean_cpu(float *x, int batch, int filters, int spatial, float *mean)
{
// scale即求均值中的分母项
float scale = 1./(batch * spatial);
int i,j,k;
// 外层循环次数为filters
for(i = 0; i < filters; ++i){
mean[i] = 0;
// 中层循环次数为batch
for(j = 0; j < batch; ++j){
// 内层循环即叠加一张输出特征图的所有像素值
for(k = 0; k < spatial; ++k){
int index = j*filters*spatial + i*spatial + k;
mean[i] += x[index];
}
}
mean[i] *= scale;
}
}
void variance_cpu(float *x, float *mean, int batch, int filters, int spatial, float *variance)
{
float scale = 1./(batch * spatial - 1);
int i,j,k;
for(i = 0; i < filters; ++i){
variance[i] = 0;
for(j = 0; j < batch; ++j){
for(k = 0; k < spatial; ++k){
int index = j*filters*spatial + i*spatial + k;
variance[i] += pow((x[index] - mean[i]), 2);
}
}
variance[i] *= scale;
}
}
void normalize_cpu(float *x, float *mean, float *variance, int batch, int filters, int spatial)
{
int b, f, i;
for(b = 0; b < batch; ++b){
for(f = 0; f < filters; ++f){
for(i = 0; i < spatial; ++i){
int index = b*filters*spatial + f*spatial + i;
x[index] = (x[index] - mean[f])/(sqrt(variance[f]) + .000001f);
}
}
}
}
void axpy_cpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY)
{
int i;
for(i = 0; i < N; ++i) Y[i*INCY] += ALPHA*X[i*INCX];
}
void scal_cpu(int N, float ALPHA, float *X, int INCX)
{
int i;
for(i = 0; i < N; ++i) X[i*INCX] *= ALPHA;
}
void fill_cpu(int N, float ALPHA, float *X, int INCX)
{
int i;
for(i = 0; i < N; ++i) X[i*INCX] = ALPHA;
}
void copy_cpu(int N, float *X, int INCX, float *Y, int INCY)
{
int i;
for(i = 0; i < N; ++i) Y[i*INCY] = X[i*INCX];
}
void l2_cpu(int n, float *pred, float *truth, float *delta, float *error)
{
int i;
for(i = 0; i < n; ++i){
float diff = truth[i] - pred[i];
error[i] = diff * diff;
delta[i] = diff;
}
}