MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
NeuralStyleTransfer.cs
1using MyCaffe.basecode;
2using MyCaffe.common;
3using MyCaffe.data;
4using MyCaffe.layers;
5using MyCaffe.layers.nt;
6using MyCaffe.param;
7using MyCaffe.param.nt;
8using MyCaffe.solvers;
9using System;
10using System.Collections.Generic;
11using System.Drawing;
12using System.IO;
13using System.Linq;
14using System.Text;
15using System.Threading.Tasks;
16
17namespace MyCaffe.extras
18{
30 public class NeuralStyleTransfer<T> : IDisposable
31 {
32 CudaDnn<T> m_cuda;
33 Log m_log;
34 int m_nIterations = 1000;
35 int m_nDisplayEvery = 100; // vgg19 settings
36 double m_dfTVLossWeight = 0; // 0.01 to smooth out result -or- 0 to disable.
37 double m_dfStyleDataScale1 = 0.0001; // 0.0001
38 double m_dfStyleDataScale2 = 1; // 1
39 double m_dfContentDataScale = 0.0001; // 0.0001
40 double m_dfContentLossScale = 0.0001; // 0.0001 to 1 (larger make image granier)
41 CancelEvent m_evtCancel;
42 DataTransformer<T> m_transformer = null;
43 TransformationParameter m_transformationParam;
44 PersistCaffe<T> m_persist;
45 NetParameter m_param;
46 byte[] m_rgWeights = null;
47 Dictionary<string, Dictionary<string, double>> m_rgLayers = new Dictionary<string, Dictionary<string, double>>();
48 List<string> m_rgstrUsedLayers = new List<string>();
49 List<double> m_rgMeanValues = new List<double>();
51 double m_dfLearningRate = 1.0;
52 int m_nDefaultMaxImageSize = 840;
53 string m_strDataBlobName = "data";
54 Solver<T> m_solver = null;
55 int m_nIntermediateOutput = 0;
56 int m_nPartialIteration = 0;
57 int m_nPartialIterations1 = 0;
58 Net<T> m_netShare = null;
59 bool m_bUsingSharedNet = false;
60 int m_nLBFGSCorrections = 100;
61 bool m_bAllowHalfSize = false;
62 bool m_bAllowHalfSizeOnGram = true;
63 bool m_bAllowHalfSizeOnEvent = true;
64 bool m_bAllowHalfSizeOnLoss = true;
65 bool m_bAllowHalfSizeOnScalar = true;
66 long m_hWorkspaceData = 0;
67 ulong m_lWorkspaceSizeInBytes = 0;
68
72 public event EventHandler<NeuralStyleIntermediateOutputArgs> OnIntermediateOutput;
73
89 public NeuralStyleTransfer(CudaDnn<T> cuda, Log log, CancelEvent evtCancel, string strModelType, string strModel, byte[] rgWeights, bool bCaffeModel, SolverParameter.SolverType solverType = SolverParameter.SolverType.LBFGS, double dfLearningRate = 1.5, int nLBFGSCorrections = 100, double dfDataScale = 1.0, Net<T> netShare = null)
90 {
91 evtCancel.Reset();
92
93 m_log = log;
94 m_evtCancel = evtCancel;
95 m_rgWeights = rgWeights;
96 m_solverType = solverType;
97 m_dfLearningRate = dfLearningRate;
98 m_nLBFGSCorrections = nLBFGSCorrections;
99
100 setupNetShare(netShare, cuda);
101
102 if (m_evtCancel != null)
103 m_evtCancel.Reset();
104
105 RawProto proto = RawProto.Parse(strModel);
106 m_param = NetParameter.FromProto(proto);
107
108 add_input_layer(m_param);
109 m_rgstrUsedLayers = load_layers(strModelType);
110 prune(m_param, m_rgstrUsedLayers);
111 add_gram_layers(m_param);
112
113 m_transformationParam = new TransformationParameter();
114 m_transformationParam.color_order = (bCaffeModel) ? TransformationParameter.COLOR_ORDER.BGR : TransformationParameter.COLOR_ORDER.RGB;
115 m_transformationParam.scale = dfDataScale;
116 m_transformationParam.mean_value = m_rgMeanValues;
117
118 m_persist = new PersistCaffe<T>(m_log, false);
119 }
120
137 public NeuralStyleTransfer(CudaDnn<T> cuda, Log log, CancelEvent evtCancel, Dictionary<string, Tuple<double, double>> rgLayers, string strModelDesc, byte[] rgWeights, bool bCaffeModel, SolverParameter.SolverType solverType = SolverParameter.SolverType.LBFGS, double dfLearningRate = 1.0, int nMaxImageSize = 840, int nLBFGSCorrections = 100, double dfDataScale = 1.0, Net<T> netShare = null)
138 {
139 m_log = log;
140 m_evtCancel = evtCancel;
141 m_rgWeights = rgWeights;
142 m_solverType = solverType;
143 m_dfLearningRate = dfLearningRate;
144 m_nDefaultMaxImageSize = nMaxImageSize;
145 m_nLBFGSCorrections = nLBFGSCorrections;
146
147 setupNetShare(netShare, cuda);
148
149 if (m_evtCancel != null)
150 m_evtCancel.Reset();
151
152 RawProto proto = RawProto.Parse(strModelDesc);
153 m_param = NetParameter.FromProto(proto);
154
155 Dictionary<string, double> rgStyle = new Dictionary<string, double>();
156 Dictionary<string, double> rgContent = new Dictionary<string, double>();
157
158 foreach (KeyValuePair<string, Tuple<double, double>> kv in rgLayers)
159 {
160 if (kv.Value.Item1 != 0)
161 rgStyle.Add(kv.Key, kv.Value.Item1);
162
163 if (kv.Value.Item2 != 0)
164 rgContent.Add(kv.Key, kv.Value.Item2);
165 }
166
167 add_input_layer(m_param);
168 m_rgstrUsedLayers = load_layers(rgStyle, rgContent);
169 prune(m_param, m_rgstrUsedLayers);
170 add_gram_layers(m_param);
171
172 m_transformationParam = new TransformationParameter();
173 m_transformationParam.color_order = (bCaffeModel) ? TransformationParameter.COLOR_ORDER.BGR : TransformationParameter.COLOR_ORDER.RGB;
174 m_transformationParam.scale = dfDataScale;
175 m_transformationParam.mean_value = m_rgMeanValues;
176
177 m_persist = new PersistCaffe<T>(m_log, false);
178 }
179
183 public void Dispose()
184 {
185 m_evtCancel.Set();
186
187 if (m_solver != null)
188 {
189 m_solver.Dispose();
190 m_solver = null;
191 }
192
193 if (m_hWorkspaceData != 0)
194 {
195 m_cuda.FreeMemory(m_hWorkspaceData);
196 m_hWorkspaceData = 0;
197 m_lWorkspaceSizeInBytes = 0;
198 }
199
200 if (m_transformer != null)
201 {
202 m_transformer.Dispose();
203 m_transformer = null;
204 }
205 }
206
215 public void SetupHalfSize(bool bAllowHs, bool bAllowOnGram, bool bAllowOnEvent, bool bAllowOnLoss, bool bAllowOnScalar)
216 {
217 m_bAllowHalfSize = bAllowHs;
218 m_bAllowHalfSizeOnEvent = bAllowOnEvent;
219 m_bAllowHalfSizeOnGram = bAllowOnGram;
220 m_bAllowHalfSizeOnLoss = bAllowOnLoss;
221 m_bAllowHalfSizeOnScalar = bAllowOnScalar;
222
223 if (!bAllowHs || !m_bAllowHalfSizeOnGram)
224 {
225 List<string> rgstrHalfLayers = new List<string>();
226
227 foreach (LayerParameter layer1 in m_param.layer)
228 {
229 if (layer1.use_halfsize)
230 {
231 if (layer1.name.Contains("gram"))
232 layer1.use_halfsize = false;
233 else
234 rgstrHalfLayers.Add(layer1.name);
235 }
236 }
237
238 if (!bAllowHs && rgstrHalfLayers.Count > 0)
239 {
240 string strErr = "Half-sized memory not supported! Disable half-size in the following layers: " + Utility.ToString<string>(rgstrHalfLayers);
241 m_log.FAIL(strErr);
242 }
243 }
244 }
245
246 private void setupNetShare(Net<T> net, CudaDnn<T> cuda)
247 {
248 if (net == null)
249 {
250 m_cuda = cuda;
251 return;
252 }
253
254 int nNetDeviceId = net.Cuda.GetDeviceID();
255 int nCudaDeviceId = cuda.GetDeviceID();
256
257 if (nNetDeviceId != nCudaDeviceId)
258 {
259 m_cuda = cuda;
260 return;
261 }
262
263 m_netShare = net;
264 m_cuda = m_netShare.Cuda;
265 m_bUsingSharedNet = true;
266
267 return;
268 }
269
270 private void add_input_layer(NetParameter p)
271 {
272 List<int> rgDelIdx = new List<int>();
273 LayerParameter data_param = null;
274 LayerParameter input = null;
275
276 for (int i = 0; i < p.layer.Count; i++)
277 {
278 if (p.layer[i].type == LayerParameter.LayerType.DATA)
279 {
280 if (data_param == null)
281 {
282 data_param = p.layer[i];
283 m_strDataBlobName = data_param.top[0];
284 }
285
286 rgDelIdx.Add(i);
287 }
288 else if (p.layer[i].type == LayerParameter.LayerType.INPUT)
289 {
290 input = p.layer[i];
291 m_strDataBlobName = input.top[0];
292 }
293 }
294
295 for (int i = rgDelIdx.Count - 1; i >= 0; i--)
296 {
297 p.layer.RemoveAt(rgDelIdx[i]);
298 }
299
300 if (input == null)
301 {
302 input = new LayerParameter(LayerParameter.LayerType.INPUT);
303 int nH = 224;
304 int nW = 224;
305 input.input_param.shape.Add(new BlobShape(1, 3, nH, nW));
306 input.name = "input1";
307 input.top.Add(m_strDataBlobName);
308
309 p.layer.Insert(0, input);
310 }
311 else
312 {
313 input.name = "input1";
314 }
315 }
316
317 private List<string> load_layers(string strName)
318 {
319 Dictionary<string, double> rgContent = new Dictionary<string, double>();
320 Dictionary<string, double> rgStyle = new Dictionary<string, double>();
321
322 switch (strName)
323 {
324 case "vgg19":
325 case "vgg16":
326 rgContent.Add("conv4_2", 1);
327 rgStyle.Add("conv1_1", 0.2);
328 rgStyle.Add("conv2_1", 0.2);
329 rgStyle.Add("conv3_1", 0.2);
330 rgStyle.Add("conv4_1", 0.2);
331 rgStyle.Add("conv5_1", 0.2);
332 // mean is taken from gist.github.com/ksimonyan/3785162f95cd2d5fee77
333 m_rgMeanValues = new List<double>() { 103.939, 116.779, 123.68 };
334 break;
335
336 case "googlenet":
337 rgContent.Add("conv2/3x3", 2e-4);
338 rgContent.Add("inception_3a/output", 1 - 2e-4);
339 rgStyle.Add("conv1/7x7_s2", 0.2);
340 rgStyle.Add("conv2/3x3", 0.2);
341 rgStyle.Add("inception_3a/output", 0.2);
342 rgStyle.Add("inception_4a/output", 0.2);
343 rgStyle.Add("inception_5a/output", 0.2);
344 m_rgMeanValues = new List<double>() { 104, 117, 123 };
345 break;
346
347 case "caffenet":
348 rgContent.Add("conv4", 1);
349 rgStyle.Add("conv1", 0.2);
350 rgStyle.Add("conv2", 0.2);
351 rgStyle.Add("conv3", 0.2);
352 rgStyle.Add("conv4", 0.2);
353 rgStyle.Add("conv5", 0.2);
354 break;
355
356 default:
357 throw new Exception("Model '" + strName + "' is not supported.");
358 }
359
360 return load_layers(rgStyle, rgContent);
361 }
362
363 private List<string> load_layers(Dictionary<string, double> rgStyle, Dictionary<string, double> rgContent)
364 {
365 m_rgLayers = new Dictionary<string, Dictionary<string, double>>();
366 m_rgLayers.Add("content", rgContent);
367 m_rgLayers.Add("style", rgStyle);
368
369 List<string> rgstrUsedLayers = new List<string>();
370
371 foreach (KeyValuePair<string, double> kv in rgContent)
372 {
373 rgstrUsedLayers.Add(kv.Key);
374 }
375
376 // Add the gram layers
377 Dictionary<string, double> rgGram = new Dictionary<string, double>();
378 foreach (KeyValuePair<string, double> kv in rgStyle)
379 {
380 rgstrUsedLayers.Add(kv.Key);
381 rgGram.Add("gram_" + kv.Key, kv.Value);
382 }
383
384 m_rgLayers.Add("gram", rgGram);
385
386 // Add the input layers
387 Dictionary<string, double> rgInput = new Dictionary<string, double>();
388 foreach (KeyValuePair<string, double> kv in rgContent)
389 {
390 rgInput.Add(kv.Key, kv.Value);
391 }
392
393 foreach (KeyValuePair<string, double> kv in rgGram)
394 {
395 rgInput.Add(kv.Key, kv.Value);
396 }
397
398 m_rgLayers.Add("input", rgInput);
399
400 rgstrUsedLayers.Sort();
401
402 return rgstrUsedLayers;
403 }
404
405 private void prune(NetParameter p, List<string> rgUsedLayers)
406 {
407 int nPruneFrom = -1;
408
409 // We assume that all layers after the used layers are not useful.
410 for (int i = 0; i < p.layer.Count; i++)
411 {
412 for (int j = 0; j < p.layer[i].top.Count; j++)
413 {
414 bool bIsUsed = rgUsedLayers.Contains(p.layer[i].top[j]);
415
416 if (nPruneFrom >= 0 && bIsUsed)
417 {
418 nPruneFrom = -1;
419 break;
420 }
421 else if (nPruneFrom < 0 && !bIsUsed)
422 {
423 nPruneFrom = i;
424 }
425 }
426 }
427
428 if (nPruneFrom >= 0)
429 {
430 for (int i = p.layer.Count - 1; i >= nPruneFrom; i--)
431 {
432 m_log.WriteLine("Pruning layer '" + p.layer[i].name);
433 p.layer.RemoveAt(i);
434 }
435 }
436 }
437
438 private void add_gram_layers(NetParameter p)
439 {
440 List<KeyValuePair<string, double>> lstStyle = m_rgLayers["style"].ToList();
441 List<KeyValuePair<string, double>> lstGram = m_rgLayers["gram"].ToList();
442
443 for (int i=0; i<lstStyle.Count; i++)
444 {
445 bool bUseHalfSize = false;
447 string strStyle = lstStyle[i].Key;
448 string strGram = lstGram[i].Key;
449
450 foreach (LayerParameter layer1 in p.layer)
451 {
452 if (layer1.type == LayerParameter.LayerType.CONVOLUTION)
453 {
454 if (layer1.top.Contains(strStyle))
455 {
456 bUseHalfSize = layer1.use_halfsize;
457 break;
458 }
459 }
460 }
461
462 layer.name = strGram;
463
464 layer.bottom.Add(strStyle);
465 layer.top.Add(strGram);
466 layer.gram_param.alpha = m_dfStyleDataScale1;
468 layer.gram_param.beta = m_dfStyleDataScale2;
469 layer.use_halfsize = (bUseHalfSize && m_bAllowHalfSizeOnGram);
470
471 p.layer.Add(layer);
472 }
473 }
474
475 private double get_style_scale(Blob<T> b)
476 {
477 double df1 = b.shape(0);
478 df1 = Math.Pow(df1, -2);
479 double df2 = b.count(1);
480 df2 = Math.Pow(df2, -2);
481
482 double dfC = (df1 * df2);
483
484 return dfC / 4;
485 }
486
487 private double get_content_scale(Blob<T> b)
488 {
489 return m_dfContentLossScale;
490 }
491
492 private void prepare_data_blob(Net<T> net, Bitmap bmp)
493 {
494 List<int> rgDataShape = new List<int>() { 1, 3, bmp.Height, bmp.Width };
495 m_transformer = new DataTransformer<T>(m_cuda, m_log, m_transformationParam, Phase.TEST, 3, bmp.Height, bmp.Width);
496
497 Blob<T> data = net.blob_by_name(m_strDataBlobName);
498 data.Reshape(rgDataShape, data.HalfSize);
499 data.mutable_cpu_data = m_transformer.Transform(ImageData.GetImageDataD(bmp, 3, false, -1));
500 }
501
502 private void prepare_input_param(Net<T> net, Bitmap bmp)
503 {
504 List<int> rgDataShape = new List<int>() { 1, 3, bmp.Height, bmp.Width };
505 m_transformer = new DataTransformer<T>(m_cuda, m_log, m_transformationParam, Phase.TEST, 3, bmp.Height, bmp.Width);
506
507 Blob<T> data = net.param_by_name("input1");
508 data.Reshape(rgDataShape, data.HalfSize);
509 data.mutable_cpu_data = m_transformer.Transform(ImageData.GetImageDataD(bmp, 3, false, -1));
510 }
511
512 private Bitmap save(Net<T> net)
513 {
514 Blob<T> blob = net.param_by_name("input1");
515 Datum d = m_transformer.UnTransform(blob);
516 return ImageData.GetImage(d);
517 }
518
530 public Bitmap Process(Bitmap bmpStyle, Bitmap bmpContent, int nIterations, int nIntermediateOutput = -1, double dfTvLoss = 0, int nMaxSize = -1, bool bEnablePartialSolution = false)
531 {
532 Solver<T> solver = null;
533 Net<T> net = null;
534 BlobCollection<T> colContentActivations = new BlobCollection<T>();
535 BlobCollection<T> colGramActivations = new BlobCollection<T>();
536 double dfLoss;
537 bool bDone = true;
538
539 try
540 {
541 m_dfTVLossWeight = dfTvLoss;
542 m_nIterations = nIterations;
543
544 if (nMaxSize == -1)
545 nMaxSize = m_nDefaultMaxImageSize;
546
547 if (bmpContent.Width > nMaxSize ||
548 bmpContent.Height > nMaxSize)
549 {
550 double dfAspectRatio = (double)bmpContent.Height / (double)bmpContent.Width;
551 int nWidth = nMaxSize;
552 int nHeight = (int)(nMaxSize * dfAspectRatio);
553 bmpContent = ImageTools.ResizeImage(bmpContent, nWidth, nHeight);
554 }
555
556 if (bmpStyle.Width != bmpContent.Width ||
557 bmpStyle.Height != bmpContent.Height)
558 bmpStyle = ImageTools.ResizeImage(bmpStyle, bmpContent.Width, bmpContent.Height);
559
560 m_log.WriteLine("Creating input network...");
561 m_log.Enable = false;
562 net = new Net<T>(m_cuda, m_log, m_param, m_evtCancel, null, Phase.TEST, null, m_netShare, net_OnGetWorkspace, net_OnSetWorkspace);
563 m_log.Enable = true;
564
565 if (m_rgWeights != null && !m_bUsingSharedNet)
566 net.LoadWeights(m_rgWeights, m_persist);
567
568 //-----------------------------------------
569 // Get style and content activations.
570 //-----------------------------------------
571
572 prepare_data_blob(net, bmpStyle);
573 net.Forward(out dfLoss);
574
575 foreach (KeyValuePair<string, double> kvGram in m_rgLayers["gram"])
576 {
577 string strGram = kvGram.Key;
578 Blob<T> blobGram = net.blob_by_name(strGram);
579 colGramActivations.Add(blobGram.Clone());
580 }
581
582 prepare_data_blob(net, bmpContent);
583 net.Forward(out dfLoss);
584
585 foreach (KeyValuePair<string, double> kvContent in m_rgLayers["content"])
586 {
587 string strContent = kvContent.Key;
588 Blob<T> blobContent = net.blob_by_name(strContent);
589 colContentActivations.Add(blobContent.Clone());
590 }
591
592
593 //-----------------------------------------
594 // Prepare the network by adding new layers.
595 //-----------------------------------------
596
597 NetParameter net_param = m_param;
598
599 foreach (KeyValuePair<string, double> kvInput in m_rgLayers["input"])
600 {
601 string strName = kvInput.Key;
603 p.name = "input_" + strName;
604 p.top.Add(p.name);
605
606 Blob<T> blob = net.blob_by_name(strName);
607 p.input_param.shape.Add(new BlobShape(blob.shape()));
608 p.use_halfsize = blob.HalfSize;
609
610 net_param.layer.Add(p);
611 }
612
613 foreach (KeyValuePair<string, double> kvContent in m_rgLayers["content"])
614 {
615 string strName = kvContent.Key;
616 string strScale1 = "input_" + strName;
617 string strScale2 = strName;
618 Blob<T> blobContent = colContentActivations[strName];
619
620 if (m_dfContentDataScale != 1.0)
621 {
622 strScale1 += "b";
624 ps1.scalar_param.value = m_dfContentDataScale;
627 ps1.use_halfsize = (blobContent.HalfSize && m_bAllowHalfSizeOnScalar);
628 ps1.bottom.Add("input_" + strName);
629 ps1.top.Add(strScale1);
630
631 net_param.layer.Add(ps1);
632
633 strScale2 += "b";
635 ps2.scalar_param.value = m_dfContentDataScale;
638 ps2.use_halfsize = (blobContent.HalfSize && m_bAllowHalfSizeOnScalar);
639 ps2.bottom.Add(strName);
640 ps2.top.Add(strScale2);
641
642 net_param.layer.Add(ps2);
643 }
644
645 LayerParameter event_param = new LayerParameter(LayerParameter.LayerType.EVENT);
646 event_param.name = "event_" + strName;
647 event_param.bottom.Add(strScale2);
648 event_param.bottom.Add(strScale1);
649 event_param.use_halfsize = (blobContent.HalfSize && m_bAllowHalfSizeOnEvent);
650 event_param.top.Add("event_" + strName);
651
652 net_param.layer.Add(event_param);
653
655 p.name = "loss_" + strName;
656
657 double dfScale = get_content_scale(blobContent);
658 p.loss_weight.Add(kvContent.Value * dfScale);
659 p.use_halfsize = (blobContent.HalfSize && m_bAllowHalfSizeOnLoss);
660 p.bottom.Add("event_" + strName);
661 p.bottom.Add(strScale1);
662 p.top.Add("loss_" + strName);
663
664 net_param.layer.Add(p);
665 }
666
667 foreach (KeyValuePair<string, double> kvGram in m_rgLayers["gram"].ToList())
668 {
669 string strGramName = kvGram.Key;
670 Blob<T> blobGram = colGramActivations[strGramName];
671
672 LayerParameter event_param = new LayerParameter(LayerParameter.LayerType.EVENT);
673 event_param.name = "event_" + strGramName;
674 event_param.use_halfsize = (blobGram.HalfSize && m_bAllowHalfSizeOnEvent);
675 event_param.bottom.Add(strGramName);
676 event_param.bottom.Add("input_" + strGramName);
677 event_param.top.Add("event_" + strGramName);
678
679 net_param.layer.Add(event_param);
680
682 p.name = "loss_" + strGramName;
683 p.use_halfsize = (blobGram.HalfSize && m_bAllowHalfSizeOnLoss);
684
685 double dfScale = get_style_scale(blobGram);
686 p.loss_weight.Add(kvGram.Value * dfScale);
687
688 p.bottom.Add("input_" + strGramName);
689 p.bottom.Add("event_" + strGramName);
690 p.top.Add("loss_" + strGramName);
691
692 net_param.layer.Add(p);
693 }
694
695 // Add TV Loss;
696 if (m_dfTVLossWeight != 0)
697 {
699 p.name = "loss_tv";
700
701 double dfWeight = m_dfTVLossWeight;
702 p.loss_weight.Add(dfWeight);
703
704 p.bottom.Add(m_strDataBlobName);
705 p.top.Add("loss_tv");
706
707 net_param.layer.Add(p);
708 }
709
710 // Replace InputLayer with ParameterLayer,
711 // so that we'll be able to backprop into the image.
712 Blob<T> data = net.blob_by_name(m_strDataBlobName);
713 for (int i=0; i<net_param.layer.Count; i++)
714 {
715 LayerParameter p = net_param.layer[i];
716
717 if (p.name == "input1")
718 {
719 net_param.layer[i].SetType(LayerParameter.LayerType.PARAMETER);
720 net_param.layer[i].parameter_param.shape = new BlobShape(data.shape());
721 break;
722 }
723 }
724
725 // Disable weights learning.
726 List<LayerParameter.LayerType> rgTypes = new List<LayerParameter.LayerType>();
727 rgTypes.Add(LayerParameter.LayerType.CONVOLUTION);
728 rgTypes.Add(LayerParameter.LayerType.DECONVOLUTION);
729 rgTypes.Add(LayerParameter.LayerType.INNERPRODUCT);
730 rgTypes.Add(LayerParameter.LayerType.PRELU);
731 rgTypes.Add(LayerParameter.LayerType.BIAS);
732 rgTypes.Add(LayerParameter.LayerType.EMBED);
733 rgTypes.Add(LayerParameter.LayerType.LSTM);
734 rgTypes.Add(LayerParameter.LayerType.LSTM_ATTENTION);
735 rgTypes.Add(LayerParameter.LayerType.LSTM_SIMPLE); // DEPRECIATED
736 rgTypes.Add(LayerParameter.LayerType.RNN);
737
738 foreach (LayerParameter layer in net_param.layer)
739 {
740 if (rgTypes.Contains(layer.type))
741 {
742 layer.parameters = new List<ParamSpec>();
743 layer.parameters.Add(new ParamSpec(0, 0));
744 layer.parameters.Add(new ParamSpec(0, 0));
745 }
746 }
747
748 net.Dispose();
749 net = null;
750
751
752 //-----------------------------------------
753 // Create solver and assign inputs.
754 //-----------------------------------------
755
756 SolverParameter solver_param = new SolverParameter();
757 solver_param.display = m_nDisplayEvery;
758 solver_param.train_net_param = net_param;
759 solver_param.test_iter.Clear();
760 solver_param.test_interval = 0;
761 solver_param.test_initialization = false;
762 solver_param.base_lr = m_dfLearningRate;
763 solver_param.type = m_solverType;
764 solver_param.lbgfs_corrections = m_nLBFGSCorrections;
765
766 m_log.WriteLine("Creating " + m_solverType.ToString() + " solver with learning rate = " + m_dfLearningRate.ToString() + "...");
767 m_log.Enable = false;
768
769 if (m_solverType == SolverParameter.SolverType.LBFGS)
770 solver = new LBFGSSolver<T>(m_cuda, m_log, solver_param, m_evtCancel, null, null, null, m_persist, 1, 0, m_netShare, net_OnGetWorkspace, net_OnSetWorkspace);
771 else
772 solver = Solver<T>.Create(m_cuda, m_log, solver_param, m_evtCancel, null, null, null, m_persist, 1, 0, m_netShare, net_OnGetWorkspace, net_OnSetWorkspace);
773
774 m_log.Enable = true;
775 solver.OnSnapshot += Solver_OnSnapshot;
776 solver.OnTrainingIteration += Solver_OnTrainingIteration;
777
778 foreach (Layer<T> layer in solver.net.layers)
779 {
780 if (layer.type == LayerParameter.LayerType.EVENT)
781 {
782 EventLayer<T> eventLayer = layer as EventLayer<T>;
783 eventLayer.OnBackward += EventLayer_OnBackward;
784 }
785 }
786
787 prepare_input_param(solver.net, bmpContent);
788
789 foreach (KeyValuePair<string, double> kvContent in m_rgLayers["content"])
790 {
791 string strName = kvContent.Key;
792 Blob<T> blobDst = solver.net.blob_by_name("input_" + strName);
793 Blob<T> blobSrc = colContentActivations[strName];
794 blobDst.CopyFrom(blobSrc);
795 }
796
797 foreach (KeyValuePair<string, double> kvGram in m_rgLayers["gram"])
798 {
799 string strName = kvGram.Key;
800 Blob<T> blobDst = solver.net.blob_by_name("input_" + strName);
801 Blob<T> blobSrc = colGramActivations[strName];
802 blobDst.CopyFrom(blobSrc);
803 }
804
805 colGramActivations.Dispose();
806 colGramActivations = null;
807
808 colContentActivations.Dispose();
809 colContentActivations = null;
810
811
812 //-----------------------------------------
813 // Optimize.
814 //-----------------------------------------
815
816 if (nIntermediateOutput <= 0 || nIntermediateOutput == m_nIterations)
817 {
818 bEnablePartialSolution = false;
819 nIntermediateOutput = m_nIterations;
820 }
821
822 int nIterations1 = m_nIterations / nIntermediateOutput;
823
824 if (m_rgWeights != null && !m_bUsingSharedNet)
825 {
826 Blob<T> blobInput = solver.net.learnable_parameters[0];
827 solver.net.learnable_parameters.RemoveAt(0);
828 solver.net.LoadWeights(m_rgWeights, m_persist);
829 solver.net.learnable_parameters.Insert(0, blobInput);
830 }
831
832 if (bEnablePartialSolution)
833 {
834 m_solver = solver;
835 m_nPartialIteration = 0;
836 m_nPartialIterations1 = nIterations1;
837 m_nIntermediateOutput = nIntermediateOutput;
838 bDone = false;
839 return null;
840 }
841
842 for (int i = 0; i < nIterations1; i++)
843 {
844 if (m_evtCancel.WaitOne(0))
845 break;
846
847 solver.Step(nIntermediateOutput, TRAIN_STEP.NONE, true, true, true);
848
849 if (!m_evtCancel.WaitOne(0))
850 {
851 if (OnIntermediateOutput != null && nIntermediateOutput > 0 && i < nIterations1 - 1)
852 {
853 Bitmap bmpTemp = save(solver.net);
854 double dfPct = (double)i / (double)nIterations1;
855 OnIntermediateOutput(this, new NeuralStyleIntermediateOutputArgs(i, bmpTemp, dfPct));
856 bmpTemp.Dispose();
857 }
858 }
859 }
860
861 return save(solver.net);
862 }
863 catch (Exception excpt)
864 {
865 if (solver != null)
866 {
867 m_solver = null;
868 solver.Dispose();
869 }
870
871 throw excpt;
872 }
873 finally
874 {
875 if (net != null)
876 net.Dispose();
877
878 if (colGramActivations != null)
879 colGramActivations.Dispose();
880
881 if (colContentActivations != null)
882 colContentActivations.Dispose();
883
884 if (bDone)
885 {
886 if (solver != null)
887 solver.Dispose();
888 }
889 }
890 }
891
892 private void net_OnSetWorkspace(object sender, WorkspaceArgs e)
893 {
894 if (e.WorkspaceSizeInBytes < m_lWorkspaceSizeInBytes || e.WorkspaceSizeInBytes == 0)
895 return;
896
897 m_lWorkspaceSizeInBytes = e.WorkspaceSizeInBytes;
898 m_cuda.DisableGhostMemory();
899
900 if (m_hWorkspaceData != 0)
901 m_cuda.FreeMemory(m_hWorkspaceData);
902
903 m_hWorkspaceData = m_cuda.AllocMemory((long)m_lWorkspaceSizeInBytes);
904
905 m_cuda.ResetGhostMemory();
906 }
907
908 private void net_OnGetWorkspace(object sender, WorkspaceArgs e)
909 {
910 e.WorkspaceData = m_hWorkspaceData;
911 e.WorkspaceSizeInBytes = m_lWorkspaceSizeInBytes;
912 }
913
920 public Bitmap ProcessNext(out Bitmap bmpIntermediate, out int nIntermediateIdx)
921 {
922 try
923 {
924 bmpIntermediate = null;
925 nIntermediateIdx = m_nPartialIteration * m_nIntermediateOutput;
926
927 if (m_solver == null)
928 throw new Exception("To run the next in process, the solver cannot be null! You must call Process first.");
929
930 m_solver.Step(m_nIntermediateOutput, TRAIN_STEP.NONE, true, true, true);
931
932 if (m_evtCancel.WaitOne(0))
933 return null;
934
935 m_nPartialIteration++;
936
937 if (m_nIntermediateOutput > 0 && m_nPartialIteration < m_nPartialIterations1)
938 {
939 bmpIntermediate = save(m_solver.net);
940
941 if (OnIntermediateOutput != null)
942 {
943 double dfPct = (double)m_nPartialIteration / (double)m_nPartialIterations1;
944 OnIntermediateOutput(this, new NeuralStyleIntermediateOutputArgs(m_nPartialIteration * m_nIntermediateOutput, bmpIntermediate, dfPct));
945 }
946 }
947
948 if (m_nPartialIteration < m_nPartialIterations1)
949 return null;
950
951 return save(m_solver.net);
952 }
953 catch (Exception excpt)
954 {
955 throw excpt;
956 }
957 finally
958 {
959 if (m_nPartialIteration == m_nPartialIterations1)
960 {
961 if (m_solver != null)
962 {
963 m_solver.Dispose();
964 m_solver = null;
965 }
966 }
967 }
968 }
969
970 private void EventLayer_OnBackward(object sender, BackwardArgs<T> e)
971 {
972 int nCount = e.BottomVec[0].count();
973 long hTopDiff0 = e.TopVec[0].mutable_gpu_diff;
974 long hBottomData1 = e.BottomVec[1].gpu_data;
975 long hBottomDiff1 = e.BottomVec[1].mutable_gpu_diff;
976 long hBottomDiff = e.BottomVec[0].mutable_gpu_diff;
977
978 m_cuda.sign(nCount, hBottomData1, hBottomDiff1);
979 m_cuda.abs(nCount, hBottomDiff1, hBottomDiff1);
980 m_cuda.mul(nCount, hBottomDiff1, hTopDiff0, hBottomDiff);
981 }
982
983 private void Solver_OnTrainingIteration(object sender, TrainingIterationArgs<T> e)
984 {
985 m_log.WriteLine("Iteration = " + e.Iteration.ToString() + " - Loss = " + e.SmoothedLoss.ToString());
986
987 if (double.IsNaN(e.Loss))
988 {
989 m_evtCancel.Set();
990 m_log.FAIL("Loss = NAN!");
991 return;
992 }
993
994 if (double.IsInfinity(e.Loss))
995 {
996 m_evtCancel.Set();
997 m_log.FAIL("Loss = Infinity!");
998 return;
999 }
1000 }
1001
1002 private void Solver_OnSnapshot(object sender, SnapshotArgs e)
1003 {
1004 }
1005
1024 public static string CreateConfigurationString(string strSolver, double dfLearningRate, int nMaxImageSize, int nIterations, int nIntermediateIterations, Dictionary<string, Tuple<double, double>> rgWts, List<int> rgGpuID, int nLBFGSCorrections, double dfDataScale, bool bAllowHs, bool bAllowHsGram, bool bAllowHsEvent, bool bAllowHsScalar, bool bAllowHsLoss)
1025 {
1026 RawProtoCollection rgChildren = new RawProtoCollection();
1027
1028 rgChildren.Add("solver", strSolver);
1029 rgChildren.Add("learning_rate", dfLearningRate);
1030 rgChildren.Add("max_image_size", nMaxImageSize);
1031 rgChildren.Add("iterations", nIterations);
1032 rgChildren.Add("intermediate_iterations", nIntermediateIterations);
1033
1034 RawProtoCollection rgLayerWt = new RawProtoCollection();
1035 foreach (KeyValuePair<string, Tuple<double, double>> kv in rgWts)
1036 {
1038 layer.Add("name", kv.Key);
1039 layer.Add("style_wt", kv.Value.Item1);
1040 layer.Add("content_wt", kv.Value.Item2);
1041
1042 rgLayerWt.Add(new RawProto("layer", "", layer));
1043 }
1044
1045 rgChildren.Add(rgLayerWt);
1046
1048 foreach (int nGpuID in rgGpuID)
1049 {
1050 gpus.Add("gpuid", nGpuID.ToString());
1051 }
1052
1053 rgChildren.Add(gpus);
1054 rgChildren.Add("lbfgs_corrections", nLBFGSCorrections);
1055 rgChildren.Add("data_scale", dfDataScale);
1056 rgChildren.Add("allow_hs", bAllowHs);
1057 rgChildren.Add("allow_hs_gram", bAllowHsGram);
1058 rgChildren.Add("allow_hs_event", bAllowHsEvent);
1059 rgChildren.Add("allow_hs_scalar", bAllowHsScalar);
1060 rgChildren.Add("allow_hs_loss", bAllowHsLoss);
1061
1062 RawProto proto = new RawProto("root", "", rgChildren);
1063
1064 return proto.ToString();
1065 }
1066
1085 public static Dictionary<string, Tuple<double, double>> ParseConfigurationString(string strConfig, out string strSolver, out double dfLearningRate, out int nMaxImageSize, out int nIterations, out int nIntermediateIterations, out List<int> rgGpuID, out int nLBFGSCorrections, out double dfDataScale, out bool bAllowHs, out bool bAllowHsGram, out bool bAllowHsEvent, out bool bAllowHsScalar, out bool bAllowHsLoss)
1086 {
1087 RawProto proto = RawProto.Parse(strConfig);
1088 string strVal;
1089
1090 strSolver = null;
1091 if ((strVal = proto.FindValue("solver")) != null)
1092 strSolver = strVal;
1093
1094 dfLearningRate = 0;
1095 if ((strVal = proto.FindValue("learning_rate")) != null)
1096 dfLearningRate = BaseParameter.ParseDouble(strVal);
1097
1098 nMaxImageSize = 0;
1099 if ((strVal = proto.FindValue("max_image_size")) != null)
1100 nMaxImageSize = int.Parse(strVal);
1101
1102 nIterations = 1000;
1103 if ((strVal = proto.FindValue("iterations")) != null)
1104 nIterations = int.Parse(strVal);
1105
1106 nIntermediateIterations = 0;
1107 if ((strVal = proto.FindValue("intermediate_iterations")) != null)
1108 nIntermediateIterations = int.Parse(strVal);
1109
1110 Dictionary<string, Tuple<double, double>> rgLayers = new Dictionary<string, Tuple<double, double>>();
1111 RawProtoCollection style = proto.FindChildren("layer");
1112 foreach (RawProto styleProto in style)
1113 {
1114 string strLayer = null;
1115 if ((strVal = styleProto.FindValue("name")) != null)
1116 strLayer = strVal;
1117
1118 double dfSWt = 0;
1119 if ((strVal = styleProto.FindValue("style_wt")) != null)
1120 dfSWt = BaseParameter.ParseDouble(strVal);
1121
1122 double dfCWt = 0;
1123 if ((strVal = styleProto.FindValue("content_wt")) != null)
1124 dfCWt = BaseParameter.ParseDouble(strVal);
1125
1126 rgLayers.Add(strLayer, new Tuple<double, double>(dfSWt, dfCWt));
1127 }
1128
1129 rgGpuID = new List<int>();
1130 RawProtoCollection gpus = proto.FindChildren("gpuid");
1131 foreach (RawProto gpuProto in gpus)
1132 {
1133 rgGpuID.Add(int.Parse(gpuProto.Value));
1134 }
1135
1136 nLBFGSCorrections = 100;
1137 if ((strVal = proto.FindValue("lbfgs_corrections")) != null)
1138 nLBFGSCorrections = int.Parse(strVal);
1139
1140 dfDataScale = 1.0;
1141 if ((strVal = proto.FindValue("data_scale")) != null)
1142 dfDataScale = BaseParameter.ParseDouble(strVal);
1143
1144 bAllowHs = false;
1145 if ((strVal = proto.FindValue("allow_hs")) != null)
1146 bAllowHs = bool.Parse(strVal);
1147
1148 bAllowHsGram = true;
1149 if ((strVal = proto.FindValue("allow_hs_gram")) != null)
1150 bAllowHsGram = bool.Parse(strVal);
1151
1152 bAllowHsEvent = true;
1153 if ((strVal = proto.FindValue("allow_hs_event")) != null)
1154 bAllowHsEvent = bool.Parse(strVal);
1155
1156 bAllowHsScalar = true;
1157 if ((strVal = proto.FindValue("allow_hs_scalar")) != null)
1158 bAllowHsScalar = bool.Parse(strVal);
1159
1160 bAllowHsLoss = true;
1161 if ((strVal = proto.FindValue("allow_hs_loss")) != null)
1162 bAllowHsLoss = bool.Parse(strVal);
1163
1164 return rgLayers;
1165 }
1166 }
1167
1171 public class NeuralStyleIntermediateOutputArgs : EventArgs
1172 {
1173 Bitmap m_img;
1174 int m_nIteration;
1175 double m_dfPercent;
1176
1183 public NeuralStyleIntermediateOutputArgs(int nIteration, Bitmap bmp, double dfPct)
1184 {
1185 m_nIteration = nIteration;
1186 m_img = bmp;
1187 m_dfPercent = dfPct;
1188 }
1189
1193 public int Iteration
1194 {
1195 get { return m_nIteration; }
1196 }
1197
1201 public Bitmap Image
1202 {
1203 get { return m_img; }
1204 }
1205
1209 public double Percent
1210 {
1211 get { return m_dfPercent; }
1212 }
1213 }
1214}
The BaseParameter class is the base class for all other parameter classes.
static double ParseDouble(string strVal)
Parse double values using the US culture if the decimal separator = '.', then using the native cultur...
The CancelEvent provides an extension to the manual cancel event that allows for overriding the manua...
Definition: CancelEvent.cs:17
void Reset()
Resets the event clearing any signaled state.
Definition: CancelEvent.cs:279
bool WaitOne(int nMs=int.MaxValue)
Waits for the signal state to occur.
Definition: CancelEvent.cs:290
void Set()
Sets the event to the signaled state.
Definition: CancelEvent.cs:270
The Datum class is a simple wrapper to the SimpleDatum class to ensure compatibility with the origina...
Definition: Datum.cs:12
The ImageData class is a helper class used to convert between Datum, other raw data,...
Definition: ImageData.cs:14
static Bitmap GetImage(SimpleDatum d, ColorMapper clrMap=null, List< int > rgClrOrder=null)
Converts a SimplDatum (or Datum) into an image, optionally using a ColorMapper.
Definition: ImageData.cs:506
static Datum GetImageDataD(Bitmap bmp, int nChannels, bool bDataIsReal, int nLabel, bool bUseLockBitmap=true, int[] rgFocusMap=null)
The GetImageDataD function converts a Bitmap into a Datum using the double type for real data.
Definition: ImageData.cs:44
The ImageTools class is a helper class used to manipulate image data.
Definition: ImageTools.cs:16
static Bitmap ResizeImage(Image image, int width, int height)
Resize the image to the specified width and height.
Definition: ImageTools.cs:39
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 Enable
Enables/disables the Log. When disabled, the Log does not output any data.
Definition: Log.cs:42
void FAIL(string str)
Causes a failure which throws an exception with the desciptive text.
Definition: Log.cs:394
The RawProtoCollection class is a list of RawProto objects.
void Add(RawProto p)
Adds a RawProto to the collection.
The RawProto class is used to parse and output Google prototxt file data.
Definition: RawProto.cs:17
string Value
Get/set the value of the node.
Definition: RawProto.cs:79
override string ToString()
Returns the RawProto as its full prototxt string.
Definition: RawProto.cs:681
static RawProto Parse(string str)
Parses a prototxt and places it in a new RawProto.
Definition: RawProto.cs:306
string FindValue(string strName)
Searches for a falue of a node within this nodes children.
Definition: RawProto.cs:105
RawProtoCollection FindChildren(params string[] rgstrName)
Searches for all children with a given name in this node's children.
Definition: RawProto.cs:263
The Utility class provides general utility funtions.
Definition: Utility.cs:35
The BackwardArgs are passed to the OnBackward event of the EventLayer.
Definition: EventArgs.cs:703
The BlobCollection contains a list of Blobs.
void Dispose()
Release all resource used by the collection and its Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
bool HalfSize
Returns whether or not this blob is using half sizes.
Definition: Blob.cs:369
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:1461
Blob< T > Clone()
Copies the Blob, including its data and diff.
Definition: Blob.cs:2202
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
Definition: Blob.cs:442
void CopyFrom(Blob< T > src, int nSrcOffset, int nDstOffset, int nCount, bool bCopyData, bool bCopyDiff)
Copy from a source Blob.
Definition: Blob.cs:903
List< int > shape()
Returns an array where each element contains the shape of an axis of the Blob.
Definition: Blob.cs:684
int count()
Returns the total number of items in the Blob.
Definition: Blob.cs:739
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
int GetDeviceID()
Returns the current device id set within Cuda.
Definition: CudaDnn.cs:2013
BlobCollection< T > BottomVec
Returns the bottom blobs.
Definition: EventArgs.cs:685
BlobCollection< T > TopVec
Returns the top blobs.
Definition: EventArgs.cs:693
Connects Layer's together into a direct acrylic graph (DAG) specified by a NetParameter
Definition: Net.cs:23
BlobCollection< T > Forward()
Run forward with the input Blob's already fed separately.
Definition: Net.cs:1445
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
Blob< T > param_by_name(string strName, bool bThrowExceptionOnError=true)
Returns a parameter given its name.
Definition: Net.cs:2167
Blob< T > blob_by_name(string strName, bool bThrowExceptionOnError=true)
Returns a blob given its name.
Definition: Net.cs:2245
CudaDnn< T > Cuda
Returns the instance of CudaDnn used by this network.
Definition: Net.cs:2821
The PersistCaffe class is used to load and save weight files in the .caffemodel format.
Definition: PersistCaffe.cs:20
The SnapshotArgs is sent to the Solver::OnSnapshot event which fires each time the Solver::Snapshot m...
Definition: EventArgs.cs:416
int Iteration
Return the iteration of the test cycle.
Definition: EventArgs.cs:246
The TrainingIterationArgs is sent to the Solver::OnTrainingIteration event that fires at the end of a...
Definition: EventArgs.cs:264
double Loss
Returns the loss of the training cycle.
Definition: EventArgs.cs:311
double SmoothedLoss
Retunrs the average loss after the training cycle.
Definition: EventArgs.cs:319
The WorkspaceArgs are passed to both the Layer::OnSetWorkspace and Layer::OnGetWorkspace events.
Definition: EventArgs.cs:17
long WorkspaceData
Get/set the handle to workspace data in GPU memory.
Definition: EventArgs.cs:36
ulong WorkspaceSizeInBytes
Get/set the workspace memory size in bytes.
Definition: EventArgs.cs:45
Applies common transformations to the input data, such as scaling, mirroring, subtracting the image m...
Datum UnTransform(Blob< T > blob, bool bIncludeMean=true)
Reverse the transformation made when calling Transform.
void Dispose()
Cleanup all resources used.
void Transform(List< Datum > rgDatum, Blob< T > blobTransformed, CudaDnn< T > cuda, Log log)
Transforms a list of Datum and places the transformed data into a Blob.
The NeuralStyleIntermediateOutputArgs contains the arguments sent to the OnIntermediateOutput event.
Bitmap Image
Returns the current intermediate image.
NeuralStyleIntermediateOutputArgs(int nIteration, Bitmap bmp, double dfPct)
The constructor.
double Percent
Returns the total processing progress.
The NeuralStyleTransfer object uses the GramLayer, TVLossLayer and LBFGSSolver to perform the neural ...
EventHandler< NeuralStyleIntermediateOutputArgs > OnIntermediateOutput
Specifies the event fired after producing intermediate output (e.g. when m_nIntermediateOutput > 0)
static string CreateConfigurationString(string strSolver, double dfLearningRate, int nMaxImageSize, int nIterations, int nIntermediateIterations, Dictionary< string, Tuple< double, double > > rgWts, List< int > rgGpuID, int nLBFGSCorrections, double dfDataScale, bool bAllowHs, bool bAllowHsGram, bool bAllowHsEvent, bool bAllowHsScalar, bool bAllowHsLoss)
The CreateConfigurationString function packs all deep draw settings into a configuration string.
NeuralStyleTransfer(CudaDnn< T > cuda, Log log, CancelEvent evtCancel, Dictionary< string, Tuple< double, double > > rgLayers, string strModelDesc, byte[] rgWeights, bool bCaffeModel, SolverParameter.SolverType solverType=SolverParameter.SolverType.LBFGS, double dfLearningRate=1.0, int nMaxImageSize=840, int nLBFGSCorrections=100, double dfDataScale=1.0, Net< T > netShare=null)
The constructor.
Bitmap Process(Bitmap bmpStyle, Bitmap bmpContent, int nIterations, int nIntermediateOutput=-1, double dfTvLoss=0, int nMaxSize=-1, bool bEnablePartialSolution=false)
Process the content image by applying the style to it that was learned from the style image.
void SetupHalfSize(bool bAllowHs, bool bAllowOnGram, bool bAllowOnEvent, bool bAllowOnLoss, bool bAllowOnScalar)
Setup which layers are allowed to use half-sized memory when their convolution counterparts use it.
Bitmap ProcessNext(out Bitmap bmpIntermediate, out int nIntermediateIdx)
Process the next partial part of the solution. This function is only valid after calling Process with...
void Dispose()
Release all resources used.
NeuralStyleTransfer(CudaDnn< T > cuda, Log log, CancelEvent evtCancel, string strModelType, string strModel, byte[] rgWeights, bool bCaffeModel, SolverParameter.SolverType solverType=SolverParameter.SolverType.LBFGS, double dfLearningRate=1.5, int nLBFGSCorrections=100, double dfDataScale=1.0, Net< T > netShare=null)
The constructor.
static Dictionary< string, Tuple< double, double > > ParseConfigurationString(string strConfig, out string strSolver, out double dfLearningRate, out int nMaxImageSize, out int nIterations, out int nIntermediateIterations, out List< int > rgGpuID, out int nLBFGSCorrections, out double dfDataScale, out bool bAllowHs, out bool bAllowHsGram, out bool bAllowHsEvent, out bool bAllowHsScalar, out bool bAllowHsLoss)
The ParseConfigurationString method parses a deep draw configuration string into the actual settings.
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:927
The EventLayer provides an event that fires on the forward pass and another that fires on the backwar...
Definition: EventLayer.cs:23
EventHandler< BackwardArgs< T > > OnBackward
Defines the event that fires from within the backward pass.
Definition: EventLayer.cs:39
Specifies the shape of a Blob.
Definition: BlobShape.cs:15
List< BlobShape > shape
Define N shapes to set a shape for each top. Define 1 shape to set the same shape for every top....
Specifies the base parameter for all layers.
List< ParamSpec > parameters
Specifies the ParamSpec parameters of the LayerParameter.
string name
Specifies the name of this LayerParameter.
List< double > loss_weight
Specifies the loss weight.
LayerType type
Specifies the type of this LayerParameter.
bool use_halfsize
Specifies whether or not to use half sized memory or not.
GramParameter gram_param
Returns the parameter set when initialized with LayerType.GRAM
InputParameter input_param
Returns the parameter set when initialized with LayerType.INPUT
List< string > top
Specifies the active top connections (in the bottom, out the top)
ScalarParameter scalar_param
Returns the parameter set when initialized with LayerType.SCALAR
List< string > bottom
Specifies the active bottom connections (in the bottom, out the top).
LayerType
Specifies the layer type.
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< LayerParameter > layer
The layers that make up the net. Each of their configurations, including connectivity and behavior,...
Specifies training parameters (multipliers on global learning constants, and the name of other settin...
Definition: ParamSpec.cs:19
The SolverParameter is a parameter for the solver, specifying the train and test networks.
int lbgfs_corrections
Specifies the number of lbgfs corrections used with the L-BGFS solver.
List< int > test_iter
The number of iterations for each test.
NetParameter train_net_param
Inline train net param, possibly combined with one or more test nets.
SolverType
Defines the type of solver.
int test_interval
The number of iterations between two testing phases.
bool test_initialization
If true, run an initial test pass before the first iteration, ensuring memory availability and printi...
int display
The number of iterations between displaying info. If display = 0, no info will be displayed.
double base_lr
The base learning rate (default = 0.01).
SolverType type
Specifies the solver type.
Stores parameters used to apply transformation to the data layer's data.
COLOR_ORDER
Defines the color ordering used to tranform the input data.
List< double > mean_value
If specified can be repeated once (would subtract it from all the channels or can be repeated the sam...
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....
double beta
Specifies the scaling factor applied after the gram operation.
bool disable_scaling_on_gradient
Specifies whether or not to apply the un-scaling of the alpha and beta values during the during the b...
double alpha
Specifies the scaling factor applied before the gram operation.
Specifies the parameters for the ScalarLayer
double value
Specifies the scalar value to apply.
ScalarOp operation
Specifies the scalar operation to apply (mul, add, etc).
bool passthrough_gradient
Specifies whether or not to pass-through the gradient without performing the back-prop calculation (d...
ScalarOp
Defines the scalar operations that may be performed.
Optimizes the parameters of a Net using L-BFGS. This implementation is based on minFunc,...
Definition: LBFGSSolver.cs:26
An interface for classes that perform optimization on Nets - this class serves as the base class for ...
Definition: Solver.cs:28
void Dispose()
Discards the resources (GPU and Host) used by this Solver.
Definition: Solver.cs:218
EventHandler< TrainingIterationArgs< T > > OnTrainingIteration
The OnTrainingIteration event fires at the end of each training iteration.
Definition: Solver.cs:134
static SGDSolver< T > Create(CudaDnn< T > cuda, Log log, ProjectEx p, CancelEvent evtCancel, AutoResetEvent evtForceSnapshot, AutoResetEvent evtForceTest, IXDatabaseBase db, IXPersist< T > persist, int nSolverCount=1, int nSolverRank=0, Net< T > shareNet=null, onGetWorkspace getws=null, onSetWorkspace setws=null)
Create a new Solver based on the project containing the SolverParameter.
Definition: Solver.cs:1889
EventHandler< SnapshotArgs > OnSnapshot
The OnSnapshot event fires when the Solver detects that a snapshot is needed.
Definition: Solver.cs:130
Net< T > net
Returns the main training Net.
Definition: Solver.cs:1229
bool Step(int nIters, TRAIN_STEP step=TRAIN_STEP.NONE, bool bZeroDiffs=true, bool bApplyUpdates=true, bool bDisableOutput=false, bool bDisableProgress=false, double? dfLossOverride=null, bool? bAllowSnapshot=null)
Steps a set of iterations through a training cycle.
Definition: Solver.cs:818
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
TRAIN_STEP
Defines the training stepping method (if any).
Definition: Interfaces.cs:131
The MyCaffe.data namespace contains dataset creators used to create common testing datasets such as M...
Definition: BinaryFile.cs:16
The MyCaffe.extras namespace contains classes that use the MyCaffe and other namespaces to add enhanc...
Definition: DeepDraw.cs:17
The MyCaffe.layers.nt namespace contains all Neural Transfer related layers.
Definition: LayerFactory.cs:19
The MyCaffe.layers namespace contains all layers that have a solidified code base,...
Definition: LayerFactory.cs:15
The MyCaffe.param.nt namespace defines the parameters used by the Nerual Style Transfer layers.
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe.solvers namespace contains all solver classes, including the base Solver.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12