private static void ComputeApproximateGradient(int[] rowP, int[] colP, double[] valP, double[,] y, int n, int d, double[,] dC, double theta) { var tree = new SpacePartitioningTree(y); var sumQ = 0.0; var posF = new double[n, d]; var negF = new double[n, d]; SpacePartitioningTree.ComputeEdgeForces(rowP, colP, valP, n, posF, y, d); var row = new double[d]; for (var n1 = 0; n1 < n; n1++) { Array.Clear(row, 0, row.Length); tree.ComputeNonEdgeForces(n1, theta, row, ref sumQ); Buffer.BlockCopy(row, 0, negF, (sizeof(double) * n1 * d), d * sizeof(double)); } // Compute final t-SNE gradient for (var i = 0; i < n; i++) { for (var j = 0; j < d; j++) { dC[i, j] = posF[i, j] - negF[i, j] / sumQ; } } }
private void Subdivide() { // Create new children var newCorner = new double[dimension]; var newWidth = new double[dimension]; for (var i = 0; i < noChildren; i++) { var div = 1; for (var d = 0; d < dimension; d++) { newWidth[d] = .5 * boundary.GetWidth(d); if (i / div % 2 == 1) { newCorner[d] = boundary.GetCorner(d) - .5 * boundary.GetWidth(d); } else { newCorner[d] = boundary.GetCorner(d) + .5 * boundary.GetWidth(d); } div *= 2; } children[i] = new SpacePartitioningTree(data, newCorner, newWidth); } // Move existing points to correct children for (var i = 0; i < size; i++) { var success = false; for (var j = 0; j < noChildren; j++) { if (!success) { success = children[j].Insert(index[i]); } } index[i] = -1; // as in tSNE implementation by van der Maaten } // Empty parent node size = 0; isLeaf = false; }
private static double EvaluateErrorApproximate(IReadOnlyList <int> rowP, IReadOnlyList <int> colP, IReadOnlyList <double> valP, double[,] y, double theta) { // Get estimate of normalization term var n = y.GetLength(0); var d = y.GetLength(1); var tree = new SpacePartitioningTree(y); var buff = new double[d]; var sumQ = 0.0; for (var i = 0; i < n; i++) { tree.ComputeNonEdgeForces(i, theta, buff, ref sumQ); } // Loop over all edges to compute t-SNE error var c = .0; for (var k = 0; k < n; k++) { for (var i = rowP[k]; i < rowP[k + 1]; i++) { var q = .0; for (var j = 0; j < d; j++) { buff[j] = y[k, j]; } for (var j = 0; j < d; j++) { buff[j] -= y[colP[i], j]; } for (var j = 0; j < d; j++) { q += buff[j] * buff[j]; } q = (1.0 / (1.0 + q)) / sumQ; c += valP[i] * Math.Log((valP[i] + float.Epsilon) / (q + float.Epsilon)); } } return(c); }