Skip to content

Commit

Permalink
Improve numerical stability of variance computation in MVNLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
kkhoot committed Oct 11, 2015
1 parent 8ef3d63 commit ee5191b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 60 deletions.
42 changes: 12 additions & 30 deletions src/caffe/layers/mvn_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,21 @@ void MVNLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,

int dim = bottom[0]->count() / num;

if (this->layer_param_.mvn_param().normalize_variance()) {
// put the squares of bottom into temp_
caffe_powx(bottom[0]->count(), bottom_data, Dtype(2),
temp_.mutable_cpu_data());
// subtract mean
caffe_cpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, bottom_data,
sum_multiplier_.cpu_data(), 0., mean_.mutable_cpu_data()); // EX
caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, dim, 1, -1.,
mean_.cpu_data(), sum_multiplier_.cpu_data(), 0.,
temp_.mutable_cpu_data());
caffe_add(temp_.count(), bottom_data, temp_.cpu_data(), top_data); // X-EX

// computes variance using var(X) = E(X^2) - (EX)^2
caffe_cpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, bottom_data,
sum_multiplier_.cpu_data(), 0., mean_.mutable_cpu_data()); // EX
if (this->layer_param_.mvn_param().normalize_variance()) {
// compute variance using var(X) = E((X-EX)^2)
caffe_powx(bottom[0]->count(), top_data, Dtype(2),
temp_.mutable_cpu_data()); // (X-EX)^2
caffe_cpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, temp_.cpu_data(),
sum_multiplier_.cpu_data(), 0.,
variance_.mutable_cpu_data()); // E(X^2)
caffe_powx(mean_.count(), mean_.cpu_data(), Dtype(2),
temp_.mutable_cpu_data()); // (EX)^2
caffe_sub(mean_.count(), variance_.cpu_data(), temp_.cpu_data(),
variance_.mutable_cpu_data()); // variance

// do mean and variance normalization
// subtract mean
caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, dim, 1, -1.,
mean_.cpu_data(), sum_multiplier_.cpu_data(), 0.,
temp_.mutable_cpu_data());

caffe_add(temp_.count(), bottom_data, temp_.cpu_data(), top_data);
variance_.mutable_cpu_data()); // E((X-EX)^2)

// normalize variance
caffe_powx(variance_.count(), variance_.cpu_data(), Dtype(0.5),
Expand All @@ -77,16 +69,6 @@ void MVNLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
temp_.mutable_cpu_data());

caffe_div(temp_.count(), top_data, temp_.cpu_data(), top_data);
} else {
caffe_cpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, bottom_data,
sum_multiplier_.cpu_data(), 0., mean_.mutable_cpu_data()); // EX

// subtract mean
caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, dim, 1, -1.,
mean_.cpu_data(), sum_multiplier_.cpu_data(), 0.,
temp_.mutable_cpu_data());

caffe_add(temp_.count(), bottom_data, temp_.cpu_data(), top_data);
}
}

Expand Down
43 changes: 13 additions & 30 deletions src/caffe/layers/mvn_layer.cu
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,22 @@ void MVNLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,

int dim = bottom[0]->count() / num;

if (this->layer_param_.mvn_param().normalize_variance()) {
// put the squares of bottom into temp_
caffe_gpu_powx(bottom[0]->count(), bottom_data, Dtype(2),
temp_.mutable_gpu_data());
// subtract mean
caffe_gpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, bottom_data,
sum_multiplier_.gpu_data(), 0., mean_.mutable_gpu_data()); // EX
caffe_gpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, dim, 1, -1.,
mean_.gpu_data(), sum_multiplier_.gpu_data(), 0.,
temp_.mutable_gpu_data());
caffe_gpu_add(temp_.count(), bottom_data, temp_.gpu_data(),
top_data); // X-EX

// computes variance using var(X) = E(X^2) - (EX)^2
caffe_gpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, bottom_data,
sum_multiplier_.gpu_data(), 0., mean_.mutable_gpu_data()); // EX
if (this->layer_param_.mvn_param().normalize_variance()) {
// compute variance using var(X) = E((X-EX)^2)
caffe_gpu_powx(bottom[0]->count(), top_data, Dtype(2),
temp_.mutable_gpu_data()); // (X-EX)^2
caffe_gpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, temp_.gpu_data(),
sum_multiplier_.gpu_data(), 0.,
variance_.mutable_gpu_data()); // E(X^2)
caffe_gpu_powx(mean_.count(), mean_.gpu_data(), Dtype(2),
temp_.mutable_gpu_data()); // (EX)^2
caffe_gpu_sub(mean_.count(), variance_.gpu_data(), temp_.gpu_data(),
variance_.mutable_gpu_data()); // variance

// do mean and variance normalization
// subtract mean
caffe_gpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, dim, 1, -1.,
mean_.gpu_data(), sum_multiplier_.gpu_data(), 0.,
temp_.mutable_gpu_data());

caffe_gpu_add(temp_.count(), bottom_data, temp_.gpu_data(), top_data);
variance_.mutable_gpu_data()); // E((X-EX)^2)

// normalize variance
caffe_gpu_powx(variance_.count(), variance_.gpu_data(), Dtype(0.5),
Expand All @@ -55,16 +48,6 @@ void MVNLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
temp_.mutable_gpu_data());

caffe_gpu_div(temp_.count(), top_data, temp_.gpu_data(), top_data);
} else {
caffe_gpu_gemv<Dtype>(CblasNoTrans, num, dim, 1. / dim, bottom_data,
sum_multiplier_.gpu_data(), 0., mean_.mutable_gpu_data()); // EX

// subtract mean
caffe_gpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, dim, 1, -1.,
mean_.gpu_data(), sum_multiplier_.gpu_data(), 0.,
temp_.mutable_gpu_data());

caffe_gpu_add(temp_.count(), bottom_data, temp_.gpu_data(), top_data);
}
}

Expand Down

0 comments on commit ee5191b

Please sign in to comment.