/// <summary> /// Given a set of values <c>Ln(a1), Ln(a2), ... Ln(an)</c>, /// return <c>Ln(a1+a2+...+an)</c>. This is especially useful /// when working with log probabilities and likelihoods. /// </summary> /// <param name="terms"></param> public static Float LnSum(IEnumerable <Float> terms) { // Two passes to find the overall max is a *lot* simpler, // but potentially more computationally intensive. Float max = Float.NegativeInfinity; Double soFar = 0; foreach (Float term in terms) { // At this point, all *prior* terms, Math.Exp(x - max). if (Float.IsNegativeInfinity(term)) { continue; } if (!(term > max)) { soFar += Math.Exp(term - max); } else { soFar = Math.Exp(max - term) * soFar + 1; max = term; } } return((Float)Math.Log(soFar) + max); }
/// <summary> /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. /// </summary> /// <param name="f">32-bit single-precision floating-point number.</param> /// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param> public Half(Single f, bool throwOnError) : this(f) { if (throwOnError) { // handle cases that cause overflow rather than silently ignoring it if (f > Half.MaxValue) { throw new ArithmeticException("Half: Positive maximum value exceeded."); } if (f < -Half.MaxValue) { throw new ArithmeticException("Half: Negative minimum value exceeded."); } // handle cases that make no sense if (Single.IsNaN(f)) { throw new ArithmeticException("Half: Input is not a number (NaN)."); } if (Single.IsPositiveInfinity(f)) { throw new ArithmeticException("Half: Input is positive infinity."); } if (Single.IsNegativeInfinity(f)) { throw new ArithmeticException("Half: Input is negative infinity."); } } }
/// <summary> /// computes the "softmax" function: log sum_i exp x_i /// </summary> /// <param name="inputs">Array of numbers to softmax</param> /// <param name="count">the number of input array elements to process</param> /// <returns>the softmax of the numbers</returns> /// <remarks>may have slightly lower roundoff error if inputs are sorted, smallest first</remarks> public static Float SoftMax(Float[] inputs, int count) { Contracts.AssertValue(inputs); Contracts.Assert(0 < count & count <= inputs.Length); int maxIdx = 0; Float max = Float.NegativeInfinity; for (int i = 0; i < count; i++) { if (inputs[i] > max) { maxIdx = i; max = inputs[i]; } } if (Float.IsNegativeInfinity(max)) { return(Float.NegativeInfinity); } if (count == 1) { return(max); } //else if (leng == 2) { // return SoftMax(inputs[0], inputs[1]); //} double intermediate = 0.0; Float cutoff = max - LogTolerance; for (int i = 0; i < count; i++) { if (i == maxIdx) { continue; } if (inputs[i] > cutoff) { intermediate += Math.Exp(inputs[i] - max); } } if (intermediate > 0.0) { return((Float)(max + Math.Log(1.0 + intermediate))); } return(max); }
/// <summary> /// computes the "softmax" function: log sum_i exp x_i /// </summary> /// <param name="inputs">Span of numbers to softmax</param> /// <returns>the softmax of the numbers</returns> /// <remarks>may have slightly lower roundoff error if inputs are sorted, smallest first</remarks> public static Float SoftMax(ReadOnlySpan <float> inputs) { int maxIdx = 0; Float max = Float.NegativeInfinity; for (int i = 0; i < inputs.Length; i++) { if (inputs[i] > max) { maxIdx = i; max = inputs[i]; } } if (Float.IsNegativeInfinity(max)) { return(Float.NegativeInfinity); } if (inputs.Length == 1) { return(max); } double intermediate = 0.0; Float cutoff = max - LogTolerance; for (int i = 0; i < inputs.Length; i++) { if (i == maxIdx) { continue; } if (inputs[i] > cutoff) { intermediate += Math.Exp(inputs[i] - max); } } if (intermediate > 0.0) { return((Float)(max + Math.Log(1.0 + intermediate))); } return(max); }
/// <summary> /// computes "softmax" function of two arguments: log (exp x + exp y) /// </summary> public static Float SoftMax(Float lx, Float ly) { Float max; Float negDiff; if (lx > ly) { max = lx; negDiff = ly - lx; } else { max = ly; negDiff = lx - ly; } if (Float.IsNegativeInfinity(max) || negDiff < -LogTolerance) { return(max); } else { return((Float)(max + Math.Log(1.0 + Math.Exp(negDiff)))); } }
/// <summary> /// Returns a value indicating whether the specified number evaluates to negative infinity /// </summary> /// <param name="number">a floating point number</param> /// <returns>a boolean</returns> public static bool IsNegativeInfinity(Real number) { return(Numeric.IsNegativeInfinity((Numeric)number)); }