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