/// <summary> /// The gradient being used by the optimizer /// </summary> protected virtual float DifferentiableFunction(ref VBuffer <float> x, ref VBuffer <float> gradient, IProgressChannelProvider progress) { Contracts.Assert((_numChunks == 0) != (_data == null)); Contracts.Assert((_cursorFactory == null) == (_data == null)); Contracts.Assert(x.Length == BiasCount + WeightCount); Contracts.Assert(gradient.Length == BiasCount + WeightCount); // REVIEW: if/when LBFGS test code is removed, the progress provider needs to become required. Contracts.AssertValueOrNull(progress); float scaleFactor = 1 / (float)WeightSum; VBuffer <float> xDense = default(VBuffer <float>); if (x.IsDense) { xDense = x; } else { x.CopyToDense(ref xDense); } IProgressChannel pch = progress != null?progress.StartProgressChannel("Gradient") : null; float loss; using (pch) { loss = _data == null ? DifferentiableFunctionMultithreaded(ref xDense, ref gradient, pch) : DifferentiableFunctionStream(_cursorFactory, ref xDense, ref gradient, pch); } float regLoss = 0; if (L2Weight > 0) { Contracts.Assert(xDense.IsDense); var values = xDense.Values; Double r = 0; for (int i = BiasCount; i < values.Length; i++) { var xx = values[i]; r += xx * xx; } regLoss = (float)(r * L2Weight * 0.5); // Here we probably want to use sparse x VBufferUtils.ApplyWithEitherDefined(ref x, ref gradient, (int ind, float v1, ref float v2) => { if (ind >= BiasCount) { v2 += L2Weight * v1; } }); } VectorUtils.ScaleBy(ref gradient, scaleFactor); // REVIEW: The regularization component of the loss is being scaled as well, // but it's unclear that it should be scaled. return((loss + regLoss) * scaleFactor); }
protected void FixDirZeros() { VBufferUtils.ApplyWithEitherDefined(ref _steepestDescDir, ref _dir, (int i, Float sdVal, ref Float dirVal) => { if (sdVal == 0) { dirVal = 0; } }); }
/// <summary> /// Multiplies arrays Dst *= A element by element and returns the result in <paramref name="dst"/> (Hadamard product). /// </summary> public static void MulElementWise(ref VBuffer <Float> a, ref VBuffer <Float> dst) { Contracts.Check(a.Length == dst.Length, "Vectors must have the same dimensionality."); if (a.IsDense && dst.IsDense) { CpuMathUtils.MulElementWise(a.Values, dst.Values, dst.Values, a.Length); } else { VBufferUtils.ApplyWithEitherDefined(ref a, ref dst, (int ind, Float v1, ref Float v2) => { v2 *= v1; }); } }