public static Tensor Expand(this Session session, Tensor x, int axis) { const string ActionName = "expand"; if (axis < 0) { throw new ArgumentException(Properties.Resources.E_NegativeAxisIndex, nameof(axis)); } return(session.RunOperation( ActionName, () => { bool calculateGradient = session.CalculateGradients && x.CalculateGradient; // allocate destination Tensor y = session.AllocateTensor(ActionName, x.Shape.InsertAxis(axis, 1), calculateGradient); // simply copy tensor content Vectors.Copy(x.Length, x.Weights, 0, y.Weights, 0); #if !NOLEARNING if (calculateGradient) { // simply copy tensor content session.Push(ActionName, () => x.AddGradient(y.Gradient)); } #endif return y; })); }
private static void Unstack(Tensor x, int axis, IList <Tensor> ys, bool useGradients) { int xlen = x.Length; int xdim = x.Axes[axis]; int xstride0 = x.Strides[axis]; // axis inner stride int xstride1 = axis == 0 ? xlen : x.Strides[axis - 1]; // axis outer stride float[] xw = useGradients ? x.Gradient : x.Weights; for (int i = 0, offx = 0; i < xdim; i++, offx += xstride0) { Tensor y = ys[i]; float[] yw = useGradients ? y.Gradient : y.Weights; for (int offxx = offx, offy = 0; offxx < xlen; offxx += xstride1, offy += xstride0) { if (useGradients) { Mathematics.Add(xstride0, xw, offxx, yw, offy); } else { Vectors.Copy(xstride0, xw, offxx, yw, offy); } } } }
private static void Split(Tensor x, int axis, IList <Tensor> ys, bool useGradients) { int xstride = axis == 0 ? x.Length : x.Strides[axis - 1]; int ydim = axis == 0 ? 1 : x.Length / xstride; float[] xw = useGradients ? x.Gradient : x.Weights; for (int i = 0, offx = 0, ii = ys.Count; i < ii; i++) { Tensor y = ys[i]; float[] yw = useGradients ? y.Gradient : y.Weights; int ystride = axis == 0 ? y.Length : y.Strides[axis - 1]; for (int n = 0, offxx = offx, offy = 0; n < ydim; n++, offxx += xstride, offy += ystride) { if (useGradients) { Mathematics.Add(ystride, xw, offxx, yw, offy); } else { Vectors.Copy(ystride, xw, offxx, yw, offy); } } offx += ystride; } }
public static Tensor Reshape(this Session session, Tensor x, Shape shape) { const string ActionName = "reshape"; // validate new shape if (shape.Length != x.Length) { throw new ArgumentException("The size of new shape must be the same as tensor length.", nameof(shape)); } return(session.RunOperation( ActionName, () => { bool calculateGradient = session.CalculateGradients && x.CalculateGradient; // allocate destination Tensor y = session.AllocateTensor(ActionName, shape, calculateGradient); // simply copy tensor content Vectors.Copy(x.Length, x.Weights, 0, y.Weights, 0); #if !NOLEARNING if (calculateGradient) { // simply copy tensor content session.Push(ActionName, () => x.AddGradient(y.Gradient)); } #endif return y; })); }
private static void CopyArea(Image dst, int xdst, int ydst, int width, int height, Image src, int xsrc, int ysrc) { ulong[] bitssrc = src.Bits; ulong[] bitsdst = dst.Bits; int stride1src = src.Stride1; int stride1dst = dst.Stride1; int offsrc = (ysrc * stride1src) + (xsrc * src.BitsPerPixel); int offdst = (ydst * stride1dst) + (xdst * src.BitsPerPixel); int count = width * src.BitsPerPixel; if (stride1src == stride1dst && xsrc == 0 && xdst == 0 && width == src.Width) { Vectors.Copy(height * src.Stride, bitssrc, ysrc * src.Stride, bitsdst, ydst * dst.Stride); } else { for (int i = 0; i < height; i++, offsrc += stride1src, offdst += stride1dst) { BitUtils.CopyBits(count, bitssrc, offsrc, bitsdst, offdst); } } }
/// <summary> /// Performs initial cluster seeding according to K-Means++ algorithm. /// </summary> /// <param name="x">The data points <paramref name="x"/> to clusterize.</param> /// <param name="weights">The <c>weight</c> of importance for each data point.</param> /// <param name="cancellationToken">The cancellationToken token used to notify the clusterizer that the operation should be canceled.</param> /// <see href="https://en.wikipedia.org/wiki/K-means++"/> internal void KMeansPlusPlusSeeding(IList <IVector <float> > x, IList <float> weights, CancellationToken cancellationToken) { Random random = new Random(0); int k = this.Count; int dimension = this.Dimension; int samples = x.Count; // 1. Choose one center uniformly at random from among the data points. int idx = random.Next(0, samples); x[idx].Copy(this[0].Centroid, 0); float[] distances = new float[samples]; for (int centroid = 1; centroid < k; centroid++) { cancellationToken.ThrowIfCancellationRequested(); // 2. For each data point x, compute D(x), the distance between x and the nearest center that has already been chosen. this.Assign(0, centroid, x, distances, cancellationToken); // 3. Choose one new data point at random as a new center, // using a weighted probability distribution where a point x is chosen with probability proportional to D(x)^2. Vectors.Square(samples, distances, 0); float sum = Vectors.Sum(samples, distances, 0); if (sum < 1e-10f) { // all points are the same for (; centroid < k; centroid++) { Vectors.Copy(dimension, this[0].Centroid, 0, this[centroid].Centroid, 0); } } else { // Choose a point from a weighted probability distribution float randomValue = (float)random.NextDouble() * sum; idx = -1; sum = 0.0f; for (int i = 0; i < samples; i++) { sum += distances[i]; if (randomValue < sum) { idx = i; break; } } if (idx == -1) { idx = random.Next(0, samples); } x[idx].Copy(this[centroid].Centroid, 0); } // 4. Repeat Steps 2 and 3 until k centers have been chosen. } }
private int TryFall(Vector3i _blockPos, BlockValue _blockValue) { int k = 0; Vector3i pos = Vectors.Copy(_blockPos); int y0 = pos.y; for (k = 1; k <= gravity; k++) { pos.y = y0 - k; BlockValue below = GameManager.Instance.World.GetBlock(pos); if (below.Equals(BlockValue.Air) || IsEmpty(below.Block)) { } else { k = k - 1; break; } } pos.y = y0 - k; // There was a gap and < len : insert at new pos if (k > 0 && k < gravity) { GameManager.Instance.World.SetBlockRPC(pos, _blockValue); } // There was a gap : delete initial if (k > 0) { GameManager.Instance.World.SetBlockRPC(_blockPos, BlockValue.Air); } return(k); // -> true if if it felt // int mdom = _myBlockValue.damage; // this.DamageBlock(GameManager.Instance.World, 0, _myBlockPos, _myBlockValue, 10, -1, false, false); }
private static void Stack(IList <Tensor> xs, int axis, Tensor y, bool useGradients) { int xdim = xs.Count; int ylen = y.Length; int ystride = y.Strides[axis]; float[] yw = useGradients ? y.Gradient : y.Weights; for (int offx = 0, offy = 0; offy < ylen; offx += ystride) { for (int i = 0; i < xdim; i++, offy += ystride) { Tensor x = xs[i]; float[] xw = useGradients ? x.Gradient : x.Weights; if (useGradients) { Mathematics.Add(ystride, xw, offx, yw, offy); } else { Vectors.Copy(ystride, xw, offx, yw, offy); } } } }
/// <summary> /// Reduces the height of the <see cref="Image"/> by the factor of 2. /// </summary> /// <returns>The scaled <see cref="Image"/>.</returns> public Image Reduce1x2() { if (this.BitsPerPixel != 1) { throw new NotSupportedException(Properties.Resources.E_UnsupportedDepth_1bpp); } Image dst = new Image( this.Width, (this.Height + 1) >> 1, this.BitsPerPixel, this.HorizontalResolution, this.VerticalResolution / 2); int stride = this.Stride; ulong[] bitssrc = this.Bits; ulong[] bitsdst = dst.Bits; int offsrc = 0; int offdst = 0; for (int i = 0, ii = this.Height >> 1; i < ii; i++, offsrc += 2 * stride, offdst += stride) { Vectors.Or(stride, bitssrc, offsrc, bitssrc, offsrc + stride, bitsdst, offdst); } if ((this.Height & 1) != 0) { Vectors.Copy(stride, bitssrc, offsrc, bitsdst, offdst); } dst.AppendTransform(new MatrixTransform(1.0, 0.5)); return(dst); }
public static Bounds BoundToPosition(Vector3 pos, Bounds bounds) { Vector3 bcenter = Vectors.Copy(bounds.center); Vector3 bsize = Vectors.Copy(bounds.size); bcenter.y = pos.y; bsize.y = 30; return(new Bounds(bcenter, bsize)); // take size, not ray }
/// <summary> /// Creates a new <see cref="Image"/> that is a copy of the current instance. /// </summary> /// <param name="copyBits">The value indicating whether the <see cref="Image{T}.Bits"/> should be copied to the new <see cref="Image"/>.</param> /// <returns> /// A new object that is a copy of this instance. /// </returns> public Image Clone(bool copyBits) { Image dst = new Image(this.Width, this.Height, this); if (copyBits) { Vectors.Copy(this.Bits.Length, this.Bits, 0, dst.Bits, 0); } return(dst); }
public void Set(int[] classes, int length, int hash, float probBlank, float probNoBlank, State state) { Vectors.Copy(length, classes, 0, this.Classes, 0); this.Length = length; this.Hash = hash; this.ProbBlank = probBlank; this.ProbNoBlank = probNoBlank; this.Prob = Mathematics.LogSumExp(probBlank, probNoBlank); this.State = state; }
/// <inheritdoc /> public float Loss(Tensor y, Tensor expected, bool calculateGradient) { if (y == null) { throw new ArgumentNullException(nameof(y)); } if (expected == null) { throw new ArgumentNullException(nameof(expected)); } if (expected.Length != y.Length) { throw new ArgumentException(string.Format( CultureInfo.CurrentCulture, "The number of expected labels: {0} does not match the tensor length: {1}.", expected.Length, y.Length)); } float[] yw = y.Weights; float[] ew = expected.Weights; if (calculateGradient) { Vectors.Copy(expected.Length, ew, 0, y.Gradient, 0); } if (y.Shape.Rank == 1) { return(Calculate(expected.Length, 0, 0)); } else { int mb = y.Shape.Axes[0]; // number of items in a mini-batch int mbsize = y.Shape.Strides[0]; // item size float loss = 0.0f; for (int i = 0, yi = 0, ei = 0; i < mb; i++, yi += mbsize, ei += mbsize) { loss += Calculate(mbsize, yi, ei); } return(loss / mb); } float Calculate(int length, int offy, int offe) { return(Vectors.EuclideanDistance(length, yw, offy, ew, offe) / length); } }
public void ShlTest() { const int RepeatCount = 5; UlongRandomGenerator random = new UlongRandomGenerator(); ulong[] y = new ulong[3]; ulong[] copy = new ulong[3]; int size = y.Length * 64; for (int count = 0; count <= size; count++) { for (int pos = 0; pos < size - count; pos++) { for (int shift = 0; shift <= count; shift++) { for (int i = 0; i < RepeatCount; i++) { random.Generate(y.Length, y); Vectors.Copy(y.Length, y, 0, copy, 0); BitUtils.Shl(count, shift, y, pos); // right part that was not copied if (pos > 0) { Assert.IsTrue(BitUtils.Equals(pos, y, 0, copy, 0)); } // shifted part if (shift < count) { Assert.IsTrue(BitUtils.Equals(count - shift, y, pos + shift, copy, pos)); } // zeroed part if (shift > 0) { Assert.AreEqual(0, BitUtils.CountOneBits(shift, y, pos)); } // left part that was not copied if (pos + count < size) { Assert.IsTrue(BitUtils.Equals(size - (pos + count), y, pos + count, copy, pos + count)); } } } } } }
/// <summary> /// Computes output of the network. /// </summary> /// <param name="x">The input tensor.</param> /// <returns> /// The object that contains the computed results and tensor. /// </returns> public (IList <IList <(string Answer, float Probability)> > Answers, Tensor Y) Execute(Tensor x) { const float MaxConfidenceDistance = 0.5f; Tensor y = this.Forward(null, x); float[] yw = y.Weights; int mb = y.Rank == 1 ? 1 : y.Axes[0]; int numAnswers = y.Rank == 1 ? y.Length : y.Strides[0]; List <IList <(string, float)> > answers = new List <IList <(string, float)> >(mb); float[] ywmb = new float[numAnswers]; int[] ywidx = new int[numAnswers]; for (int i = 0, offy = 0; i < mb; i++, offy += numAnswers) { // copy weights into temporary buffer and sort along with their indexes Vectors.Copy(numAnswers, yw, offy, ywmb, 0); for (int j = 0; j < numAnswers; j++) { ywidx[j] = j; } Vectors.Sort(numAnswers, ywmb, 0, ywidx, 0, false); // create answer for a mini-batch item List <(string, float)> mbanswers = new List <(string, float)>(numAnswers); float probThreshold = MinMax.Max(ywmb[0] - MaxConfidenceDistance, 0.0f); for (int j = 0; j < numAnswers; j++) { float prob = ywmb[j]; if (prob <= probThreshold) { break; } int idx = ywidx[j]; string cls = this.classes[idx]; mbanswers.Add((cls, prob)); } answers.Add(mbanswers); } return(answers, y); }
/* * * Options: * - ground (water, traps) * - recursion * - size / depth (puis avant) * - other content : Z, animal, torch, lights ... * */ public static IEnumerator Rift(EntityPlayer player, Emplacement place, OptionEffect options) { /* * Laisse des blocks tomber au dessus ? just changed erase="yes" * (longueur 1, hauteur (profonfeur), replicats) */ EntityPlayerLocal epl = player as EntityPlayerLocal; epl.cameraTransform.SendMessage("ShakeBig"); yield return(new WaitForSeconds(1f)); BlockSetter setter = new BlockSetter(options.OptionBlock); Vector3 direction = Vectors.Copy(place.direction); direction.y = 0; direction = direction.normalized; Vector3i start = Geo3D.Surface(place.ipos); for (int k = 0; k < options.OptionShape.shape.z; k++) { Vector3 kdirection = direction + Vectors.Float.Randomize(GameManager.Instance.World.GetGameRandom(), 0.2f); // IntLine traj = new IntLine(start, direction); //east IEnumerable <Vector3i> segment = IntLine.Segment(Vectors.ToFloat(start), kdirection, 0, options.OptionShape.shape.x); Vector3i prev = new Vector3i(); bool hasprev = false; foreach (Vector3i where in segment) { Vector3i Swhere = Geo3D.Surface(where); setter.Apply(Swhere); if (hasprev) { for (int creuse = 1; creuse < options.OptionShape.shape.y; creuse++) { setter.Apply(prev + creuse * Vectors.Down); } } setter.Push(); start = Swhere; yield return(new WaitForEndOfFrame()); hasprev = true; prev = Swhere; } yield return(new WaitForSeconds(1f)); } }
/// <summary> /// Creates a scan line filled with pixels of the specified color. /// </summary> /// <param name="length">The scan line length.</param> /// <param name="color">The color to fill the scan line.</param> /// <returns>The array that contains the created scan line.</returns> private ulong[] ColorScanline(int length, uint color) { // fill one line with specified color uint maxcolor = this.MaxColor; color &= maxcolor; ulong[] buf = new ulong[length]; if (color == maxcolor) { Vectors.Set(length, ulong.MaxValue, buf, 0); } else if (color != 0) { if (this.BitsPerPixel == 24) { ulong ucolor = (ulong)color | ((ulong)color << 24); buf[0] = ucolor | (ucolor << 48); if (length > 1) { buf[1] = ((ucolor >> 16) & 0x0000_0000_ffff_fffful) | (ucolor << 32); } if (length > 2) { buf[2] = ((ucolor >> 32) & 0x0000_0000_0000_fffful) | (ucolor << 16); } if (length > 3) { for (int yoff = 3, count = 3; yoff < length; count *= 2) { Vectors.Copy(Math.Min(count, length - yoff), buf, 0, buf, yoff); yoff += count; } } } else { // create 64-bit value with each position filled with given color Vectors.Set(length, this.ColorBits(color), buf, 0); } } return(buf); }
/// <summary> /// Reduces the height of the <see cref="Image"/> by the factor of 4. /// </summary> /// <returns>The scaled <see cref="Image"/>.</returns> public Image Reduce1x4() { if (this.BitsPerPixel != 1) { throw new NotSupportedException(Properties.Resources.E_UnsupportedDepth_1bpp); } Image dst = new Image( this.Width, (this.Height + 3) / 4, this.BitsPerPixel, this.HorizontalResolution, this.VerticalResolution / 4); int stride = this.Stride; ulong[] bitssrc = this.Bits; ulong[] bitsdst = dst.Bits; int offsrc = 0; int offdst = 0; for (int i = 0, ii = this.Height / 4; i < ii; i++, offsrc += 4 * stride, offdst += stride) { Vectors.Or(stride, bitssrc, offsrc, bitssrc, offsrc + stride, bitssrc, offsrc + (2 * stride), bitssrc, offsrc + (3 * stride), bitsdst, offdst); } switch (this.Height % 4) { case 1: Vectors.Copy(stride, bitssrc, offsrc, bitsdst, offdst); break; case 2: Vectors.Or(stride, bitssrc, offsrc, bitssrc, offsrc + stride, bitsdst, offdst); break; case 3: Vectors.Or(stride, bitssrc, offsrc, bitssrc, offsrc + stride, bitssrc, offsrc + (2 * stride), bitsdst, offdst); break; } dst.AppendTransform(new MatrixTransform(1.0, 0.25)); return(dst); }
public static IEnumerator Ensure() { /* Call this and wait for finish whenever prior to using the global ghost */ EntityPlayerLocal player = GameManager.Instance.World.GetLocalPlayers()[0]; Bounds area = BoundsUtils.BoundsForMinMax(-2, -1, -2, 2, 1, 2); while (true) { Vector3 ppos = Vectors.Copy(player.GetPosition()); area.center = ppos; // will be surfaced anyway pool.Update(area); // update in any case to invalidate if (pool.Entities[0] != null) { yield break; } yield return(Yield); } }
private IEnumerator _Search(EntityPlayer player, int cycle=1, int repeat=1) { // TODO: check player motion since last reset ! World World = GameManager.Instance.World; for (int k=0; k<cycle; k++) { yield return SearchYield; _ResetTooFar(player); for (int q=0; q<repeat; q++) { Searcher.Next(); if (! Searcher.ok) {Printer.Log(85, "Searcher not ok !", Searcher.x, Searcher.y); yield break;} BlockValue existing = World.GetBlock(Searcher.Position); if (existing.ischild) continue; // inserts a single will help ! if (Positions.Count >= maxSize) continue; if (Selector != null && !Selector(existing.Block)) continue; Vector3i pos = Vectors.Copy(Searcher.Position); Printer.Log(85, "Found decoration:", existing.Block, pos, existing); Positions.Enqueue(pos); } } }
public static Tensor Squeeze(this Session session, Tensor x, int axis) { const string ActionName = "squeeze"; if (axis < 0) { throw new ArgumentException(Properties.Resources.E_NegativeAxisIndex, nameof(axis)); } if (x.Rank < 2) { throw new ArgumentException("The tensor must have the rank of at least 2.", nameof(axis)); } if (x.Axes[axis] != 1) { throw new ArgumentException("The dimension to remove must be of size 1.", nameof(axis)); } return(session.RunOperation( ActionName, () => { bool calculateGradient = session.CalculateGradients && x.CalculateGradient; // allocate destination Tensor y = session.AllocateTensor(ActionName, x.Shape.RemoveAxis(axis), calculateGradient); // simply copy tensor content Vectors.Copy(x.Length, x.Weights, 0, y.Weights, 0); #if !NOLEARNING if (calculateGradient) { // simply copy tensors session.Push(ActionName, () => x.AddGradient(y.Gradient)); } #endif return y; })); }
/// <summary> /// Copies the data from this <see cref="Image"/> to destination <see cref="Image"/>. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="copyBits">The value indicating whether the <see cref="Image{T}.Bits"/> should be copied to the new <see cref="Image"/>.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> /// <remarks> /// <para>If <paramref name="dst"/> is <b>null</b> the method creates new destination <see cref="Image"/> with dimensions of this <see cref="Image"/>.</para> /// <para>If <paramref name="dst"/> equals this <see cref="Image"/>, the method returns this <see cref="Image"/>.</para> /// <para>Conversely, the <paramref name="dst"/> is reallocated to the dimensions of this <see cref="Image"/>.</para> /// </remarks> public Image Copy(Image dst, bool copyBits) { if (dst == this) { return(this); } else { // reallocate destination image dst = this.CreateTemplate(dst, this.BitsPerPixel); // copy bits if (copyBits) { Vectors.Copy(this.Bits.Length, this.Bits, 0, dst.Bits, 0); } return(dst); } }
/// <inheritdoc /> public void ComputeDeltas(int epoch, int length, float[] gradient, int totalSamples) { float learningRate = this.LearningRate; if (this.Decay != 0.0f && epoch > 0) { learningRate /= 1.0f + (this.Decay * epoch); } float momentum = this.Momentum; if (momentum > 0.0f) { // get accumulator float[] velocity = this.accumulators.GetAccumulator( gradient, () => new float[length]); if (this.Nesterov) { // apply Nesterov momentum // dx = velocity = momentum^2 * velocity - (1 + momentum) * learningRate * g Mathematics.MultiplyAndAdd(gradient.Length, momentum * momentum, velocity, 0, -(1.0f + momentum) * learningRate, gradient, 0); Vectors.Copy(gradient.Length, gradient, 0, velocity, 0); } else { // momentum update // dx = velocity = momentum * velocity - learningRate * g Mathematics.MultiplyAndAdd(gradient.Length, momentum, velocity, 0, -learningRate, gradient, 0); Vectors.Copy(gradient.Length, gradient, 0, velocity, 0); } } else { // vanilla sgd // dx = -learningRate * g Mathematics.MulC(gradient.Length, -learningRate, gradient, 0); } }
/// <summary> /// Packs a collection of dense vectors. /// </summary> /// <param name="vectors">The dense vectors to pack.</param> /// <returns> /// The <see cref="DenseVectorPackF"/> object that contains packed dense vectors. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="vectors"/> is <b>null</b>. /// </exception> public static DenseVectorPackF Pack(IList <IDenseVector <float> > vectors) { if (vectors == null) { throw new ArgumentNullException(nameof(vectors)); } if (vectors.Count == 0) { return(new DenseVectorPackF()); } DenseVectorPackF result = new DenseVectorPackF(vectors.Count, vectors[0].Length); float[] x = result.X; for (int i = 0, ii = result.Count, len = result.Length, off = 0; i < ii; i++, off += len) { Vectors.Copy(len, vectors[i].X, vectors[i].Offset, x, off); } return(result); }
public static Tensor[] Repeat(this Session session, Tensor x, int count) { const string ActionName = "repeat"; return(session.RunOperation( ActionName, () => { bool calculateGradient = session.CalculateGradients && x.CalculateGradient; Tensor[] ys = session.AllocateTensors(ActionName, count, x.Shape, calculateGradient); for (int i = 0; i < count; i++) { Vectors.Copy(x.Length, x.Weights, 0, ys[i].Weights, 0); } #if !NOLEARNING if (calculateGradient) { session.Push( ActionName, () => { float alpha = 1.0f / count; for (int i = 0; i < count; i++) { Mathematics.AddProductC(x.Length, ys[i].Gradient, 0, alpha, x.Gradient, 0); } }); // return copy of the array; calling method can replace its content; our closure keeps the array, not its items return ys.ToArray(); } #endif return ys; })); }
private static void Untile(Tensor x, int axis, int count, Tensor y, bool useGradients) { int ylen = y.Length; int ystride = axis == 0 ? ylen : y.Strides[axis - 1]; float[] xw = useGradients ? x.Gradient : x.Weights; float[] yw = useGradients ? y.Gradient : y.Weights; for (int offx = 0, offy = 0; offy < ylen; offy += ystride) { for (int i = 0; i < count; i++, offx += ystride) { if (useGradients || i > 0) { Mathematics.Add(ystride, xw, offx, yw, offy); } else { Vectors.Copy(ystride, xw, offx, yw, offy); } } } }
public static Tensor Copy(this Session session, Tensor x) { const string ActionName = "copy"; return(session.RunOperation( ActionName, () => { bool calculateGradient = session.CalculateGradients && x.CalculateGradient; Tensor y = session.AllocateTensor(ActionName, x.Shape, calculateGradient); Vectors.Copy(x.Length, x.Weights, 0, y.Weights, 0); #if !NOLEARNING if (calculateGradient) { session.Push(ActionName, () => x.AddGradient(y.Gradient)); } #endif return y; })); }
/// <summary> /// Calculates the histogram of oriented gradients (HOG) on the <see cref="Image"/>. /// </summary> /// <param name="cellSize">The cell size, in pixels.</param> /// <param name="blockSize">The block size, in number of <paramref name="cellSize"/>.</param> /// <param name="blockStride">The block stride size, in number of <paramref name="cellSize"/>.</param> /// <param name="numberOfBins">The number of bins (orientations) in the histogram.</param> /// <param name="threshold"> /// The threshold value to apply after normalization. /// Bins that are less than the threshold, are set to zero. /// </param> /// <returns> /// The <see cref="DenseVectorPackF"/> that contains packed points of interest. /// </returns> /// <exception cref="NotSupportedException"> /// The <see cref="Image{T}.BitsPerPixel"/> is not 1, 8, 24, or 32. /// </exception> public DenseVectorPackF HOG( int cellSize, int blockSize, int blockStride, int numberOfBins, float threshold) { // convert image to float ImageF srcf = PrepareImage(); int width = srcf.Width; int height = srcf.Height; int stride = srcf.Stride; float[] bits = srcf.Bits; /*if (NativeMethods.hog( * srcf.BitsPerPixel, * srcf.Width, * srcf.Height, * srcf.Stride, * srcf.Bits) != 0) * { * throw new OutOfMemoryException(); * }*/ // calculate gradient vectors magnitude and direction using Prewitt operator (-1 0 1) float[] mag = new float[bits.Length]; float[] ang = new float[bits.Length]; NativeMethods.gradientVectorPrewitt_f32(width, height, bits, stride, mag, stride, ang, stride); // convert angles to bins Mathematics.DivC(ang.Length, (float)(Math.PI / numberOfBins), ang, 0); Vectors.Abs(ang.Length, ang, 0); // calculate histograms int cellCountX = width / cellSize; int cellCountY = height / cellSize; int blockCountX = ComputeBlockCount(cellCountX); int blockCountY = ComputeBlockCount(cellCountY); int blockCount = blockCountX * blockCountY; int blockSizeInBins = blockSize * blockSize * numberOfBins; float[] blocks = new float[blockCount * blockSizeInBins]; int offblock = 0; // running block offset // to save memory we allocate histograms needed for one row of blocks only // when we move throw the rows, the first histogram (not needed anymore) becomes last (working) List <float[]> hist = CreateRotatingHist(); for (int iy = 0, offy = 0; iy < cellCountY; iy++, offy += stride * cellSize) { float[] h = hist[Core.MinMax.Min(iy, blockSize - 1)]; ComputeHistLine(offy, h); if (iy + 1 >= blockSize) { // calculate blocks - we are at the last block line if (((iy + 1 - blockSize) % blockStride) == 0) { ComputeBlockLine(); } // rotate histograms if (blockSize > 1 && iy + 1 < cellCountY) { RotateHist(hist); } } } Debug.Assert(offblock == blocks.Length, "We must have processed all blocks by now."); // normalize blocks const float Eps = 1e-10f; for (int i = 0, off = 0; i < blockCount; i++, off += blockSizeInBins) { float norm = Vectors.L2Norm(blockSizeInBins, blocks, off); Mathematics.DivC(blockSizeInBins, norm + Eps, blocks, off); } // apply threshold if (threshold > 0.0f) { Vectors.ThresholdLT(blocks.Length, threshold, 0.0f, blocks, 0); } /*DenseVectorProxyF[] dense = new DenseVectorProxyF[blockCount]; * for (int i = 0, off = 0; i < blockCount; i++, off += blockSizeInBins) * { * dense[i] = new DenseVectorProxyF(blockSizeInBins, blocks, off); * }*/ /*SparseVectorF[] sparse = new SparseVectorF[blockCount]; * for (int i = 0; i < blockCount; i++) * { * sparse[i] = SparseVectorF.FromDense(blockSizeInBins, vectors[i].X, 0); * }*/ return(new DenseVectorPackF(blockCount, blockSizeInBins, blocks)); ImageF PrepareImage() { // convert image to 8bpp, then float return(this .ConvertTo(null, 8) .Convert8To32f( ComputeImageSize(this.Width), ComputeImageSize(this.Height), BorderType.BorderRepl, 0)); int ComputeImageSize(int size) { int kernelSize = cellSize * blockSize; int kernelStride = cellSize * blockStride; return(Core.MinMax.Max(size - kernelSize, 0).RoundUp(kernelStride) + kernelSize); } } int ComputeBlockCount(int cellCount) { return((Core.MinMax.Max(cellCount - blockSize, 0) / blockStride) + 1); } List <float[]> CreateRotatingHist() { List <float[]> h = new List <float[]>(blockSize); for (int i = 0; i < blockSize; i++) { h.Add(new float[cellCountX * numberOfBins]); } return(h); } void RotateHist(List <float[]> h) { float[] temp = h[0]; h.RemoveAt(0); h.Add(temp); Vectors.Set(temp.Length, 0, temp, 0); } void ComputeHistLine(int offy, float[] h) { for (int ix = 0, offx = offy, offh = 0; ix < cellCountX; ix++, offx += cellSize, offh += numberOfBins) { for (int iyc = 0, offyc = offx; iyc < cellSize; iyc++, offyc += stride) { for (int ixc = 0, offxc = offyc; ixc < cellSize; ixc++, offxc++) { float value = mag[offxc]; if (value != 0.0f) { ////int bin = (int)ang[offxc] % numberOfBins; ////h[offh + bin] += mag[offxc]; float angle = ang[offxc]; int bin = (int)angle; float value1 = value * (angle - bin); h[offh + (bin % numberOfBins)] += value1; h[offh + ((bin + 1) % numberOfBins)] += value - value1; } } } } } void ComputeBlockLine() { int blockLengthInBins = blockSize * numberOfBins; int blockStrideInBins = blockStride * numberOfBins; for (int ix = 0, offh = 0; ix < blockCountX; ix++, offh += blockStrideInBins) { for (int iyc = 0; iyc < blockSize; iyc++) { Vectors.Copy(blockLengthInBins, hist[iyc], offh, blocks, offblock); offblock += blockLengthInBins; } } } }
public bool Optimize( int numberOfVariables, float[] c, float[] p, int[] y, Func <int, int[], int, float[], float[]> q, out float[] solution, out float rho) { // make copies, these array will be modified p = p.ToArray(); y = y.ToArray(); float[] temp = new float[numberOfVariables]; float[] g = new float[numberOfVariables]; // gradient float[] gbar = new float[numberOfVariables]; // gradient, if we treat free variables as 0 float[] qd = new float[numberOfVariables]; for (int k = 0; k < qd.Length; k++) { qd[k] = q(k, new[] { k }, 1, temp)[0]; } float[] qi = new float[numberOfVariables]; float[] qj = new float[numberOfVariables]; bool unshrink = false; // Lagrange multipliers float[] alpha = new float[numberOfVariables]; // initialize alpha_status Status[] alphaStatus = new Status[numberOfVariables]; for (int i = 0; i < numberOfVariables; i++) { UpdateAlphaStatus(i); } // initialize active set (for shrinking) int activeSize = numberOfVariables; int[] activeSet = Arrays.Indexes(numberOfVariables); // initialize index lookup vector int[] indices = Arrays.Indexes(numberOfVariables); // initialize gradient Vectors.Copy(numberOfVariables, p, 0, g, 0); Vectors.Set(numberOfVariables, 0.0f, gbar, 0); /*for (int i = 0; i < numberOfVariables; i++) * { * g[i] = p[i]; * gbar[i] = 0; * }*/ for (int i = 0; i < numberOfVariables; i++) { if (!IsLowerBound(i)) { q(i, indices, numberOfVariables, qi); Mathematics.AddProductC(numberOfVariables, qi, 0, alpha[i], g, 0); /*float alpha_i = alpha[i]; * for (int j = 0; j < numberOfVariables; j++) * { * g[j] += alpha_i * qi[j]; * }*/ if (IsUpperBound(i)) { Mathematics.AddProductC(numberOfVariables, qi, 0, c[i], gbar, 0); /*for (int j = 0; j < numberOfVariables; j++) * { * gbar[j] += c[i] * qi[j]; * }*/ } } } // optimization step int iter = 0; int max_iter = MinMax.Max(10000000, numberOfVariables > int.MaxValue / 100 ? int.MaxValue : 100 * numberOfVariables); int counter = MinMax.Min(numberOfVariables, 1000) + 1; while (iter < max_iter) { // show progress and do shrinking if (--counter == 0) { counter = MinMax.Min(numberOfVariables, 1000); if (this.Shrinking) { Shrink(); } Trace.WriteLine("."); } if (SelectWorkingSet(out int i, out int j) != 0) { // reconstruct the whole gradient ReconstructGradient(); // reset active set size and check activeSize = numberOfVariables; Trace.WriteLine("*"); if (SelectWorkingSet(out i, out j) != 0) { break; } else { counter = 1; // do shrinking next iteration } } iter++; // update alpha[i] and alpha[j], handle bounds carefully q(i, indices, activeSize, qi); q(j, indices, activeSize, qj); float ci = c[i]; float cj = c[j]; float old_alpha_i = alpha[i]; float old_alpha_j = alpha[j]; if (y[i] != y[j]) { float quad_coef = qd[i] + qd[j] + (2.0f * qi[j]); if (quad_coef <= 0) { quad_coef = TAU; } float delta = (-g[i] - g[j]) / quad_coef; float diff = alpha[i] - alpha[j]; alpha[i] += delta; alpha[j] += delta; if (diff > 0) { if (alpha[j] < 0) { alpha[j] = 0; alpha[i] = diff; } } else { if (alpha[i] < 0) { alpha[i] = 0; alpha[j] = -diff; } } if (diff > ci - cj) { if (alpha[i] > ci) { alpha[i] = ci; alpha[j] = ci - diff; } } else { if (alpha[j] > cj) { alpha[j] = cj; alpha[i] = cj + diff; } } } else { float quad_coef = qd[i] + qd[j] - (2.0f * qi[j]); if (quad_coef <= 0) { quad_coef = TAU; } float delta = (g[i] - g[j]) / quad_coef; float sum = alpha[i] + alpha[j]; alpha[i] -= delta; alpha[j] += delta; if (sum > ci) { if (alpha[i] > ci) { alpha[i] = ci; alpha[j] = sum - ci; } } else { if (alpha[j] < 0) { alpha[j] = 0; alpha[i] = sum; } } if (sum > cj) { if (alpha[j] > cj) { alpha[j] = cj; alpha[i] = sum - cj; } } else { if (alpha[i] < 0) { alpha[i] = 0; alpha[j] = sum; } } } // update G float delta_alpha_i = alpha[i] - old_alpha_i; float delta_alpha_j = alpha[j] - old_alpha_j; for (int k = 0; k < activeSize; k++) { g[k] += (qi[k] * delta_alpha_i) + (qj[k] * delta_alpha_j); } // update alpha_status and G_bar { bool ui = IsUpperBound(i); bool uj = IsUpperBound(j); UpdateAlphaStatus(i); UpdateAlphaStatus(j); if (ui != IsUpperBound(i)) { q(i, indices, numberOfVariables, qi); Mathematics.AddProductC(numberOfVariables, qi, 0, ui ? -ci : ci, gbar, 0); /*if (ui) * { * for (int k = 0; k < numberOfVariables; k++) * { * gbar[k] -= ci * qi[k]; * } * } * else * { * for (int k = 0; k < numberOfVariables; k++) * { * gbar[k] += ci * qi[k]; * } * }*/ } if (uj != IsUpperBound(j)) { q(j, indices, numberOfVariables, qj); Mathematics.AddProductC(numberOfVariables, qj, 0, uj ? -cj : cj, gbar, 0); /*if (uj) * { * for (int k = 0; k < numberOfVariables; k++) * { * gbar[k] -= cj * qj[k]; * } * } * else * { * for (int k = 0; k < numberOfVariables; k++) * { * gbar[k] += cj * qj[k]; * } * }*/ } } } if (iter >= max_iter) { if (activeSize < numberOfVariables) { // reconstruct the whole gradient to calculate objective value ReconstructGradient(); activeSize = numberOfVariables; Trace.WriteLine("*"); } Trace.WriteLine("WARNING: reaching max number of iterations."); } // calculate rho rho = CalculateRho(); // calculate objective value /*float v = 0; * for (int i = 0; i < numberOfVariables; i++) * { * v += alpha[i] * (g[i] + p[i]); * } * * si->obj = v / 2;*/ // put back the solution solution = new float[numberOfVariables]; for (int i = 0; i < numberOfVariables; i++) { solution[activeSet[i]] = alpha[i]; } ////si->upper_bound_p = Cp; ////si->upper_bound_n = Cn; Trace.WriteLine(string.Format( CultureInfo.InvariantCulture, "optimization finished, #iter = {0}", iter)); return(iter < max_iter); // return 1 if already optimal, return 0 otherwise int SelectWorkingSet(out int out_i, out int out_j) { // return i,j such that // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha) // j: minimizes the decrease of obj value // (if quadratic coefficient <= 0, replace it with tau) // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha) float gmax = float.NegativeInfinity; float gmax2 = float.NegativeInfinity; int gmax_idx = -1; int gmin_idx = -1; float obj_diff_min = float.PositiveInfinity; for (int t = 0; t < activeSize; t++) { if (y[t] == +1) { if (!IsUpperBound(t)) { if (-g[t] >= gmax) { gmax = -g[t]; gmax_idx = t; } } } else { if (!IsLowerBound(t)) { if (g[t] >= gmax) { gmax = g[t]; gmax_idx = t; } } } } int i = gmax_idx; if (i != -1) { q(i, indices, activeSize, temp); // NULL Q_i not accessed: Gmax=-INF if i=-1 } for (int j = 0; j < activeSize; j++) { if (y[j] == +1) { if (!IsLowerBound(j)) { float grad_diff = gmax + g[j]; if (g[j] >= gmax2) { gmax2 = g[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = qd[i] + qd[j] - (2.0f * y[i] * temp[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = -(grad_diff * grad_diff) / TAU; } if (obj_diff <= obj_diff_min) { gmin_idx = j; obj_diff_min = obj_diff; } } } } else { if (!IsUpperBound(j)) { float grad_diff = gmax - g[j]; if (-g[j] >= gmax2) { gmax2 = -g[j]; } if (grad_diff > 0) { float obj_diff; float quad_coef = qd[i] + qd[j] + (2.0f * y[i] * temp[j]); if (quad_coef > 0) { obj_diff = -(grad_diff * grad_diff) / quad_coef; } else { obj_diff = -(grad_diff * grad_diff) / TAU; } if (obj_diff <= obj_diff_min) { gmin_idx = j; obj_diff_min = obj_diff; } } } } } if (gmax + gmax2 < this.Tolerance) { out_i = 0; out_j = 0; return(1); } out_i = gmax_idx; out_j = gmin_idx; return(0); } void Shrink() { float gmax1 = float.NegativeInfinity; // max { -y_i * grad(f)_i | i in I_up(\alpha) } float gmax2 = float.NegativeInfinity; // max { y_i * grad(f)_i | i in I_low(\alpha) } // find maximal violating pair first for (int i = 0; i < activeSize; i++) { if (y[i] == 1) { if (!IsUpperBound(i)) { if (-g[i] >= gmax1) { gmax1 = -g[i]; } } if (!IsLowerBound(i)) { if (g[i] >= gmax2) { gmax2 = g[i]; } } } else { if (!IsUpperBound(i)) { if (-g[i] >= gmax2) { gmax2 = -g[i]; } } if (!IsLowerBound(i)) { if (g[i] >= gmax1) { gmax1 = g[i]; } } } } if (!unshrink && gmax1 + gmax2 <= this.Tolerance * 10) { unshrink = true; ReconstructGradient(); activeSize = numberOfVariables; Trace.WriteLine("*"); } for (int i = 0; i < activeSize; i++) { if (IsShrunk(i, gmax1, gmax2)) { activeSize--; while (activeSize > i) { if (!IsShrunk(activeSize, gmax1, gmax2)) { SwapIndex(i, activeSize); break; } activeSize--; } } } } void ReconstructGradient() { // reconstruct inactive elements of G from G_bar and free variables if (activeSize == numberOfVariables) { return; } Mathematics.Add( numberOfVariables - activeSize, gbar, activeSize, p, activeSize, g, activeSize); /*for (int j = activeSize; j < numberOfVariables; j++) * { * g[j] = gbar[j] + p[j]; * }*/ int freeCount = 0; for (int j = 0; j < activeSize; j++) { if (IsFree(j)) { freeCount++; } } if (2 * freeCount < activeSize) { Trace.WriteLine("WARNING: using -h 0 may be faster"); } if (freeCount * numberOfVariables > 2 * activeSize * (numberOfVariables - activeSize)) { for (int i = activeSize; i < numberOfVariables; i++) { q(indices[i], indices, activeSize, temp); for (int j = 0; j < activeSize; j++) { if (IsFree(j)) { g[i] += alpha[j] * temp[j]; } } } } else { for (int i = 0; i < activeSize; i++) { if (IsFree(i)) { q(indices[i], indices, numberOfVariables, temp); Mathematics.AddProductC( numberOfVariables - activeSize, temp, activeSize, alpha[i], g, activeSize); /*float alpha_i = alpha[i]; * for (int j = activeSize; j < numberOfVariables; j++) * { * g[j] += alpha_i * temp[j]; * }*/ } } } } void SwapIndex(int i, int j) { Swap(indices); Swap(y); Swap(g); Swap(alphaStatus); Swap(alpha); Swap(p); Swap(activeSet); Swap(gbar); void Swap <T>(T[] array) { T t = array[i]; array[i] = array[j]; array[j] = t; } }
public void DrawRectangle(int x, int y, int width, int height, uint color) { this.ValidateArea(x, y, width, height); if (width == 0 || height == 0) { // nothing to draw return; } ulong[] bits = this.Bits; int bitsPerPixel = this.BitsPerPixel; if (bitsPerPixel == 24) { ulong[] colors = this.ColorScanline(Image.CalculateStride(width, 24), color); int stride8 = this.Stride8; unsafe { fixed(ulong *ubits = &bits[y * this.Stride], ucolors = colors) { byte *ptrcolors = (byte *)ucolors; byte *ptrbits = (byte *)ubits + (x * 3); // draw top Vectors.Copy(width * 3, ptrcolors, ptrbits); ptrbits += stride8; // draw left and right for (int i = 1, ii = height - 1; i < ii; i++, ptrbits += stride8) { Vectors.Copy(3, ptrcolors, ptrbits); Vectors.Copy(3, ptrcolors, ptrbits + (width * 3)); } // draw bottom Vectors.Copy(width * 3, ptrcolors, ptrbits); } } } else { int stride1 = this.Stride1; ulong colorbits = this.ColorBits(color); // draw top int pos = (y * stride1) + (x * bitsPerPixel); BitUtils.SetBits(width * bitsPerPixel, colorbits, bits, pos); pos += stride1; // draw left and right int posend = pos + (width * bitsPerPixel); for (int i = 1, ii = height - 1; i < ii; i++, pos += stride1, posend += stride1) { BitUtils.SetBits(bitsPerPixel, colorbits, bits, pos); BitUtils.SetBits(bitsPerPixel, colorbits, bits, posend); } // draw bottom BitUtils.SetBits(width * bitsPerPixel, colorbits, bits, pos); } }