public static IEnumerable <INodeLink> MakeLink(this IEnumerable <INode> nodes, int width, int filterSize, int offsetX, int offsetY, Func <int, int, IWeight> getWeight) { var inputNodes = nodes.ToArray(); var height = inputNodes.Length / width; var bias = new NodeLink { InputNode = new ValueNode() { Value = 1 }, Weight = Weight.Make(DLF.GetRandomWeight()) }; var links = ( from y in Enumerable.Range(0, filterSize) from x in Enumerable.Range(0, filterSize) where (offsetX + x) < width where (offsetY + y) < height let nodeIndex = ((offsetY + y) * width) + offsetX + x let inputNode = inputNodes[nodeIndex] select new NodeLink { InputNode = inputNode, Weight = getWeight(x, y) }) .ToArray(); return (new[] { bias }.Concat(links).ToArray()); }
public ConvolutionLayer(ILayer before, ValueTuple <int, int, int> filter , Func <IEnumerable <double>, IEnumerable <double> > activation , Func <double, bool> ignoreUpdate = null) { (int filterSize, int stride, int filterCount) = filter; this.CalcFunction = DLF.CalcFunction; this.ActivationFunction = activation; this.UpdateWeightFunction = DLF.UpdateWeight(ignoreUpdate); int width, height, chSize = 0; if (before is I2DLayer dLayer) { width = dLayer.OutputWidth; height = dLayer.OutputHeight; chSize = dLayer.OutputCh; } else { width = before.Nodes.Count(); height = 1; chSize = 1; } var xSize = (int)Math.Ceiling((width - filterSize) / (double)stride); var ySize = (int)Math.Ceiling((height - filterSize) / (double)stride); this.OutputWidth = xSize; this.OutputHeight = ySize; this.OutputCh = filterCount; this.Nodes = ( from filterIndex in Enumerable.Range(0, filterCount) let weights = ( from fx in Enumerable.Range(0, filterSize) from fy in Enumerable.Range(0, filterSize) select Weight.Make(DLF.GetRandomWeight(), xSize * ySize * chSize)) .ToArray() from y in Enumerable.Range(0, height - filterSize).Where(i => i % stride == 0) from x in Enumerable.Range(0, width - filterSize).Where(i => i % stride == 0) let links = from channelOffset in Enumerable.Range(0, chSize) let lx = before.Nodes.MakeLink(width, filterSize, x, y + (channelOffset * height), (wx, wy) => weights[(wy * filterSize) + wx]).ToArray() select lx let node = new Node(ActivationFunction, links.SelectMany(l => l).ToArray()) select node).ToArray(); }