1 /** 2 Contains an implementation of convolutional layers. 3 4 Authors: Henry Gouk 5 */ 6 module dopt.nnet.layers.conv; 7 8 import dopt.core; 9 import dopt.nnet; 10 import dopt.nnet.layers.util; 11 import dopt.online; 12 13 /** 14 Encapsulates the additional options for a $(D Layer) created with conv2D. 15 */ 16 class Conv2DOptions 17 { 18 this() 19 { 20 _useBias = true; 21 _filterInit = heGaussianInit(); 22 _biasInit = constantInit(0.0f); 23 _padding = [0, 0]; 24 _stride = [1, 1]; 25 _weightDecay = 0.0f; 26 27 } 28 29 mixin(dynamicProperties( 30 "size_t[]", "padding", 31 "size_t[]", "stride", 32 "ParamInitializer", "filterInit", 33 "ParamInitializer", "biasInit", 34 "Projection", "filterProj", 35 "Projection", "biasProj", 36 "float", "weightDecay", 37 "bool", "useBias" 38 )); 39 } 40 41 /// 42 unittest 43 { 44 //Creates a Conv2DOptions object with the default parameter values 45 auto opts = new Conv2DOptions() 46 .padding([0, 0]) 47 .stride([1, 1]) 48 .filterInit(heGaussianInit()) 49 .biasInit(constantInit(0.0f)) 50 .filterProj(null) 51 .biasProj(null) 52 .weightDecay(0.0f) 53 .useBias(true); 54 55 //The fields can also be accessed again later 56 assert(opts.padding == [0, 0]); 57 assert(opts.stride == [1, 1]); 58 } 59 60 /** 61 Creates a convolutional layer typically found in a convnet used for image classification. 62 63 Params: 64 input = The previous (i.e., input) layer. 65 outputChannels = The number of feature maps that this layer should produce. 66 filterDims = The size of the kernels that should be convolved with the inputs. 67 opts = Additional options, with sensible defaults. 68 69 Returns: 70 The new convolutional $(D Layer). 71 */ 72 Layer conv2D(Layer input, size_t outputChannels, size_t[] filterDims, Conv2DOptions opts = new Conv2DOptions()) 73 { 74 auto padding = opts.padding; 75 auto stride = opts.stride; 76 auto filterInit = opts.filterInit; 77 auto biasInit = opts.biasInit; 78 auto filterProj = opts.filterProj; 79 auto biasProj = opts.biasProj; 80 auto weightDecay = opts.weightDecay; 81 auto useBias = opts.useBias; 82 83 auto x = input.output; 84 auto xTr = input.trainOutput; 85 86 auto filters = float32([outputChannels, x.shape[1]] ~ filterDims); 87 filterInit(filters); 88 89 import std.math : isNaN; 90 91 auto filterLoss = (weightDecay == 0.0f) ? null : (weightDecay * sum(filters * filters)); 92 93 Parameter[] params = [ 94 Parameter(filters, filterLoss, filterProj) 95 ]; 96 97 auto y = x.convolution(filters, padding, stride); 98 auto yTr = xTr.convolution(filters, padding, stride); 99 100 if(useBias) 101 { 102 auto biases = float32([outputChannels]); 103 biasInit(biases); 104 105 y = y.addBias(biases); 106 yTr = yTr.addBias(biases); 107 108 params ~= Parameter(biases, null, biasProj); 109 } 110 111 return new Layer([input], y, yTr, params); 112 }