convolver 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99ab37662a25bbb5d060946aff94c533e336db14
4
- data.tar.gz: 5ef276e831151248a543a6f33adbb3524c82a37f
3
+ metadata.gz: 914f6026eed57b309e6a10b58b865b92cce1216c
4
+ data.tar.gz: 4d2eff7796eddaf75629ec5d90fe1e4e68681d39
5
5
  SHA512:
6
- metadata.gz: c97668640eb1ac262397b20915e2739ec3617d0c13c6e06a70a5e7306f8bcb85553ae7022160dea7e63c2d9a7325e2e45d641f7949de6c694b5a3eff9f73f54b
7
- data.tar.gz: a3f26841861e48034835af3ed730c1a0cae33d565287c4197f772bf7a1ee6de59cfe0c91abfb75fd5d9789fe54a83f34769fb0700ff22e96302571f0b5715099
6
+ metadata.gz: 7fd430b3292eef1f7246bfb681eb0532d5826b91937c1b9db2c9ccec1dc03f9379c25b863d24a1e531c2922ca032ec290e102371f2d8cff8df149babd0297ca6
7
+ data.tar.gz: fe553601923c635c3f186676d4571c644b5bd6978654176acce4bdeeadeac77dae1eaae796c4b2059c0aacfdec044c7d4e4381cebd0d93436844dd6ff2a26818
data/README.md CHANGED
@@ -1,21 +1,18 @@
1
1
  # Convolver
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/convolver.png)](http://badge.fury.io/rb/convolver)
3
4
  [![Build Status](https://travis-ci.org/neilslater/convolver.png?branch=master)](http://travis-ci.org/neilslater/convolver)
5
+ [![Dependency Status](https://gemnasium.com/neilslater/convolver.png)](https://gemnasium.com/neilslater/convolver)
4
6
 
5
- Calculates discrete convolution between two multi-dimensional arrays.
7
+ Calculates discrete convolution between two multi-dimensional arrays of floats.
6
8
  See http://en.wikipedia.org/wiki/Convolution
7
9
 
8
- ## Planned features
9
-
10
- The *convolver* gem will eventually contain a basic kit for creating, training and running
11
- convolutional neural networks. As a side effect of this plan, it currently contains code for
12
- calculating floating-point convolutions for other types of analysis.
13
-
14
10
  ## Installation
15
11
 
16
12
  ### Dependency: FFTW3
17
13
 
18
- Before you install *convolver*, you should install FFTW3. See http://www.fftw.org/ for details.
14
+ Before you install *convolver*, you should install the FFTW3 library on your system.
15
+ See http://www.fftw.org/ for details.
19
16
 
20
17
  ### Installing the gem
21
18
 
@@ -41,10 +38,10 @@ Basic convolution:
41
38
  => NArray.float(2): [ 0.19, 0.27 ]
42
39
 
43
40
  * Convolver only works on single-precision floats internally. It will cast NArray types to this, if
44
- possible, prior to calculating.
41
+ possible, prior to calculating. For best speed, use NArray.sfloat arrays.
45
42
 
46
- * The output is smaller than the input, each dimension is reduced by 1 less than the width of the
47
- kernel in the same dimension.
43
+ * The output is smaller than the input, it only contains fully-calculated values. The output size
44
+ is the original size, minus the kernel size, plus 1, in each dimension.
48
45
 
49
46
  * Convolver expects input a and kernel b to have the same rank, and for the kernel to be same size
50
47
  or smaller in all dimensions as the input.
@@ -54,6 +51,11 @@ small convolutions are processed directly by multiplying out all combinations an
54
51
  and large convolutions are processed using FFTW3 to convert to frequency space where convolution
55
52
  is simpler and faster to calculate, then convert back.
56
53
 
54
+ ## Convolutional Neural Nets
55
+
56
+ Code for CNNs in Ruby, based on the convolve_basic method from this gem, is planned for a
57
+ new gem.
58
+
57
59
  ## Contributing
58
60
 
59
61
  1. Fork it
@@ -7,7 +7,6 @@
7
7
 
8
8
  #include "narray_shared.h"
9
9
  #include "convolve_raw.h"
10
- #include "cnn_components.h"
11
10
 
12
11
  ////////////////////////////////////////////////////////////////////////////////////////////////////
13
12
 
@@ -111,63 +110,10 @@ static VALUE narray_convolve( VALUE self, VALUE a, VALUE b ) {
111
110
  return val_c;
112
111
  }
113
112
 
114
- /* @overload nn_run_layer( inputs, weights, thresholds )
115
- * Calculates activations of a fully-connected neural network layer. The transfer function after
116
- * summing weights and applying threshold is a "ReLU", equivalent to
117
- * y = x < 0.0 ? 0.0 : x
118
- * this is less sophisticated than many other neural net functions (such as sigma), but is fast to
119
- * calculate and to train.
120
- * @param [NArray] inputs must be rank 1 array of floats
121
- * @param [NArray] weights must be rank 2 array of floats, with first dimension size of inputs, and second dimension size equal to number of outputs
122
- * @param [NArray] thresholds must be rank 1 array of floats, size equal to number of outputs desired
123
- * @return [NArray] neuron activations
124
- */
125
- static VALUE narray_nn_run_single_layer( VALUE self, VALUE inputs, VALUE weights, VALUE thresholds ) {
126
- struct NARRAY *na_inputs, *na_weights, *na_thresholds, *na_outputs;
127
- volatile VALUE val_inputs, val_weights, val_thresholds, val_outputs;
128
- int input_size, output_size;
129
- int output_shape[1];
130
-
131
- val_inputs = na_cast_object(inputs, NA_SFLOAT);
132
- GetNArray( val_inputs, na_inputs );
133
- if ( na_inputs->rank != 1 ) {
134
- rb_raise( rb_eArgError, "input must be array of rank 1" );
135
- }
136
- input_size = na_inputs->total;
137
-
138
- val_weights = na_cast_object(weights, NA_SFLOAT);
139
- GetNArray( val_weights, na_weights );
140
- if ( na_weights->rank != 2 ) {
141
- rb_raise( rb_eArgError, "weights must be array of rank 2" );
142
- }
143
- if ( na_weights->shape[0] != input_size ) {
144
- rb_raise( rb_eArgError, "weights shape mismatch, expected %d across, got %d", input_size, na_weights->shape[0] );
145
- }
146
- output_size = na_weights->shape[1];
147
-
148
- val_thresholds = na_cast_object(thresholds, NA_SFLOAT);
149
- GetNArray( val_thresholds, na_thresholds );
150
- if ( na_thresholds->rank != 1 ) {
151
- rb_raise( rb_eArgError, "thresholds must be narray of rank 1" );
152
- }
153
- if ( na_thresholds->shape[0] != output_size ) {
154
- rb_raise( rb_eArgError, "thresholds expected size %d, but got %d", output_size, na_thresholds->shape[0] );
155
- }
156
-
157
- output_shape[0] = output_size;
158
- val_outputs = na_make_object( NA_SFLOAT, 1, output_shape, CLASS_OF( val_inputs ) );
159
- GetNArray( val_outputs, na_outputs );
160
-
161
- nn_run_layer_raw( input_size, output_size, (float*) na_inputs->ptr, (float*) na_weights->ptr,
162
- (float*) na_thresholds->ptr, (float*) na_outputs->ptr );
163
-
164
- return val_outputs;
165
- }
166
-
167
-
168
113
  void Init_convolver() {
169
114
  Convolver = rb_define_module( "Convolver" );
170
115
  rb_define_singleton_method( Convolver, "convolve_basic", narray_convolve, 2 );
171
- rb_define_singleton_method( Convolver, "nn_run_layer", narray_nn_run_single_layer, 3 );
116
+
117
+ // private method
172
118
  rb_define_singleton_method( Convolver, "fit_kernel_backwards", narray_fit_backwards, 2 );
173
119
  }
@@ -21,6 +21,25 @@ void na_quick_pos_to_idxs( int rank, int *shape, int pos, int *idxs ) {
21
21
  return;
22
22
  }
23
23
 
24
+ // This is copied from na_array.c, with safety checks and temp vars removed
25
+ inline int na_inline_idxs_to_pos( int rank, int *shape, int *idxs ) {
26
+ int i, pos = 0;
27
+ for ( i = rank - 1; i >= 0; i-- ) {
28
+ pos = pos * shape[i] + idxs[i];
29
+ }
30
+ return pos;
31
+ }
32
+
33
+ // This is inverse of above
34
+ inline void na_inline_pos_to_idxs( int rank, int *shape, int pos, int *idxs ) {
35
+ int i;
36
+ for ( i = 0; i < rank; i++ ) {
37
+ idxs[ i ] = pos % shape[i];
38
+ pos /= shape[i];
39
+ }
40
+ return;
41
+ }
42
+
24
43
  // used to place kernel data into array for FFTW3 processing
25
44
  void fit_backwards_raw( int rank, int *dst_shape, float *dst, int *src_shape, float *src, int *shift_shape ) {
26
45
  int i, j, size, x;
@@ -30,13 +49,13 @@ void fit_backwards_raw( int rank, int *dst_shape, float *dst, int *src_shape, fl
30
49
  for ( j = 0; j < rank; j++ ) { size *= src_shape[j]; }
31
50
 
32
51
  for ( i = 0; i < size; i++ ) {
33
- na_quick_pos_to_idxs( rank, src_shape, i, k_idx );
52
+ na_inline_pos_to_idxs( rank, src_shape, i, k_idx );
34
53
  for ( j = 0; j < rank; j++ ) {
35
54
  x = src_shape[j] - shift_shape[j] - k_idx[j] - 1;
36
55
  if ( x < 0 ) x = x + dst_shape[j];
37
56
  dst_idx[j] = x;
38
57
  }
39
- dst[ na_quick_idxs_to_pos( rank, dst_shape, dst_idx ) ] = src[i];
58
+ dst[ na_inline_idxs_to_pos( rank, dst_shape, dst_idx ) ] = src[i];
40
59
  }
41
60
  return;
42
61
  }
@@ -1,3 +1,3 @@
1
1
  module Convolver
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convolver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Slater
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-27 00:00:00.000000000 Z
11
+ date: 2013-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: narray
@@ -137,8 +137,6 @@ files:
137
137
  - README.md
138
138
  - Rakefile
139
139
  - convolver.gemspec
140
- - ext/convolver/cnn_components.c
141
- - ext/convolver/cnn_components.h
142
140
  - ext/convolver/convolve_raw.c
143
141
  - ext/convolver/convolve_raw.h
144
142
  - ext/convolver/convolver.c
@@ -151,7 +149,6 @@ files:
151
149
  - spec/convolve_fftw3_spec.rb
152
150
  - spec/convolve_spec.rb
153
151
  - spec/helpers.rb
154
- - spec/nn_run_layer_spec.rb
155
152
  homepage: http://github.com/neilslater/convolver
156
153
  licenses:
157
154
  - MIT
@@ -181,5 +178,4 @@ test_files:
181
178
  - spec/convolve_fftw3_spec.rb
182
179
  - spec/convolve_spec.rb
183
180
  - spec/helpers.rb
184
- - spec/nn_run_layer_spec.rb
185
181
  has_rdoc:
@@ -1,52 +0,0 @@
1
- // ext/convolver/cnn_components.c
2
-
3
- #include <xmmintrin.h>
4
- #include "cnn_components.h"
5
-
6
- ////////////////////////////////////////////////////////////////////////////////////////////////////
7
- //
8
- // Run a single fully-connected layer, calculating output from input
9
- //
10
- // Benchmark: 1024 inputs, 256 outputs. 1000 iterations. 0.56 seconds
11
- //
12
- //
13
-
14
- void nn_run_layer_raw( int in_size, int out_size,
15
- float *in_ptr, float *weights, float *thresholds, float *out_ptr ) {
16
- int i, j, in_aligned_size, out_aligned_size, offset;
17
- __m128 simd_x, simd_y, simd_t;
18
-
19
- in_aligned_size = 4 * ( in_size/4 );
20
- out_aligned_size = 4 * ( out_size/4 );
21
-
22
- // Calculate activation
23
- for ( i = 0; i < out_size; i++ ) {
24
-
25
- float t = 0.0;
26
- simd_t = _mm_setzero_ps();
27
- offset = i * in_size;
28
-
29
- // Use SIMD for all the aligned values in groups of 4
30
- for ( j = 0; j < in_aligned_size; j +=4 ) {
31
- simd_x = _mm_load_ps( in_ptr + j );
32
- // Weights might not align to 16 bytes due to size of layers
33
- simd_y = _mm_loadu_ps( weights + (offset + j) );
34
- simd_x = _mm_mul_ps( simd_x, simd_y );
35
- simd_t = _mm_add_ps( simd_x, simd_t );
36
- }
37
-
38
- // Complete any remaining 1,2 or 3 items one at a time
39
- for ( j = in_aligned_size; j < in_size; j++ ) {
40
- t += in_ptr[ j ] * weights[ offset + j ];
41
- }
42
-
43
- out_ptr[i] = simd_t[0] + simd_t[1] + simd_t[2] + simd_t[3] + t;
44
- }
45
-
46
- for ( i = 0; i < out_size; i++ ) {
47
- out_ptr[i] -= thresholds[i];
48
- if ( out_ptr[i] < 0.0 ) { out_ptr[i] = 0.0; }
49
- }
50
-
51
- return;
52
- }
@@ -1,14 +0,0 @@
1
- // ext/convolver/cnn_components.h
2
-
3
- ////////////////////////////////////////////////////////////////////////////////////////////////
4
- //
5
- // Declarations of narray helper functions
6
- //
7
-
8
- #ifndef CNN_COMPONENTS_H
9
- #define CNN_COMPONENTS_H
10
-
11
- void nn_run_layer_raw( int in_size, int out_size,
12
- float *in_ptr, float *weights, float *thresholds, float *out_ptr );
13
-
14
- #endif
@@ -1,25 +0,0 @@
1
- require 'helpers'
2
-
3
- describe Convolver do
4
- describe "#nn_run_layer" do
5
- it "should calculate basic layer rules" do
6
- inputs = NArray[ 1.0 ]
7
- weights = NArray[ [ 1.0 ] ]
8
- thresholds = NArray[ 0.0 ]
9
- outputs = Convolver.nn_run_layer( inputs, weights, thresholds );
10
- outputs.should be_narray_like NArray[ 1.0 ]
11
-
12
- inputs = NArray[ 0.5, -0.5 ]
13
- weights = NArray[ [ 1.0, 2.0 ], [ 2.0, 1.0 ] ]
14
- thresholds = NArray[ 0.0, 0.0 ]
15
- outputs = Convolver.nn_run_layer( inputs, weights, thresholds );
16
- outputs.should be_narray_like NArray[ 0.0, 0.5 ]
17
-
18
- inputs = NArray[ 0.3, -0.4, 0.8, -0.7 ]
19
- weights = NArray[ [ 1.0, 0.25, 0.5, -0.5 ], [ -1.0, -0.25, -0.5, 0.5 ] ]
20
- thresholds = NArray[ 0.0, 0.0 ]
21
- outputs = Convolver.nn_run_layer( inputs, weights, thresholds );
22
- outputs.should be_narray_like NArray[ 0.95, 0.0 ]
23
- end
24
- end
25
- end