Skip to content

Commit

Permalink
Merge branch 'release/v2.8.2'
Browse files Browse the repository at this point in the history
# Conflicts:
#	pom.xml
#	src/main/java/es/ubu/lsi/ubumonitor/AppInfo.java
  • Loading branch information
yjx0003 committed Mar 19, 2021
2 parents 6d23bd9 + 56270ae commit 96cabab
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 24 deletions.
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

<groupId>es.ubu.lsi</groupId>
<artifactId>ubumonitor</artifactId>
<version>2.8.1</version>
<version>2.8.2</version>



<name>UBUMonitor</name>
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/es/ubu/lsi/ubumonitor/AppInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
*/
public class AppInfo {

public static final String VERSION = "2.8.1";

public static final String VERSION = "2.8.2";

public static final String APPLICATION_VERSION = "v" + VERSION;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.math3.exception.NumberIsTooSmallException;
import org.apache.commons.math3.ml.clustering.Cluster;
Expand All @@ -28,10 +27,12 @@
* Clase encargada de ejecutar un algoritmo de clustering.
*
* @author Xing Long Ji
* @author Raúl Marticorena Sánchez
*
*/
public class AlgorithmExecuter {

private static final int MINUS_ONE = -1;
private Clusterer<UserData> clusterer;
private Distance distance;
private List<UserData> usersData;
Expand Down Expand Up @@ -184,40 +185,121 @@ public static List<Map<UserData, double[]>> clustersTo(int dim, List<ClusterWrap
if (clusters.isEmpty()) {
return Collections.emptyList();
}

List<double[]> centers = new ArrayList<>();
for (ClusterWrapper clusterWrapper : clusters) {
double[] center = clusterWrapper.getCenter();
if (center != null) {
centers.add(center);
}
}

double[][] matrix = Stream
.concat(clusters.stream().flatMap(ClusterWrapper::stream).map(UserData::getPoint), centers.stream())

// Only use the point data, not use centroids (corrected bug).
double[][] matrix = clusters.stream().flatMap(ClusterWrapper::stream).map(UserData::getPoint)
.toArray(double[][]::new);

PrincipalComponentAnalysis pca = new PrincipalComponentAnalysis();
List<Map<UserData, double[]>> points = new ArrayList<>();

List<Map<UserData, double[]>> points = new ArrayList<>();
// PCA with T-SNE
PrincipalComponentAnalysis pca = new PrincipalComponentAnalysis();
if (matrix[0].length > dim) {
matrix = pca.pca(matrix, dim);
}

// Correct problem of twists with PCA projections
changeSignInMatrixProjection(matrix, pca, dim); // fix problem of symmetry wit PCA

// Add points
int i = 0;
for (List<UserData> list : clusters) {
Map<UserData, double[]> map = new LinkedHashMap<>();
for (UserData userData : list) {
map.put(userData, matrix[i++]);
}
points.add(map);
}
}

// Add centroides
for (int j = 0; i < matrix.length; i++, j++) {
points.get(j).put(null, matrix[i]);
}
// We need to calculate the centroid projections in N dimensions...
double[][] centroids = calculateCentroids(clusters, matrix);
// Add centroids
for (int j = 0; j < centroids.length; j++) {
points.get(j).put(null, centroids[j]);
}

return points;
}


/**
* Calculate the projections in N dimensions for each centroid.
*
* @param clusters clusters
* @param matrix data numerical points
* @return current projections of centroids
*/
private static double[][] calculateCentroids(final List<ClusterWrapper> clusters, final double[][] matrix){
// number of clusters x number of dimensions after PCA
double[][] centroids = new double[clusters.size()][matrix[0].length];

int position = 0; // initial row position in data numerical matrix
int currentNumberOfCentroid = 0;
for (ClusterWrapper cluster : clusters) {
double[] centroid = obtainCentroid(matrix, position, position + cluster.size());
centroids[currentNumberOfCentroid++] = centroid; // add centroid
position += cluster.size(); // move forward to the next cluster row
}
return centroids;
}

/**
* Obtain the projection in N dimensions for a cluster.
*
* @param matrix data numerical points
* @param begin initial row in the cluster
* @param end number of elements in the cluster
* @return centroid coordinates
*/
private static double[] obtainCentroid(double[][] matrix, final int begin, final int end) {
int dimensions = matrix[0].length;
double[] centroid = new double[dimensions];
// add the x_i values in each dimension...
for (int i = begin; i < end; i++) {
for (int j = 0; j < dimensions; j++) {
centroid[j] += matrix[i][j];
}
}
// aritmetic mean for added values in each dimension
for (int j = 0; j < dimensions; j++) {
centroid[j] = centroid[j]/(end-begin);
}
return centroid;
}

/**
* Corrects the sign problem with PCA.
*
* The PCA algorithm can give different solutions with the only different of the
* sign in the principal components. To correct the problem, we check the sign (of
* the first value in the principal component) and in the case of being negative,
* we change the corresponding sign in the projected column. In this way, it is
* guaranteed that the projections are always the same (without twists).
*
* Thanks to César Ignacio García Osorio and Juan José Rodriguez Diez.
*
* @param matrix matrix
* @param pca pca
* @param numberOfComponents number of components
*/
private static void changeSignInMatrixProjection(double[][] matrix, final PrincipalComponentAnalysis pca, final int numberOfComponents) {
for (int i = 0; i < numberOfComponents; i++) {
// first element sign in i component
boolean negativeComponent = pca.getBasisVector(i)[0] < 0 ? true : false;
if (negativeComponent) {
changeSignInColumn(matrix, i); // Chaging sign in i-component (i-column)
}
}
}

/**
* Change sign in all elements in column.
*
* @param matrix matrix
* @param column column to change sign
*/
private static void changeSignInColumn(double[][] matrix, final int column) {
for (int i = 0; i < matrix.length; i++) {
matrix[i][column] = matrix[i][column] * MINUS_ONE;
}
}

}

0 comments on commit 96cabab

Please sign in to comment.