public Cluster[] em(double[][] data, int numObs, int numFeatures) {
		Instances ds = convertMatrixToWeka(data, numObs, numFeatures);
		EM clusterer = new EM();
		try {
			clusterer.buildClusterer(ds);
			ClusterEvaluation eval = new ClusterEvaluation();                                        
			eval.setClusterer(clusterer);                                  
			eval.evaluateClusterer(new Instances(ds));                               
			int numClusters = eval.getNumClusters();
			
			Cluster[] clusters = new Cluster[numClusters];
			double[][] clusterCentroids = new double[numClusters][numFeatures];
			int[] clusterCount = new int[numClusters];
			
			double[] assignments = eval.getClusterAssignments();
			for(int i = 0; i < ds.numInstances(); i++) {
				Instance inst = ds.instance(i);
				int clusterId = (int) assignments[i];
				for(int j = 0; j < numFeatures; j++) {
					clusterCentroids[clusterId][j] += inst.value(j);
				}
				clusterCount[clusterId]++;
			}
			
			for(int i = 0; i < numClusters; i++) {
				double[] mean = new double[numFeatures];
				for(int j = 0; j < numFeatures; j++) {
					mean[j] = clusterCentroids[i][j]/clusterCount[i];
				}
				clusters[i] = new Cluster(mean, i);
			}
			
			// cluster members & std dev
			double[][] clusterStdDev = new double[numClusters][numFeatures];
			for(int i = 0; i < ds.numInstances(); i++) {
				int clusterId = (int)assignments[i];
				clusters[clusterId].addMember(i);
				for(int j = 0; j < numFeatures; j++) {
					clusterStdDev[clusterId][j] += Math.pow(ds.instance(i).value(j) - clusters[clusterId].getCentroid()[j], 2);
				}
			}
			
			for(int i = 0; i < numClusters; i++) {
				double[] dev = new double[numFeatures];
				for(int j = 0; j < numFeatures; j++) {
					dev[j] = Math.sqrt(clusterStdDev[i][j]/clusterCount[i]);
				}
				clusters[i].setStdDev(dev);
			}
			
			return clusters;
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-1);
			return null;
		}
	}