Permalink
Browse files

added support for arbitrary strides during convolution

  • Loading branch information...
khalednasr committed May 31, 2014
1 parent 7ce25f0 commit 9439b742f70bb0da00ece9b00eaaf31ab7dadcc8
@@ -41,14 +41,27 @@
using namespace shogun;
CConvolutionalFeatureMap::CConvolutionalFeatureMap(
int32_t width, int32_t height,
int32_t radius_x, int32_t radius_y, int32_t index,
int32_t input_width, int32_t input_height,
int32_t radius_x, int32_t radius_y,
int32_t stride_x, int32_t stride_y,
int32_t index,
EConvMapActivationFunction function) :
m_width(width), m_height(height),
m_radius_x(radius_x), m_radius_y(radius_y), m_index(index),
m_activation_function(function)
m_input_width(input_width), m_input_height(input_height),
m_radius_x(radius_x), m_radius_y(radius_y),
m_stride_x(stride_x), m_stride_y(stride_y),
m_index(index),
m_activation_function(function)
{
m_output_width = m_input_width/m_stride_x;
m_output_height = m_input_height/m_stride_y;
m_input_num_neurons = m_input_width*m_input_height;
m_output_num_neurons = m_output_width*m_output_height;
m_row_offset = m_index*m_output_num_neurons;
m_filter_width = 2*m_radius_x+1;
m_filter_height = 2*m_radius_y+1;
}
void CConvolutionalFeatureMap::compute_activations(
@@ -58,28 +71,27 @@ void CConvolutionalFeatureMap::compute_activations(
SGMatrix<float64_t> activations,
SGMatrix<float64_t> buffer)
{
int32_t num_neurons = m_width*m_height;
int32_t row_offset = m_index*num_neurons;
int32_t batch_size = activations.num_cols;
// sum up all the inputs into the buffer
buffer.zero();
buffer.zero();
for (int32_t l=0; l<input_indices.vlen; l++)
{
CNeuralLayer* layer =
(CNeuralLayer*)layers->element(input_indices[l]);
SGMatrix<float64_t> input = layer->get_activations();
int32_t num_maps = layer->get_num_neurons()/num_neurons;
int32_t num_maps = layer->get_num_neurons()/m_input_num_neurons;
for (int32_t m=0; m<num_maps; m++)
{
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_input_num_neurons; i++)
{
for (int32_t j=0; j<batch_size; j++)
{
buffer(i+row_offset,j) += input(i+m*num_neurons,j);
buffer(i,j) +=
input(i+m*m_input_num_neurons,j);
}
}
}
@@ -88,33 +100,34 @@ void CConvolutionalFeatureMap::compute_activations(
}
SGMatrix<float64_t> weights_matrix(
parameters.vector+num_neurons, 2*m_radius_x+1, 2*m_radius_y+1, false);
parameters.vector+m_output_num_neurons,
m_filter_height, m_filter_width, false);
convolve(buffer, weights_matrix, activations,
false, true, row_offset, row_offset);
false, true, 0, m_row_offset);
float64_t* biases = parameters.vector;
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_output_num_neurons; i++)
{
for (int32_t j=0; j<batch_size; j++)
{
activations(i+row_offset,j) += biases[i];
activations(i+m_row_offset,j) += biases[i];
}
}
if (m_activation_function==CMAF_LOGISTIC)
{
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_output_num_neurons; i++)
for (int32_t j=0; j<batch_size; j++)
activations(i+row_offset,j) =
1.0/(1.0+CMath::exp(-1.0*activations(i+row_offset,j)));
activations(i+m_row_offset,j) =
1.0/(1.0+CMath::exp(-1.0*activations(i+m_row_offset,j)));
}
else if (m_activation_function==CMAF_RECTIFIED_LINEAR)
{
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_output_num_neurons; i++)
for (int32_t j=0; j<batch_size; j++)
activations(i+row_offset,j) =
CMath::max<float64_t>(0, activations(i+row_offset,j));
activations(i+m_row_offset,j) =
CMath::max<float64_t>(0, activations(i+m_row_offset,j));
}
}
@@ -126,43 +139,41 @@ void CConvolutionalFeatureMap::compute_gradients(
SGVector< int32_t > input_indices,
SGVector< float64_t > parameter_gradients)
{
int32_t num_neurons = m_width*m_height;
int32_t batch_size = activation_gradients.num_cols;
int32_t row_offset = m_index*num_neurons;
if (m_activation_function==CMAF_LOGISTIC)
{
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_output_num_neurons; i++)
{
for (int32_t j=0; j<batch_size; j++)
{
activation_gradients(i+row_offset,j) *=
activation_gradients(i+row_offset,j) *
(1.0-activation_gradients(i+row_offset,j));
activation_gradients(i+m_row_offset,j) *=
activation_gradients(i+m_row_offset,j) *
(1.0-activation_gradients(i+m_row_offset,j));
}
}
}
else if (m_activation_function==CMAF_RECTIFIED_LINEAR)
{
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_output_num_neurons; i++)
for (int32_t j=0; j<batch_size; j++)
if (activations(i+row_offset,j)==0)
activation_gradients(i+row_offset,j) = 0;
if (activations(i+m_row_offset,j)==0)
activation_gradients(i+m_row_offset,j) = 0;
}
float64_t* bias_gradients = parameter_gradients.vector;
for (int32_t i=0; i<num_neurons; i++)
for (int32_t i=0; i<m_output_num_neurons; i++)
{
bias_gradients[i] = 0;
for (int32_t j=0; j<batch_size; j++)
bias_gradients[i] += activation_gradients(i+row_offset,j);
bias_gradients[i] += activation_gradients(i+m_row_offset,j);
}
SGMatrix<float64_t> W(parameters.vector + num_neurons,
2*m_radius_x+1, 2*m_radius_y+1, false);
SGMatrix<float64_t> W(parameters.vector + m_output_num_neurons,
m_filter_height, m_filter_width, false);
SGMatrix<float64_t> WG(parameter_gradients.vector + num_neurons,
2*m_radius_x+1, 2*m_radius_y+1, false);
SGMatrix<float64_t> WG(parameter_gradients.vector + m_output_num_neurons,
m_filter_height, m_filter_width, false);
WG.zero();
for (int32_t l=0; l<input_indices.vlen; l++)
@@ -172,17 +183,17 @@ void CConvolutionalFeatureMap::compute_gradients(
SGMatrix<float64_t> input = layer->get_activations();
int32_t num_maps = layer->get_num_neurons()/num_neurons;
int32_t num_maps = layer->get_num_neurons()/m_input_num_neurons;
for (int32_t m=0; m<num_maps; m++)
{
compute_weight_gradients(layer->get_activations(),
activation_gradients, WG, m*num_neurons, row_offset);
activation_gradients, WG, m*m_input_num_neurons, m_row_offset);
if (!layer->is_input())
convolve(activation_gradients, W,
layer->get_activation_gradients(), true, false,
row_offset, m*num_neurons);
m_row_offset, m*m_input_num_neurons);
}
SG_UNREF(layer);
@@ -195,33 +206,28 @@ void CConvolutionalFeatureMap::pool_activations(
SGMatrix< float64_t > pooled_activations,
SGMatrix< float64_t > max_indices)
{
int32_t activations_row_offset = m_index*m_width*m_height;
int32_t pooled_activations_row_offset =
activations_row_offset/(pooling_width*pooling_height);
int32_t pooled_row_offset = m_row_offset/(pooling_width*pooling_height);
for (int32_t i=0; i<pooled_activations.num_cols; i++)
{
SGMatrix<float64_t> image(
activations.matrix+i*activations.num_rows + activations_row_offset,
m_height, m_width, false);
activations.matrix+i*activations.num_rows + m_row_offset,
m_output_height, m_output_width, false);
SGMatrix<float64_t> result(
pooled_activations.matrix+i*pooled_activations.num_rows
+ pooled_activations_row_offset,
m_height/pooling_height, m_width/pooling_width, false);
pooled_activations.matrix+i*pooled_activations.num_rows + pooled_row_offset,
m_output_height/pooling_height, m_output_width/pooling_width, false);
SGMatrix<float64_t> indices(
max_indices.matrix+i*max_indices.num_rows
+ pooled_activations_row_offset,
m_height/pooling_height, m_width/pooling_width, false);
max_indices.matrix+i*max_indices.num_rows + pooled_row_offset,
m_output_height/pooling_height, m_output_width/pooling_width, false);
for (int32_t x=0; x<m_width; x+=pooling_width)
for (int32_t x=0; x<m_output_width; x+=pooling_width)
{
for (int32_t y=0; y<m_height; y+=pooling_height)
for (int32_t y=0; y<m_output_height; y+=pooling_height)
{
float64_t max = image(y,x);
int32_t max_index = activations_row_offset+y+x*image.num_rows;
int32_t max_index = m_row_offset+y+x*image.num_rows;
for (int32_t x1=x; x1<x+pooling_width; x1++)
{
@@ -230,7 +236,7 @@ void CConvolutionalFeatureMap::pool_activations(
if (image(y1,x1) > max)
{
max = image(y1,x1);
max_index = activations_row_offset+y1+x1*image.num_rows;
max_index = m_row_offset+y1+x1*image.num_rows;
}
}
}
@@ -254,17 +260,17 @@ void CConvolutionalFeatureMap::convolve(
{
SGMatrix<float64_t> image(
inputs.matrix+i*inputs.num_rows + inputs_row_offset,
m_height, m_width, false);
m_input_height, m_input_width, false);
SGMatrix<float64_t> result(
outputs.matrix+i*outputs.num_rows + outputs_row_offset,
m_height, m_width, false);
m_output_height, m_output_width, false);
for (int32_t x=0; x<m_width; x++)
for (int32_t x=0; x<m_input_width; x+=m_stride_x)
{
for (int32_t y=0; y<m_height; y++)
for (int32_t y=0; y<m_input_height; y+=m_stride_y)
{
float64_t sum = reset_output ? 0 : result(y,x);
float64_t sum = reset_output ? 0 : result(y/m_stride_y,x/m_stride_x);
for (int32_t x1=x-m_radius_x; x1<=x+m_radius_x; x1++)
{
for (int32_t y1=y-m_radius_y; y1<=y+m_radius_y; y1++)
@@ -280,7 +286,7 @@ void CConvolutionalFeatureMap::convolve(
}
}
}
result(y,x) = sum;
result(y/m_stride_y,x/m_stride_x) = sum;
}
}
}
@@ -297,23 +303,23 @@ void CConvolutionalFeatureMap::compute_weight_gradients(
{
SGMatrix<float64_t> image(
inputs.matrix+i*inputs.num_rows + inputs_row_offset,
m_height, m_width, false);
m_input_height, m_input_width, false);
SGMatrix<float64_t> LG_image(
local_gradients.matrix+i*local_gradients.num_rows
+ local_gradients_row_offset, m_height, m_width, false);
+ local_gradients_row_offset, m_output_height, m_output_width, false);
for (int32_t x=0; x<m_width; x++)
for (int32_t x=0; x<m_input_width; x+=m_stride_x)
{
for (int32_t y=0; y<m_height; y++)
for (int32_t y=0; y<m_input_height; y+=m_stride_y)
{
for (int32_t x1=x-m_radius_x; x1<=x+m_radius_x; x1++)
{
for (int32_t y1=y-m_radius_y; y1<=y+m_radius_y; y1++)
{
if (x1>=0 && y1>=0 && x1<image.num_cols && y1<image.num_rows)
weight_gradients(m_radius_y-y1+y,m_radius_x-x1+x) +=
LG_image(y,x)*image(y1,x1);
LG_image(y/m_stride_y,x/m_stride_x)*image(y1,x1);
}
}
}
Oops, something went wrong.

0 comments on commit 9439b74

Please sign in to comment.