MyCaffe  1.12.2.2
Deep learning software for Windows C# programmers.
MyCaffeConversionControl.cs
1using Google.Protobuf;
2using Google.Protobuf.Collections;
3using MyCaffe.basecode;
5using MyCaffe.common;
6using MyCaffe.fillers;
7using MyCaffe.layers;
8using MyCaffe.param;
9using MyCaffe.param.beta;
10using Onnx;
11using OnnxControl;
12using System;
13using System.Collections;
14using System.Collections.Generic;
16using System.Diagnostics;
17using System.IO;
18using System.Linq;
19using System.Reflection;
20using System.Text;
21using System.Threading.Tasks;
22
30{
35 public partial class MyCaffeConversionControl<T> : Component
36 {
37 string m_strReport = "";
38 string m_strOriginalPath = null;
39 bool m_bEnableBackward = false;
40 double? m_dfWtScaleMin = null;
41 double? m_dfWtScaleMax = null;
42 List<string> m_rgstrIgnoreLayerNames = new List<string>();
43 int m_nReshapeCount = 0;
44 int m_nFlattenCount = 0;
45 int m_nDropoutCount = 0;
46 List<string> m_rgstrTensorsAlreadyAdded = new List<string>();
47 Dictionary<Blob<T>, string> m_rgBlobNameFixups = new Dictionary<Blob<T>, string>();
48
53 {
54 InitializeComponent();
55 m_strOriginalPath = AssemblyDirectory;
56 }
57
62 public MyCaffeConversionControl(IContainer container)
63 {
64 container.Add(this);
65
66 InitializeComponent();
67 m_strOriginalPath = AssemblyDirectory;
68 }
69
70 private static string AssemblyDirectory
71 {
72 get
73 {
74 string codeBase = Assembly.GetExecutingAssembly().CodeBase;
75 UriBuilder uri = new UriBuilder(codeBase);
76 string path = Uri.UnescapeDataString(uri.Path);
77 return Path.GetDirectoryName(path);
78 }
79 }
80
86 public void SetWeightScaling(double dfMin, double dfMax)
87 {
88 m_dfWtScaleMax = dfMax;
89 m_dfWtScaleMin = dfMin;
90 }
91
95 public List<string> IgnoreLayerNames
96 {
97 get { return m_rgstrIgnoreLayerNames; }
98 set { m_rgstrIgnoreLayerNames = value; }
99 }
100
104 public string ReportString
105 {
106 get { return m_strReport; }
107 }
108
120 public void ConvertMyCaffeToOnnxFile(CudaDnn<T> cuda, Log log, MyCaffeModelData data, string strOutputFile, int nOpSetVersion = 9, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT)
121 {
122 m_strOriginalPath = Path.GetDirectoryName(strOutputFile);
123 ModelProto protoOnnx = ConvertMyCaffeToOnnx(cuda, log, data, nOpSetVersion, bUseRawData, dstDataType);
124 PersistOnnx persist = new PersistOnnx();
125
126 // Save the new model
127 persist.Save(protoOnnx, strOutputFile);
128 }
129
141 public ModelProto ConvertMyCaffeToOnnx(CudaDnn<T> cuda, Log log, MyCaffeModelData data, int nOpSetVersion = 9, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT)
142 {
143 // Parse the Caffe Model Description;
144 RawProto protoMyCaffe = RawProto.Parse(data.ModelDescription);
145 NetParameter netParam = NetParameter.FromProto(protoMyCaffe);
146
147 Net<T> net = new Net<T>(cuda, log, netParam, new CancelEvent(), null);
148
149 // Load the weights
150 if (data.Weights != null)
151 {
152 PersistCaffe<T> persistCaffe = new PersistCaffe<T>(log, false);
153 net.LoadWeights(data.Weights, persistCaffe);
154 }
155
156 // Convert the MyCaffe net to an Onnx model.
157 ModelProto protoOnnx = convertToOnnx(log, net, nOpSetVersion, bUseRawData, dstDataType);
158
159 // Cleanup
160 if (net != null)
161 net.Dispose();
162
163 return protoOnnx;
164 }
165
175 public ModelProto ConvertMyCaffeToOnnx(MyCaffeControl<T> ctrl, int nOpSetVersion = 9, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT, Phase phase = Phase.RUN)
176 {
177 Net<T> net = ctrl.GetInternalNet(phase);
178 return convertToOnnx(ctrl.Log, net, nOpSetVersion, bUseRawData, dstDataType);
179 }
180
190 public void ConvertMyCaffeToOnnxFile(MyCaffeControl<T> ctrl, string strOnnxFile, int nOpSetVersion = 9, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT, Phase phase = Phase.RUN)
191 {
192 m_strOriginalPath = Path.GetDirectoryName(strOnnxFile);
193 ModelProto proto = ConvertMyCaffeToOnnx(ctrl, nOpSetVersion, bUseRawData, dstDataType, phase);
194 PersistOnnx persist = new PersistOnnx();
195 persist.Save(proto, strOnnxFile);
196 }
197
209 public MyCaffeModelData ConvertOnnxToMyCaffeFromFile(CudaDnn<T> cuda, Log log, string strOnnxFile, bool bFixlupNeuronNodes = true, bool bIncludeLastLayerWeights = false, DatasetDescriptor dsTraining = null)
210 {
211 m_strOriginalPath = Path.GetDirectoryName(strOnnxFile);
212 PersistOnnx persist = new PersistOnnx();
213 ModelProto proto = persist.Load(strOnnxFile);
214 MyCaffeModelData data = ConvertOnnxToMyCaffe(cuda, log, proto, bFixlupNeuronNodes, bIncludeLastLayerWeights, dsTraining);
215 data.OriginalDownloadFile = strOnnxFile;
216
217 return data;
218 }
219
231 public MyCaffeModelData ConvertOnnxToMyCaffe(CudaDnn<T> cuda, Log log, ModelProto onnxModel, bool bFixupNeuronNodes = true, bool bIncludeLastLayerWeights = false, DatasetDescriptor dsTraining = null)
232 {
233 Tuple<NetParameter, BlobCollection<T>> data = convertToMyCaffe(cuda, log, onnxModel, bFixupNeuronNodes, dsTraining);
234
235 NetParameter netParam = data.Item1;
236 RawProto protoMyCaffe = netParam.ToProto("root");
237
238 if (!bIncludeLastLayerWeights && data.Item2.Count > 0)
239 data.Item2.RemoveAt(data.Item2.Count - 1);
240
241 PersistCaffe<T> persist = new PersistCaffe<T>(log, false);
242 byte[] rgWeights = persist.SaveWeights(data.Item2, false);
243
244 return new MyCaffeModelData(protoMyCaffe.ToString(), rgWeights);
245 }
246
247 private ModelProto convertToOnnx(Log log, Net<T> net, int nOpSetVersion = 9, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT)
248 {
249 ModelProto proto = new ModelProto();
250 NetParameter netParam = net.net_param.Clone();
251
253
254 Assembly assembly = Assembly.GetExecutingAssembly();
255 FileVersionInfo ver = FileVersionInfo.GetVersionInfo(assembly.Location);
256
257 proto.IrVersion = 1;
258 proto.ProducerName = "MyCaffe Converter for ONNX";
259 proto.ProducerVersion = ver.FileVersion;
260 proto.Domain = "org.mycaffe";
261 proto.ModelVersion = 1;
262
263 OperatorSetIdProto opset = new OperatorSetIdProto();
264 opset.Version = nOpSetVersion;
265 opset.Domain = "";
266 proto.OpsetImport.Add(opset);
267
268 StringStringEntryProto author = new StringStringEntryProto();
269 author.Key = "model_author";
270 author.Value = "SignalPop LLC";
271 proto.MetadataProps.Add(author);
272
273 StringStringEntryProto license = new StringStringEntryProto();
274 license.Key = "model_license";
275 license.Value = "https://github.com/MyCaffe/MyCaffe/blob/master/LICENSE";
276 proto.MetadataProps.Add(license);
277
278 proto.Graph = new GraphProto();
279 proto.Graph.Name = netParam.name;
280 addValueInfo(proto.Graph.Input, net.input_blobs);
281 addValueInfo(proto.Graph.Output, net.output_blobs);
282 addNodes(log, proto.Graph.Node, net.layers, proto.Graph.Initializer);
283 addTensors(proto.Graph.Initializer, net.learnable_parameters, bUseRawData, dstDataType);
284
285 foreach (KeyValuePair<Blob<T>, string> kv in m_rgBlobNameFixups)
286 {
287 kv.Key.Name = kv.Value;
288 }
289
290 return proto;
291 }
292
293 private void addValueInfo(RepeatedField<ValueInfoProto> rg, BlobCollection<T> blobs)
294 {
295 foreach (Blob<T> blob in blobs)
296 {
297 ValueInfoProto val = new ValueInfoProto();
298 val.Name = blob.Name;
299
300 TypeProto type = new TypeProto();
301 type.TensorType = new TypeProto.Types.Tensor();
302 type.TensorType.ElemType = (int)OnnxDefinitions.DataType.FLOAT;
303 type.TensorType.Shape = new TensorShapeProto();
304
305 foreach (int nShape in blob.shape())
306 {
307 TensorShapeProto.Types.Dimension dim = new TensorShapeProto.Types.Dimension();
308 dim.DimValue = nShape;
309 type.TensorType.Shape.Dim.Add(dim);
310 }
311
312 val.Type = type;
313 rg.Add(val);
314 }
315 }
316
317 private string removeWs(string str, char ch)
318 {
319 string strOut = "";
320
321 foreach (char ch1 in str)
322 {
323 if (char.IsWhiteSpace(ch1))
324 strOut += ch;
325 else
326 strOut += ch1;
327 }
328
329 return strOut;
330 }
331
332 private void addShapeTensor(RepeatedField<TensorProto> rg, string strName, List<int> rgShape)
333 {
334 TensorProto tensor = new TensorProto();
335 tensor.Name = strName;
336 tensor.DataType = (int)OnnxDefinitions.DataType.INT64;
337 tensor.Dims.Add(rgShape.Count);
338
339 for (int i = 0; i < rgShape.Count; i++)
340 {
341 tensor.Int64Data.Add(rgShape[i]);
342 }
343
344 rg.Add(tensor);
345 }
346
347 private string addTensor(RepeatedField<TensorProto> rg, Blob<T> blob, string strExtra, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT)
348 {
349 TensorProto tensor = new TensorProto();
350 tensor.Name = removeWs(blob.Name, '_') + strExtra;
351 tensor.DataType = (int)dstDataType;
352
353 List<int> rgShape = new List<int>();
354 foreach (int nShape in blob.shape())
355 {
356 rgShape.Add(nShape);
357 }
358
359 while (rgShape.Count > 1 && rgShape[rgShape.Count - 1] == 1)
360 {
361 rgShape.RemoveAt(rgShape.Count - 1);
362 }
363
364 for (int i = 0; i < rgShape.Count; i++)
365 {
366 tensor.Dims.Add(rgShape[i]);
367 }
368
369 T[] rgData = blob.mutable_cpu_data;
370
371 if (bUseRawData)
372 {
373 if (dstDataType == OnnxDefinitions.DataType.FLOAT)
374 {
375 if (typeof(T) == typeof(float))
376 {
377 float[] rgfData = Utility.ConvertVecF<T>(rgData);
378 byte[] rgByte = new byte[rgfData.Length * sizeof(float)];
379 Buffer.BlockCopy(rgfData, 0, rgByte, 0, rgByte.Length);
380 tensor.RawData = ByteString.CopyFrom(rgByte);
381 }
382 else
383 {
384 double[] rgfData = Utility.ConvertVec<T>(rgData);
385 float[] rgfData2 = rgfData.Select(p => (float)p).ToArray();
386 byte[] rgByte = new byte[rgfData2.Length * sizeof(float)];
387 Buffer.BlockCopy(rgfData2, 0, rgByte, 0, rgByte.Length);
388 tensor.RawData = ByteString.CopyFrom(rgByte);
389 }
390 }
391 else if (dstDataType == OnnxDefinitions.DataType.DOUBLE)
392 {
393 if (typeof(T) == typeof(float))
394 {
395 float[] rgfData = Utility.ConvertVecF<T>(rgData);
396 double[] rgfData2 = rgfData.Select(p => (double)p).ToArray();
397 byte[] rgByte = new byte[rgfData2.Length * sizeof(double)];
398 Buffer.BlockCopy(rgfData2, 0, rgByte, 0, rgByte.Length);
399 tensor.RawData = ByteString.CopyFrom(rgByte);
400 }
401 else
402 {
403 double[] rgfData = Utility.ConvertVec<T>(rgData);
404 byte[] rgByte = new byte[rgfData.Length * sizeof(double)];
405 Buffer.BlockCopy(rgfData, 0, rgByte, 0, rgByte.Length);
406 tensor.RawData = ByteString.CopyFrom(rgByte);
407 }
408 }
409 else
410 throw new Exception("Currently only the FLOAT and DOUBLE data types are supported when exporting.");
411 }
412 else
413 {
414 if (dstDataType == OnnxDefinitions.DataType.FLOAT)
415 {
416 if (typeof(T) == typeof(float))
417 {
418 float[] rgfData = Utility.ConvertVecF<T>(rgData);
419
420 foreach (float val in rgfData)
421 {
422 tensor.FloatData.Add(val);
423 }
424 }
425 else
426 {
427 double[] rgfData = Utility.ConvertVec<T>(rgData);
428
429 foreach (double val in rgfData)
430 {
431 tensor.FloatData.Add(Convert.ToSingle(val));
432 }
433 }
434 }
435 else if (dstDataType == OnnxDefinitions.DataType.DOUBLE)
436 {
437 if (typeof(T) == typeof(float))
438 {
439 float[] rgfData = Utility.ConvertVecF<T>(rgData);
440
441 foreach (float val in rgfData)
442 {
443 tensor.DoubleData.Add(Convert.ToDouble(val));
444 }
445 }
446 else
447 {
448 double[] rgfData = Utility.ConvertVec<T>(rgData);
449
450 foreach (double val in rgfData)
451 {
452 tensor.DoubleData.Add(val);
453 }
454 }
455 }
456 else
457 throw new Exception("Currently only the FLOAT and DOUBLE data types are supported when exporting.");
458 }
459
460 rg.Add(tensor);
461
462 m_rgstrTensorsAlreadyAdded.Add(blob.Name);
463
464 return tensor.Name;
465 }
466
467 private void addTensors(RepeatedField<TensorProto> rg, BlobCollection<T> blobs, bool bUseRawData = true, OnnxDefinitions.DataType dstDataType = OnnxDefinitions.DataType.FLOAT)
468 {
469 foreach (Blob<T> blob in blobs)
470 {
471 if (m_rgstrTensorsAlreadyAdded.Contains(blob.Name))
472 continue;
473
474 addTensor(rg, blob, "", bUseRawData, dstDataType);
475 }
476 }
477
478 private void addNodes(Log log, RepeatedField<NodeProto> rg, List<Layer<T>> rgLayers, RepeatedField<TensorProto> rgTensors)
479 {
480 Dictionary<string, List<string>> rgTopCounts = new Dictionary<string, List<string>>();
482
483 foreach (Layer<T> layer in rgLayers)
484 {
485 NodeProto node = new NodeProto();
486
487 node.Name = layer.layer_param.name;
488
489 foreach (string strBottom in layer.layer_param.bottom)
490 {
491 string strBtm1 = strBottom;
492
493 if (rgTopCounts.ContainsKey(strBottom))
494 strBtm1 = rgTopCounts[strBottom].Last();
495
496 node.Input.Add(strBottom);
497 }
498
499 foreach (string strTop in layer.layer_param.top)
500 {
501 if (!rgTopCounts.ContainsKey(strTop))
502 rgTopCounts.Add(strTop, new List<string>() { strTop });
503 else
504 rgTopCounts[strTop].Add(strTop + "_" + rgTopCounts[strTop].Count.ToString());
505
506 string strTop1 = rgTopCounts[strTop].Last();
507 node.Output.Add(strTop1);
508 }
509
510 BlobCollection<T> colParams = new BlobCollection<T>();
511
512 switch (layer.type)
513 {
514 case LayerParameter.LayerType.ABSVAL:
515 node.OpType = OnnxDefinitions.OPERATORS.Abs.ToString();
516 break;
517
518 case LayerParameter.LayerType.ARGMAX:
520 node.OpType = OnnxDefinitions.OPERATORS.ArgMin.ToString();
521 else
522 node.OpType = OnnxDefinitions.OPERATORS.ArgMax.ToString();
523 break;
524
525 case LayerParameter.LayerType.BATCHNORM:
526 node.OpType = OnnxDefinitions.OPERATORS.BatchNormalization.ToString();
527 addAttributes(node.Attribute, layer.layer_param.batch_norm_param);
528
530 {
531 colParams.Add(layer.blobs[3]);
532 colParams.Add(layer.blobs[4]);
533 }
534 else
535 {
536 Blob<T> blobScale = new Blob<T>(layer.blobs[0].Cuda, log, false);
537 blobScale.ReshapeLike(layer.blobs[0]);
538 blobScale.SetData(1.0);
539 blobScale.Name = node.Name + "_scale";
540 string strScale = addTensor(rgTensors, blobScale, "");
541 node.Input.Add(strScale);
542 blobScale.Dispose();
543
544 Blob<T> blobBias = new Blob<T>(layer.blobs[0].Cuda, log, false);
545 blobBias.ReshapeLike(layer.blobs[0]);
546 blobBias.SetData(1.0);
547 blobBias.Name = node.Name + "_bias";
548 string strBias = addTensor(rgTensors, blobBias, "");
549 node.Input.Add(strBias);
550 blobBias.Dispose();
551 }
552
553// m_rgBlobNameFixups.Add(layer.blobs[0], layer.blobs[0].Name);
554// layer.blobs[0].Name = layer.layer_param.name;
555 colParams.Add(layer.blobs[0]);
556 colParams.Add(layer.blobs[1]);
557 break;
558
559 case LayerParameter.LayerType.CLIP:
560 node.OpType = OnnxDefinitions.OPERATORS.Clip.ToString();
561 addAttributes(node.Attribute, layer.layer_param.clip_param);
562 break;
563
564 case LayerParameter.LayerType.CONCAT:
565 node.OpType = OnnxDefinitions.OPERATORS.Concat.ToString();
566 addAttributes(node.Attribute, layer.layer_param.concat_param);
567 break;
568
569 case LayerParameter.LayerType.CONSTANT:
570 node.OpType = OnnxDefinitions.OPERATORS.Constant.ToString();
571 addAttributes(node.Attribute, layer.layer_param.constant_param);
572 break;
573
574 case LayerParameter.LayerType.CONVOLUTION:
575 node.OpType = OnnxDefinitions.OPERATORS.Conv.ToString();
576 addAttributes(node.Attribute, layer.layer_param.convolution_param);
577 colParams.Add(layer.blobs[0]);
579 colParams.Add(layer.blobs[1]);
580 break;
581
582 case LayerParameter.LayerType.DROPOUT:
583 node.OpType = OnnxDefinitions.OPERATORS.Dropout.ToString();
584 string strTraining = addAttributes(node.Attribute, rgTensors, layer.layer_param.dropout_param);
585 if (strTraining != null)
586 node.Input.Add(strTraining);
587 break;
588
589 case LayerParameter.LayerType.ELTWISE:
591 node.OpType = OnnxDefinitions.OPERATORS.Add.ToString();
593 node.OpType = OnnxDefinitions.OPERATORS.Sub.ToString();
595 node.OpType = OnnxDefinitions.OPERATORS.Mul.ToString();
597 node.OpType = OnnxDefinitions.OPERATORS.Div.ToString();
599 node.OpType = OnnxDefinitions.OPERATORS.Max.ToString();
601 node.OpType = OnnxDefinitions.OPERATORS.Min.ToString();
602 break;
603
604 case LayerParameter.LayerType.ELU:
605 node.OpType = OnnxDefinitions.OPERATORS.Elu.ToString();
606 addAttributes(node.Attribute, layer.layer_param.elu_param);
607 break;
608
609 case LayerParameter.LayerType.EXP:
610 node.OpType = OnnxDefinitions.OPERATORS.Exp.ToString();
611 addAttributes(node.Attribute, layer.layer_param.exp_param);
612 break;
613
614 case LayerParameter.LayerType.FLATTEN:
615 node.OpType = OnnxDefinitions.OPERATORS.Flatten.ToString();
616 addAttributes(node.Attribute, layer.layer_param.flatten_param);
617 break;
618
619 case LayerParameter.LayerType.GATHER:
620 node.OpType = OnnxDefinitions.OPERATORS.Gather.ToString();
621 addAttributes(node.Attribute, layer.layer_param.gather_param);
622 break;
623
624 case LayerParameter.LayerType.INNERPRODUCT:
625 if (m_lastType != LayerParameter.LayerType.RESHAPE &&
626 m_lastType != LayerParameter.LayerType.FLATTEN &&
627 m_lastType != LayerParameter.LayerType.INNERPRODUCT)
628 {
629 NodeProto node1 = new NodeProto();
630 node1.OpType = OnnxDefinitions.OPERATORS.Flatten.ToString();
631 node1.Name = "flatten" + m_nFlattenCount.ToString();
632 node1.Input.Add(node.Input[0]);
633 node1.Output.Add(node1.Name);
634 FlattenParameter flatten_param = new FlattenParameter();
635 flatten_param.axis = 1;
636 addAttributes(node1.Attribute, flatten_param);
637 m_nFlattenCount++;
638
639 rg.Add(node1);
640 node.Input[0] = node1.Name;
641 }
642
643 node.OpType = OnnxDefinitions.OPERATORS.Gemm.ToString();
644 addAttributes(node.Attribute, layer.layer_param.inner_product_param);
645 colParams.Add(layer.blobs[0]);
647 colParams.Add(layer.blobs[1]);
648 break;
649
650 case LayerParameter.LayerType.LRN:
651 node.OpType = OnnxDefinitions.OPERATORS.LRN.ToString();
652 addAttributes(node.Attribute, layer.layer_param.lrn_param);
653 break;
654
655 case LayerParameter.LayerType.LOG:
656 node.OpType = OnnxDefinitions.OPERATORS.Log.ToString();
657 addAttributes(node.Attribute, layer.layer_param.log_param);
658 break;
659
660 case LayerParameter.LayerType.MATH:
662 node.OpType = OnnxDefinitions.OPERATORS.Acos.ToString();
663 else if (layer.layer_param.math_param.function == MATH_FUNCTION.ACOSH)
664 node.OpType = OnnxDefinitions.OPERATORS.Acosh.ToString();
665 else if (layer.layer_param.math_param.function == MATH_FUNCTION.COS)
666 node.OpType = OnnxDefinitions.OPERATORS.Cos.ToString();
667 else if (layer.layer_param.math_param.function == MATH_FUNCTION.COSH)
668 node.OpType = OnnxDefinitions.OPERATORS.Cosh.ToString();
669
670 else if (layer.layer_param.math_param.function == MATH_FUNCTION.ASIN)
671 node.OpType = OnnxDefinitions.OPERATORS.Asin.ToString();
672 else if (layer.layer_param.math_param.function == MATH_FUNCTION.ASINH)
673 node.OpType = OnnxDefinitions.OPERATORS.Asinh.ToString();
674 else if (layer.layer_param.math_param.function == MATH_FUNCTION.SIN)
675 node.OpType = OnnxDefinitions.OPERATORS.Sin.ToString();
676 else if (layer.layer_param.math_param.function == MATH_FUNCTION.SINH)
677 node.OpType = OnnxDefinitions.OPERATORS.Sinh.ToString();
678
679 else if (layer.layer_param.math_param.function == MATH_FUNCTION.ATAN)
680 node.OpType = OnnxDefinitions.OPERATORS.Atan.ToString();
681 else if (layer.layer_param.math_param.function == MATH_FUNCTION.ATANH)
682 node.OpType = OnnxDefinitions.OPERATORS.Atanh.ToString();
683 else if (layer.layer_param.math_param.function == MATH_FUNCTION.TAN)
684 node.OpType = OnnxDefinitions.OPERATORS.Tan.ToString();
685 else if (layer.layer_param.math_param.function == MATH_FUNCTION.TANH)
686 node.OpType = OnnxDefinitions.OPERATORS.Tanh.ToString();
687
688 else if (layer.layer_param.math_param.function == MATH_FUNCTION.CEIL)
689 node.OpType = OnnxDefinitions.OPERATORS.Ceil.ToString();
690 else if (layer.layer_param.math_param.function == MATH_FUNCTION.FLOOR)
691 node.OpType = OnnxDefinitions.OPERATORS.Floor.ToString();
692 else if (layer.layer_param.math_param.function == MATH_FUNCTION.NEG)
693 node.OpType = OnnxDefinitions.OPERATORS.Neg.ToString();
694 else if (layer.layer_param.math_param.function == MATH_FUNCTION.SIGN)
695 node.OpType = OnnxDefinitions.OPERATORS.Sign.ToString();
696 else if (layer.layer_param.math_param.function == MATH_FUNCTION.SQRT)
697 node.OpType = OnnxDefinitions.OPERATORS.Sqrt.ToString();
698 break;
699
700 case LayerParameter.LayerType.POOLING:
702 {
704 node.OpType = OnnxDefinitions.OPERATORS.GlobalAveragePool.ToString();
706 node.OpType = OnnxDefinitions.OPERATORS.GlobalMaxPool.ToString();
707 else if (layer.layer_param.pooling_param.pool == PoolingParameter.PoolingMethod.STOCHASTIC)
708 throw new Exception("Currently global STOCHASTIC pooling is not supported for ONNX conversion.");
709 }
710 else
711 {
713 node.OpType = OnnxDefinitions.OPERATORS.AveragePool.ToString();
715 node.OpType = OnnxDefinitions.OPERATORS.MaxPool.ToString();
716 else if (layer.layer_param.pooling_param.pool == PoolingParameter.PoolingMethod.STOCHASTIC)
717 throw new Exception("Currently STOCHASTIC pooling is not supported for ONNX conversion.");
718 }
719 addAttributes(node.Attribute, layer.layer_param.pooling_param);
720 break;
721
722 case LayerParameter.LayerType.PRELU:
723 node.OpType = OnnxDefinitions.OPERATORS.PRelu.ToString();
724 colParams = layer.blobs;
725 break;
726
727 case LayerParameter.LayerType.POWER:
728 node.OpType = OnnxDefinitions.OPERATORS.Pow.ToString();
729 break;
730
731 case LayerParameter.LayerType.REDUCTION:
733 node.OpType = OnnxDefinitions.OPERATORS.ReduceMax.ToString();
735 node.OpType = OnnxDefinitions.OPERATORS.ReduceMean.ToString();
737 node.OpType = OnnxDefinitions.OPERATORS.ReduceMin.ToString();
739 node.OpType = OnnxDefinitions.OPERATORS.ReduceSum.ToString();
741 node.OpType = OnnxDefinitions.OPERATORS.ReduceSumSquare.ToString();
742 addAttributes(node.Attribute, layer.layer_param.reduction_param);
743 break;
744
745 case LayerParameter.LayerType.RELU:
747 node.OpType = OnnxDefinitions.OPERATORS.LeakyRelu.ToString();
748 else
749 node.OpType = OnnxDefinitions.OPERATORS.Relu.ToString();
750 addAttributes(node.Attribute, layer.layer_param.relu_param);
751 break;
752
753 case LayerParameter.LayerType.RESHAPE:
754 node.OpType = OnnxDefinitions.OPERATORS.Reshape.ToString();
755 string strName = "reshape" + m_nReshapeCount.ToString();
756 node.Input.Add(strName);
757 m_nReshapeCount++;
758 addAttributes(node.Attribute, rgTensors, strName, layer.layer_param.reshape_param, true);
759 break;
760
761 case LayerParameter.LayerType.SOFTMAX:
762 node.OpType = OnnxDefinitions.OPERATORS.Softmax.ToString();
763 addAttributes(node.Attribute, layer.layer_param.softmax_param);
764 break;
765
766 case LayerParameter.LayerType.SPLIT:
767 node.OpType = OnnxDefinitions.OPERATORS.Split.ToString();
768 break;
769
770 case LayerParameter.LayerType.SQUEEZE:
771 node.OpType = OnnxDefinitions.OPERATORS.Squeeze.ToString();
772 break;
773
774 case LayerParameter.LayerType.UNSQUEEZE:
775 node.OpType = OnnxDefinitions.OPERATORS.Unsqueeze.ToString();
776 break;
777
778 case LayerParameter.LayerType.TRANSPOSE:
779 node.OpType = OnnxDefinitions.OPERATORS.Transpose.ToString();
780 addAttributes(node.Attribute, layer.layer_param.transpose_param);
781 break;
782
783 default:
784 bool bTraceEnabled = log.EnableTrace;
785 log.EnableTrace = true;
786 log.WriteLine("Ignoring layer '" + layer.layer_param.name + "'(" + layer.type.ToString() + ")");
787 log.EnableTrace = bTraceEnabled;
788 node = null;
789 break;
790 }
791
792 if (node != null)
793 {
794 foreach (Blob<T> blob in colParams)
795 {
796 node.Input.Add(removeWs(blob.Name, '_'));
797 }
798
799 rg.Add(node);
800 }
801
802 //Get last non Neuron Node.
803 if (layer.layer_param.top.Count > 1 ||
804 layer.layer_param.bottom.Count > 1 ||
805 layer.layer_param.top.Count == 0 ||
806 layer.layer_param.bottom.Count == 0 ||
807 layer.layer_param.top[0] != layer.layer_param.bottom[0])
808 m_lastType = layer.type;
809 }
810 }
811
812 private void addAttributes(RepeatedField<AttributeProto> rgA, BatchNormParameter p)
813 {
814 AttributeProto attrib = new AttributeProto();
815 attrib.Name = "epsilon";
816 attrib.Type = AttributeProto.Types.AttributeType.Float;
817 attrib.F = (float)p.eps;
818 rgA.Add(attrib);
819
820 attrib = new AttributeProto();
821 attrib.Name = "momentum";
822 attrib.Type = AttributeProto.Types.AttributeType.Float;
823 attrib.F = (float)p.moving_average_fraction;
824 rgA.Add(attrib);
825 }
826
827 private void addAttributes(RepeatedField<AttributeProto> rgA, ClipParameter p)
828 {
829 AttributeProto attrib = new AttributeProto();
830 attrib.Name = "min";
831 attrib.Type = AttributeProto.Types.AttributeType.Float;
832 attrib.F = (float)p.min;
833 rgA.Add(attrib);
834
835 attrib = new AttributeProto();
836 attrib.Name = "max";
837 attrib.Type = AttributeProto.Types.AttributeType.Float;
838 attrib.F = (float)p.max;
839 rgA.Add(attrib);
840 }
841
842 private void addAttributes(RepeatedField<AttributeProto> rgA, ConcatParameter p)
843 {
844 AttributeProto attrib = new AttributeProto();
845 attrib.Name = "axis";
846 attrib.Type = AttributeProto.Types.AttributeType.Int;
847 attrib.I = p.axis;
848 rgA.Add(attrib);
849 }
850
851 private void addAttributes(RepeatedField<AttributeProto> rgA, ConstantParameter p)
852 {
853 AttributeProto attrib = new AttributeProto();
854 attrib.Name = "value";
855 attrib.Type = AttributeProto.Types.AttributeType.Tensor;
856 attrib.T = new TensorProto();
857 attrib.T.DataType = (int)OnnxDefinitions.DataType.FLOAT;
858
859 for (int i = 0; i < p.values_f.Count; i++)
860 {
861 attrib.T.FloatData.Add(p.values_f[i]);
862 }
863
864 foreach (int nDim in p.output_shape.dim)
865 {
866 attrib.T.Dims.Add(nDim);
867 }
868
869 rgA.Add(attrib);
870 }
871
872 private void addAttributes(RepeatedField<AttributeProto> rgA, ConvolutionParameter p)
873 {
874 AttributeProto attrib = new AttributeProto();
875 attrib.Name = "kernel_shape";
876 attrib.Type = AttributeProto.Types.AttributeType.Ints;
877 uint h = (p.kernel_h.HasValue) ? p.kernel_h.Value : (p.kernel_size.Count > 0) ? p.kernel_size[0] : 3;
878 attrib.Ints.Add(h);
879 uint w = (p.kernel_w.HasValue) ? p.kernel_w.Value : (p.kernel_size.Count > 0) ? p.kernel_size[0] : 3;
880 attrib.Ints.Add(w);
881 rgA.Add(attrib);
882
883 attrib = new AttributeProto();
884 attrib.Name = "strides";
885 attrib.Type = AttributeProto.Types.AttributeType.Ints;
886 h = (p.stride_h.HasValue) ? p.stride_h.Value : (p.stride.Count > 0) ? p.stride[0] : 1;
887 attrib.Ints.Add(h);
888 w = (p.stride_w.HasValue) ? p.stride_w.Value : (p.stride.Count > 0) ? p.stride[0] : 1;
889 attrib.Ints.Add(w);
890 rgA.Add(attrib);
891
892 if ((p.pad_h.HasValue && p.pad_w.HasValue && p.pad_h != 0 && p.pad_w != 0) || (p.pad.Count > 0 && p.pad[0] != 0))
893 {
894 attrib = new AttributeProto();
895 attrib.Name = "pads";
896 attrib.Type = AttributeProto.Types.AttributeType.Ints;
897 h = (p.pad_h.HasValue) ? p.pad_h.Value : (p.pad.Count > 0) ? p.pad[0] : 0;
898 attrib.Ints.Add(h);
899 w = (p.pad_w.HasValue) ? p.pad_w.Value : (p.pad.Count > 0) ? p.pad[0] : 0;
900 attrib.Ints.Add(w);
901 attrib.Ints.Add(h);
902 attrib.Ints.Add(w);
903 rgA.Add(attrib);
904 }
905
906 if (p.dilation.Count > 0)
907 {
908 attrib = new AttributeProto();
909 attrib.Name = "dilations";
910 attrib.Type = AttributeProto.Types.AttributeType.Ints;
911 h = (p.dilation.Count > 0) ? p.dilation[0] : 1;
912 attrib.Ints.Add(h);
913 w = (p.dilation.Count > 0) ? (p.dilation.Count > 1) ? p.dilation[1] : p.dilation[0] : 1;
914 attrib.Ints.Add(w);
915 rgA.Add(attrib);
916 }
917 else
918 {
919 attrib = new AttributeProto();
920 attrib.Name = "dilations";
921 attrib.Type = AttributeProto.Types.AttributeType.Ints;
922 h = 1;
923 attrib.Ints.Add(h);
924 w = 1;
925 attrib.Ints.Add(w);
926 rgA.Add(attrib);
927 }
928
929 attrib = new AttributeProto();
930 attrib.Name = "group";
931 attrib.Type = AttributeProto.Types.AttributeType.Int;
932 attrib.I = p.group;
933 rgA.Add(attrib);
934 }
935
936 private string addAttributes(RepeatedField<AttributeProto> rgA, RepeatedField<TensorProto> rgTensors, DropoutParameter p)
937 {
938 AttributeProto attrib = new AttributeProto();
939 attrib.Name = "ratio";
940 attrib.Type = AttributeProto.Types.AttributeType.Float;
941 attrib.F = (float)p.dropout_ratio;
942 rgA.Add(attrib);
943
944 //List<int> rgShape = new List<int>() { 1 };
945 //TensorProto tensor_training_mode = new TensorProto();
946 //tensor_training_mode.Name = "training_mode" + m_nDropoutCount;
947 //tensor_training_mode.DataType = (int)OnnxDefinitions.DataType.BOOL;
948 //tensor_training_mode.Int32Data.Add(1);
949 //rgTensors.Add(tensor_training_mode);
950 //m_nDropoutCount++;
951
952 //return tensor_training_mode.Name;
953
954 return null;
955 }
956
957 private void addAttributes(RepeatedField<AttributeProto> rgA, FlattenParameter p)
958 {
959 AttributeProto attrib = new AttributeProto();
960 attrib.Name = "axis";
961 attrib.Type = AttributeProto.Types.AttributeType.Int;
962 attrib.I = p.axis;
963 rgA.Add(attrib);
964 }
965
966 private void addAttributes(RepeatedField<AttributeProto> rgA, GatherParameter p)
967 {
968 AttributeProto attrib = new AttributeProto();
969 attrib.Name = "axis";
970 attrib.Type = AttributeProto.Types.AttributeType.Int;
971 attrib.I = p.axis;
972 rgA.Add(attrib);
973 }
974
975 private void addAttributes(RepeatedField<AttributeProto> rgA, InnerProductParameter p)
976 {
977 AttributeProto attrib = new AttributeProto();
978 attrib.Name = "alpha";
979 attrib.Type = AttributeProto.Types.AttributeType.Float;
980 attrib.F = 1.0f;
981 rgA.Add(attrib);
982
983 attrib = new AttributeProto();
984 attrib.Name = "beta";
985 attrib.Type = AttributeProto.Types.AttributeType.Float;
986 attrib.F = 1.0f; // ONNX requires this to be non zero.
987 rgA.Add(attrib);
988
989 attrib = new AttributeProto();
990 attrib.Name = "transA";
991 attrib.Type = AttributeProto.Types.AttributeType.Int;
992 attrib.I = 0;
993 rgA.Add(attrib);
994
995 attrib = new AttributeProto();
996 attrib.Name = "transB";
997 attrib.Type = AttributeProto.Types.AttributeType.Int;
998 attrib.I = (p.transpose) ? 0 : 1; // see line 381 InnerProductLayer.cs (value is opposite of p.transpose)
999 rgA.Add(attrib);
1000 }
1001
1002 private void addAttributes(RepeatedField<AttributeProto> rgA, LRNParameter p)
1003 {
1004 AttributeProto attrib = new AttributeProto();
1005 attrib.Name = "alpha";
1006 attrib.Type = AttributeProto.Types.AttributeType.Float;
1007 attrib.F = (float)p.alpha;
1008 rgA.Add(attrib);
1009
1010 attrib = new AttributeProto();
1011 attrib.Name = "beta";
1012 attrib.Type = AttributeProto.Types.AttributeType.Float;
1013 attrib.F = (float)p.beta;
1014 rgA.Add(attrib);
1015
1016 attrib = new AttributeProto();
1017 attrib.Name = "bias";
1018 attrib.Type = AttributeProto.Types.AttributeType.Float;
1019 attrib.F = (float)p.k;
1020 rgA.Add(attrib);
1021
1022 attrib = new AttributeProto();
1023 attrib.Name = "size";
1024 attrib.Type = AttributeProto.Types.AttributeType.Int;
1025 attrib.I = p.local_size;
1026 rgA.Add(attrib);
1027 }
1028
1029 private void addAttributes(RepeatedField<AttributeProto> rgA, LogParameter p)
1030 {
1031 }
1032
1033 private void addAttributes(RepeatedField<AttributeProto> rgA, PoolingParameter p)
1034 {
1035 AttributeProto attrib = new AttributeProto();
1036 attrib.Name = "kernel_shape";
1037 attrib.Type = AttributeProto.Types.AttributeType.Ints;
1038 uint h = (p.kernel_h.HasValue) ? p.kernel_h.Value : (p.kernel_size.Count > 0) ? p.kernel_size[0] : 3;
1039 attrib.Ints.Add(h);
1040 uint w = (p.kernel_w.HasValue) ? p.kernel_w.Value : (p.kernel_size.Count > 0) ? p.kernel_size[0] : 3;
1041 attrib.Ints.Add(w);
1042 rgA.Add(attrib);
1043
1044 attrib = new AttributeProto();
1045 attrib.Name = "strides";
1046 attrib.Type = AttributeProto.Types.AttributeType.Ints;
1047 h = (p.stride_h.HasValue) ? p.stride_h.Value : (p.stride.Count > 0) ? p.stride[0] : 1;
1048 attrib.Ints.Add(h);
1049 w = (p.stride_w.HasValue) ? p.stride_w.Value : (p.stride.Count > 0) ? p.stride[0] : 1;
1050 attrib.Ints.Add(w);
1051 rgA.Add(attrib);
1052
1053 if ((p.pad_h.HasValue && p.pad_w.HasValue && p.pad_h != 0 && p.pad_w != 0) || (p.pad.Count > 0 && p.pad[0] != 0))
1054 {
1055 attrib = new AttributeProto();
1056 attrib.Name = "pads";
1057 attrib.Type = AttributeProto.Types.AttributeType.Ints;
1058 h = (p.pad_h.HasValue) ? p.pad_h.Value : (p.pad.Count > 0) ? p.pad[0] : 0;
1059 attrib.Ints.Add(h);
1060 w = (p.pad_w.HasValue) ? p.pad_w.Value : (p.pad.Count > 0) ? p.pad[0] : 0;
1061 attrib.Ints.Add(w);
1062 attrib.Ints.Add(h);
1063 attrib.Ints.Add(w);
1064 rgA.Add(attrib);
1065 }
1066 }
1067
1068 private void addAttributes(RepeatedField<AttributeProto> rgA, EluParameter p)
1069 {
1070 }
1071
1072 private void addAttributes(RepeatedField<AttributeProto> rgA, ExpParameter p)
1073 {
1074 }
1075
1076 private void addAttributes(RepeatedField<AttributeProto> rgA, ReductionParameter p)
1077 {
1078 AttributeProto attrib = new AttributeProto();
1079 attrib.Name = "axes";
1080 attrib.Type = AttributeProto.Types.AttributeType.Ints;
1081 attrib.Ints.Add(p.axis);
1082
1083 rgA.Add(attrib);
1084 }
1085
1086 private void addAttributes(RepeatedField<AttributeProto> rgA, ReLUParameter p)
1087 {
1088 if (p.negative_slope != 0)
1089 {
1090 AttributeProto attrib = new AttributeProto();
1091 attrib.Name = "alpha";
1092 attrib.Type = AttributeProto.Types.AttributeType.Float;
1093 attrib.F = (float)p.negative_slope;
1094 rgA.Add(attrib);
1095 }
1096 }
1097
1098 private void addAttributes(RepeatedField<AttributeProto> rgA, RepeatedField<TensorProto> rgTensors, string strName, ReshapeParameter p, bool bRemoveTrailingOnes)
1099 {
1100 List<int> rgShape = new List<int>();
1101
1102 for (int i = 0; i < p.axis; i++)
1103 {
1104 rgShape.Add(-1);
1105 }
1106
1107 for (int i = 0; i < p.shape.dim.Count; i++)
1108 {
1109 rgShape.Add(p.shape.dim[i]);
1110 }
1111
1112 if (bRemoveTrailingOnes)
1113 {
1114 while (rgShape.Count > 2 && rgShape[rgShape.Count - 1] == 1)
1115 {
1116 rgShape.RemoveAt(rgShape.Count - 1);
1117 }
1118 }
1119
1120 if (rgShape[0] == -1)
1121 rgShape[0] = 0;
1122
1123 addShapeTensor(rgTensors, strName, rgShape);
1124 }
1125
1126 private void addAttributes(RepeatedField<AttributeProto> rgA, SoftmaxParameter p)
1127 {
1128 AttributeProto attrib = new AttributeProto();
1129 attrib.Name = "axis";
1130 attrib.Type = AttributeProto.Types.AttributeType.Int;
1131 attrib.I = p.axis;
1132 rgA.Add(attrib);
1133 }
1134
1135 private void addAttributes(RepeatedField<AttributeProto> rgA, TransposeParameter p)
1136 {
1137 foreach (int nDim in p.dim)
1138 {
1139 AttributeProto attrib = new AttributeProto();
1140 attrib.Name = "dim";
1141 attrib.Type = AttributeProto.Types.AttributeType.Int;
1142 attrib.I = nDim;
1143 rgA.Add(attrib);
1144 }
1145 }
1146
1147 private string clean(string str)
1148 {
1149 string strOut = "";
1150
1151 foreach (char ch in str)
1152 {
1153 if (!char.IsWhiteSpace(ch))
1154 {
1155 strOut += ch;
1156 }
1157 }
1158
1159 return strOut;
1160 }
1161
1162 private Tuple<NetParameter, BlobCollection<T>> convertToMyCaffe(CudaDnn<T> cuda, Log log, ModelProto proto, bool bFixupNeuronNodes, DatasetDescriptor dsTraining = null)
1163 {
1164 try
1165 {
1166 NetParameter netParam = new NetParameter();
1167 BlobCollection<T> colTensors = new BlobCollection<T>();
1168 BlobCollection<T> colLearnableBlobs = new BlobCollection<T>();
1169 OnnxDefinitions onnx = new OnnxDefinitions();
1170
1171 m_strReport = "";
1172
1173 netParam.name = clean(proto.Graph.Name);
1174 Tuple<List<string>, List<string>> rgInputs = addInputs(proto.Graph.Input, netParam, false);
1175 addTensors(proto.Graph.Initializer, colTensors, cuda, log);
1176 colLearnableBlobs = addLayers(proto.Graph.Node, proto.Graph.Input, netParam, colTensors, onnx, rgInputs.Item1, cuda, log, false);
1177 addInputs(proto.Graph.Input, netParam, true, rgInputs.Item1, rgInputs.Item2);
1178
1179 NetParameter netParamFixed = fixupModel(netParam, colLearnableBlobs, rgInputs.Item2);
1180
1181 if (bFixupNeuronNodes)
1182 netParamFixed = fixupModelNeuronNodes(netParamFixed);
1183
1184 if (dsTraining != null)
1185 netParamFixed = fixupModelForTraining(netParamFixed, dsTraining);
1186
1187 netParamFixed = linkEmptyBottoms(netParamFixed);
1188
1189 netParamFixed = removeLayersWithOrphanedBottoms(netParamFixed);
1190
1191 return new Tuple<NetParameter, BlobCollection<T>>(netParamFixed, colLearnableBlobs);
1192 }
1193 catch (Exception excpt)
1194 {
1195 m_strReport += "ERROR: " + excpt.Message + Environment.NewLine;
1196 throw excpt;
1197 }
1198 }
1199
1200 private NetParameter linkEmptyBottoms(NetParameter net)
1201 {
1202 for (int i = 1; i < net.layer.Count; i++)
1203 {
1204 if (net.layer[i].type != LayerParameter.LayerType.DATA &&
1205 net.layer[i].type != LayerParameter.LayerType.ANNOTATED_DATA &&
1206 net.layer[i].type != LayerParameter.LayerType.DUMMYDATA &&
1207 net.layer[i].type != LayerParameter.LayerType.INPUT &&
1208 net.layer[i].type != LayerParameter.LayerType.MEMORYDATA &&
1209 net.layer[i].bottom.Count == 0 &&
1210 net.layer[i-1].top.Count == 1)
1211 {
1212 net.layer[i].bottom.Add(net.layer[i - 1].top[0]);
1213 }
1214 }
1215
1216 return net;
1217 }
1218
1219 private NetParameter removeLayersWithOrphanedBottoms(NetParameter net)
1220 {
1221 List<int> rgRemoveIdx = new List<int>();
1222 Dictionary<string, Tuple<int, int>> rgTopToLayerIdx = new Dictionary<string, Tuple<int, int>>();
1223
1224 // Find all tops and their associated layer index and top index.
1225 for (int i = 0; i < net.layer.Count; i++)
1226 {
1227 for (int j=0; j<net.layer[i].top.Count; j++)
1228 {
1229 if (!rgTopToLayerIdx.ContainsKey(net.layer[i].top[j]))
1230 rgTopToLayerIdx.Add(net.layer[i].top[j], new Tuple<int, int>(i, j));
1231 }
1232 }
1233
1234 // Replace the parent top with the bottom of the layer to be removed.
1235 for (int i=1; i<net.layer.Count; i++)
1236 {
1237 Dictionary<string, Tuple<int, int>> rgBtmToParentTop = new Dictionary<string, Tuple<int, int>>();
1238 bool bMissingBtmFound = false;
1239
1240 foreach (string strBtm in net.layer[i].bottom)
1241 {
1242 if (!rgTopToLayerIdx.ContainsKey(strBtm))
1243 {
1244 rgRemoveIdx.Add(i);
1245 bMissingBtmFound = true;
1246 }
1247 else
1248 {
1249 rgBtmToParentTop.Add(strBtm, rgTopToLayerIdx[strBtm]);
1250 }
1251 }
1252
1253 if (!bMissingBtmFound && net.layer[i].bottom.Count >= net.layer[i].expected_bottom.Count)
1254 rgBtmToParentTop.Clear();
1255 else if (!rgRemoveIdx.Contains(i))
1256 rgRemoveIdx.Add(i);
1257
1258 foreach (KeyValuePair<string, Tuple<int, int>> kvTopInParent in rgBtmToParentTop)
1259 {
1260 if (net.layer[i].top.Count > 0)
1261 net.layer[kvTopInParent.Value.Item1].top[kvTopInParent.Value.Item2] = net.layer[i].top[0];
1262 }
1263 }
1264
1265 // Remove the layer.
1266 for (int i = rgRemoveIdx.Count - 1; i >= 0; i--)
1267 {
1268 net.layer.RemoveAt(rgRemoveIdx[i]);
1269 }
1270
1271 return net;
1272 }
1273
1274 private NetParameter fixupModelForTraining(NetParameter netParam, DatasetDescriptor ds)
1275 {
1276 string strName = (netParam.input.Count > 0) ? netParam.input[0] : "data";
1277
1278 // Replace the inputs with the data layers.
1279 LayerParameter dataLayerTrain = new LayerParameter(LayerParameter.LayerType.DATA, strName);
1280 dataLayerTrain.include.Add(new NetStateRule(Phase.TRAIN));
1281 dataLayerTrain.transform_param.color_order = TransformationParameter.COLOR_ORDER.BGR;
1282 dataLayerTrain.transform_param.scale = 1.0;
1283 dataLayerTrain.data_param.batch_size = 16;
1284 dataLayerTrain.data_param.source = ds.TrainingSource.Name;
1285 dataLayerTrain.top.Add(strName);
1286 dataLayerTrain.top.Add("label");
1287
1288 LayerParameter dataLayerTest = new LayerParameter(LayerParameter.LayerType.DATA, strName);
1289 dataLayerTest.include.Add(new NetStateRule(Phase.TEST));
1291 dataLayerTest.transform_param.scale = 1.0;
1292 dataLayerTest.data_param.batch_size = 16;
1293 dataLayerTest.data_param.source = ds.TestingSource.Name;
1294 dataLayerTest.top.Add(strName);
1295 dataLayerTest.top.Add("label");
1296
1297 if (netParam.input.Count == 0)
1298 {
1299 if (netParam.layer[0].bottom.Count > 0)
1300 netParam.layer[0].bottom[0] = strName;
1301 else
1302 netParam.layer[0].bottom.Add(strName);
1303 }
1304
1305 m_strReport += "Removed inputs " + Utility.ToString<string>(netParam.input) + Environment.NewLine;
1306 netParam.input.Clear();
1307 netParam.input_shape.Clear();
1308
1309 m_strReport += "Added DATA layer '" + dataLayerTest.name + "' with phase TEST..." + Environment.NewLine;
1310 netParam.layer.Insert(0, dataLayerTest);
1311 m_strReport += "Added DATA layer '" + dataLayerTest.name + "' with phase TRAIN..." + Environment.NewLine;
1312 netParam.layer.Insert(0, dataLayerTrain);
1313
1314 LayerParameter lastLayer = netParam.layer[netParam.layer.Count - 1];
1315 if (lastLayer.type == LayerParameter.LayerType.SOFTMAX || lastLayer.type == LayerParameter.LayerType.INNERPRODUCT)
1316 {
1317 List<string> rgstrLossBottom;
1318 List<string> rgstrAccuracyBottom;
1319 int nAxis = 1;
1320 if (lastLayer.type == LayerParameter.LayerType.SOFTMAX)
1321 {
1322 m_strReport += "Removing last layer SOFTMAX..." + Environment.NewLine;
1323 netParam.layer.Remove(lastLayer);
1324 rgstrLossBottom = Utility.Clone<string>(lastLayer.bottom);
1325 rgstrAccuracyBottom = Utility.Clone<string>(lastLayer.bottom);
1326 }
1327 else
1328 {
1329 rgstrLossBottom = Utility.Clone<string>(lastLayer.top);
1330 rgstrAccuracyBottom = Utility.Clone<string>(lastLayer.top);
1331 }
1332
1333 LayerParameter loss = new LayerParameter(LayerParameter.LayerType.SOFTMAXWITH_LOSS, "loss");
1334 loss.top.Add("loss");
1335 loss.bottom = rgstrLossBottom;
1336 loss.bottom.Add(dataLayerTrain.top[1]);
1337
1338 if (lastLayer.softmax_param != null)
1339 {
1340 nAxis = lastLayer.softmax_param.axis;
1341 loss.softmax_param = lastLayer.softmax_param;
1342 }
1343
1344 m_strReport += "Added new last layer SOFTMAXWITH_LOSS '" + loss.name + "'..." + Environment.NewLine;
1345 netParam.layer.Add(loss);
1346
1347 LayerParameter accuracy = new LayerParameter(LayerParameter.LayerType.ACCURACY, "accuracy");
1348 accuracy.top.Add("accuracy");
1349 accuracy.bottom = rgstrAccuracyBottom;
1350 accuracy.bottom.Add(dataLayerTest.top[1]);
1351 accuracy.accuracy_param.axis = nAxis;
1352 accuracy.include.Add(new NetStateRule(Phase.TEST));
1353 m_strReport += "Added new last layer ACCURACY '" + accuracy.name + "'..." + Environment.NewLine;
1354 netParam.layer.Add(accuracy);
1355 }
1356
1357 return netParam;
1358 }
1359
1360 private bool isNeuron(LayerParameter.LayerType type)
1361 {
1362 if (type == LayerParameter.LayerType.RELU ||
1363 type == LayerParameter.LayerType.TANH ||
1364 type == LayerParameter.LayerType.MISH ||
1365 type == LayerParameter.LayerType.SWISH ||
1366 type == LayerParameter.LayerType.MATH ||
1367 type == LayerParameter.LayerType.SIGMOID ||
1368 type == LayerParameter.LayerType.ELU ||
1369 type == LayerParameter.LayerType.PRELU ||
1370 type == LayerParameter.LayerType.DROPOUT)
1371 return true;
1372
1373 return false;
1374 }
1375
1376 private bool replaceTop(LayerParameter p, string strTopToReplace, string strNewTop)
1377 {
1378 for (int i=0; i<p.top.Count; i++)
1379 {
1380 if (p.top[i] == strTopToReplace)
1381 {
1382 p.top[i] = strNewTop;
1383 return true;
1384 }
1385 }
1386
1387 return false;
1388 }
1389
1390 private bool replaceBtm(LayerParameter p, string strBtmToReplace, string strNewBtm)
1391 {
1392 for (int i = 0; i < p.bottom.Count; i++)
1393 {
1394 if (p.bottom[i] == strBtmToReplace)
1395 {
1396 p.bottom[i] = strNewBtm;
1397 return true;
1398 }
1399 }
1400
1401 return false;
1402 }
1403
1404 private NetParameter fixupModelNeuronNodes(NetParameter netParam)
1405 {
1406 foreach (LayerParameter layer in netParam.layer)
1407 {
1408 if (isNeuron(layer.type))
1409 {
1410 string strBtm = layer.bottom[0];
1411
1412 if (layer.top.Count == 0)
1413 {
1414 layer.top.Add(strBtm);
1415 }
1416 else
1417 {
1418 string strTop = layer.top[0];
1419
1420 LayerParameter layerPrev = findLayerWithTop(netParam, strBtm);
1421 List<LayerParameter> rgLayerNext = findLayersWithBtm(netParam, strTop);
1422
1423 // MyCaffe neural nodes pass data right back to the prev node.
1424 layer.top[0] = layer.bottom[0];
1425
1426 // Connect the prev node top with the next node btm.
1427 foreach (LayerParameter layerNext in rgLayerNext)
1428 {
1429 replaceBtm(layerNext, strTop, strBtm);
1430 }
1431 }
1432 }
1433 }
1434
1435 return netParam;
1436 }
1437
1438 private NetParameter fixupModel(NetParameter netParam, BlobCollection<T> col, List<string> rgstrInvalidInput)
1439 {
1440 NetParameter p = netParam.Clone();
1441
1442 // Find the data input.
1443 int nDataInputIdx = 0;
1444 for (int i = 0; i < p.input.Count; i++)
1445 {
1446 if (p.input[i].Contains("data"))
1447 {
1448 nDataInputIdx = i;
1449 break;
1450 }
1451 }
1452
1453 // Change input name to 'data'
1454 List<LayerParameter> rgLayer1 = findLayersWithBtm(p, p.input[nDataInputIdx]);
1455 foreach (LayerParameter layer1 in rgLayer1)
1456 {
1457 replaceBtm(layer1, p.input[nDataInputIdx], "data");
1458 m_strReport += "Changed layer '" + layer1.name + " (" + layer1.type.ToString() + ")' input from '" + p.input[nDataInputIdx] + "' to 'data'";
1459 }
1460
1461 m_strReport += "Changed data input[" + nDataInputIdx.ToString() + "] from '" + p.input[nDataInputIdx] + "' to 'data'";
1462 p.input[nDataInputIdx] = "data";
1463
1464
1465 // Remove all input orphans.
1466 List<string> rgInputs = Utility.Clone<string>(p.input);
1467 foreach (LayerParameter layer1 in p.layer)
1468 {
1469 foreach (string strBtm in layer1.bottom)
1470 {
1471 rgInputs.Remove(strBtm);
1472 }
1473
1474 if (rgInputs.Count == 0)
1475 break;
1476 }
1477
1478 foreach (string strOrphanInput in rgInputs)
1479 {
1480 p.input.Remove(strOrphanInput);
1481 }
1482
1483 // Find all orphan bottoms
1484 LayerDataCollection rgBtmOrphans = new LayerDataCollection(LayerData.TYPE.BTM);
1485 for (int i = p.layer.Count-1; i>=0; i--)
1486 {
1487 LayerParameter layer = p.layer[i];
1488
1489 rgBtmOrphans.Add(layer.bottom, i, layer);
1490 rgBtmOrphans.Remove(layer.top);
1491 }
1492
1493 rgBtmOrphans.Remove(p.input);
1494
1495 // Find all orphan tops
1496 LayerDataCollection rgTopOrphans = new LayerDataCollection(LayerData.TYPE.TOP);
1497 for (int i=0; i<p.layer.Count; i++)
1498 {
1499 LayerParameter layer = p.layer[i];
1500
1501 if (i < p.layer.Count-1)
1502 rgTopOrphans.Add(layer.top, i, layer);
1503
1504 rgTopOrphans.Remove(layer.bottom);
1505 }
1506
1507 // Fixup - remove all top orphans.
1508 if (rgTopOrphans.Count > 0)
1509 {
1510 m_strReport += "[Found '" + rgTopOrphans.Count.ToString() + " Top Orphans]" + Environment.NewLine;
1511 foreach (LayerData top in rgTopOrphans)
1512 {
1513 m_strReport += " " + top.Name + " found in layer " + top.Layer.ToString() + Environment.NewLine;
1514 }
1515
1516 for (int i = 0; i < p.layer.Count; i++)
1517 {
1518 LayerParameter layer = p.layer[i];
1519 m_strReport += rgTopOrphans.FixupTops(i, layer);
1520 }
1521 }
1522
1523 // Fixup - fixup bottom orphans.
1524 if (rgBtmOrphans.Count > 0)
1525 {
1526 m_strReport += "[Found '" + rgBtmOrphans.Count.ToString() + " Bottom Orphans]" + Environment.NewLine;
1527 foreach (LayerData btm in rgBtmOrphans)
1528 {
1529 m_strReport += " " + btm.Name + " found in layer " + btm.Layer.ToString() + Environment.NewLine;
1530 }
1531
1532 foreach (LayerData item in rgBtmOrphans)
1533 {
1534 // Remove reshape layers with external input sizings.
1535 if (item.Layer.type == LayerParameter.LayerType.RESHAPE)
1536 {
1537 if (item.Layer.bottom.Count > 1 && rgstrInvalidInput.Contains(item.Layer.bottom[1]))
1538 {
1539 foreach (string strBtm1 in item.Layer.bottom)
1540 {
1541 p.input.Remove(strBtm1);
1542 }
1543
1544 string strBtm = item.Layer.bottom[0];
1545 string strTop = (item.Layer.top.Count > 0) ? item.Layer.top[0] : null;
1546
1547 LayerParameter layerPrev = findLayerWithTop(p, strBtm);
1548 List<LayerParameter> rgLayerNext = findLayersWithBtm(p, strTop);
1549
1550 // Remove the reshape layer.
1551 m_strReport += "Removed RESHAPE layer..." + Environment.NewLine;
1552 p.layer.Remove(item.Layer);
1553
1554 if (layerPrev != null && rgLayerNext.Count > 0)
1555 {
1556 // Remove any blobs used by the layer.
1557 Blob<T> blob = col.FindBlob(item.Layer.bottom[1]);
1558 if (blob != null)
1559 {
1560 col.Remove(blob);
1561 m_strReport += "Removed blob '" + blob.Name + "' with shape '" + blob.shape_string + "'..." + Environment.NewLine;
1562 blob.Dispose();
1563 }
1564
1565 string strTop1 = layerPrev.top[0];
1566
1567 // Replace the bottom of next layer (that the reshape outputs to)
1568 // with the top of the layer previous to the reshape layer.
1569 foreach (LayerParameter layerNext in rgLayerNext)
1570 {
1571 for (int i = 0; i < layerNext.bottom.Count; i++)
1572 {
1573 if (layerNext.bottom[i] == strTop)
1574 {
1575 layerNext.bottom[i] = strTop1;
1576 m_strReport += "connected joining layers with '" + strTop1 + "'...";
1577
1578 break;
1579 }
1580 }
1581 }
1582 }
1583 }
1584 }
1585 }
1586 }
1587
1588 return p;
1589 }
1590
1591 private LayerParameter findLayerWithTop(NetParameter net, string strTop)
1592 {
1593 foreach (LayerParameter layer in net.layer)
1594 {
1595 if (layer.top.Contains(strTop))
1596 return layer;
1597 }
1598
1599 return null;
1600 }
1601
1602 private List<LayerParameter> findLayersWithBtm(NetParameter net, string strBtm)
1603 {
1604 List<LayerParameter> rgLayers = new List<LayerParameter>();
1605
1606 foreach (LayerParameter layer in net.layer)
1607 {
1608 if (layer.bottom.Contains(strBtm))
1609 rgLayers.Add(layer);
1610 }
1611
1612 return rgLayers;
1613 }
1614
1615 private Tuple<List<string>, List<string>> addInputs(RepeatedField<ValueInfoProto> rg, NetParameter p, bool bAdd, List<string> rgstrAvailable = null, List<string> rgstrInvalid = null)
1616 {
1617 List<string> rgstrInput = new List<string>();
1618 List<string> rgstrInvalid1 = new List<string>();
1619
1620 foreach (ValueInfoProto val in rg)
1621 {
1622 if ((rgstrAvailable == null || rgstrAvailable.Contains(val.Name)) && (rgstrInvalid == null || !rgstrInvalid.Contains(val.Name)))
1623 {
1624 if (val.Type.TensorType == null)
1625 throw new Exception("Currenly only Tensor input types are supported.");
1626
1627 if (val.Type.TensorType.ElemType != (int)OnnxDefinitions.DataType.FLOAT &&
1628 val.Type.TensorType.ElemType != (int)OnnxDefinitions.DataType.DOUBLE)
1629 rgstrInvalid1.Add(val.Name);
1630 else
1631 rgstrInput.Add(convertWs(val.Name));
1632
1633 if (bAdd)
1634 {
1635 p.input.Add(convertWs(val.Name));
1636 List<int> rgShape = new List<int>();
1637
1638 TypeProto type = val.Type;
1639 if (type.TensorType == null)
1640 throw new Exception("Currenly only Tensor input types are supported.");
1641
1642 TensorShapeProto shape = type.TensorType.Shape;
1643 foreach (TensorShapeProto.Types.Dimension dim in shape.Dim)
1644 {
1645 rgShape.Add((int)dim.DimValue);
1646 }
1647
1648 p.input_shape.Add(new BlobShape(rgShape));
1649
1650 m_strReport += "Adding input '" + val.Name + " with shape " + rgShape.ToString() + Environment.NewLine;
1651 }
1652 }
1653 }
1654
1655 return new Tuple<List<string>, List<string>>(rgstrInput, rgstrInvalid1);
1656 }
1657
1658 private void addTensors(RepeatedField<TensorProto> rg, BlobCollection<T> col, CudaDnn<T> cuda, Log log)
1659 {
1660 foreach (TensorProto tensor in rg)
1661 {
1662 List<int> rgShape = new List<int>();
1663
1664 foreach (long lDim in tensor.Dims)
1665 {
1666 rgShape.Add((int)lDim);
1667 }
1668
1669 Blob<T> blob = new Blob<T>(cuda, log, rgShape);
1670 blob.Name = convertWs(tensor.Name);
1671
1672 if (typeof(T) == typeof(float))
1673 {
1674 float[] rgData = getDataAsFloat(tensor);
1675 blob.mutable_cpu_data = Utility.ConvertVec<T>(rgData);
1676 }
1677 else
1678 {
1679 double[] rgData = getDataAsDouble(tensor);
1680 blob.mutable_cpu_data = Utility.ConvertVec<T>(rgData);
1681 }
1682
1683 m_strReport += "Adding tensor '" + blob.Name + "' " + blob.shape_string + Environment.NewLine;
1684
1685 col.Add(blob);
1686 }
1687 }
1688
1694 public static float[] getDataAsFloat(TensorProto tensor)
1695 {
1696 float[] rgData = null;
1697
1698 if (tensor.DataType == (int)OnnxDefinitions.DataType.FLOAT)
1699 {
1700 if (tensor.FloatData.Count > 0)
1701 {
1702 rgData = new float[tensor.FloatData.Count];
1703 for (int i = 0; i < tensor.FloatData.Count; i++)
1704 {
1705 rgData[i] = tensor.FloatData[i];
1706 }
1707 }
1708 else
1709 {
1710 byte[] rgRaw = tensor.RawData.ToByteArray();
1711 int nLen = rgRaw.Length / sizeof(float);
1712 rgData = new float[nLen];
1713
1714 Buffer.BlockCopy(rgRaw, 0, rgData, 0, rgRaw.Length);
1715 }
1716 }
1717 else if (tensor.DataType == (int)OnnxDefinitions.DataType.DOUBLE)
1718 {
1719 if (tensor.DoubleData.Count > 0)
1720 {
1721 rgData = new float[tensor.DoubleData.Count];
1722 for (int i = 0; i < tensor.DoubleData.Count; i++)
1723 {
1724 rgData[i] = (float)tensor.DoubleData[i];
1725 }
1726 }
1727 else
1728 {
1729 byte[] rgRaw = tensor.RawData.ToByteArray();
1730 int nLen = rgRaw.Length / sizeof(double);
1731 double[] rgData2 = new double[nLen];
1732 rgData = new float[nLen];
1733
1734 Buffer.BlockCopy(rgRaw, 0, rgData2, 0, rgRaw.Length);
1735 Array.Copy(rgData2, rgData, nLen);
1736 }
1737 }
1738 else if (tensor.DataType == (int)OnnxDefinitions.DataType.INT32)
1739 {
1740 if (tensor.Int32Data.Count > 0)
1741 {
1742 rgData = new float[tensor.Int32Data.Count];
1743 for (int i = 0; i < tensor.Int32Data.Count; i++)
1744 {
1745 rgData[i] = (float)tensor.Int32Data[i];
1746 }
1747 }
1748 else
1749 {
1750 byte[] rgRaw = tensor.RawData.ToByteArray();
1751 int nLen = rgRaw.Length / sizeof(int);
1752 int[] rgData2 = new int[nLen];
1753 rgData = new float[nLen];
1754
1755 Buffer.BlockCopy(rgRaw, 0, rgData2, 0, rgRaw.Length);
1756 Array.Copy(rgData2, rgData, nLen);
1757 }
1758 }
1759 else if (tensor.DataType == (int)OnnxDefinitions.DataType.INT64)
1760 {
1761 if (tensor.Int64Data.Count > 0)
1762 {
1763 rgData = new float[tensor.Int64Data.Count];
1764 for (int i = 0; i < tensor.Int64Data.Count; i++)
1765 {
1766 rgData[i] = (float)tensor.Int64Data[i];
1767 }
1768 }
1769 else
1770 {
1771 byte[] rgRaw = tensor.RawData.ToByteArray();
1772 int nLen = rgRaw.Length / sizeof(long);
1773 long[] rgData2 = new long[nLen];
1774 rgData = new float[nLen];
1775
1776 Buffer.BlockCopy(rgRaw, 0, rgData2, 0, rgRaw.Length);
1777 Array.Copy(rgData2, rgData, nLen);
1778 }
1779 }
1780 else
1781 {
1782 throw new Exception("Currently only the 'DataType.FLOAT' and 'DataType.DOUBLE' are supported for conversions to MyCaffe.");
1783 }
1784
1785 return rgData;
1786 }
1787
1793 public static double[] getDataAsDouble(TensorProto tensor)
1794 {
1795 double[] rgData = null;
1796
1797 if (tensor.DataType == (int)OnnxDefinitions.DataType.FLOAT)
1798 {
1799 if (tensor.FloatData.Count > 0)
1800 {
1801 rgData = new double[tensor.FloatData.Count];
1802 for (int i = 0; i < tensor.FloatData.Count; i++)
1803 {
1804 rgData[i] = tensor.FloatData[i];
1805 }
1806 }
1807 else
1808 {
1809 byte[] rgRaw = tensor.RawData.ToByteArray();
1810 int nLen = rgRaw.Length / sizeof(float);
1811 float[] rgData2 = new float[nLen];
1812 rgData = new double[nLen];
1813
1814 Buffer.BlockCopy(rgRaw, 0, rgData2, 0, rgRaw.Length);
1815 Array.Copy(rgData2, rgData, nLen);
1816 }
1817 }
1818 else if (tensor.DataType == (int)OnnxDefinitions.DataType.DOUBLE)
1819 {
1820 if (tensor.DoubleData.Count > 0)
1821 {
1822 rgData = new double[tensor.DoubleData.Count];
1823 for (int i = 0; i < tensor.DoubleData.Count; i++)
1824 {
1825 rgData[i] = (float)tensor.DoubleData[i];
1826 }
1827 }
1828 else
1829 {
1830 byte[] rgRaw = tensor.RawData.ToByteArray();
1831 int nLen = rgRaw.Length / sizeof(double);
1832 double[] rgData2 = new double[nLen];
1833 rgData = new double[nLen];
1834
1835 Buffer.BlockCopy(rgRaw, 0, rgData, 0, rgRaw.Length);
1836 }
1837 }
1838 else if (tensor.DataType == (int)OnnxDefinitions.DataType.INT32)
1839 {
1840 if (tensor.Int32Data.Count > 0)
1841 {
1842 rgData = new double[tensor.Int32Data.Count];
1843 for (int i = 0; i < tensor.Int32Data.Count; i++)
1844 {
1845 rgData[i] = (float)tensor.Int32Data[i];
1846 }
1847 }
1848 else
1849 {
1850 byte[] rgRaw = tensor.RawData.ToByteArray();
1851 int nLen = rgRaw.Length / sizeof(int);
1852 int[] rgData2 = new int[nLen];
1853 rgData = new double[nLen];
1854
1855 Buffer.BlockCopy(rgRaw, 0, rgData2, 0, rgRaw.Length);
1856 Array.Copy(rgData2, rgData, nLen);
1857 }
1858 }
1859 else if (tensor.DataType == (int)OnnxDefinitions.DataType.INT64)
1860 {
1861 if (tensor.Int64Data.Count > 0)
1862 {
1863 rgData = new double[tensor.Int64Data.Count];
1864 for (int i = 0; i < tensor.Int64Data.Count; i++)
1865 {
1866 rgData[i] = (float)tensor.Int64Data[i];
1867 }
1868 }
1869 else
1870 {
1871 byte[] rgRaw = tensor.RawData.ToByteArray();
1872 int nLen = rgRaw.Length / sizeof(long);
1873 long[] rgData2 = new long[nLen];
1874 rgData = new double[nLen];
1875
1876 Buffer.BlockCopy(rgRaw, 0, rgData2, 0, rgRaw.Length);
1877 Array.Copy(rgData2, rgData, nLen);
1878 }
1879 }
1880 else
1881 {
1882 throw new Exception("Currently only the 'DataType.FLOAT' and 'DataType.DOUBLE' are supported for conversions to MyCaffe.");
1883 }
1884
1885 return rgData;
1886 }
1887
1888 private int getOutputs(string strLayerName, BlobCollection<T> col, string strWt, string strBias, out bool bBiasTerm, int nAxis = 0)
1889 {
1890 int? nWtOutputs = null;
1891 int? nBiasOutputs = null;
1892
1893 bBiasTerm = false;
1894
1895 foreach (Blob<T> blob in col)
1896 {
1897 if (blob.Name == strWt)
1898 {
1899 blob.Tag = strLayerName;
1900
1901 int nAxis1 = (nAxis >= 0) ? nAxis : nAxis + blob.shape().Count;
1902 if (nAxis < 0)
1903 {
1904 for (int i = nAxis1; i >= 0; i--)
1905 {
1906 if (blob.shape()[i] > 1)
1907 {
1908 nAxis1 = i;
1909 break;
1910 }
1911 }
1912 }
1913
1914 nWtOutputs = blob.shape()[nAxis1];
1915 }
1916 else if (blob.Name == strBias && strBias != null)
1917 {
1918 blob.Tag = strLayerName;
1919 bBiasTerm = true;
1920 nBiasOutputs = blob.shape()[0];
1921 }
1922
1923 if (nWtOutputs.HasValue && bBiasTerm)
1924 break;
1925 }
1926
1927 if (!nWtOutputs.HasValue && !nBiasOutputs.HasValue)
1928 throw new Exception("Could not find the blob '" + strWt + "' or the blob '" + strBias + "'!");
1929
1930 if (nWtOutputs.HasValue)
1931 return nWtOutputs.Value;
1932
1933 return nBiasOutputs.Value;
1934 }
1935
1936 private string getOperator(OnnxDefinitions onnx, OnnxDefinitions.OPERATORS op)
1937 {
1938 string str = onnx.GetString(op);
1939 if (str == null)
1940 str = op.ToString();
1941
1942 return str;
1943 }
1944
1945 private string convertWs(string str)
1946 {
1947 string strOut = "";
1948
1949 foreach (char ch in str)
1950 {
1951 if (char.IsWhiteSpace(ch))
1952 strOut += "_";
1953 else
1954 strOut += ch;
1955 }
1956
1957 return strOut;
1958 }
1959
1960 private void scale(Blob<T> blob)
1961 {
1962 if (!m_dfWtScaleMin.HasValue || double.IsNaN(m_dfWtScaleMin.Value) || !m_dfWtScaleMax.HasValue || double.IsNaN(m_dfWtScaleMax.Value))
1963 return;
1964
1965 blob.scale_to_range(m_dfWtScaleMin.Value, m_dfWtScaleMax.Value);
1966 }
1967
1968 private BlobCollection<T> addLayers(RepeatedField<NodeProto> rg, RepeatedField<ValueInfoProto> rgInputs, NetParameter p, BlobCollection<T> col, OnnxDefinitions onnx, List<string> rgstrInputs, CudaDnn<T> cuda, Log log, bool bIncludeConstants)
1969 {
1970 BlobCollection<T> colLearnable = new BlobCollection<T>();
1971 Dictionary<string, ConstantParameter> rgConstants = new Dictionary<string, ConstantParameter>();
1972 List<string> rgUsedConstants = new List<string>();
1973 LayerParameter lastLayer = null;
1974 LayerParameter lastLayerAdded = null;
1975 NodeProto lastNode = null;
1976
1977 for (int nNodeIdx=0; nNodeIdx<rg.Count; nNodeIdx++)
1978 {
1979 NodeProto node = rg[nNodeIdx];
1980 List<string> rgstrLearnableBlobs = new List<string>();
1981 LayerParameter layer = null;
1982 bool bSkipLayer = false;
1983 string strNodeName = convertWs(node.Name);
1984
1985 if (string.IsNullOrEmpty(strNodeName))
1986 strNodeName = convertWs(node.Output[0]);
1987
1988 List<string> rgstrExcludedInputs = new List<string>();
1989
1990 if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Abs))
1991 {
1992 layer = new LayerParameter(LayerParameter.LayerType.ABSVAL);
1993 layer.name = strNodeName;
1994 }
1995
1996 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Acos))
1997 {
1998 layer = new LayerParameter(LayerParameter.LayerType.MATH);
1999 layer.name = strNodeName;
2000 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.ACOS);
2001 }
2002
2003 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Acosh))
2004 {
2005 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2006 layer.name = strNodeName;
2007 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.ACOSH);
2008 }
2009
2010 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Add))
2011 {
2012 layer = new LayerParameter(LayerParameter.LayerType.ELTWISE);
2013 layer.name = strNodeName;
2014 fillParameter(node.Attribute, layer.eltwise_param, EltwiseParameter.EltwiseOp.SUM);
2015
2016 // Skip this layer if adding in an external variable.
2017 foreach (string strInput in node.Input)
2018 {
2019 if (!isInputUsed(p.layer, strInput))
2020 {
2021 bSkipLayer = true;
2022 break;
2023 }
2024 }
2025 }
2026
2027 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ArgMin))
2028 {
2029 layer = new LayerParameter(LayerParameter.LayerType.ARGMAX);
2030 layer.name = strNodeName;
2031 fillParameter(node.Attribute, layer.argmax_param, ArgMaxParameter.COMPARE_OPERATOR.MIN);
2032 }
2033
2034 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ArgMax))
2035 {
2036 layer = new LayerParameter(LayerParameter.LayerType.ARGMAX);
2037 layer.name = strNodeName;
2038 fillParameter(node.Attribute, layer.argmax_param, ArgMaxParameter.COMPARE_OPERATOR.MAX);
2039 }
2040
2041 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Asin))
2042 {
2043 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2044 layer.name = strNodeName;
2045 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.ASIN);
2046 }
2047
2048 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Asinh))
2049 {
2050 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2051 layer.name = strNodeName;
2052 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.ASINH);
2053 }
2054
2055 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Atan))
2056 {
2057 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2058 layer.name = strNodeName;
2059 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.ATAN);
2060 }
2061
2062 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Atanh))
2063 {
2064 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2065 layer.name = strNodeName;
2066 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.ATANH);
2067 }
2068
2069 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.AveragePool))
2070 {
2071 layer = new LayerParameter(LayerParameter.LayerType.POOLING);
2072 layer.name = strNodeName;
2073 fillParameter(node.Attribute, layer.pooling_param, PoolingParameter.PoolingMethod.AVE, false);
2074 }
2075
2076 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.BatchNormalization))
2077 {
2078 layer = new LayerParameter(LayerParameter.LayerType.BATCHNORM);
2079 layer.name = strNodeName;
2080 fillParameter(node.Attribute, layer.batch_norm_param);
2081
2082 BlobCollection<T> colBlobs = new BlobCollection<T>();
2083
2084 for (int i = 1; i < node.Input.Count; i++)
2085 {
2086 string strInput = convertWs(node.Input[i]);
2087
2088 Blob<T> blob = col.FindBlob(strInput);
2089 if (blob == null && rgConstants.ContainsKey(strInput))
2090 {
2091 ConstantParameter constParam = rgConstants[strInput];
2092 blob = createBlobFromConstant(constParam, cuda, log, strInput);
2093 rgUsedConstants.Add(strInput);
2094 }
2095
2096 if (blob != null)
2097 {
2098 blob.Tag = strNodeName;
2099 scale(blob);
2100 colBlobs.Add(blob);
2101 }
2102 }
2103
2104 colLearnable.Add(colBlobs[2]); // mean
2105 colLearnable.Add(colBlobs[3]); // var
2106
2107 Blob<T> blobVarCor = new Blob<T>(cuda, log);
2108 blobVarCor.ReshapeLike(colBlobs[0]);
2109 blobVarCor.SetData(1.0);
2110 blobVarCor.Tag = strNodeName;
2111
2112 colLearnable.Add(blobVarCor); // varcor.
2113
2114 layer.batch_norm_param.scale_bias = true;
2115 colLearnable.Add(colBlobs[0]); // scale
2116 colLearnable.Add(colBlobs[1]); // bias;
2117
2118 for (int i = 1; i < node.Input.Count; i++)
2119 {
2120 string strInput = convertWs(node.Input[i]);
2121 rgstrExcludedInputs.Add(strInput);
2122 }
2123 }
2124
2125 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Clip))
2126 {
2127 layer = new LayerParameter(LayerParameter.LayerType.CLIP);
2128 layer.name = strNodeName;
2129 fillParameter(node.Attribute, layer.clip_param);
2130
2131 for (int i = 1; i < node.Input.Count; i++)
2132 {
2133 Blob<T> input = col.FindBlob(node.Input[i]);
2134 if (input != null)
2135 {
2136 float[] rgF = Utility.ConvertVecF<T>(input.update_cpu_data());
2137 if (rgF.Length == 1)
2138 {
2139 if (i == 1)
2140 layer.clip_param.min = rgF[0];
2141 else if (i == 2)
2142 layer.clip_param.max = rgF[0];
2143
2144 rgUsedConstants.Add(node.Input[i]);
2145 }
2146 }
2147 }
2148 }
2149
2150 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Concat))
2151 {
2152 layer = new LayerParameter(LayerParameter.LayerType.CONCAT);
2153 layer.name = strNodeName;
2154 fillParameter(node.Attribute, layer.concat_param);
2155 }
2156
2157 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Constant))
2158 {
2159 string strOutput = convertWs(node.Output[0]);
2160
2161 if (!rgConstants.ContainsKey(strOutput))
2162 {
2163 layer = new LayerParameter(LayerParameter.LayerType.CONSTANT);
2164 layer.name = strNodeName;
2165 fillParameter(node.Attribute, layer.name, layer.constant_param);
2166 rgConstants.Add(strOutput, layer.constant_param);
2167 }
2168 }
2169
2170 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ConstantOfShape))
2171 {
2172 string strOutput = convertWs(node.Output[0]);
2173
2174 layer = new LayerParameter(LayerParameter.LayerType.CONSTANT);
2175 layer.name = strNodeName;
2176 fillParameter(node.Attribute, strOutput, layer.constant_param);
2177 rgConstants.Add(strOutput, layer.constant_param);
2178 }
2179
2180 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Conv))
2181 {
2182 int nGroupReductionFactor = 1;
2183 int nFirstLearnableIdx = -1;
2184 int nAddLearnableCount = 0;
2185
2186 for (int i = 1; i < node.Input.Count; i++)
2187 {
2188 string strInput = convertWs(node.Input[i]);
2189
2190 Blob<T> blob = col.FindBlob(strInput);
2191 if (blob == null && rgConstants.ContainsKey(strInput))
2192 {
2193 ConstantParameter constParam = rgConstants[strInput];
2194 blob = createBlobFromConstant(constParam, cuda, log, strInput);
2195 rgUsedConstants.Add(strInput);
2196 }
2197
2198 if (blob != null)
2199 {
2200 rgstrLearnableBlobs.Add(convertWs(node.Input[i]));
2201 scale(blob);
2202 colLearnable.Add(blob);
2203 nAddLearnableCount++;
2204 }
2205
2206 if (i == 1)
2207 nFirstLearnableIdx = colLearnable.Count - 1;
2208 }
2209
2210 layer = new LayerParameter(LayerParameter.LayerType.CONVOLUTION);
2211 layer.name = strNodeName;
2212 fillParameter(node.Attribute, layer.convolution_param, out nGroupReductionFactor);
2213 bool bBiasTerm;
2214 string strWt = rgstrLearnableBlobs[0];
2215 string strBias = (rgstrLearnableBlobs.Count > 1) ? rgstrLearnableBlobs[1] : null;
2216 layer.convolution_param.num_output = (uint)getOutputs(layer.name, colLearnable, strWt, strBias, out bBiasTerm);
2217 layer.convolution_param.bias_term = true;
2218
2219 Filler<T> filler = Filler<T>.Create(cuda, log, layer.convolution_param.bias_filler);
2220 List<int> rgBiasShape = new List<int>() { colLearnable[colLearnable.Count - 1].num, 1, 1, 1 };
2221
2222 if (nAddLearnableCount == 1)
2223 {
2224 Blob<T> blobBias = new Blob<T>(cuda, log, rgBiasShape);
2225 filler.Fill(blobBias);
2226 blobBias.Tag = strNodeName;
2227 colLearnable.Add(blobBias);
2228 }
2229
2230 // If the group was reduced, we must expand and duplicate the weights
2231 // by the same ratio.
2232 if (nFirstLearnableIdx >= 0 && nGroupReductionFactor > 1)
2233 {
2234 Blob<T> blob = colLearnable[nFirstLearnableIdx];
2235 Blob<T> blobNew = new Blob<T>(cuda, log);
2236 blobNew.Tag = blob.Tag;
2237 blobNew.Reshape(blob.num, blob.channels * nGroupReductionFactor, blob.height, blob.width);
2238
2239 for (int c = 0; c < nGroupReductionFactor; c++)
2240 {
2241 blobNew.CopyFrom(blob, 0, c);
2242 }
2243
2244 blob.Dispose();
2245 colLearnable[nFirstLearnableIdx] = blobNew;
2246
2247 Blob<T> blobBias = new Blob<T>(cuda, log, rgBiasShape);
2248 filler.Fill(blobBias);
2249 blobBias.Tag = strNodeName;
2250 colLearnable.Add(blobBias);
2251 }
2252
2253 m_bEnableBackward = true;
2254 }
2255
2256 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Cos))
2257 {
2258 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2259 layer.name = strNodeName;
2260 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.COS);
2261 }
2262
2263 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Cosh))
2264 {
2265 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2266 layer.name = strNodeName;
2267 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.COSH);
2268 }
2269
2270 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Div))
2271 {
2272 layer = new LayerParameter(LayerParameter.LayerType.ELTWISE);
2273 layer.name = strNodeName;
2274 fillParameter(node.Attribute, layer.eltwise_param, EltwiseParameter.EltwiseOp.DIV);
2275 }
2276
2277 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Dropout))
2278 {
2279 layer = new LayerParameter(LayerParameter.LayerType.DROPOUT);
2280 layer.name = strNodeName;
2281 fillParameter(node.Attribute, layer.dropout_param);
2282 }
2283
2284 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Elu))
2285 {
2286 layer = new LayerParameter(LayerParameter.LayerType.ELU);
2287 layer.name = strNodeName;
2288 }
2289
2290 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Exp))
2291 {
2292 layer = new LayerParameter(LayerParameter.LayerType.EXP);
2293 layer.name = strNodeName;
2294 }
2295
2296 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Flatten))
2297 {
2298 layer = new LayerParameter(LayerParameter.LayerType.FLATTEN);
2299 layer.name = strNodeName;
2300 fillParameter(node.Attribute, layer.flatten_param);
2301 }
2302
2303 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Gather))
2304 {
2305 layer = new LayerParameter(LayerParameter.LayerType.GATHER);
2306 layer.name = strNodeName;
2307 fillParameter(node.Attribute, layer.gather_param);
2308 }
2309
2310 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Gemm))
2311 {
2312 int nAddLearnableCount = 0;
2313
2314 for (int i = 1; i < node.Input.Count; i++)
2315 {
2316 string strInput = convertWs(node.Input[i]);
2317 rgstrLearnableBlobs.Add(strInput);
2318 Blob<T> blob = col.FindBlob(strInput);
2319
2320 if (blob == null && rgConstants.ContainsKey(strInput))
2321 {
2322 ConstantParameter constParam = rgConstants[strInput];
2323 blob = createBlobFromConstant(constParam, cuda, log, strInput);
2324 rgUsedConstants.Add(strInput);
2325 }
2326
2327 if (blob != null)
2328 {
2329 scale(blob);
2330 colLearnable.Add(blob);
2331 nAddLearnableCount++;
2332 }
2333 }
2334
2335 layer = new LayerParameter(LayerParameter.LayerType.INNERPRODUCT);
2336 layer.name = strNodeName;
2337 fillParameter(node.Attribute, layer.inner_product_param);
2338 bool bBiasTerm;
2339 string strWt = rgstrLearnableBlobs[0];
2340 string strBias = (rgstrLearnableBlobs.Count > 1) ? rgstrLearnableBlobs[1] : null;
2341 layer.inner_product_param.num_output = (uint)getOutputs(layer.name, colLearnable, strWt, strBias, out bBiasTerm, -1);
2342 layer.inner_product_param.bias_term = (strBias != null) ? true : false;
2343
2344 //if (nAddLearnableCount == 1)
2345 //{
2346 // Filler<T> filler = Filler<T>.Create(cuda, log, layer.inner_product_param.bias_filler);
2347 // List<int> rgBiasShape = new List<int>() { colLearnable[colLearnable.Count - 1].num, 1, 1, 1 };
2348
2349 // Blob<T> blobBias = new Blob<T>(cuda, log, rgBiasShape);
2350 // filler.Fill(blobBias);
2351 // blobBias.Tag = strNodeName;
2352 // colLearnable.Add(blobBias);
2353 //}
2354
2355 m_bEnableBackward = true;
2356 }
2357
2358 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.LRN))
2359 {
2360 layer = new LayerParameter(LayerParameter.LayerType.LRN);
2361 layer.name = strNodeName;
2362 fillParameter(node.Attribute, layer.lrn_param);
2363 }
2364
2365 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Log))
2366 {
2367 layer = new LayerParameter(LayerParameter.LayerType.LOG);
2368 layer.name = strNodeName;
2369 }
2370
2371 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.LeakyRelu))
2372 {
2373 layer = new LayerParameter(LayerParameter.LayerType.RELU);
2374 layer.name = strNodeName;
2375 fillParameter(node.Attribute, layer.relu_param, true);
2376 }
2377
2378 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.MaxPool))
2379 {
2380 layer = new LayerParameter(LayerParameter.LayerType.POOLING);
2381 layer.name = strNodeName;
2382 fillParameter(node.Attribute, layer.pooling_param, PoolingParameter.PoolingMethod.MAX, false);
2383 }
2384
2385 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Min))
2386 {
2387 layer = new LayerParameter(LayerParameter.LayerType.ELTWISE);
2388 layer.name = strNodeName;
2389 fillParameter(node.Attribute, layer.eltwise_param, EltwiseParameter.EltwiseOp.MIN);
2390 }
2391
2392 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Max))
2393 {
2394 layer = new LayerParameter(LayerParameter.LayerType.ELTWISE);
2395 layer.name = strNodeName;
2396 fillParameter(node.Attribute, layer.eltwise_param, EltwiseParameter.EltwiseOp.MAX);
2397 }
2398
2399 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.MatMul))
2400 {
2401 int nAddLearnableCount = 0;
2402
2403 for (int i = 1; i < node.Input.Count; i++)
2404 {
2405 string strInput = convertWs(node.Input[i]);
2406 rgstrLearnableBlobs.Add(strInput);
2407 Blob<T> blob = col.FindBlob(strInput);
2408
2409 if (blob == null && rgConstants.ContainsKey(strInput))
2410 {
2411 ConstantParameter constParam = rgConstants[strInput];
2412 blob = createBlobFromConstant(constParam, cuda, log, strInput);
2413 rgUsedConstants.Add(strInput);
2414 }
2415
2416 if (blob != null)
2417 {
2418 scale(blob);
2419 colLearnable.Add(blob);
2420 nAddLearnableCount++;
2421 }
2422 }
2423
2424 layer = new LayerParameter(LayerParameter.LayerType.INNERPRODUCT);
2425 layer.name = strNodeName;
2426 fillParameter(node.Attribute, layer.inner_product_param);
2427 bool bBiasTerm;
2428 string strWt = rgstrLearnableBlobs[0];
2429 string strBias = (rgstrLearnableBlobs.Count > 1) ? rgstrLearnableBlobs[1] : null;
2430 layer.inner_product_param.num_output = (uint)getOutputs(layer.name, colLearnable, strWt, strBias, out bBiasTerm, -1);
2431 layer.inner_product_param.bias_term = (strBias != null) ? true : false;
2432 m_bEnableBackward = true;
2433 }
2434
2435 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Mul))
2436 {
2437 layer = new LayerParameter(LayerParameter.LayerType.ELTWISE);
2438 layer.name = strNodeName;
2439 fillParameter(node.Attribute, layer.eltwise_param, EltwiseParameter.EltwiseOp.PROD);
2440 }
2441
2442 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Neg))
2443 {
2444 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2445 layer.name = strNodeName;
2446 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.NEG);
2447 }
2448
2449 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.GlobalAveragePool))
2450 {
2451 layer = new LayerParameter(LayerParameter.LayerType.POOLING);
2452 layer.name = strNodeName;
2453 fillParameter(node.Attribute, layer.pooling_param, PoolingParameter.PoolingMethod.AVE, true);
2454 }
2455
2456 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.GlobalMaxPool))
2457 {
2458 layer = new LayerParameter(LayerParameter.LayerType.POOLING);
2459 layer.name = strNodeName;
2460 fillParameter(node.Attribute, layer.pooling_param, PoolingParameter.PoolingMethod.MAX, true);
2461 }
2462
2463 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Pow))
2464 {
2465 layer = new LayerParameter(LayerParameter.LayerType.POWER);
2466 layer.name = strNodeName;
2467 }
2468
2469 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.PRelu))
2470 {
2471 for (int i = 1; i < node.Input.Count; i++)
2472 {
2473 string strInput = convertWs(node.Input[i]);
2474 rgstrLearnableBlobs.Add(strInput);
2475 colLearnable.Add(col.FindBlob(strInput));
2476 }
2477
2478 layer = new LayerParameter(LayerParameter.LayerType.PRELU);
2479 layer.name = strNodeName;
2480 fillParameter(node.Attribute, layer.prelu_param);
2481 }
2482
2483 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Relu))
2484 {
2485 layer = new LayerParameter(LayerParameter.LayerType.RELU);
2486 layer.name = strNodeName;
2487 fillParameter(node.Attribute, layer.relu_param, false);
2488 }
2489
2490 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Reshape))
2491 {
2492 NodeProto nextNode = findNextNodeWithBtm(rg, nNodeIdx, 0);
2493 string strLastOutput = null;
2494
2495 if (lastNode == null)
2496 {
2497 ValueInfoProto input = findInput(rgInputs, rg[nNodeIdx].Input[0]);
2498 if (input != null)
2499 strLastOutput = input.Name;
2500 }
2501 else
2502 {
2503 strLastOutput = lastNode.Output[0];
2504 }
2505
2506 if (nextNode != null &&
2507 (nextNode.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.MatMul) ||
2508 nextNode.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Gemm)))
2509 {
2510 nextNode.Input[0] = strLastOutput;
2511 continue;
2512 }
2513
2514 nextNode = findNextNodeWithBtm(rg, nNodeIdx, 1);
2515
2516 if (nextNode != null &&
2517 (nextNode.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.MatMul) ||
2518 nextNode.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Gemm)))
2519 {
2520 nextNode.Input[1] = strLastOutput;
2521 continue;
2522 }
2523
2524 layer = new LayerParameter(LayerParameter.LayerType.RESHAPE);
2525 layer.name = strNodeName;
2526 if (!fillParameter(node.Attribute, layer.reshape_param, col, node.Input))
2527 bSkipLayer = true;
2528
2529 //if (lastNode != null && lastNode.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Constant))
2530 //{
2531 // if (lastLayer != null && lastLayer.type == LayerParameter.LayerType.CONSTANT)
2532 // {
2533 // List<int> rgShape1 = getShape(lastLayer.constant_param.output_shape);
2534 // List<int> rgShape2 = getShape(layer.reshape_param.shape);
2535
2536 // if (rgShape1.Count == rgShape1.Count)
2537 // {
2538 // bool bSameShape = true;
2539
2540 // for (int i = 0; i < rgShape1.Count; i++)
2541 // {
2542 // if (rgShape1[i] != rgShape2[i])
2543 // {
2544 // bSameShape = false;
2545 // break;
2546 // }
2547 // }
2548
2549 // if (bSameShape)
2550 // {
2551 // int nInputIdx = 0;
2552 // for (int i = 0; i < rg[nNodeIdx + 1].Input.Count; i++)
2553 // {
2554 // if (rg[nNodeIdx + 1].Input[i] == rg[nNodeIdx].Output[0])
2555 // {
2556 // nInputIdx = i;
2557 // break;
2558 // }
2559 // }
2560
2561 // rg[nNodeIdx + 1].Input[nInputIdx] = lastNode.Output[0];
2562 // continue;
2563 // }
2564 // }
2565 // }
2566 //}
2567 }
2568
2569 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Sin))
2570 {
2571 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2572 layer.name = strNodeName;
2573 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.SIN);
2574 }
2575
2576 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Sinh))
2577 {
2578 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2579 layer.name = strNodeName;
2580 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.SINH);
2581 }
2582
2583 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Sign))
2584 {
2585 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2586 layer.name = strNodeName;
2587 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.SIGN);
2588 }
2589
2590 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Softmax))
2591 {
2592 layer = new LayerParameter(LayerParameter.LayerType.SOFTMAX);
2593 layer.name = strNodeName;
2594 fillParameter(node.Attribute, layer.softmax_param);
2595 }
2596
2597 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Split))
2598 {
2599 layer = new LayerParameter(LayerParameter.LayerType.SPLIT);
2600 layer.name = strNodeName;
2601 }
2602
2603 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Slice))
2604 {
2605 layer = new LayerParameter(LayerParameter.LayerType.SLICE);
2606 layer.name = strNodeName;
2607 fillParameter(node.Attribute, layer.slice_param);
2608 }
2609
2610 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Sqrt))
2611 {
2612 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2613 layer.name = strNodeName;
2614 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.SQRT);
2615 }
2616
2617 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Sub))
2618 {
2619 layer = new LayerParameter(LayerParameter.LayerType.ELTWISE);
2620 layer.name = strNodeName;
2621 fillParameter(node.Attribute, layer.eltwise_param, EltwiseParameter.EltwiseOp.SUB);
2622 }
2623
2624 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Tan))
2625 {
2626 layer = new LayerParameter(LayerParameter.LayerType.MATH);
2627 layer.name = strNodeName;
2628 fillParameter(node.Attribute, layer.math_param, MyCaffe.common.MATH_FUNCTION.TAN);
2629 }
2630
2631 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Tanh))
2632 {
2633 layer = new LayerParameter(LayerParameter.LayerType.TANH);
2634 layer.name = strNodeName;
2635 }
2636
2637 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Transpose))
2638 {
2639 layer = new LayerParameter(LayerParameter.LayerType.TRANSPOSE);
2640 layer.name = strNodeName;
2641 fillParameter(node.Attribute, layer.transpose_param);
2642
2643 // Skip the initial transpose if one exists for the data layers default to BGR which already does the transpose.
2644 if (p.layer.Count == 0 || p.layer[p.layer.Count - 1].type != LayerParameter.LayerType.DATA)
2645 bSkipLayer = true;
2646 }
2647
2648 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Shape))
2649 {
2650 layer = new LayerParameter(LayerParameter.LayerType.RESHAPE);
2651 layer.name = strNodeName;
2652 fillParameter(node.Attribute, layer.reshape_param, col, node.Input);
2653 }
2654
2655 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Squeeze))
2656 {
2657 layer = new LayerParameter(LayerParameter.LayerType.SQUEEZE);
2658 layer.name = strNodeName;
2659 }
2660
2661 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Unsqueeze))
2662 {
2663 layer = new LayerParameter(LayerParameter.LayerType.UNSQUEEZE);
2664 layer.name = strNodeName;
2665 }
2666
2667 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ReduceMin))
2668 {
2669 layer = new LayerParameter(LayerParameter.LayerType.REDUCTION);
2670 layer.name = strNodeName;
2672 fillParameter(node.Attribute, layer.reduction_param);
2673 }
2674
2675 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ReduceMax))
2676 {
2677 layer = new LayerParameter(LayerParameter.LayerType.REDUCTION);
2678 layer.name = strNodeName;
2680 fillParameter(node.Attribute, layer.reduction_param);
2681 }
2682
2683 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ReduceSum))
2684 {
2685 layer = new LayerParameter(LayerParameter.LayerType.REDUCTION);
2686 layer.name = strNodeName;
2688 fillParameter(node.Attribute, layer.reduction_param);
2689 }
2690
2691 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ReduceMean))
2692 {
2693 layer = new LayerParameter(LayerParameter.LayerType.REDUCTION);
2694 layer.name = strNodeName;
2696 fillParameter(node.Attribute, layer.reduction_param);
2697 }
2698
2699 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.ReduceSumSquare))
2700 {
2701 layer = new LayerParameter(LayerParameter.LayerType.REDUCTION);
2702 layer.name = strNodeName;
2704 fillParameter(node.Attribute, layer.reduction_param);
2705 }
2706
2707 // For now skipping these layers.
2708 else if (node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.NonMaxSuppression) ||
2709 node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.Cast) ||
2710 node.OpType == getOperator(onnx, OnnxDefinitions.OPERATORS.TopK))
2711 {
2712 layer = new LayerParameter(LayerParameter.LayerType.CONSTANT);
2713 bSkipLayer = true;
2714 }
2715
2716 if (layer == null)
2717 throw new Exception("Currently the node OpType '" + node.OpType + "' is not supported!");
2718
2719 foreach (string strInput in node.Input)
2720 {
2721 string strInput1 = convertWs(strInput);
2722 if (!rgstrLearnableBlobs.Contains(strInput1) && !rgstrExcludedInputs.Contains(strInput1) && !rgUsedConstants.Contains(strInput1))
2723 layer.bottom.Add(strInput1);
2724
2725 foreach (string strLearnable in rgstrLearnableBlobs)
2726 {
2727 rgstrInputs.Remove(strLearnable);
2728 }
2729 }
2730
2731 foreach (string strOutput in node.Output)
2732 {
2733 layer.top.Add(convertWs(strOutput));
2734 }
2735
2736 // Add any constant layers for constant inputs.
2737 for (int i = 1; i < node.Input.Count; i++)
2738 {
2739 if (!rgConstants.ContainsKey(node.Input[i]) && !rgUsedConstants.Contains(node.Input[i]) && !rgstrLearnableBlobs.Contains(node.Input[i]))
2740 {
2741 Blob<T> input = col.FindBlob(node.Input[i]);
2742 if (input != null)
2743 {
2744 string strName = convertWs(node.Input[i]);
2745
2746 if (bIncludeConstants && isLayerUsed(rg, strName, strName))
2747 {
2748 LayerParameter layerConst = new LayerParameter(LayerParameter.LayerType.CONSTANT);
2749 layerConst.name = strName;
2750 layerConst.top.Add(layerConst.name);
2751 fillParameter(input, layerConst.constant_param);
2752
2753 m_strReport += "Adding constant layer '" + layerConst.ToString() + "'" + Environment.NewLine;
2754 p.layer.Add(layerConst);
2755 }
2756 }
2757 }
2758 }
2759
2760 if (!bSkipLayer && !ignoreLayer(layer))
2761 {
2762 // If we skip a layer, use the top of the last layer as input.
2763 if (lastLayer != null && lastLayerAdded != null && lastLayer.name != lastLayerAdded.name)
2764 layer.bottom = new List<string>(lastLayerAdded.top);
2765
2766 m_strReport += "Adding layer '" + layer.ToString() + "'" + Environment.NewLine;
2767 layer.freeze_learning = !m_bEnableBackward;
2768 p.layer.Add(layer);
2769 lastLayerAdded = layer;
2770 }
2771
2772 lastLayer = layer;
2773 lastNode = node;
2774 }
2775
2776 foreach (string strUsedConstant in rgUsedConstants)
2777 {
2778 removeLayer(p.layer, strUsedConstant);
2779 }
2780
2781 return colLearnable;
2782 }
2783
2784 private ValueInfoProto findInput(RepeatedField<ValueInfoProto> rg, string strName)
2785 {
2786 foreach (ValueInfoProto v in rg)
2787 {
2788 if (v.Name == strName)
2789 return v;
2790 }
2791
2792 return null;
2793 }
2794
2795 private List<int> getShape(BlobShape shape)
2796 {
2797 List<int> rgShape = new List<int>();
2798 bool bNonOneFound = false;
2799
2800 for (int i = shape.dim.Count - 1; i >= 0; i--)
2801 {
2802 if (bNonOneFound || shape.dim[i] > 1)
2803 {
2804 rgShape.Insert(0, shape.dim[i]);
2805 if (shape.dim[i] > 1)
2806 bNonOneFound = true;
2807 }
2808 }
2809
2810 return rgShape;
2811 }
2812
2813 private NodeProto findNextNodeWithBtm(RepeatedField<NodeProto> rg, int nStartIdx, int nIdx)
2814 {
2815 string strOutput = rg[nStartIdx].Output[0];
2816
2817 for (int i=nStartIdx + 1; i<rg.Count; i++)
2818 {
2819 foreach (string strInput in rg[i].Input)
2820 {
2821 if (rg[i].Input.Count > nIdx && strOutput == rg[i].Input[nIdx])
2822 return rg[i];
2823 }
2824 }
2825
2826 return null;
2827 }
2828
2829 private void removeLayer(List<LayerParameter> rgLayers, string strName)
2830 {
2831 List<LayerParameter> rg = rgLayers.Where(p => p.name == strName).ToList();
2832 if (rg.Count > 0)
2833 rgLayers.Remove(rg[0]);
2834 }
2835
2836 private Blob<T> createBlobFromInput(ValueInfoProto input, CudaDnn<T> cuda, Log log)
2837 {
2838 return null;
2839 }
2840
2841 private Blob<T> createBlobFromConstant(ConstantParameter constParam, CudaDnn<T> cuda, Log log, string strInput)
2842 {
2843 Blob<T> blob = new Blob<T>(cuda, log, constParam.output_shape.dim);
2844 blob.Name = strInput;
2845
2846 if (constParam.values_f.Count > 1)
2847 {
2848 T[] rgData = Utility.ConvertVec<T>(constParam.values_f.ToArray());
2849 blob.SetData(rgData);
2850 }
2851 else if (constParam.values_f.Count == 1)
2852 {
2853 blob.SetData(constParam.values_f[0]);
2854 }
2855 else
2856 {
2857 BlobProto proto = loadBinaryData(constParam);
2858 if (proto != null)
2859 {
2860 blob.Reshape(proto.shape);
2861 T[] rgData = Utility.ConvertVec<T>(proto.data.ToArray());
2862 if (rgData.Length > 0)
2863 blob.SetData(rgData);
2864 }
2865 }
2866
2867 return blob;
2868 }
2869
2870 private bool ignoreLayer(LayerParameter layer)
2871 {
2872 foreach (string strIgnore in m_rgstrIgnoreLayerNames)
2873 {
2874 if (layer.name.ToUpper().Contains(strIgnore.ToUpper()))
2875 return true;
2876 }
2877
2878 return false;
2879 }
2880
2881 private bool isInputUsed(List<LayerParameter> rgLayers, string strBtm)
2882 {
2883 foreach (LayerParameter layer in rgLayers)
2884 {
2885 if (layer.top.Contains(strBtm))
2886 return true;
2887 }
2888
2889 return false;
2890 }
2891
2892 private bool isLayerUsed(RepeatedField<NodeProto> rgNodes, string strName, string strTop)
2893 {
2894 foreach (NodeProto node in rgNodes)
2895 {
2896 if (node.Name != strName)
2897 {
2898 foreach (string strBtm in node.Input)
2899 {
2900 if (strBtm == strTop)
2901 return true;
2902 }
2903 }
2904 }
2905
2906 return false;
2907 }
2908
2909 private void fillParameter(RepeatedField<AttributeProto> rg, ArgMaxParameter p, ArgMaxParameter.COMPARE_OPERATOR op)
2910 {
2911 p.operation = op;
2912 }
2913
2914 private void fillParameter(RepeatedField<AttributeProto> rg, EltwiseParameter p, EltwiseParameter.EltwiseOp op)
2915 {
2916 p.operation = op;
2917 }
2918
2919 private void fillParameter(RepeatedField<AttributeProto> rg, BatchNormParameter p)
2920 {
2921 foreach (AttributeProto attrib in rg)
2922 {
2923 if (attrib.Name == "epsilon")
2924 {
2925 p.eps = attrib.F;
2926 break;
2927 }
2928 else if (attrib.Name == "momentum")
2929 {
2930 p.moving_average_fraction = attrib.F;
2931 break;
2932 }
2933 }
2934 }
2935
2936 private void fillParameter(RepeatedField<AttributeProto> rg, ClipParameter p)
2937 {
2938 foreach (AttributeProto attrib in rg)
2939 {
2940 if (attrib.Name == "min")
2941 {
2942 p.min = attrib.F;
2943 break;
2944 }
2945 else if (attrib.Name == "max")
2946 {
2947 p.max = attrib.F;
2948 break;
2949 }
2950 }
2951 }
2952
2953 private void fillParameter(RepeatedField<AttributeProto> rg, ConcatParameter p)
2954 {
2955 foreach (AttributeProto attrib in rg)
2956 {
2957 if (attrib.Name == "axis")
2958 {
2959 p.axis = (int)attrib.I;
2960 break;
2961 }
2962 }
2963 }
2964
2965 private string cleanFileName(string str)
2966 {
2967 string strOut = "";
2968
2969 foreach (char ch in str)
2970 {
2971 if (ch == '\\' || ch == '/' || ch == ':')
2972 strOut += "_";
2973 else
2974 strOut += ch;
2975 }
2976
2977 return strOut;
2978 }
2979
2980 private void saveBinaryData(ConstantParameter p, string strName, float[] rgData)
2981 {
2982 string strFile = m_strOriginalPath + "\\" + cleanFileName(strName) + ".bin";
2983
2984 if (File.Exists(strFile))
2985 File.Delete(strFile);
2986
2987 using (FileStream fs = new FileStream(strFile, FileMode.CreateNew, FileAccess.Write))
2988 using (BinaryWriter bw = new BinaryWriter(fs))
2989 {
2990 BlobProto proto = new BlobProto();
2991 proto.data = new List<float>(rgData);
2992 proto.Save(bw);
2993 }
2994
2995 p.binary_data_file = strFile;
2996 }
2997
2998 private void saveBinaryData(ConstantParameter p, string strName, RepeatedField<float> rgData)
2999 {
3000 string strFile = m_strOriginalPath + "\\" + strName + ".bin";
3001
3002 if (File.Exists(strFile))
3003 File.Delete(strFile);
3004
3005 using (FileStream fs = new FileStream(strFile, FileMode.CreateNew, FileAccess.Write))
3006 using (BinaryWriter bw = new BinaryWriter(fs))
3007 {
3008 BlobProto proto = new BlobProto(p.output_shape.dim);
3009 proto.data = rgData.ToList();
3010 proto.Save(bw);
3011 }
3012
3013 p.binary_data_file = strFile;
3014 }
3015
3016 private BlobProto loadBinaryData(ConstantParameter p)
3017 {
3018 if (p.binary_data_file == null || !File.Exists(p.binary_data_file))
3019 return null;
3020
3021 using (FileStream fs = new FileStream(p.binary_data_file, FileMode.Open, FileAccess.Read))
3022 using (BinaryReader br = new BinaryReader(fs))
3023 {
3024 return BlobProto.Load(br);
3025 }
3026 }
3027
3028 private void fillParameter(Blob<T> input, ConstantParameter p)
3029 {
3030 foreach (int nDim in input.shape())
3031 {
3032 p.output_shape.dim.Add(nDim);
3033 }
3034
3035 float[] rgData = Utility.ConvertVecF<T>(input.update_cpu_data());
3036
3037 if (rgData.Length <= 32)
3038 p.values_f = new List<float>(rgData);
3039 else
3040 saveBinaryData(p, input.Name, rgData);
3041 }
3042
3043 private void fillParameter(RepeatedField<AttributeProto> rg, string strName, ConstantParameter p)
3044 {
3045 foreach (AttributeProto attrib in rg)
3046 {
3047 if (attrib.Name == "value_float")
3048 {
3049 p.output_shape = new BlobShape(new List<int>() { 1 });
3050 p.values_f.Add(attrib.F);
3051 break;
3052 }
3053 else if (attrib.Name == "value_floats")
3054 {
3055 p.output_shape = new BlobShape(new List<int>() { attrib.Floats.Count });
3056 foreach (float f in attrib.Floats)
3057 {
3058 p.values_f.Add(f);
3059 }
3060 break;
3061 }
3062 if (attrib.Name == "value_int")
3063 {
3064 p.output_shape = new BlobShape(new List<int>() { 1 });
3065 p.values_f.Add(attrib.I);
3066 break;
3067 }
3068 else if (attrib.Name == "value_ints")
3069 {
3070 p.output_shape = new BlobShape(new List<int>() { attrib.Ints.Count });
3071 foreach (int i in attrib.Ints)
3072 {
3073 p.values_f.Add(i);
3074 }
3075 break;
3076 }
3077 else if (attrib.Name == "value")
3078 {
3079 p.output_shape = new BlobShape();
3080
3081 if (attrib.T.Dims.Count > 0)
3082 {
3083 foreach (long nDim in attrib.T.Dims)
3084 {
3085 p.output_shape.dim.Add((int)nDim);
3086 }
3087 }
3088 else
3089 {
3090 p.output_shape.dim.Add(1);
3091 }
3092
3093 if (attrib.T.DataType == (int)OnnxDefinitions.DataType.FLOAT)
3094 {
3095 if (attrib.T.FloatData.Count <= 32)
3096 {
3097 foreach (float f in attrib.T.FloatData)
3098 {
3099 p.values_f.Add(f);
3100 }
3101 }
3102 else
3103 {
3104 saveBinaryData(p, strName, attrib.T.FloatData);
3105 }
3106 }
3107 else if (attrib.T.DataType == (int)OnnxDefinitions.DataType.INT64)
3108 {
3109 if (attrib.T.Int64Data.Count > 0 && attrib.T.Int64Data.Count <= 32)
3110 {
3111 foreach (float f in attrib.T.FloatData)
3112 {
3113 p.values_f.Add(f);
3114 }
3115 }
3116 else
3117 {
3118 byte[] rgRaw = attrib.T.RawData.ToByteArray();
3119 int nLen = rgRaw.Length / sizeof(long);
3120 long[] rgData1 = new long[nLen];
3121
3122 Buffer.BlockCopy(rgRaw, 0, rgData1, 0, rgRaw.Length);
3123
3124 foreach (long lVal in rgData1)
3125 {
3126 p.values_f.Add(lVal);
3127 }
3128 }
3129 }
3130 else
3131 {
3132 throw new Exception("The datatype '" + ((OnnxDefinitions.DataType)attrib.T.DataType).ToString() + "' is not yet supported.");
3133 }
3134 }
3135 else
3136 {
3137 throw new Exception("The attribute name '" + attrib.Name + "' is not yet supported!");
3138 }
3139 }
3140 }
3141
3142 private void fillParameter(RepeatedField<AttributeProto> rg, ConvolutionParameter p, out int nGroupReductionFactor)
3143 {
3144 nGroupReductionFactor = 1;
3145
3146 foreach (AttributeProto attrib in rg)
3147 {
3148 if (attrib.Name == "kernel_shape")
3149 {
3150 long h = attrib.Ints[0];
3151 if (h <= 0)
3152 throw new Exception("Kernel height shape must be > 0!");
3153
3154 long w = attrib.Ints[1];
3155 if (w <= 0)
3156 throw new Exception("Kernel width shape must be > 0!");
3157
3158 if (h == w)
3159 {
3160 p.kernel_size = new List<uint>() { (uint)w };
3161 }
3162 else
3163 {
3164 p.kernel_size = new List<uint>();
3165 p.kernel_h = (uint)h;
3166 p.kernel_w = (uint)w;
3167 }
3168 }
3169
3170 else if (attrib.Name == "strides")
3171 {
3172 long h = attrib.Ints[0];
3173 if (h <= 0)
3174 throw new Exception("stride height shape must be > 0!");
3175
3176 long w = attrib.Ints[1];
3177 if (w <= 0)
3178 throw new Exception("stride width shape must be > 0!");
3179
3180 if (h == w)
3181 {
3182 p.stride = new List<uint>() { (uint)w };
3183 }
3184 else
3185 {
3186 p.stride = new List<uint>();
3187 p.stride_h = (uint)h;
3188 p.stride_w = (uint)w;
3189 }
3190 }
3191
3192 else if (attrib.Name == "pads")
3193 {
3194 long h = attrib.Ints[0];
3195 if (h < 0)
3196 throw new Exception("pad height shape must be >= 0!");
3197
3198 long w = attrib.Ints[1];
3199 if (w < 0)
3200 throw new Exception("pad width shape must be >= 0!");
3201
3202 if (h == w)
3203 {
3204 p.pad = new List<uint>() { (uint)w };
3205 }
3206 else
3207 {
3208 p.pad = new List<uint>();
3209 p.pad_h = (uint)h;
3210 p.pad_w = (uint)w;
3211 }
3212 }
3213
3214 else if (attrib.Name == "dilations")
3215 {
3216 long d = attrib.Ints[0];
3217 if (d < 0)
3218 throw new Exception("dilation shape must be >= 0!");
3219
3220 p.dilation = new List<uint>() { (uint)d };
3221 }
3222
3223 else if (attrib.Name == "group")
3224 {
3225 p.group = (uint)attrib.I;
3226
3227 if (p.group > 144)
3228 {
3229 nGroupReductionFactor = 3;
3230 p.group /= (uint)nGroupReductionFactor;
3231 }
3232 }
3233 }
3234
3235 // Add defaults.
3236 if (p.kernel_size.Count == 0 && !p.kernel_h.HasValue && !p.kernel_w.HasValue)
3237 p.kernel_size.Add(3);
3238
3239 if (p.pad.Count == 0 && !p.pad_h.HasValue && !p.pad_w.HasValue)
3240 p.pad.Add(0);
3241
3242 if (p.dilation.Count == 0)
3243 p.dilation.Add(1);
3244
3245 if (p.stride.Count == 0 && !p.stride_h.HasValue && !p.stride_w.HasValue)
3246 p.stride.Add(1);
3247 }
3248
3249 private void fillParameter(RepeatedField<AttributeProto> rg, DropoutParameter p)
3250 {
3251 foreach (AttributeProto attrib in rg)
3252 {
3253 if (attrib.Name == "ratio")
3254 {
3255 p.dropout_ratio = attrib.F;
3256 }
3257 else if (attrib.Name == "training_mode")
3258 {
3259 p.active = (attrib.I == 0) ? false : true;
3260 }
3261 else if (attrib.Name == "seed")
3262 {
3263 p.seed = attrib.I;
3264 }
3265 }
3266 }
3267
3268 private void fillParameter(RepeatedField<AttributeProto> rg, FlattenParameter p)
3269 {
3270 foreach (AttributeProto attrib in rg)
3271 {
3272 if (attrib.Name == "axis")
3273 {
3274 p.axis = (int)attrib.I;
3275 break;
3276 }
3277 }
3278 }
3279
3280 private void fillParameter(RepeatedField<AttributeProto> rg, GatherParameter p)
3281 {
3282 foreach (AttributeProto attrib in rg)
3283 {
3284 if (attrib.Name == "axis")
3285 {
3286 p.axis = (int)attrib.I;
3287 break;
3288 }
3289 }
3290 }
3291
3292 private void fillParameter(RepeatedField<AttributeProto> rg, PoolingParameter p, PoolingParameter.PoolingMethod pool, bool bGlobal)
3293 {
3294 foreach (AttributeProto attrib in rg)
3295 {
3296 if (attrib.Name == "kernel_shape")
3297 {
3298 long h = attrib.Ints[0];
3299 if (h <= 0)
3300 throw new Exception("Kernel height shape must be > 0!");
3301
3302 long w = attrib.Ints[1];
3303 if (w <= 0)
3304 throw new Exception("Kernel width shape must be > 0!");
3305
3306 if (h == w)
3307 {
3308 p.kernel_size = new List<uint>() { (uint)w };
3309 }
3310 else
3311 {
3312 p.kernel_size = new List<uint>();
3313 p.kernel_h = (uint)h;
3314 p.kernel_w = (uint)w;
3315 }
3316 }
3317
3318 else if (attrib.Name == "strides")
3319 {
3320 long h = attrib.Ints[0];
3321 if (h <= 0)
3322 throw new Exception("stride height shape must be > 0!");
3323
3324 long w = attrib.Ints[1];
3325 if (w <= 0)
3326 throw new Exception("stride width shape must be > 0!");
3327
3328 if (h == w)
3329 {
3330 p.stride = new List<uint>() { (uint)w };
3331 }
3332 else
3333 {
3334 p.stride = new List<uint>();
3335 p.stride_h = (uint)h;
3336 p.stride_w = (uint)w;
3337 }
3338 }
3339
3340 else if (attrib.Name == "pads")
3341 {
3342 long h = attrib.Ints[0];
3343 if (h < 0)
3344 throw new Exception("pad height shape must be >= 0!");
3345
3346 long w = attrib.Ints[1];
3347 if (w < 0)
3348 throw new Exception("pad width shape must be >= 0!");
3349
3350 if (h == w)
3351 {
3352 p.pad = new List<uint>() { (uint)w };
3353 }
3354 else
3355 {
3356 p.pad = new List<uint>();
3357 p.pad_h = (uint)h;
3358 p.pad_w = (uint)w;
3359 }
3360 }
3361 }
3362
3363 if (p.kernel_size.Count == 0 && !p.kernel_h.HasValue && !p.kernel_w.HasValue)
3364 p.kernel_size.Add(3);
3365
3366 if (p.pad.Count == 0 && !p.pad_h.HasValue && !p.pad_w.HasValue)
3367 p.pad.Add(0);
3368
3369 if (p.stride.Count == 0 && !p.stride_h.HasValue && !p.stride_w.HasValue)
3370 p.stride.Add(1);
3371
3372 p.global_pooling = bGlobal;
3374 p.pool = pool;
3375 }
3376
3377 private void fillParameter(RepeatedField<AttributeProto> rg, InnerProductParameter p)
3378 {
3379 foreach (AttributeProto attrib in rg)
3380 {
3381 if (attrib.Name == "transB")
3382 {
3383 if (attrib.I != 0)
3384 p.transpose = true;
3385 else
3386 p.transpose = false;
3387 break;
3388 }
3389 }
3390 }
3391
3392 private void fillParameter(RepeatedField<AttributeProto> rg, LRNParameter p)
3393 {
3394 foreach (AttributeProto attrib in rg)
3395 {
3396 if (attrib.Name == "alpha")
3397 {
3398 p.alpha = attrib.F;
3399 }
3400 else if (attrib.Name == "beta")
3401 {
3402 p.beta = attrib.F;
3403 }
3404 else if (attrib.Name == "bias")
3405 {
3406 p.k = attrib.F;
3407 }
3408 else if (attrib.Name == "size")
3409 {
3410 if (attrib.I != 0)
3411 p.local_size = (uint)attrib.I;
3412 }
3413 }
3414 }
3415
3416 private bool fillParameter(RepeatedField<AttributeProto> rg, ReshapeParameter p, BlobCollection<T> col, RepeatedField<string> rgInputs)
3417 {
3418 List<float> rgShape = new List<float>();
3419
3420 p.axis = 0;
3421 p.shape = new BlobShape();
3422
3423 if (rgInputs.Count > 1)
3424 {
3425 string strInput1 = convertWs(rgInputs[1]);
3426 Blob<T> shape = col.FindBlob(strInput1);
3427 if (shape == null)
3428 return false;
3429
3430 float[] rgData = Utility.ConvertVecF<T>(shape.mutable_cpu_data);
3431 rgShape = new List<float>(rgData);
3432
3433 foreach (float fDim in rgData)
3434 {
3435 p.shape.dim.Add((int)fDim);
3436 }
3437
3438 col.Remove(shape);
3439 }
3440 else
3441 {
3442 foreach (AttributeProto attrib in rg)
3443 {
3444 if (attrib.Name == "shape")
3445 {
3446 foreach (long lDim in attrib.Ints)
3447 {
3448 p.shape.dim.Add((int)lDim);
3449 }
3450 }
3451 }
3452 }
3453
3454 return true;
3455 }
3456
3457 private void fillParameter(RepeatedField<AttributeProto> rg, PReLUParameter p)
3458 {
3459 }
3460
3461 private void fillParameter(RepeatedField<AttributeProto> rg, ReductionParameter p)
3462 {
3463 foreach (AttributeProto attrib in rg)
3464 {
3465 if (attrib.Name == "keepdims")
3466 {
3467 }
3468 else if (attrib.Name == "axes")
3469 {
3470 }
3471 }
3472 }
3473
3474 private void fillParameter(RepeatedField<AttributeProto> rg, ReLUParameter p, bool bLeaky)
3475 {
3476 foreach (AttributeProto attrib in rg)
3477 {
3478 if (attrib.Name == "alpha")
3479 {
3480 p.negative_slope = attrib.F;
3481 break;
3482 }
3483 }
3484 }
3485
3486 private void fillParameter(RepeatedField<AttributeProto> rg, SliceParameter p)
3487 {
3488 foreach (AttributeProto attrib in rg)
3489 {
3490 if (attrib.Name == "axis")
3491 {
3492 p.axis = (int)attrib.I;
3493 break;
3494 }
3495 }
3496 }
3497
3498 private void fillParameter(RepeatedField<AttributeProto> rg, SoftmaxParameter p)
3499 {
3500 foreach (AttributeProto attrib in rg)
3501 {
3502 if (attrib.Name == "axis")
3503 {
3504 p.axis = (int)attrib.I;
3505 break;
3506 }
3507 }
3508 }
3509
3510 private void fillParameter(RepeatedField<AttributeProto> rg, MathParameter p, MyCaffe.common.MATH_FUNCTION fn)
3511 {
3512 p.function = fn;
3513 }
3514
3515 private void fillParameter(RepeatedField<AttributeProto> rg, TransposeParameter p)
3516 {
3517 List<int> rgDim = new List<int>();
3518
3519 foreach (AttributeProto attrib in rg)
3520 {
3521 if (attrib.Name == "dim")
3522 {
3523 rgDim.Add((int)attrib.I);
3524 }
3525 else if (attrib.Name == "perm")
3526 {
3527 foreach (long val in attrib.Ints)
3528 {
3529 rgDim.Add((int)val);
3530 }
3531 }
3532 }
3533
3534 if (rgDim.Count > 0)
3535 p.dim = rgDim;
3536 }
3537 }
3538
3539#pragma warning disable 1591
3540
3541 class LayerDataCollection : IEnumerable<LayerData>
3542 {
3543 LayerData.TYPE m_type;
3544 List<LayerData> m_rgItems = new List<LayerData>();
3545
3546 public LayerDataCollection(LayerData.TYPE type)
3547 {
3548 m_type = type;
3549 }
3550
3551 public LayerData.TYPE Type
3552 {
3553 get { return m_type; }
3554 }
3555
3556 public bool Contains(string strName)
3557 {
3558 foreach (LayerData item in m_rgItems)
3559 {
3560 if (item.Name == strName)
3561 return true;
3562 }
3563
3564 return false;
3565 }
3566
3567 public string FixupTops(int nLayerIdx, LayerParameter p)
3568 {
3569 List<LayerData> rgItems = FindAll(nLayerIdx);
3570 string strReport = "";
3571
3572 foreach (LayerData item in rgItems)
3573 {
3574 if (item.Layer.type != LayerParameter.LayerType.CONSTANT)
3575 {
3576 p.top.Remove(item.Name);
3577 strReport += "Removed top '" + item.Name + "' from layer '" + item.Layer.name + "(" + item.Layer.type.ToString() + ") at layer index = " + item.LayerIndex.ToString() + Environment.NewLine;
3578 }
3579 }
3580
3581 return strReport;
3582 }
3583
3584 public List<LayerData> FindAll(int nLayerIdx)
3585 {
3586 return m_rgItems.Where(p => p.LayerIndex == nLayerIdx).ToList();
3587 }
3588
3589 public int Count
3590 {
3591 get { return m_rgItems.Count; }
3592 }
3593
3594 public void Add(LayerData item)
3595 {
3596 m_rgItems.Add(item);
3597 }
3598
3599 public void Add(List<string> rg, int nIdx, LayerParameter layer)
3600 {
3601 foreach (string str in rg)
3602 {
3603 m_rgItems.Add(new LayerData(str, nIdx, layer, m_type));
3604 }
3605 }
3606
3607 public void Remove(List<string> rgstr)
3608 {
3609 List<int> rgDelete = new List<int>();
3610
3611 for (int i = 0; i < m_rgItems.Count; i++)
3612 {
3613 for (int j = 0; j < rgstr.Count; j++)
3614 {
3615 if (m_rgItems[i].Name == rgstr[j])
3616 rgDelete.Add(i);
3617 }
3618 }
3619
3620 for (int i = rgDelete.Count - 1; i >= 0; i--)
3621 {
3622 m_rgItems.RemoveAt(rgDelete[i]);
3623 }
3624 }
3625
3626 public IEnumerator<LayerData> GetEnumerator()
3627 {
3628 return m_rgItems.GetEnumerator();
3629 }
3630
3631 IEnumerator IEnumerable.GetEnumerator()
3632 {
3633 return m_rgItems.GetEnumerator();
3634 }
3635
3636 public LayerData this[int nIdx]
3637 {
3638 get { return m_rgItems[nIdx]; }
3639 }
3640 }
3641
3642 class LayerData
3643 {
3644 string m_strName;
3645 int m_nLayerIdx;
3646 LayerParameter m_layer;
3647 TYPE m_type;
3648
3649 public enum TYPE
3650 {
3651 TOP,
3652 BTM
3653 }
3654
3655 public LayerData(string strName, int nLayerIdx, LayerParameter layer, TYPE type)
3656 {
3657 m_strName = strName;
3658 m_nLayerIdx = nLayerIdx;
3659 m_layer = layer;
3660 m_type = type;
3661 }
3662
3663 public string Name
3664 {
3665 get { return m_strName; }
3666 }
3667
3668 public int LayerIndex
3669 {
3670 get { return m_nLayerIdx; }
3671 }
3672
3673 public LayerParameter Layer
3674 {
3675 get { return m_layer; }
3676 }
3677
3678 public TYPE Type
3679 {
3680 get { return m_type; }
3681 }
3682
3683 public override string ToString()
3684 {
3685 return m_strName + "(" + m_type.ToString() + ") at layer '" + m_layer.ToString() + "'(idx = " + m_nLayerIdx.ToString() + ")";
3686 }
3687 }
3688
3689#pragma warning restore 1591
3690}
The MyCaffeControl is the main object used to manage all training, testing and running of the MyCaffe...
Net< T > GetInternalNet(Phase phase=Phase.RUN)
Returns the internal net based on the Phase specified: TRAIN, TEST or RUN.
Log Log
Returns the Log (for output) used.
The CancelEvent provides an extension to the manual cancel event that allows for overriding the manua...
Definition: CancelEvent.cs:17
The Log class provides general output in text form.
Definition: Log.cs:13
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
Definition: Log.cs:80
bool EnableTrace
Enables/disables the Trace. When enabled, the .Net Trace.WriteLine is called in addition to the norma...
Definition: Log.cs:67
The RawProto class is used to parse and output Google prototxt file data.
Definition: RawProto.cs:17
override string ToString()
Returns the RawProto as its full prototxt string.
Definition: RawProto.cs:677
static RawProto Parse(string str)
Parses a prototxt and places it in a new RawProto.
Definition: RawProto.cs:306
The Utility class provides general utility funtions.
Definition: Utility.cs:35
static double[] ConvertVec(float[] rgf)
Convert an array of float to an array of generics.
Definition: Utility.cs:550
string Name
Get/set the name of the item.
The DatasetDescriptor class describes a dataset which contains both a training data source and testin...
SourceDescriptor TrainingSource
Get/set the training data source.
SourceDescriptor TestingSource
Get/set the testing data source.
The BlobCollection contains a list of Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
int Count
Returns the number of items in the collection.
bool Remove(Blob< T > b)
If it exists, remove a Blob from the collection.
Blob< T > FindBlob(string strName)
Finds a given blob in the collection based on its name.
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
int channels
DEPRECIATED; legacy shape accessor channels: use shape(1) instead.
Definition: Blob.cs:778
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
Definition: Blob.cs:1898
int height
DEPRECIATED; legacy shape accessor height: use shape(2) instead.
Definition: Blob.cs:786
object Tag
Returns a user defined object associated with the Blob.
Definition: Blob.cs:2746
string shape_string
Returns a string describing the Blob's shape.
Definition: Blob.cs:635
T[] mutable_cpu_data
Get data from the GPU and bring it over to the host, or Set data from the Host and send it over to th...
Definition: Blob.cs:1437
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
Definition: Blob.cs:425
void CopyFrom(Blob< T > src, int nSrcOffset, int nDstOffset, int nCount, bool bCopyData, bool bCopyDiff)
Copy from a source Blob.
Definition: Blob.cs:881
void scale_to_range(double dfMin, double dfMax)
Scale the data in the blob to the range [dfMin,dfMax].
Definition: Blob.cs:1749
int width
DEPRECIATED; legacy shape accessor width: use shape(3) instead.
Definition: Blob.cs:794
List< int > shape()
Returns an array where each element contains the shape of an axis of the Blob.
Definition: Blob.cs:662
T[] update_cpu_data()
Update the CPU data by transferring the GPU data over to the Host.
Definition: Blob.cs:1446
void ReshapeLike(Blob< T > b, bool? bUseHalfSize=null)
Reshape this Blob to have the same shape as another Blob.
Definition: Blob.cs:626
string Name
Get/set the name of the Blob.
Definition: Blob.cs:2160
virtual void Dispose(bool bDisposing)
Releases all resources used by the Blob (including both GPU and Host).
Definition: Blob.cs:385
int num
DEPRECIATED; legacy shape accessor num: use shape(0) instead.
Definition: Blob.cs:770
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:943
Connects Layer's together into a direct acrylic graph (DAG) specified by a NetParameter
Definition: Net.cs:23
List< Layer< T > > layers
Returns the layers.
Definition: Net.cs:2003
BlobCollection< T > input_blobs
Returns the collection of input Blobs.
Definition: Net.cs:2201
virtual void Dispose(bool bDisposing)
Releases all resources (GPU and Host) used by the Net.
Definition: Net.cs:184
void LoadWeights(byte[] rgWeights, IXPersist< T > persist, List< string > inputWtInfo=null, List< string > targetWtInfo=null, string strSkipBlobType=null)
Loads new weights into the Net.
Definition: Net.cs:2510
BlobCollection< T > output_blobs
Returns the collection of output Blobs.
Definition: Net.cs:2209
BlobCollection< T > learnable_parameters
Returns the learnable parameters.
Definition: Net.cs:2117
NetParameter net_param
Returns the net parameter.
Definition: Net.cs:1857
The PersistCaffe class is used to load and save weight files in the .caffemodel format.
Definition: PersistCaffe.cs:20
byte[] SaveWeights(BlobCollection< T > colBlobs, bool bSaveDiffs=false)
Save the weights to a byte array.
The MyCaffeConversionControl handles converting between MyCaffe and ONNX formats. The OnnxControl is ...
static float[] getDataAsFloat(TensorProto tensor)
Converts the tensor data into an array of float.
static double[] getDataAsDouble(TensorProto tensor)
Converts the tensor data into an array of double.
List< string > IgnoreLayerNames
Get/set the list of layer names to ignore (layers are ignored when they contain the text from one of ...
string ReportString
Returns the report from the conversion.
ModelProto ConvertMyCaffeToOnnx(MyCaffeControl< T > ctrl, int nOpSetVersion=9, bool bUseRawData=true, OnnxDefinitions.DataType dstDataType=OnnxDefinitions.DataType.FLOAT, Phase phase=Phase.RUN)
Convert a model currently loaded into the MyCaffeControl to an ONNX ModelProto.
void ConvertMyCaffeToOnnxFile(MyCaffeControl< T > ctrl, string strOnnxFile, int nOpSetVersion=9, bool bUseRawData=true, OnnxDefinitions.DataType dstDataType=OnnxDefinitions.DataType.FLOAT, Phase phase=Phase.RUN)
Convert a model currently loaded into the MyCaffeControl to an ONNX .onnx model file.
MyCaffeConversionControl(IContainer container)
The constructor.
void SetWeightScaling(double dfMin, double dfMax)
Set the scaling factors applied to the weights.
ModelProto ConvertMyCaffeToOnnx(CudaDnn< T > cuda, Log log, MyCaffeModelData data, int nOpSetVersion=9, bool bUseRawData=true, OnnxDefinitions.DataType dstDataType=OnnxDefinitions.DataType.FLOAT)
Convert a MyCaffe model description, weights and optionally mean image from the MyCaffe model format ...
void ConvertMyCaffeToOnnxFile(CudaDnn< T > cuda, Log log, MyCaffeModelData data, string strOutputFile, int nOpSetVersion=9, bool bUseRawData=true, OnnxDefinitions.DataType dstDataType=OnnxDefinitions.DataType.FLOAT)
Convert a MyCaffe model description, weights and optionally mean image from the MyCaffe model format ...
MyCaffeModelData ConvertOnnxToMyCaffe(CudaDnn< T > cuda, Log log, ModelProto onnxModel, bool bFixupNeuronNodes=true, bool bIncludeLastLayerWeights=false, DatasetDescriptor dsTraining=null)
Convert an ONNX ModelProto to the MyCaffe model description, weights and optionally mean image.
MyCaffeModelData ConvertOnnxToMyCaffeFromFile(CudaDnn< T > cuda, Log log, string strOnnxFile, bool bFixlupNeuronNodes=true, bool bIncludeLastLayerWeights=false, DatasetDescriptor dsTraining=null)
Convert an ONNX .onnx model file to the MyCaffe model description, weights and optionally mean image.
The MyCaffeModelData object contains the model descriptor, model weights and optionally the image mea...
string ModelDescription
Get/set the model descriptor.
byte[] Weights
Returns the model weights.
string OriginalDownloadFile
Specifies the original download file, if any.
Abstract Filler class used to fill blobs with values.
Definition: Filler.cs:19
void Fill(Blob< T > b)
Fill the blob with values based on the actual filler used.
Definition: Filler.cs:50
static Filler< T > Create(CudaDnn< T > cuda, Log log, FillerParameter p)
Create a new Filler instance.
Definition: Filler.cs:79
An interface for the units of computation which can be composed into a Net.
Definition: Layer.cs:31
LayerParameter.LayerType type
Returns the LayerType of this Layer.
Definition: Layer.cs:900
LayerParameter layer_param
Returns the LayerParameter for this Layer.
Definition: Layer.cs:872
BlobCollection< T > blobs
Returns the collection of learnable parameter Blobs for the Layer.
Definition: Layer.cs:848
int axis
The 'label' axis of the prediction blob, whos argmax corresponds to the predicted label – may be nega...
Specifies the parameters for the ArgMaxLayer
COMPARE_OPERATOR operation
Specifies the operation to use (default = MAX).
COMPARE_OPERATOR
Defines the compare operator to use (max or min, default = max).
Specifies the parameters for the BatchNormLayer.
bool scale_bias
Specifies to use the scale and bias terms, otherwise the scale = 1 and bias = 0 are used to form an i...
double eps
Specifies a small value to add to the variance estimate so that we don't divide by zero.
double moving_average_fraction
Specifies how much the moving average decays each iteration. Smaller values make the moving average d...
The BlobProto contains the descripion of a blob.
Definition: BlobProto.cs:15
List< float > data
Get/set the data as a List of float.
Definition: BlobProto.cs:180
object Load(BinaryReader br, bool bNewInstance)
Loads a BlobProto from a binary reader.
Definition: BlobProto.cs:84
BlobShape shape
Specifies the shape of the Blob.
Definition: BlobProto.cs:117
void Save(BinaryWriter bw)
Saves the BlobProto to a binary writer.
Definition: BlobProto.cs:48
Specifies the shape of a Blob.
Definition: BlobShape.cs:15
List< int > dim
The blob shape dimensions.
Definition: BlobShape.cs:93
Stores the parameters used by the ClipLayer
double min
Specifies the min value for the Clip activation function.
double max
Specifies the max value for the Clip activation function.
Specifies the parameters for the ConcatLayer
int axis
The axis along which to concatenate – may be negative to index from the end (e.g.,...
Specifies the parameters for the ConstantLayer.
BlobShape output_shape
Specifies the output shape.
string binary_data_file
Specifies a binary data file containing the values to load.
List< float > values_f
Specifies a set of float values used to fill the output. When only one item is specified,...
Specifies the parameters for the ConvolutionLayer. The default weight filler is set to the XavierFill...
uint group
The group size for group convolution.
FillerParameter bias_filler
The filler for the bias. The default is set to use the 'constant = 0.1' filler.
bool bias_term
Whether to have bias terms or not.
uint num_output
The number of outputs for the layer.
virtual uint batch_size
Specifies the batch size.
string source
When used with the DATA parameter, specifies the data 'source' within the database....
Specifies the parameters of the DropoutLayer.
double dropout_ratio
Specifies the dropout ratio. (e.g. the probability that values will be dropped out and set to zero....
long seed
Specifies the seed used by cuDnn for random number generation.
bool active
Specifies whether or not the dropout is active or not. When inactive and training,...
Specifies the parameters for the EltwiseLayer.
EltwiseOp
Defines the operation to perform.
EltwiseOp operation
Specifies the element-wise operation.
Specifies the parameters for the EluLayer.
Definition: EluParameter.cs:20
Specifies the parameters for the ExpLayer.
Definition: ExpParameter.cs:26
Specifies the parameters for the FlattenLayer.
int axis
Specifies the first axis to flatten: all preceding axes are retained in the output....
Specifies the parameters for the InnerProductLayer.
bool transpose
Specifies whether to transpose the weight matrix or not. If transpose == true, any operations will be...
uint num_output
The number of outputs for the layer.
bool bias_term
Whether to have bias terms or not.
uint? stride_h
The stride height (2D only)
List< uint > kernel_size
Kernel size is given as a single value for equal dimensions in all spatial dimensions,...
List< uint > dilation
Factor used to dilate the kernel, (implicitly) zero-filling the resulting holes. (Kernel dilation is ...
uint? stride_w
The stride width (2D only)
uint? pad_h
The padding height (2D only)
uint? kernel_h
The kernel height (2D only)
List< uint > stride
Stride is given as a single value for equal dimensions in all spatial dimensions, or once per spatial...
uint? kernel_w
The kernel width (2D only)
uint? pad_w
The padding width (2D only)
List< uint > pad
Pad is given as a single value for equal dimensions in all spatial dimensions, or once per spatial di...
Specifies the parameter for the LRNLayer.
Definition: LRNParameter.cs:20
double beta
Specifies the beta value used as the power parameter in the normalization formula....
uint local_size
Specifies the local size of the normalization window width.
Definition: LRNParameter.cs:81
double alpha
Specifies the alpha value used for variance scaling in the normalization formula. NOTE: cuDNN uses a ...
Definition: LRNParameter.cs:91
double k
Specifies the k value used by the normalization parameter. NOTE: cuDNN uses a default of k = 2....
Specifies the base parameter for all layers.
ConvolutionParameter convolution_param
Returns the parameter set when initialized with LayerType.CONVOLUTION
SliceParameter slice_param
Returns the parameter set when initialized with LayerType.SLICE
LogParameter log_param
Returns the parameter set when initialized with LayerType.LOG
string name
Specifies the name of this LayerParameter.
ClipParameter clip_param
Returns the parameter set when initialized with LayerType.CLIP
LayerType type
Specifies the type of this LayerParameter.
ConstantParameter constant_param
Returns the parameter set when initialized with LayerType.CONSTANT
SoftmaxParameter softmax_param
Returns the parameter set when initialized with LayerType.SOFTMAX
LRNParameter lrn_param
Returns the parameter set when initialized with LayerType.LRN
List< NetStateRule > include
Specifies the NetStateRule's for which this LayerParameter should be included.
MathParameter math_param
Returns the parameter set when initialized with LayerType.MATH
ReLUParameter relu_param
Returns the parameter set when initialized with LayerType.RELU
bool freeze_learning
Get/set whether or not to freeze the learning for this layer globally.
ArgMaxParameter argmax_param
Returns the parameter set when initialized with LayerType.ARGMAX
ReductionParameter reduction_param
Returns the parameter set when initialized with LayerType.REDUCTION
PoolingParameter pooling_param
Returns the parameter set when initialized with LayerType.POOLING
ExpParameter exp_param
Returns the parameter set when initialized with LayerType.EXP
EltwiseParameter eltwise_param
Returns the parameter set when initialized with LayerType.ELTWISE
List< string > top
Specifies the active top connections (in the bottom, out the top)
ReshapeParameter reshape_param
Returns the parameter set when initialized with LayerType.RESHAPE
EluParameter elu_param
Returns the parameter set when initialized with LayerType.ELU
InnerProductParameter inner_product_param
Returns the parameter set when initialized with LayerType.INNERPRODUCT
AccuracyParameter accuracy_param
Returns the parameter set when initialized with LayerType.ACCURACY
ConcatParameter concat_param
Returns the parameter set when initialized with LayerType.CONCAT
GatherParameter gather_param
Returns the parameter set when initialized with LayerType.GATHER
TransformationParameter transform_param
Returns the parameter set when initialized with LayerType.TRANSFORM
TransposeParameter transpose_param
Returns the parameter set when initialized with LayerType.TRANSPOSE
DataParameter data_param
Returns the parameter set when initialized with LayerType.DATA
FlattenParameter flatten_param
Returns the parameter set when initialized with LayerType.FLATTEN
BatchNormParameter batch_norm_param
Returns the parameter set when initialized with LayerType.BATCHNORM
List< string > bottom
Specifies the active bottom connections (in the bottom, out the top).
LayerType
Specifies the layer type.
override string ToString()
Returns a string representation of the LayerParameter.
DropoutParameter dropout_param
Returns the parameter set when initialized with LayerType.DROPOUT
PReLUParameter prelu_param
Returns the parameter set when initialized with LayerType.PRELU
Specifies the parameters for the LogLayer.
Definition: LogParameter.cs:26
Specifies the parameters for the MathLayer.
MyCaffe.common.MATH_FUNCTION function
Get/set the function to run.
Specifies the parameters use to create a Net
Definition: NetParameter.cs:18
static NetParameter FromProto(RawProto rp)
Parse a RawProto into a new instance of the parameter.
List< string > input
The input blobs to the network.
string name
The name of the network.
Definition: NetParameter.cs:90
override RawProto ToProto(string strName)
Constructor for the parameter.
List< LayerParameter > layer
The layers that make up the net. Each of their configurations, including connectivity and behavior,...
void SetPoolingReshapeAlgorithm(PoolingParameter.PoolingReshapeAlgorithm alg)
Sets all pooling layers to use the specified reshape algorithm.
NetParameter Clone(bool bCloneLayers=true, int? nSolverCount=null, int? nSolverRank=null)
Creates a new copy of this instance of the parameter.
List< BlobShape > input_shape
The shape of the input blobs.
Specifies a NetStateRule used to determine whether a Net falls within a given include or exclude patt...
Definition: NetStateRule.cs:20
Specifies the parameters for the PReLULayer.
Specifies the parameters for the PoolingLayer.
PoolingReshapeAlgorithm
Defines the pooling reshape algorithm to use.
PoolingMethod
Defines the pooling method.
PoolingMethod pool
Specifies the pooling method.
bool global_pooling
Specifies whether or not to enable global pooling.
PoolingReshapeAlgorithm reshape_algorithm
Specifies the reshape algorithm to use, either the original Caffe reshape (default = false) or the ne...
Specifies the parameters for the ReLULayer
double negative_slope
Specifies the negative slope. Allow non-zero slope for negative inputs to speed up optimization.
Specifies the parameters used by ReductionLayer.
int axis
The first axis to reduce to scalar – may be negative index from the end (e.g., -1 for the last axis)....
ReductionOp
Defines the reduction operation.
ReductionOp operation
Specifies the reduction operation.
Specifies the parameters for the ReshapeLayer.
int axis
Specifies the axis portion of the bottom blob's shape that is replaced by (included in) the reshape....
BlobShape shape
Specifies the output dimensions.
Specifies the parameters for the SliceLayer.
int axis
Specifies the axis along wich to slice – may be negative to index from the end (e....
Specifies the parameters for the SoftmaxLayer
int axis
The axis along which to perform the softmax – may be negative to index from the end (e....
Stores parameters used to apply transformation to the data layer's data.
COLOR_ORDER
Defines the color ordering used to tranform the input data.
COLOR_ORDER color_order
Specifies the color ordering to use. Native Caffe models often uses COLOR_ORDER.BGR,...
double scale
For data pre-processing, we can do simple scaling and subtracting the data mean, if provided....
Specifies the parameters for the GatherLayer.
int axis
Specifies the first axis to gather: all preceding axes are retained in the output....
Specifies the parameters for the TransposeLayer.
List< int > dim
Specifies the dimensions to transpose.
The Component class is a standard Microsoft.NET class that implements the IComponent interface and is...
Definition: Component.cs:18
The descriptors namespace contains all descriptor used to describe various items stored within the da...
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
Phase
Defines the Phase under which to run a Net.
Definition: Interfaces.cs:61
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
MATH_FUNCTION
Defines the mathematical function to run.
Definition: CudaDnn.cs:52
The MyCaffe.converter.onnx namespace contains the objects used to convert to/from the MyCaffe and CAF...
The MyCaffe.fillers namespace contains all fillers including the Filler class.
The MyCaffe.layers namespace contains all layers that have a solidified code base,...
Definition: LayerFactory.cs:15
The MyCaffe.param.beta parameters are used by the MyCaffe.layer.beta layers.
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12