//TODO public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows) { int n = data1.GetLength(1); double[] x = new double[n]; double[] y = new double[n]; for (int i = 0; i < n; i++) { x[i] = data1[index1, i]; y[i] = data2[index2, i]; } return(Get(x, y)); } else { int n = data1.GetLength(0); double[] x = new double[n]; double[] y = new double[n]; for (int i = 0; i < n; i++) { x[i] = data1[i, index1]; y[i] = data2[i, index2]; } return(Get(x, y)); } }
/// <summary> /// Performs a hierarchical clustering on the the given data matrix. /// </summary> /// <param name="data">Data matrix that is going to be clustered.</param> /// <param name="access">Specifies whether rows or columns are to be clustered</param> /// <param name="distance">Defines the distance between two elements</param> /// <param name="linkage">Specifies the linkage for the clustering.</param> /// <param name="preserveOrder"></param> /// <param name="periodic"></param> /// <param name="nthreads"></param> /// <param name="progress"></param> /// <returns>An array of cluster nodes defining the resulting tree.</returns> public HierarchicalClusterNode[] TreeCluster(MatrixIndexer data, MatrixAccess access, IDistance distance, HierarchicalClusterLinkage linkage, bool preserveOrder, bool periodic, int nthreads, Action<int> progress) { int nelements = (access == MatrixAccess.Rows) ? data.RowCount : data.ColumnCount; if (nelements < 2){ return new HierarchicalClusterNode[0]; } float[,] distMatrix = DistanceMatrix(data, distance, access); return TreeCluster(distMatrix, linkage, preserveOrder, periodic, nthreads, progress); }
/// <summary> /// Performs a hierarchical clustering on the the given data matrix. /// </summary> /// <param name="data">Data matrix that is going to be clustered.</param> /// <param name="access">Specifies whether rows or columns are to be clustered</param> /// <param name="distance">Defines the distance between two elements</param> /// <param name="linkage">Specifies the linkage for the clustering.</param> /// <param name="preserveOrder"></param> /// <param name="periodic"></param> /// <param name="nthreads"></param> /// <param name="progress"></param> /// <returns>An array of cluster nodes defining the resulting tree.</returns> public HierarchicalClusterNode[] TreeCluster(MatrixIndexer data, MatrixAccess access, IDistance distance, HierarchicalClusterLinkage linkage, bool preserveOrder, bool periodic, int nthreads, Action <int> progress) { int nelements = (access == MatrixAccess.Rows) ? data.RowCount : data.ColumnCount; if (nelements < 2) { return(new HierarchicalClusterNode[0]); } float[,] distMatrix = DistanceMatrix(data, distance, access); return(TreeCluster(distMatrix, linkage, preserveOrder, periodic, nthreads, progress)); }
public static bool HasNanOrInf(MatrixIndexer m, MatrixAccess access) { switch (access) { case MatrixAccess.Columns: return(HasNaNOrInfColumns(m)); case MatrixAccess.Rows: return(HasNaNOrInfRows(m)); default: throw new NotImplementedException($"Not implemented for access {access}"); } }
public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows) { int n = data1.GetLength(1); int c = 0; double sum = 0; for (int i = 0; i < n; i++) { double d = data1[index1, i] - data2[index2, i]; if (!double.IsNaN(d)) { sum += Math.Abs(d); c++; } } if (c == 0) { return(double.NaN); } return(sum / c * n); } else { int n = data1.GetLength(0); int c = 0; double sum = 0; for (int i = 0; i < n; i++) { double d = data1[i, index1] - data2[i, index2]; if (!double.IsNaN(d)) { sum += Math.Abs(d); c++; } } if (c == 0) { return(double.NaN); } return(sum / c * n); } }
public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows) { int n = data1.GetLength(1); double max = double.MinValue; for (int i = 0; i < n; i++) { double d = data1[index1, i] - data2[index2, i]; if (double.IsNaN(d) || double.IsInfinity(d)) { continue; } double dist = Math.Abs(d); if (dist > max) { max = dist; } } return(max == double.MinValue ? double.NaN : max); } else { int n = data1.GetLength(0); double max = double.MinValue; for (int i = 0; i < n; i++) { double d = data1[i, index1] - data2[i, index2]; if (double.IsNaN(d) || double.IsInfinity(d)) { continue; } double dist = Math.Abs(d); if (dist > max) { max = dist; } } return(max == double.MinValue ? double.NaN : max); } }
public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows) { int n = data1.GetLength(1); double sum = 0; int c = 0; for (int i = 0; i < n; i++) { double d = data1[index1, i] - data2[index2, i]; if (double.IsNaN(d)) { continue; } sum += d * d; c++; } return(c == 0 ? double.NaN : Math.Sqrt(sum / c * n)); } else { int n = data1.GetLength(0); double sum = 0; int c = 0; for (int i = 0; i < n; i++) { double d = data1[i, index1] - data2[i, index2]; if (double.IsNaN(d)) { continue; } sum += d * d; c++; } return(c == 0 ? double.NaN : Math.Sqrt(sum / c * n)); } }
public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows){ int n = data1.GetLength(1); double sum = 0; int c = 0; for (int i = 0; i < n; i++){ double d = data1[index1, i] - data2[index2, i]; if (double.IsNaN(d)){ continue; } sum += d*d; c++; } return c == 0 ? double.NaN : Math.Sqrt(sum/c*n); } else{ int n = data1.GetLength(0); double sum = 0; int c = 0; for (int i = 0; i < n; i++){ double d = data1[i, index1] - data2[i, index2]; if (double.IsNaN(d)){ continue; } sum += d*d; c++; } return c == 0 ? double.NaN : Math.Sqrt(sum/c*n); } }
//TODO public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows){ int n = data1.GetLength(1); double[] x = new double[n]; double[] y = new double[n]; for (int i = 0; i < n; i++){ x[i] = data1[index1, i]; y[i] = data2[index2, i]; } return Get(x, y); } else{ int n = data1.GetLength(0); double[] x = new double[n]; double[] y = new double[n]; for (int i = 0; i < n; i++){ x[i] = data1[i, index1]; y[i] = data2[i, index2]; } return Get(x, y); } }
public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows){ int n = data1.GetLength(1); int c = 0; double sum = 0; for (int i = 0; i < n; i++){ double d = data1[index1, i] - data2[index2, i]; if (!double.IsNaN(d)){ sum += Math.Abs(d); c++; } } if (c == 0){ return double.NaN; } return sum/c*n; } else{ int n = data1.GetLength(0); int c = 0; double sum = 0; for (int i = 0; i < n; i++){ double d = data1[i, index1] - data2[i, index2]; if (!double.IsNaN(d)){ sum += Math.Abs(d); c++; } } if (c == 0){ return double.NaN; } return sum/c*n; } }
public HierarchicalClusterNode[] TreeClusterKmeans(MatrixIndexer data, MatrixAccess access, IDistance distance, HierarchicalClusterLinkage linkage, bool preserveOrder, bool periodic, int nthreads, int nmeans, int restarts, int maxIter, Action<int> progress) { int nelements = (access == MatrixAccess.Rows) ? data.RowCount : data.ColumnCount; if (nelements <= nmeans){ return TreeCluster(data, access, distance, linkage, preserveOrder, periodic, nthreads, progress); } float[,] c; int[] inds; if (access == MatrixAccess.Rows){ KmeansClustering.GenerateClusters(data, nmeans, maxIter, restarts, progress, out c, out inds); } else{ KmeansClustering.GenerateClusters(data.Transpose(), nmeans, maxIter, restarts, progress, out c, out inds); } float[,] distMatrix = DistanceMatrix(new FloatMatrixIndexer(c), distance, MatrixAccess.Rows); HierarchicalClusterNode[] nodes = TreeCluster(distMatrix, linkage, preserveOrder, periodic, nthreads, progress); Dictionary<int, int[]> clusters; Dictionary<int, int> singletons; RearrangeClusters(inds, c.GetLength(0), out clusters, out singletons); HierarchicalClusterNode[] newNodes = new HierarchicalClusterNode[nelements - 1]; int fill = nelements - nmeans; Array.Copy(nodes, 0, newNodes, fill, nodes.Length); int pos = 0; for (int i = fill; i < newNodes.Length; i++){ HierarchicalClusterNode node = newNodes[i]; if (node.left < 0){ node.left -= fill; } else if (singletons.ContainsKey(node.left)){ node.left = singletons[node.left]; } else{ if (clusters.ContainsKey(node.left)){ HierarchicalClusterNode[] branch = FillTerminalBranch(clusters[node.left], pos); Array.Copy(branch, 0, newNodes, pos, branch.Length); pos += branch.Length; node.left = -pos; } } if (node.right < 0){ node.right -= fill; } else if (singletons.ContainsKey(node.right)){ node.right = singletons[node.right]; } else{ if (clusters.ContainsKey(node.right)){ HierarchicalClusterNode[] branch = FillTerminalBranch(clusters[node.right], pos); Array.Copy(branch, 0, newNodes, pos, branch.Length); pos += branch.Length; node.right = -pos; } } } return newNodes; }
private static float[,] DistanceMatrix(MatrixIndexer data, IDistance distance, MatrixAccess access) { int nrows = data.RowCount; int ncols = data.ColumnCount; int nelements = (access == MatrixAccess.Rows) ? nrows : ncols; float[,] result = new float[nelements, nelements]; for (int i = 0; i < nelements; i++){ for (int j = 0; j < i; j++){ result[i, j] = (float) distance.Get(GetVector(data, i, access), GetVector(data, j, access)); } } return result; }
public HierarchicalClusterNode[] TreeClusterKmeans(MatrixIndexer data, MatrixAccess access, IDistance distance, HierarchicalClusterLinkage linkage, bool preserveOrder, bool periodic, int nthreads, int nmeans, int restarts, int maxIter, Action <int> progress) { int nelements = (access == MatrixAccess.Rows) ? data.RowCount : data.ColumnCount; if (nelements <= nmeans) { return(TreeCluster(data, access, distance, linkage, preserveOrder, periodic, nthreads, progress)); } float[,] c; int[] inds; if (access == MatrixAccess.Rows) { KmeansClustering.GenerateClusters(data, nmeans, maxIter, restarts, progress, out c, out inds); } else { KmeansClustering.GenerateClusters(data.Transpose(), nmeans, maxIter, restarts, progress, out c, out inds); } float[,] distMatrix = DistanceMatrix(new FloatMatrixIndexer(c), distance, MatrixAccess.Rows); HierarchicalClusterNode[] nodes = TreeCluster(distMatrix, linkage, preserveOrder, periodic, nthreads, progress); Dictionary <int, int[]> clusters; Dictionary <int, int> singletons; RearrangeClusters(inds, c.GetLength(0), out clusters, out singletons); HierarchicalClusterNode[] newNodes = new HierarchicalClusterNode[nelements - 1]; int fill = nelements - nmeans; Array.Copy(nodes, 0, newNodes, fill, nodes.Length); int pos = 0; for (int i = fill; i < newNodes.Length; i++) { HierarchicalClusterNode node = newNodes[i]; if (node.left < 0) { node.left -= fill; } else if (singletons.ContainsKey(node.left)) { node.left = singletons[node.left]; } else { if (clusters.ContainsKey(node.left)) { HierarchicalClusterNode[] branch = FillTerminalBranch(clusters[node.left], pos); Array.Copy(branch, 0, newNodes, pos, branch.Length); pos += branch.Length; node.left = -pos; } } if (node.right < 0) { node.right -= fill; } else if (singletons.ContainsKey(node.right)) { node.right = singletons[node.right]; } else { if (clusters.ContainsKey(node.right)) { HierarchicalClusterNode[] branch = FillTerminalBranch(clusters[node.right], pos); Array.Copy(branch, 0, newNodes, pos, branch.Length); pos += branch.Length; node.right = -pos; } } } return(newNodes); }
private static BaseVector GetVector(MatrixIndexer data, int index, MatrixAccess access) { return(access == MatrixAccess.Rows ? data.GetRow(index) : data.GetColumn(index)); }
private static float[,] DistanceMatrix(MatrixIndexer data, IDistance distance, MatrixAccess access) { int nrows = data.RowCount; int ncols = data.ColumnCount; int nelements = (access == MatrixAccess.Rows) ? nrows : ncols; float[,] result = new float[nelements, nelements]; for (int i = 0; i < nelements; i++) { for (int j = 0; j < i; j++) { result[i, j] = (float)distance.Get(GetVector(data, i, access), GetVector(data, j, access)); } } return(result); }
public double Get(double[,] data1, double[,] data2, int index1, int index2, MatrixAccess access) { if (access == MatrixAccess.Rows){ int n = data1.GetLength(1); double max = double.MinValue; for (int i = 0; i < n; i++){ double d = data1[index1, i] - data2[index2, i]; if (double.IsNaN(d) || double.IsInfinity(d)){ continue; } double dist = Math.Abs(d); if (dist > max){ max = dist; } } return max == double.MinValue ? double.NaN : max; } else{ int n = data1.GetLength(0); double max = double.MinValue; for (int i = 0; i < n; i++){ double d = data1[i, index1] - data2[i, index2]; if (double.IsNaN(d) || double.IsInfinity(d)){ continue; } double dist = Math.Abs(d); if (dist > max){ max = dist; } } return max == double.MinValue ? double.NaN : max; } }
private static BaseVector GetVector(MatrixIndexer data, int index, MatrixAccess access) { return access == MatrixAccess.Rows ? data.GetRow(index) : data.GetColumn(index); }