/** * Gradient * * @param x a <code>double[]</code> input vector * @return */ @Override public double[] gradient(double[] x) { double[] sqrtPsi = new double[nVariables]; double[] invSqrtPsi = new double[nVariables]; for (int i = 0; i < nVariables; i++) { x[i] = Math.max(0.005, x[i]); // ensure that no parameters are negative sqrtPsi[i] = Math.sqrt(x[i]); invSqrtPsi[i] = 1.0 / Math.sqrt(x[i]); } DiagonalMatrix diagPsi = new DiagonalMatrix(x); DiagonalMatrix diagSqtPsi = new DiagonalMatrix(sqrtPsi); DiagonalMatrix SC = new DiagonalMatrix(invSqrtPsi); RealMatrix Sstar = SC.multiply(R2).multiply(SC); EigenDecomposition E = new EigenDecomposition(Sstar); RealMatrix L = E.getV().getSubMatrix(0, nVariables - 1, 0, nFactors - 1); double[] ev = new double[nFactors]; for (int i = 0; i < nFactors; i++) { ev[i] = Math.sqrt(Math.max(E.getRealEigenvalue(i) - 1, 0)); } DiagonalMatrix M = new DiagonalMatrix(ev); RealMatrix LOAD = L.multiply(M); RealMatrix LL = diagSqtPsi.multiply(LOAD); RealMatrix G = LL.multiply(LL.transpose()).add(diagPsi).subtract(R2); double[] gradient = new double[nVariables]; for (int i = 0; i < nVariables; i++) { gradient[i] = G.getEntry(i, i) / (x[i] * x[i]); } return gradient; }
public double valueAt(double[] param) { double[] sdInv = new double[nVariables]; for (int i = 0; i < nVariables; i++) { R.setEntry(i, i, 1.0 - param[i]); sdInv[i] = 1.0 / Sinv.getEntry(i, i); } DiagonalMatrix diagSdInv = new DiagonalMatrix(sdInv); EigenDecomposition eigen = new EigenDecomposition(R); RealMatrix eigenVectors = eigen.getV().getSubMatrix(0, nVariables - 1, 0, nFactors - 1); double[] ev = new double[nFactors]; for (int i = 0; i < nFactors; i++) { ev[i] = Math.sqrt(eigen.getRealEigenvalue(i)); } DiagonalMatrix evMatrix = new DiagonalMatrix( ev); // USE Apache version of Diagonal matrix when upgrade to version 3.2 RealMatrix LAMBDA = eigenVectors.multiply(evMatrix); RealMatrix SIGMA = (LAMBDA.multiply(LAMBDA.transpose())); double value = 0.0; RealMatrix DIF = R.subtract(SIGMA); for (int i = 0; i < DIF.getRowDimension(); i++) { for (int j = 0; j < DIF.getColumnDimension(); j++) { value = DIF.getEntry(i, j); DIF.setEntry(i, j, Math.pow(value, 2)); } } RealMatrix RESID = diagSdInv.multiply(DIF).multiply(diagSdInv); double sum = 0.0; for (int i = 0; i < RESID.getRowDimension(); i++) { for (int j = 0; j < RESID.getColumnDimension(); j++) { sum += RESID.getEntry(i, j); } } return sum; }
public RealMatrix makeZta(RealMatrix userFeature, RealMatrix articleFeature) { RealMatrix product = userFeature.multiply(articleFeature.transpose()); double[][] productData = product.getData(); double[] productVector = new double[36]; int count = 0; for (int row = 0; row < 6; row++) { for (int col = 0; col < 6; col++) { productVector[count] = productData[row][col]; count++; } } return MatrixUtils.createColumnRealMatrix(productVector); }
private double prediction(long user, long item) { double baseline = baselineScorer.score(user, item); try { RealMatrix userFeature = model.getUserVector(user); RealMatrix featureWeights = model.getFeatureWeights(); RealMatrix itemFeature = model.getItemVector(item); double product = userFeature.multiply(featureWeights).multiply(itemFeature.transpose()).getEntry(0, 0); return baseline + product; } catch (NullPointerException npe) { return baseline; } }
@Override public void updateReward(User user, Article a, boolean clicked) { String aId = a.getId(); // Collect Variables RealMatrix xta = MatrixUtils.createColumnRealMatrix(a.getFeatures()); RealMatrix zta = makeZta(MatrixUtils.createColumnRealMatrix(user.getFeatures()), xta); RealMatrix Aa = AMap.get(aId); RealMatrix ba = bMap.get(aId); RealMatrix Ba = BMap.get(aId); // Find common transpose/inverse to save computation RealMatrix AaInverse = MatrixUtils.inverse(Aa); RealMatrix BaTranspose = Ba.transpose(); RealMatrix xtaTranspose = xta.transpose(); RealMatrix ztaTranspose = zta.transpose(); // Update A0 = A0.add(BaTranspose.multiply(AaInverse).multiply(Ba)); b0 = b0.add(BaTranspose.multiply(AaInverse).multiply(ba)); Aa = Aa.add(xta.multiply(xtaTranspose)); AMap.put(aId, Aa); Ba = Ba.add(xta.multiply(ztaTranspose)); BMap.put(aId, Ba); if (clicked) { ba = ba.add(xta); bMap.put(aId, ba); } // Update A0 and b0 with the new values A0 = A0.add(zta.multiply(ztaTranspose)) .subtract(Ba.transpose().multiply(MatrixUtils.inverse(Aa).multiply(Ba))); b0 = b0.subtract(Ba.transpose().multiply(MatrixUtils.inverse(Aa)).multiply(ba)); if (clicked) { b0 = b0.add(zta); } }
@Override public Article chooseArm(User user, List<Article> articles) { Article bestA = null; double bestArmP = Double.MIN_VALUE; RealMatrix Aa; RealMatrix Ba; RealMatrix ba; for (Article a : articles) { String aId = a.getId(); if (!AMap.containsKey(aId)) { Aa = MatrixUtils.createRealIdentityMatrix(6); AMap.put(aId, Aa); // set as identity for now and we will update // in reward double[] zeros = {0, 0, 0, 0, 0, 0}; ba = MatrixUtils.createColumnRealMatrix(zeros); bMap.put(aId, ba); double[][] BMapZeros = new double[6][36]; for (double[] row : BMapZeros) { Arrays.fill(row, 0.0); } Ba = MatrixUtils.createRealMatrix(BMapZeros); BMap.put(aId, Ba); } else { Aa = AMap.get(aId); ba = bMap.get(aId); Ba = BMap.get(aId); } // Make column vector out of features RealMatrix xta = MatrixUtils.createColumnRealMatrix(a.getFeatures()); RealMatrix zta = makeZta(MatrixUtils.createColumnRealMatrix(user.getFeatures()), xta); // Set up common variables RealMatrix A0Inverse = MatrixUtils.inverse(A0); RealMatrix AaInverse = MatrixUtils.inverse(Aa); RealMatrix ztaTranspose = zta.transpose(); RealMatrix BaTranspose = Ba.transpose(); RealMatrix xtaTranspose = xta.transpose(); // Find theta RealMatrix theta = AaInverse.multiply(ba.subtract(Ba.multiply(BetaHat))); // Find sta RealMatrix staMatrix = ztaTranspose.multiply(A0Inverse).multiply(zta); staMatrix = staMatrix.subtract( ztaTranspose .multiply(A0Inverse) .multiply(BaTranspose) .multiply(AaInverse) .multiply(xta) .scalarMultiply(2)); staMatrix = staMatrix.add(xtaTranspose.multiply(AaInverse).multiply(xta)); staMatrix = staMatrix.add( xtaTranspose .multiply(AaInverse) .multiply(Ba) .multiply(A0Inverse) .multiply(BaTranspose) .multiply(AaInverse) .multiply(xta)); // Find pta for arm RealMatrix ptaMatrix = ztaTranspose.multiply(BetaHat); ptaMatrix = ptaMatrix.add(xtaTranspose.multiply(theta)); double ptaVal = ptaMatrix.getData()[0][0]; double staVal = staMatrix.getData()[0][0]; ptaVal = ptaVal + alpha * Math.sqrt(staVal); // Update argmax if (ptaVal > bestArmP) { bestArmP = ptaVal; bestA = a; } } return bestA; }
@Override protected Object execute(Object[] data) { if (data[0] == null) { throw new ExecutionPlanRuntimeException( "Invalid input given to kf:kalmanFilter() " + "function. First argument should be a double"); } if (data[1] == null) { throw new ExecutionPlanRuntimeException( "Invalid input given to kf:kalmanFilter() " + "function. Second argument should be a double"); } if (data.length == 2) { double measuredValue = (Double) data[0]; // to remain as the initial state if (prevEstimatedValue == 0) { transition = 1; variance = 1000; measurementNoiseSD = (Double) data[1]; prevEstimatedValue = measuredValue; } prevEstimatedValue = transition * prevEstimatedValue; double kalmanGain = variance / (variance + measurementNoiseSD); prevEstimatedValue = prevEstimatedValue + kalmanGain * (measuredValue - prevEstimatedValue); variance = (1 - kalmanGain) * variance; return prevEstimatedValue; } else { if (data[2] == null) { throw new ExecutionPlanRuntimeException( "Invalid input given to kf:kalmanFilter() " + "function. Third argument should be a double"); } if (data[3] == null) { throw new ExecutionPlanRuntimeException( "Invalid input given to kf:kalmanFilter() " + "function. Fourth argument should be a long"); } double measuredXValue = (Double) data[0]; double measuredChangingRate = (Double) data[1]; double measurementNoiseSD = (Double) data[2]; long timestamp = (Long) data[3]; long timestampDiff; double[][] measuredValues = {{measuredXValue}, {measuredChangingRate}}; if (measurementMatrixH == null) { timestampDiff = 1; double[][] varianceValues = {{1000, 0}, {0, 1000}}; double[][] measurementValues = {{1, 0}, {0, 1}}; measurementMatrixH = MatrixUtils.createRealMatrix(measurementValues); varianceMatrixP = MatrixUtils.createRealMatrix(varianceValues); prevMeasuredMatrix = MatrixUtils.createRealMatrix(measuredValues); } else { timestampDiff = (timestamp - prevTimestamp); } double[][] Rvalues = {{measurementNoiseSD, 0}, {0, measurementNoiseSD}}; RealMatrix rMatrix = MatrixUtils.createRealMatrix(Rvalues); double[][] transitionValues = {{1d, timestampDiff}, {0d, 1d}}; RealMatrix transitionMatrixA = MatrixUtils.createRealMatrix(transitionValues); RealMatrix measuredMatrixX = MatrixUtils.createRealMatrix(measuredValues); // Xk = (A * Xk-1) prevMeasuredMatrix = transitionMatrixA.multiply(prevMeasuredMatrix); // Pk = (A * P * AT) + Q varianceMatrixP = (transitionMatrixA.multiply(varianceMatrixP)).multiply(transitionMatrixA.transpose()); // S = (H * P * HT) + R RealMatrix S = ((measurementMatrixH.multiply(varianceMatrixP)).multiply(measurementMatrixH.transpose())) .add(rMatrix); RealMatrix S_1 = new LUDecomposition(S).getSolver().getInverse(); // P * HT * S-1 RealMatrix kalmanGainMatrix = (varianceMatrixP.multiply(measurementMatrixH.transpose())).multiply(S_1); // Xk = Xk + kalmanGainMatrix (Zk - HkXk ) prevMeasuredMatrix = prevMeasuredMatrix.add( kalmanGainMatrix.multiply( (measuredMatrixX.subtract(measurementMatrixH.multiply(prevMeasuredMatrix))))); // Pk = Pk - K.Hk.Pk varianceMatrixP = varianceMatrixP.subtract( (kalmanGainMatrix.multiply(measurementMatrixH)).multiply(varianceMatrixP)); prevTimestamp = timestamp; return prevMeasuredMatrix.getRow(0)[0]; } }
private void computeFactorLoadings(double[] x) { uniqueness = x; communality = new double[nVariables]; for (int i = 0; i < nVariables; i++) { R.setEntry(i, i, 1.0 - x[i]); } EigenDecomposition E = new EigenDecomposition(R); RealMatrix L = E.getV().getSubMatrix(0, nVariables - 1, 0, nFactors - 1); double[] ev = new double[nFactors]; for (int i = 0; i < nFactors; i++) { ev[i] = Math.sqrt(E.getRealEigenvalue(i)); } DiagonalMatrix M = new DiagonalMatrix(ev); RealMatrix LOAD = L.multiply(M); // rotate factor loadings if (rotationMethod != RotationMethod.NONE) { GPArotation gpa = new GPArotation(); RotationResults results = gpa.rotate(LOAD, rotationMethod); LOAD = results.getFactorLoadings(); } Sum[] colSums = new Sum[nFactors]; Sum[] colSumsSquares = new Sum[nFactors]; for (int j = 0; j < nFactors; j++) { colSums[j] = new Sum(); colSumsSquares[j] = new Sum(); } factorLoading = new double[nVariables][nFactors]; for (int i = 0; i < nVariables; i++) { for (int j = 0; j < nFactors; j++) { factorLoading[i][j] = LOAD.getEntry(i, j); colSums[j].increment(factorLoading[i][j]); colSumsSquares[j].increment(Math.pow(factorLoading[i][j], 2)); communality[i] += Math.pow(factorLoading[i][j], 2); } } // check sign of factor double sign = 1.0; for (int i = 0; i < nVariables; i++) { for (int j = 0; j < nFactors; j++) { if (colSums[j].getResult() < 0) { sign = -1.0; } else { sign = 1.0; } factorLoading[i][j] = factorLoading[i][j] * sign; } } double totSumOfSquares = 0.0; sumsOfSquares = new double[nFactors]; proportionOfExplainedVariance = new double[nFactors]; proportionOfVariance = new double[nFactors]; for (int j = 0; j < nFactors; j++) { sumsOfSquares[j] = colSumsSquares[j].getResult(); totSumOfSquares += sumsOfSquares[j]; } for (int j = 0; j < nFactors; j++) { proportionOfExplainedVariance[j] = sumsOfSquares[j] / totSumOfSquares; proportionOfVariance[j] = sumsOfSquares[j] / nVariables; } }
@Override public List<MLCallbackResult> detect( final String user, final String algorithm, UserActivityAggModel userActivity, UserProfileEigenModel aModel) { RealMatrix inputData = userActivity.matrix(); LOG.warn( "EigenBasedAnomalyDetection predictAnomaly called with dimension: " + inputData.getRowDimension() + "x" + inputData.getColumnDimension()); if (aModel == null) { LOG.warn( "nothing to do as the input model does not have required values, returning from evaluating this algorithm.."); return null; } List<MLCallbackResult> mlCallbackResults = new ArrayList<MLCallbackResult>(); RealMatrix normalizedMat = normalizeData(inputData, aModel); UserCommandStatistics[] listStats = aModel.statistics(); int colWithHighVariant = 0; for (int j = 0; j < normalizedMat.getColumnDimension(); j++) { if (listStats[j].isLowVariant() == false) { colWithHighVariant++; } } final Map<String, String> context = new HashMap<String, String>() { { put(UserProfileConstants.USER_TAG, user); put(UserProfileConstants.ALGORITHM_TAG, algorithm); } }; Map<Integer, String> lineNoWithVariantBasedAnomalyDetection = new HashMap<Integer, String>(); for (int i = 0; i < normalizedMat.getRowDimension(); i++) { MLCallbackResult aResult = new MLCallbackResult(); aResult.setContext(context); for (int j = 0; j < normalizedMat.getColumnDimension(); j++) { // LOG.info("mean for j=" + j + " is:" + listStats[j].getMean()); // LOG.info("stddev for j=" + j + " is:" + listStats[j].getStddev()); if (listStats[j].isLowVariant() == true) { // LOG.info(listOfCmds[j] + " is low variant"); if (normalizedMat.getEntry(i, j) > listStats[j].getMean()) { lineNoWithVariantBasedAnomalyDetection.put(i, "lowVariantAnomaly"); aResult.setAnomaly(true); aResult.setTimestamp(userActivity.timestamp()); aResult.setFeature(listStats[j].getCommandName()); aResult.setAlgorithm(UserProfileConstants.EIGEN_DECOMPOSITION_ALGORITHM); List<String> datapoints = new ArrayList<String>(); double[] rowVals = inputData.getRow(i); for (double rowVal : rowVals) datapoints.add(rowVal + ""); aResult.setDatapoints(datapoints); aResult.setId(user); mlCallbackResults.add(aResult); } else { aResult.setAnomaly(false); aResult.setTimestamp(userActivity.timestamp()); mlCallbackResults.add(aResult); } } } // return results; } // LOG.info("results size here: " + results.length); // LOG.info("col with high variant: " + colWithHighVariant); RealMatrix finalMatWithoutLowVariantFeatures = new Array2DRowRealMatrix(normalizedMat.getRowDimension(), colWithHighVariant); // LOG.info("size of final test data: " + finalMatWithoutLowVariantFeatures.getRowDimension() // +"x"+ finalMatWithoutLowVariantFeatures.getColumnDimension()); int finalMatrixRow = 0; int finalMatrixCol = 0; for (int i = 0; i < normalizedMat.getRowDimension(); i++) { for (int j = 0; j < normalizedMat.getColumnDimension(); j++) { if (listStats[j].isLowVariant() == false) { finalMatWithoutLowVariantFeatures.setEntry( finalMatrixRow, finalMatrixCol, normalizedMat.getEntry(i, j)); finalMatrixCol++; } } finalMatrixCol = 0; finalMatrixRow++; } RealVector[] pcs = aModel.principalComponents(); // LOG.info("pc size: " + pcs.getRowDimension() +"x" + pcs.getColumnDimension()); RealMatrix finalInputMatTranspose = finalMatWithoutLowVariantFeatures.transpose(); for (int i = 0; i < finalMatWithoutLowVariantFeatures.getRowDimension(); i++) { if (lineNoWithVariantBasedAnomalyDetection.get(i) == null) { MLCallbackResult result = new MLCallbackResult(); result.setContext(context); for (int sz = 0; sz < pcs.length; sz++) { double[] pc1 = pcs[sz].toArray(); RealMatrix pc1Mat = new Array2DRowRealMatrix(pc1); RealMatrix transposePC1Mat = pc1Mat.transpose(); RealMatrix testData = pc1Mat.multiply(transposePC1Mat).multiply(finalInputMatTranspose.getColumnMatrix(i)); // LOG.info("testData size: " + testData.getRowDimension() + "x" + // testData.getColumnDimension()); RealMatrix testDataTranspose = testData.transpose(); // LOG.info("testData transpose size: " + testDataTranspose.getRowDimension() + "x" + // testDataTranspose.getColumnDimension()); RealVector iRowVector = testDataTranspose.getRowVector(0); // RealVector pc1Vector = transposePC1Mat.getRowVector(sz); RealVector pc1Vector = transposePC1Mat.getRowVector(0); double distanceiRowAndPC1 = iRowVector.getDistance(pc1Vector); // LOG.info("distance from pc sz: " + sz + " " + distanceiRowAndPC1 + " " + // model.getMaxL2Norm().getEntry(sz)); // LOG.info("model.getMaxL2Norm().getEntry(sz):" + model.getMaxL2Norm().getEntry(sz)); if (distanceiRowAndPC1 > aModel.maximumL2Norm().getEntry(sz)) { // LOG.info("distance from pc sz: " + sz + " " + distanceiRowAndPC1 + " " + // model.getMaxL2Norm().getEntry(sz)); result.setAnomaly(true); result.setFeature(aModel.statistics()[sz].getCommandName()); result.setTimestamp(System.currentTimeMillis()); result.setAlgorithm(UserProfileConstants.EIGEN_DECOMPOSITION_ALGORITHM); List<String> datapoints = new ArrayList<String>(); double[] rowVals = inputData.getRow(i); for (double rowVal : rowVals) datapoints.add(rowVal + ""); result.setDatapoints(datapoints); result.setId(user); } } mlCallbackResults.add(result); } } return mlCallbackResults; }
private double generalizedCorrelationRatio(SampleIterator it, int inputDim, int out) { Map<Double, Integer> n_y = new HashMap<>(); Map<Double, MultivariateSummaryStatistics> stat_y = new HashMap<>(); List<RealMatrix> x = new ArrayList<>(); MultivariateSummaryStatistics stat = new MultivariateSummaryStatistics(inputDim, unbiased); for (int i = 0; i < maxSamples && it.hasNext(); i++) { Sample sample = it.next(); double[] input = sample.getEncodedInput().toArray(); double output = sample.getEncodedOutput().getEntry(out); if (!n_y.containsKey(output)) { n_y.put(output, 0); stat_y.put(output, new MultivariateSummaryStatistics(inputDim, unbiased)); } injectNoise(input); n_y.put(output, n_y.get(output) + 1); stat_y.get(output).addValue(input); x.add(new Array2DRowRealMatrix(input)); stat.addValue(input); } RealMatrix x_sum = new Array2DRowRealMatrix(stat.getSum()); Map<Double, RealMatrix> x_y_sum = new HashMap<>(); for (Entry<Double, MultivariateSummaryStatistics> entry : stat_y.entrySet()) { x_y_sum.put(entry.getKey(), new Array2DRowRealMatrix(entry.getValue().getSum())); } RealMatrix H = new Array2DRowRealMatrix(inputDim, inputDim); RealMatrix temp = new Array2DRowRealMatrix(inputDim, inputDim); for (double key : n_y.keySet()) { temp = temp.add( x_y_sum .get(key) .multiply(x_y_sum.get(key).transpose()) .scalarMultiply(1.0 / n_y.get(key))); } H = temp.subtract(x_sum.multiply(x_sum.transpose()).scalarMultiply(1.0 / x.size())); RealMatrix E = new Array2DRowRealMatrix(inputDim, inputDim); for (RealMatrix m : x) { E = E.add(m.multiply(m.transpose())); } E = E.subtract(temp); List<Integer> zeroColumns = findZeroColumns(E); E = removeZeroColumns(E, zeroColumns); H = removeZeroColumns(H, zeroColumns); Matrix JE = new Matrix(E.getData()); Matrix JH = new Matrix(H.getData()); if (JE.rank() < JE.getRowDimension()) { Log.write(this, "Some error occurred (E matrix is singular)"); return -1; } else { double lambda; if (useEigenvalues) { Matrix L = JE.inverse().times(JH); double[] eigs = L.eig().getRealEigenvalues(); Arrays.sort(eigs); lambda = 1; int nonNullEigs = n_y.keySet().size() - 1; for (int i = eigs.length - nonNullEigs; i < eigs.length; i++) { if (Math.abs(eigs[i]) < zeroThreshold) { Log.write(this, "Some error occurred (E matrix has too many null eigenvalues)"); return -1; } lambda *= 1.0 / (1.0 + eigs[i]); } } else { Matrix sum = JE.plus(JH); if (sum.rank() < sum.getRowDimension()) { Log.write(this, "Some error occourred (E+H is singular"); return -1; } lambda = JE.det() / sum.det(); } return Math.sqrt(1 - lambda); } }