public Array <float> Fit(Array <float> X, bool center = true) { var m = X.Shape[0]; var n = X.Shape[1]; var k = Math.Min(m, n); this.means = NN.Mean(X, axis: 0); if (center) { X -= means; } var copy = (float[])X.Values.Clone(); var s = new float[k]; var u = NN.Zeros <float>(m, m); components_ = NN.Zeros <float>(n, n); var superb = new float[k - 1]; BlasNet.Lapack.gesvd('A', 'A', m, n, copy, n, s, u.Values, m, components_.Values, n, superb); var components = nComponents == 0 ? k : Math.Min(k, nComponents); SVDFlip(u, components); return(X); }
/// <summary> /// Fills the result array using the value from a, and the indexes from selected. /// </summary> /// <typeparam name="T">The type of a content</typeparam> /// <param name="thiz"></param> /// <param name="selected">the result of a ArgMax/ArgMin operation</param> /// <param name="axis"></param> /// <param name="axisSize"></param> /// <param name="keepDims"></param> /// <param name="result"></param> /// <returns></returns> public static Array <T> UnArgmax <T>(this Array <T> thiz, Array <int> selected, int axis, int axisSize, bool keepDims = false, Array <T> result = null) { thiz.AssertOfShape(selected); var dim = thiz.NDim + (keepDims ? 0 : 1); var shape = new int[dim]; if (keepDims) { System.Array.Copy(thiz.Shape, shape, dim); } else { System.Array.Copy(thiz.Shape, 0, shape, 0, axis); System.Array.Copy(thiz.Shape, axis, shape, axis + 1, thiz.NDim - axis); } shape[axis] = axisSize; result = result ?? NN.Zeros <T>(shape); result.AssertOfShape(shape); var resultInc = result.Stride[axis]; // HACK // as result have one more shape than thiz and selected, we have to lie about the number of shapes var resultSlices = new Slice[dim]; for (int i = 0; i < dim; ++i) { resultSlices[i] = Slicer._; } if (!keepDims) { resultSlices[axis] = 0; } else { resultSlices[axis] = Slicer.Upto(1); } var res = result[resultSlices]; Array_.ElementwiseOp(thiz, selected, res, (n, x, offsetx, incx, s, offsetS, incS, r, offsetR, incR) => { for (int i = 0; i < n; ++i) { r[offsetR + resultInc * s[offsetS]] = x[offsetx]; offsetR += incR; offsetS += incS; offsetx += incx; } }); return(result); }
// "fast" softmax for 1D and 2D arrays public static Array <Real> Softmax_(Array <Real> a, Array <Real> result = null) { if (a.Shape.Length > 2) { throw new RankException(string.Format("Must be 1-d or 2-d tensor, got {0}-d with shape ({1}).", a.Shape.Length, string.Join(", ", a.Shape))); } if (result == null) { result = Zeros <Real>(a.Shape); } else { result.AssertOfShape(a); } if (a.Shape.Length == 1) { var max = a.Max(); result = NN.Exp(a - max, result: result); } else { var maxes = NN.Zeros <Real>(a.Shape[0], 1); var vMax = maxes.Values; int off = a.Offset, offX; int incX = a.Stride[0], incY = a.Stride[1]; int nX = a.Shape[0], nY = a.Shape[1]; Real max = Real.NegativeInfinity; var v = a.Values; for (int i = 0; i < nX; ++i) { offX = off; max = Real.NegativeInfinity; for (int j = 0; j < nY; ++j) { max = Math.Max(v[off], max); off += incY; } off = offX + incX; vMax[i] = max; } result = NN.Exp(a - maxes, result: result); } var sum = NN.Sum(result, axis: a.Shape.Length - 1, keepDims: true); result = result.Div(sum, result: result); //result = result.Apply(sum, (x, s) => Math.Max(x / s, 0.000001f), result: result); return(result); }
public static Array <float> EinsteinSum(Array <float> x, Array <float> y, Einstein[] einstein, Array <float> result = null) { var resultShape = EinsteinShape(x.Shape, y.Shape, einstein); if (result == null) { result = NN.Zeros <float>(resultShape); } else { result.AssertOfShape(resultShape); } _EinsteinSum(0, einstein, x, x.Offset, y, y.Offset, result, result.Offset); return(result); }