@@ -18,8 +18,7 @@ public static partial class CpuDnn
18
18
/// <param name="wInfo">The kernels volume info (depth and 2D slices size)</param>
19
19
/// <param name="b">The bias <see cref="Tensor"/> to sum to the resulting images</param>
20
20
/// <param name="y">The resulting convolution <see cref="Tensor"/></param>
21
- /// <exception cref="ArgumentException">The size of the matrix isn't valid, or the kernels list isn't valid</exception>
22
- /// <exception cref="ArgumentOutOfRangeException">The size of the matrix doesn't match the expected values</exception>
21
+ /// <exception cref="ArgumentException">The size of one of the input <see cref="Tensor"/> instances isn't valid</exception>
23
22
public static unsafe void ConvolutionForward (
24
23
in Tensor x , in TensorInfo xInfo ,
25
24
in Tensor w , in TensorInfo wInfo ,
@@ -42,9 +41,9 @@ public static unsafe void ConvolutionForward(
42
41
imgSize = xInfo . SliceSize ,
43
42
imgHeight = xInfo . Height ,
44
43
imgWidth = xInfo . Width ; // Size of an edge of one of the inner images per sample
45
- if ( imgSize * xInfo . Channels != l ) throw new ArgumentException ( "Invalid depth parameter for the input matrix " , nameof ( x ) ) ;
46
- if ( imgSize < kSize ) throw new ArgumentOutOfRangeException ( "Each subdivided matrix must at least have the size of the kernels" ) ;
47
- if ( xInfo . Channels != wInfo . Channels ) throw new InvalidOperationException ( "The depth of each kernel must be equal to the depth of each input volume" ) ;
44
+ if ( imgSize * xInfo . Channels != l ) throw new ArgumentException ( "Invalid depth parameter for the input tensor " , nameof ( x ) ) ;
45
+ if ( imgSize < kSize ) throw new ArgumentException ( "Each subdivided tensor must at least have the size of the kernels" ) ;
46
+ if ( xInfo . Channels != wInfo . Channels ) throw new ArgumentException ( "The depth of each kernel must be equal to the depth of each input volume" ) ;
48
47
if ( b . Length != nKernels ) throw new ArgumentException ( "The sum vector must be as long as the depth of the input volume" ) ;
49
48
50
49
/* ============================
@@ -115,8 +114,7 @@ void ForwardKernel(int index)
115
114
/// <param name="wInfo">The kernels volume info (depth and 2D slices size)</param>
116
115
/// <param name="dx">The resulting backpropagated error <see cref="Tensor"/></param>
117
116
/// <param name="dxInfo">The info on the layer inputs</param>
118
- /// <exception cref="ArgumentException">The size of the matrix isn't valid, or the kernels list isn't valid</exception>
119
- /// <exception cref="ArgumentOutOfRangeException">The size of the matrix doesn't match the expected values</exception>
117
+ /// <exception cref="ArgumentException">The size of one of the input <see cref="Tensor"/> instances isn't valid</exception>
120
118
public static unsafe void ConvolutionBackwardData (
121
119
in Tensor dy , in TensorInfo dyInfo ,
122
120
in Tensor w , in TensorInfo wInfo ,
@@ -137,8 +135,8 @@ public static unsafe void ConvolutionBackwardData(
137
135
imgSize = dyInfo . SliceSize ,
138
136
imgHeight = dyInfo . Height ,
139
137
imgWidth = dyInfo . Width ;
140
- if ( imgSize * dyInfo . Channels != l ) throw new ArgumentException ( "Invalid depth parameter for the input matrix " , nameof ( dy ) ) ;
141
- if ( imgSize < kSize ) throw new ArgumentOutOfRangeException ( "Each subdivided matrix must at least have the size of the kernels" ) ;
138
+ if ( imgSize * dyInfo . Channels != l ) throw new ArgumentException ( "Invalid depth parameter for the input tensor " , nameof ( dy ) ) ;
139
+ if ( imgSize < kSize ) throw new ArgumentException ( "Each subdivided tensor must at least have the size of the kernels" ) ;
142
140
if ( dyInfo . Channels != nKernels ) throw new ArgumentException ( "The source depth must be equal to the number of kernels" ) ;
143
141
144
142
// Traanspose the layer kernels
@@ -209,17 +207,16 @@ void BackwardsKernel(int index)
209
207
/// <summary>
210
208
/// Performs a the backward convolution operation for a network layer and computes the gradient with respect to the layer weights
211
209
/// </summary>
212
- /// <param name="x">The source matrix , where each row is a sample in the dataset and each one contains a series of images in row-first order</param>
210
+ /// <param name="x">The source <see cref="Tensor"/> , where each row is a sample in the dataset and each one contains a series of images in row-first order</param>
213
211
/// <param name="xInfo">The source volume info (depth and 2D slices size)</param>
214
- /// <param name="dy">The list of convolution kernels to apply to each image</param>
215
- /// <param name="dyInfo">The kernels volume info (depth and 2D slices size)</param>
216
- /// <param name="result">The resulting convolution volume</param>
217
- /// <exception cref="ArgumentException">The size of the matrix isn't valid, or the kernels list isn't valid</exception>
218
- /// <exception cref="ArgumentOutOfRangeException">The size of the matrix doesn't match the expected values</exception>
219
- public static unsafe void ConvoluteGradient (
212
+ /// <param name="dy">The output error <see cref="Tensor"/></param>
213
+ /// <param name="dyInfo">The output error volume info (depth and 2D slices size)</param>
214
+ /// <param name="dw">The resulting weights gradient</param>
215
+ /// <exception cref="ArgumentException">The size of one of the input <see cref="Tensor"/> instances isn't valid</exception>
216
+ public static unsafe void ConvolutionBackwardFilter (
220
217
in Tensor x , in TensorInfo xInfo ,
221
218
in Tensor dy , in TensorInfo dyInfo ,
222
- out Tensor result )
219
+ in Tensor dw )
223
220
{
224
221
// Checks and local parameters
225
222
int
@@ -236,8 +233,8 @@ public static unsafe void ConvoluteGradient(
236
233
imgSize = xInfo . SliceSize ,
237
234
imgHeight = xInfo . Height ,
238
235
imgWidth = xInfo . Width ;
239
- if ( imgSize * xInfo . Channels != l ) throw new ArgumentException ( nameof ( x ) , "Invalid depth parameter for the input matrix " ) ;
240
- if ( imgSize < kSize ) throw new ArgumentOutOfRangeException ( "Each subdivided matrix must at least have the size of the kernels" ) ;
236
+ if ( imgSize * xInfo . Channels != l ) throw new ArgumentException ( nameof ( x ) , "Invalid depth parameter for the input tensor " ) ;
237
+ if ( imgSize < kSize ) throw new ArgumentOutOfRangeException ( "Each subdivided tensor must at least have the size of the kernels" ) ;
241
238
if ( nKernels != n ) throw new ArgumentException ( nameof ( dy ) , "There must be a delta volume for each activation sample" ) ;
242
239
243
240
/* ============================
@@ -255,8 +252,7 @@ public static unsafe void ConvoluteGradient(
255
252
iterationsPerSample = xInfo . Channels * kDepth ; // Each sample has its own list of 3D gradients, one for each kernel
256
253
257
254
// Process the valid convolution
258
- Tensor . New ( n , finalWidth , out result ) ;
259
- float * psource = x , pkernels = dy , presult = result ;
255
+ float * px = x , pdy = dy , pdw = dw ;
260
256
void GradientKernel ( int index )
261
257
{
262
258
// Calculate the current indexes
@@ -287,16 +283,14 @@ void GradientKernel(int index)
287
283
kernelRowOffset = kernelBaseOffset + ( xEnd - r ) * kWidth + highY ;
288
284
for ( int c = j ; c <= highY ; c ++ )
289
285
{
290
- temp += psource [ sourceRowOffset + c ] * pkernels [ kernelRowOffset - c ] ;
286
+ temp += px [ sourceRowOffset + c ] * pdy [ kernelRowOffset - c ] ;
291
287
}
292
288
}
293
- presult [ targetRowOffset + j ] = temp ;
289
+ pdw [ targetRowOffset + j ] = temp ;
294
290
}
295
291
}
296
292
}
297
293
Parallel . For ( 0 , n * iterationsPerSample , GradientKernel ) . AssertCompleted ( ) ;
298
-
299
- // TODO: correct gradient implementation
300
294
throw new NotImplementedException ( "The CPU gradient convolution isn't implemented correctly yet" ) ;
301
295
}
302
296
@@ -306,6 +300,7 @@ void GradientKernel(int index)
306
300
/// <param name="dy">The output error <see cref="Tensor"/></param>
307
301
/// <param name="dyInfo">The info on the output <see cref="Tensor"/></param>
308
302
/// <param name="db">The resulting gradient</param>
303
+ /// <exception cref="ArgumentException">The size of one of the input <see cref="Tensor"/> instances isn't valid</exception>
309
304
[ PublicAPI ]
310
305
public static unsafe void ConvolutionBackwardBias ( in Tensor dy , in TensorInfo dyInfo , in Tensor db )
311
306
{
@@ -314,9 +309,9 @@ public static unsafe void ConvolutionBackwardBias(in Tensor dy, in TensorInfo dy
314
309
depth = dyInfo . Channels ,
315
310
h = dy . Entities ,
316
311
w = dy . Length ,
317
- imgSize = w % depth == 0 ? w / depth : throw new ArgumentException ( nameof ( dy ) , "Invalid depth parameter for the input matrix" ) ,
312
+ imgSize = w % depth == 0 ? w / depth : throw new ArgumentException ( "Invalid depth parameter for the input tensor" , nameof ( dy ) ) ,
318
313
imgAxis = imgSize . IntegerSquare ( ) ; // Size of an edge of one of the inner images per sample
319
- if ( imgAxis * imgAxis != imgSize ) throw new ArgumentOutOfRangeException ( nameof ( dy ) , "The size of the input matrix isn't valid" ) ;
314
+ if ( imgAxis * imgAxis != imgSize ) throw new ArgumentException ( "The size of the input tensor isn't valid" , nameof ( dy ) ) ;
320
315
Tensor . New ( h , depth , out Tensor temp ) ;
321
316
322
317
// Kernel to sum each slice
@@ -328,7 +323,7 @@ void Kernel(int index)
328
323
iSample = index / depth , // Sample index
329
324
z = index % depth ; // 2D slice index
330
325
331
- // Reverse the input matrix sequentially
326
+ // Reverse the input tensor sequentially
332
327
int baseOffset = iSample * w + z * imgSize ;
333
328
float sum = 0 ;
334
329
for ( int i = 0 ; i < imgSize ; i ++ )
@@ -347,19 +342,19 @@ void Kernel(int index)
347
342
/// <summary>
348
343
/// Rotates the input volume by 180 degrees
349
344
/// </summary>
350
- /// <param name="x">The input matrix to rotate</param>
345
+ /// <param name="x">The input <see cref="Tensor"/> to rotate</param>
351
346
/// <param name="depth">The number of images per row</param>
352
- /// <param name="y">The rotated input matrix </param>
347
+ /// <param name="y">The rotated input <see cref="Tensor"/> </param>
353
348
private static unsafe void Rotate180 ( in Tensor x , int depth , out Tensor y )
354
349
{
355
350
// Checks and local parameters
356
- if ( depth < 1 ) throw new ArgumentOutOfRangeException ( nameof ( depth ) , "The number of images per row can't be lower than 1" ) ;
351
+ if ( depth < 1 ) throw new ArgumentException ( "The number of images per row can't be lower than 1" , nameof ( depth ) ) ;
357
352
int
358
353
n = x . Entities ,
359
354
l = x . Length ,
360
- imgSize = l % depth == 0 ? l / depth : throw new ArgumentException ( nameof ( x ) , "Invalid depth parameter for the input matrix" ) ,
355
+ imgSize = l % depth == 0 ? l / depth : throw new ArgumentException ( "Invalid depth parameter for the input tensor" , nameof ( x ) ) ,
361
356
imgAxis = imgSize . IntegerSquare ( ) ; // Size of an edge of one of the inner images per sample
362
- if ( imgAxis * imgAxis != imgSize ) throw new ArgumentOutOfRangeException ( nameof ( x ) , "The size of the input matrix isn't valid" ) ;
357
+ if ( imgAxis * imgAxis != imgSize ) throw new ArgumentException ( "The size of the input tensor isn't valid" , nameof ( x ) ) ;
363
358
int
364
359
threshold = imgSize / 2 ,
365
360
edge = imgSize - 1 ;
@@ -375,7 +370,7 @@ void Kernel(int index)
375
370
iSample = index / depth , // Sample index
376
371
z = index % depth ; // 2D slice index
377
372
378
- // Reverse the input matrix sequentially
373
+ // Reverse the input tensor sequentially
379
374
int baseOffset = iSample * l + z * imgSize ;
380
375
for ( int i = 0 ; i < threshold ; i ++ )
381
376
{
0 commit comments