private static string StringMap(Model.Input inp) { string s = ""; for (int i = 0; i < s.Length; i++) { s = s + s[i] + " "; } return(s); }
public void ModelBuilderTest() { TensorCachingAllocator tca = new TensorCachingAllocator(); ModelBuilder mb = new ModelBuilder(); Model.Input inputLayer = mb.Input("Input", new int[] { -1, 1, 1, 1 }); Layer prevLayer = null; prevLayer = mb.Dense(MultiLayerPerception.LayerNames.Hidden, inputLayer, tca.Alloc(new TensorShape(1, 1)), tca.Alloc(new TensorShape(1, 1))); prevLayer.weights[0] = 1; prevLayer.weights[1] = 1; Debug.Log(prevLayer.weights.Length + ": " + string.Join(",", prevLayer.weights)); for (int i = 0; i < prevLayer.datasets.Length; i++) { Debug.Log(prevLayer.datasets[i].name + ":" + prevLayer.datasets[i].offset); } prevLayer = mb.Identity("hiddenAct", prevLayer); Debug.Log(prevLayer.weights.Length + ": " + string.Join(",", prevLayer.weights)); prevLayer = mb.Dense("output", prevLayer, tca.Alloc(new TensorShape(1, 1)), tca.Alloc(new TensorShape(1, 1))); prevLayer.weights[0] = 3; prevLayer.weights[1] = 5; Debug.Log(prevLayer.weights.Length + ": " + string.Join(",", prevLayer.weights)); prevLayer = mb.Identity("outputActive", prevLayer); Debug.Log(prevLayer.weights.Length + ": " + string.Join(",", prevLayer.weights)); mb.Output(prevLayer); IWorker worker = WorkerFactory.CreateWorker(mb.model, WorkerFactory.Device.GPU); Tensor input = tca.Alloc(new TensorShape(4, 1, 1, 1)); for (int i = 0; i < 4; i++) { input[i] = i; } IWorker ex = worker.Execute(input); ex.FlushSchedule(true); Tensor output = ex.PeekOutput(); for (int i = 0; i < 4; i++) { Debug.Log($"output[{i}] = {output[i]}"); } tca.Dispose(); ex.Dispose(); worker.Dispose(); Debug.Assert(true); // Just getting here is good enough }
private void CreateBarracudaWorker() { int savedAlphaBetasIndex = 0; model = ModelLoader.Load(nnModel, verbose); layerNameToPatch = new List <string>(); List <Layer> layerList = new List <Layer>(model.layers); // Pre-process Network for run-time use Layer lastConv = null; for (int i = 0; i < layerList.Count; i++) { Layer layer = layerList[i]; // Remove Style_Prediction_Network: constant with style, executed once in Setup() if (layer.name.Contains("Style_Prediction_Network/")) { layerList.RemoveAt(i); i--; continue; } // Fix Upsample2D size parameters if (layer.type == Layer.Type.Upsample2D) { layer.pool = new[] { 2, 2 }; //ref model is supposed to be nearest sampling but bilinear scale better when network is applied at lower resoltions bool useBilinearUpsampling = internalSetup.forceBilinearUpsample2DInModel || (modelToUse != UsedModel.Reference); layer.axis = useBilinearUpsampling ? 1 : -1; } // Remove Mirror padding layers (not supported, TODO) if (layer.name.Contains("reflect_padding")) { layerList[i + 1].inputs = layer.inputs; layerList[i + 1].pad = layer.pad.ToArray(); layerList.RemoveAt(i); i--; } else if (layer.type == Layer.Type.Conv2D || layer.type == Layer.Type.Conv2DTrans) { lastConv = layer; } else if (layer.type == Layer.Type.Normalization) { // Manually set alpha/betas from Style_Prediction_Network as scale/bias tensors for InstanceNormalization if (layerList[i - 1].type == Layer.Type.StridedSlice) { int channels = predictionAlphasBetasData[savedAlphaBetasIndex].Length; layer.datasets = new Layer.DataSet[2]; layer.datasets[0].shape = new TensorShape(1, 1, 1, channels); layer.datasets[0].offset = 0; layer.datasets[0].length = channels; layer.datasets[1].shape = new TensorShape(1, 1, 1, channels); layer.datasets[1].offset = channels; layer.datasets[1].length = channels; layerNameToPatch.Add(layer.name); float[] data = new float[channels * 2]; for (int j = 0; j < data.Length / 2; j++) { data[j] = predictionAlphasBetasData[savedAlphaBetasIndex][j]; } for (int j = data.Length / 2; j < data.Length; j++) { data[j] = predictionAlphasBetasData[savedAlphaBetasIndex + 1][j - data.Length / 2]; } layer.weights = data; savedAlphaBetasIndex += 2; } // Else initialize scale/bias tensors of InstanceNormalization to default 1/0 else { int channels = lastConv.datasets[1].shape.channels; layer.datasets = new Layer.DataSet[2]; layer.datasets[0].shape = new TensorShape(1, 1, 1, channels); layer.datasets[0].offset = 0; layer.datasets[0].length = channels; layer.datasets[1].shape = new TensorShape(1, 1, 1, channels); layer.datasets[1].offset = channels; layer.datasets[1].length = channels; float[] data = new float[channels * 2]; for (int j = 0; j < data.Length / 2; j++) { data[j] = 1.0f; } for (int j = data.Length / 2; j < data.Length; j++) { data[j] = 0.0f; } layer.weights = data; } } } // Remove Slice layers originally used to get alpha/beta tensors into Style_Network for (int i = 0; i < layerList.Count; i++) { Layer layer = layerList[i]; if (layer.type == Layer.Type.StridedSlice) { layerList.RemoveAt(i); i--; } } // Fold Relu into instance normalisation Dictionary <string, string> reluToInstNorm = new Dictionary <string, string>(); for (int i = 0; i < layerList.Count; i++) { Layer layer = layerList[i]; if (layer.type == Layer.Type.Activation && layer.activation == Layer.Activation.Relu) { if (layerList[i - 1].type == Layer.Type.Normalization) { layerList[i - 1].activation = layer.activation; reluToInstNorm[layer.name] = layerList[i - 1].name; layerList.RemoveAt(i); i--; } } } for (int i = 0; i < layerList.Count; i++) { Layer layer = layerList[i]; for (int j = 0; j < layer.inputs.Length; j++) { if (reluToInstNorm.ContainsKey(layer.inputs[j])) { layer.inputs[j] = reluToInstNorm[layer.inputs[j]]; } } } // Feed first convolution directly with input (no need for normalisation from the model) string firstConvName = "StyleNetwork/conv1/convolution_conv1/convolution"; int firstConv = FindLayerIndexByName(layerList, firstConvName); layerList[firstConv].inputs = new[] { model.inputs[1].name }; if (modelToUse == UsedModel.Reference) { layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/add")); layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/add/y")); layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/normalized_contentFrames")); layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/normalized_contentFrames/y")); layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/sub")); layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/sub/y")); } if (modelToUse == UsedModel.RefBut32Channels) { layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalized_contentFrames")); layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalized_contentFrames/y")); } // Remove final model post processing, post process happen in tensor to texture instead int postAdd = FindLayerIndexByName(layerList, "StyleNetwork/clamp_0_255/add"); layerList.RemoveRange(postAdd, 5); // Correct wrong output layer list model.outputs = new List <string>() { layerList[postAdd - 1].name }; model.layers = layerList; Model.Input input = model.inputs[1]; input.shape[0] = 0; input.shape[1] = 1080;//TODO get framebuffer size rather than hardcoded value input.shape[2] = 1920; input.shape[3] = 3; model.inputs = new List <Model.Input> { model.inputs[1] }; //Create worker and execute it once at target resolution to prime all memory allocation (however in editor resolution can still change at runtime) worker = WorkerFactory.CreateWorker(WorkerFactory.ValidateType(internalSetup.workerType), model, verbose); Dictionary <string, Tensor> temp = new Dictionary <string, Tensor>(); var inputTensor = new Tensor(input.shape, input.name); temp.Add("frame", inputTensor); worker.Execute(temp); inputTensor.Dispose(); }