NN don't evaluate well with back propagation algorithm - java

I've tried to create a basic NN using the book
"Make Your Own Neural Network" by Tariq Rashid
and using the coding train videos:
https://www.youtube.com/watch?v=XJ7HLz9VYz0&list=PLRqwX-V7Uu6aCibgK1PTWWu9by6XFdCfh
and the nn.js class on the coding train git as a reference
https://github.com/shiffman/Neural-Network-p5/blob/master/nn.js
I writing the NN network in java, and I tried just like in the playlist to train the network on XOR after I succeeded in doing a single perceptron.
but for some reason, even though my code is similar to what the book is doing and same in the videos (except in the videos he using JS).
when I train the network for around 500000 times with randomized data set of XOR inputs (total of 4 input [1,0] [0,1] [0,0] [1,1]).
when I giving it to guess after the training the all the 4 options I get results closer to 0.5 than to 1,1,0,0 (the order of the inputs in the test are [1,0] [0,1] [0,0] [1,1])
this is my training function:
public void train(double [] inputs, double[] target) {
//generates the Hidden layer values
this.input = Matrix.fromArrayToMatrix(inputs);
feedForward(inputs);
//convert to matrices
Matrix targets = Matrix.fromArrayToMatrix(target);
//calculate the output error
Matrix outputErrors = Matrix.subtract(targets, output);
//calculate the Gradient
Matrix outputGradient = Matrix.map(output, NeuralNetwork::sigmoidDerivative);
outputGradient = Matrix.matrixMultiplication(outputGradient, outputErrors);
outputGradient.multiply(this.learningRate);
//adjust the output layer bias
this.bias_Output.add(outputGradient);
//calculate the hidden layer weights delta
Matrix hiddenT = Matrix.Transpose(hidden);
Matrix hiddenToOutputDelta = Matrix.matrixMultiplication(outputGradient, hiddenT);
//adjust the hidden layer weights
this.weightsHiddenToOutput.add(hiddenToOutputDelta);
//calculate the hidden layer error
Matrix weightsHiddenToOutputT = Matrix.Transpose(weightsHiddenToOutput);
Matrix hiddenErrors = Matrix.matrixMultiplication(weightsHiddenToOutputT, outputErrors);
//calculate the hidden gradient
Matrix hiddenGradient = Matrix.map(this.hidden, NeuralNetwork::sigmoidDerivative);
hiddenGradient = Matrix.matrixMultiplication(hiddenGradient, hiddenErrors);
hiddenGradient.multiply(this.learningRate);
//adjust the hidden layer bias
this.bias_Hidden.add(hiddenGradient);
//calculate the input layer weights delta
Matrix inputT = Matrix.Transpose(this.input);
Matrix inputToHiddenDelta = Matrix.matrixMultiplication(hiddenGradient, inputT);
//adjust the hidden layer weights
this.weightsInputToHidden.add(inputToHiddenDelta);
}
those are the sigmoid functions:
private static double sigmoid(double x) {
return 1d / (1d+ Math.exp(-x));
}
private static double sigmoidDerivative(double x) {
return (x * (1d - x));
}
I'm using this method to calculate the derivative because the network already getting the sigmoid function on the feed-forward process so all I do is calculate the derivative like that.
and this is my guess/ feedforward function:
public double[] feedForward(double [] inputs) {
double[] guess;
//generates the Hidden layer values
input = Matrix.fromArrayToMatrix(inputs);
hidden = Matrix.matrixMultiplication(weightsInputToHidden, input);
hidden.add(bias_Hidden);
//activation function
hidden.map(NeuralNetwork::sigmoid);
//Generates the output layer values
output = Matrix.matrixMultiplication(weightsHiddenToOutput, hidden);
output.add(bias_Output);
//activation function
output.map(NeuralNetwork::sigmoid);
guess = Matrix.fromMatrixToArray(output);
return guess;
}
this is in the main class the data set I'm giving him:
NeuralNetwork nn = new NeuralNetwork(2,2,1);
double [] label0 = {0};
double [] label1 = {1};
Literal l1 = new Literal(label1,0,1);
Literal l2 = new Literal(label1,1,0);
Literal l3 = new Literal(label0,0,0);
Literal l4 = new Literal(label0,1,1);
Literal[] arr = {l1, l2, l3, l4};
Random random = new Random();
for(int i = 0 ; i<500000 ; i++) {
Literal l = arr[i%4];
nn.train(l.getTruthValue(), l.getLabel());
}
System.out.println(Arrays.toString(nn.feedForward(l1.getTruthValue())));
System.out.println(Arrays.toString(nn.feedForward(l2.getTruthValue())));
System.out.println(Arrays.toString(nn.feedForward(l3.getTruthValue())));
System.out.println(Arrays.toString(nn.feedForward(l4.getTruthValue())));
but for some reason the outputs look like that:
[0.47935468493879807]
[0.5041956026507048]
[0.4575246472403595]
[0.5217568912941623]
I've tried changing it to subtract instead of add-on every bias and weights update (cause you need the negative gradient although both in the book and in the videos they use add instead of subtract) meaning changing those 4 lines to subtract:
this.bias_Output.subtract(outputGradient);
this.weightsHiddenToOutput.subtract(hiddenToOutputDelta);
this.bias_Hidden.subtract(hiddenGradient);
this.weightsInputToHidden.subtract(inputToHiddenDelta);
those are the 2 main outputs I get:
[0.9999779359460259]
[0.9999935716126019]
[0.9999860145346924]
[0.999990155468117]
or
[1.7489664881918983E-5]
[6.205315404676972E-6]
[8.41530873105465E-6]
[1.1853929628341918E-5]
I'm pretty sure the problem isn't in my Matrix class that I've created because I checked it before and all the add, subtract, multiply, transpose and it worked fine.
I would really appreciate if someone could look at this code and help me to figure out the problem

Related

Minimize portoflio return difference using ojAlgo

I have a dataset of daily prices for a portfolio (I do not have details about the constituents, simply the total daily price). My goal is to select n funds from a pool of funds and create a new portfolio with daily returns as close as possible compared to the original portfolio. I came up with the following formula to describe the problem:
with Yi the original portfolio returns, π the fund weights and X the fund returns.
Additionally, I defined 3 constraints:
To solve this I need to use ojAlgo. I tried the following but I almost instantly got stuck because of 2 issues.
public static void main(String[] [] args){
ExpressionsBasedModel model = new ExpressionsBasedModel();
float[] x1 = getDailyReturns("fund1");
float[] x2 = getDailyReturns("fund2");
float[] x3 = getDailyReturns("fund3");
Variable pi1 = new Variable("pi1");
Variable pi2 = new Variable("pi2");
Variable pi3 = new Variable("pi3");
List<Variable> variables = Arrays.asList(w1, w2, w3);
model.addVariables(variables);
Expression expr = model.addExpression("objective");
expr.setLinearFactor(pi1, x1);
expr.setLinearFactor(pi2, x2);
expr.setLinearFactor(pi3, x3);
expr.weight(1.0);
Optimisation.Result result = model.minimise();
}
First of all, I have X as a vector while .setLinearFactor can only use Number. Secondly I obviously missed something on how I should define the Expression.
Do you know where I could find examples helping me understanding how I am supposed to use the ExpressionBasedModel() for my problem?
Thank you

What input should I use for my Neural Network?

I recently implemented a simple Deep Q-Learning agent in Processing for a game called Frozen Lake (game from OpenAI Gym). The agent basically has to find the shortest path between the starting and the ending points, avoiding obstacles (holes in the ice) and without going out of the map.
This is the code that generates the state passed to the Neural Network:
//Return an array of double containing all 0s except for the cell the Agent is on that is 1.
private double[] getState()
{
double[] state = new double[cellNum];
for(Cell cell : lake.cells)
{
if((x - cellDim/2) == cell.x && (y - cellDim/2) == cell.y)
{
state[lake.cells.indexOf(cell)] = 1;
}
else
{
state[lake.cells.indexOf(cell)] = 0;
}
}
return state;
}
where lake is the environment object, cells is an ArrayList attribute of lake containing all the squares of the map, x and y are the agent's coordinates on the map.
And all of this works well, but the agent only learns the best path for a single game map and if the map changes the agent must be trained all over again.
I wanted the agent to learn how to play the game and not how to play a single map.
So, instead of setting all the map squares to 0 except the one the agent is on that is set to 1, I tried to associated some random numbers for every kind of square (Goal:1, Ice:8, Hole:0, Goal:3, Agent:7) and set the input like that, but it didn't work at all.
So I tried to convert all the colors of the squares into a grayscale value (from 0 to 255), so that now the different squares were mapped as (roughly): Goal:45, Ice:243.37, Hole:34.57, Goal:70.8, Agent:150.
But this didn't work either, so I mapped all the grayscale values to values between 0 and 1.
But no result with this either.
By the way, this is the code for the Neural Network to calculate the output:
public Layer[] estimateOutput(double[] input)
{
Layer[] neurons = new Layer[2]; //Hidden neurons [0] and Output neurons [1].
neurons[0] = new Layer(input); //To be transformed into Hidden neurons.
//Hidden neurons values calculation.
neurons[0] = neurons[0].dotProduct(weightsHiddenNeurons).addition(biasesHiddenNeurons).sigmoid();
//Output neurons values calculation.
neurons[1] = neurons[0].dotProduct(weightsOutputNeurons).addition(biasesOutputNeurons);
if(gameData.trainingGames == gameData.gamesThreshold)
{
//this.render(new Layer(input), neurons[0], neurons[1].sigmoid()); //Draw Agent's Neural Network.
}
return neurons;
}
and to learn:
public void learn(Layer inputNeurons, Layer[] neurons, Layer desiredOutput)
{
Layer hiddenNeurons = neurons[0];
Layer outputNeurons = neurons[1];
Layer dBiasO = (outputNeurons.subtraction(desiredOutput)).valueMultiplication(2);
Layer dBiasH = (dBiasO.dotProduct(weightsOutputNeurons.transpose())).layerMultiplication((inputNeurons.dotProduct(weightsHiddenNeurons).addition(biasesHiddenNeurons)).sigmoidDerivative());
Layer dWeightO = (hiddenNeurons.transpose()).dotProduct(dBiasO);
Layer dWeightH = (inputNeurons.transpose()).dotProduct(dBiasH);
//Set new values for Weights and Biases
weightsHiddenNeurons = weightsHiddenNeurons.subtraction(dWeightH.valueMultiplication(learningRate));
biasesHiddenNeurons = biasesHiddenNeurons.subtraction(dBiasH.valueMultiplication(learningRate));
weightsOutputNeurons = weightsOutputNeurons.subtraction(dWeightO.valueMultiplication(learningRate));
biasesOutputNeurons = biasesOutputNeurons.subtraction(dBiasO.valueMultiplication(learningRate));
}
Anyway, the whole project is available on GitHub, where the code is better commented: https://github.com/Nyphet/Frozen-Lake-DQL
What am I doing wrong on setting the input? How can I achieve "learning the game" instead of "learning the map"?
Thanks in advance.

How to prevent genetic algorithm from converging on local minima?

I am trying to build a 4 x 4 sudoku solver by using the genetic algorithm. I have some issues with values converging to local minima. I am using a ranked approach and removing the bottom two ranked answer possibilities and replacing them with a crossover between the two highest ranked answer possibilities. For additional help avoiding local mininma, I am also using mutation. If an answer is not determined within a specific amount of generation, my population is filled with completely new and random state values. However, my algorithm seems to get stuck in local minima. As a fitness function, I am using:
(Total Amount of Open Squares * 7 (possible violations at each square; row, column, and box)) - total Violations
population is an ArrayList of integer arrays in which each array is a possible end state for sudoku based on the input. Fitness is determined for each array in the population.
Would someone be able to assist me in determining why my algorithm converges on local minima or perhaps recommend a technique to use to avoid local minima. Any help is greatly appreciated.
Fitness Function:
public int[] fitnessFunction(ArrayList<int[]> population)
{
int emptySpaces = this.blankData.size();
int maxError = emptySpaces*7;
int[] fitness = new int[populationSize];
for(int i=0; i<population.size();i++)
{
int[] temp = population.get(i);
int value = evaluationFunc(temp);
fitness[i] = maxError - value;
System.out.println("Fitness(i)" + fitness[i]);
}
return fitness;
}
Crossover Function:
public void crossover(ArrayList<int[]> population, int indexWeakest, int indexStrong, int indexSecStrong, int indexSecWeak)
{
int[] tempWeak = new int[16];
int[] tempStrong = new int[16];
int[] tempSecStrong = new int[16];
int[] tempSecWeak = new int[16];
tempStrong = population.get(indexStrong);
tempSecStrong = population.get(indexSecStrong);
tempWeak = population.get(indexWeakest);
tempSecWeak = population.get(indexSecWeak);
population.remove(indexWeakest);
population.remove(indexSecWeak);
int crossoverSite = random.nextInt(14)+1;
for(int i=0;i<tempWeak.length;i++)
{
if(i<crossoverSite)
{
tempWeak[i] = tempStrong[i];
tempSecWeak[i] = tempSecStrong[i];
}
else
{
tempWeak[i] = tempSecStrong[i];
tempSecWeak[i] = tempStrong[i];
}
}
mutation(tempWeak);
mutation(tempSecWeak);
population.add(tempWeak);
population.add(tempSecWeak);
for(int j=0; j<tempWeak.length;j++)
{
System.out.print(tempWeak[j] + ", ");
}
for(int j=0; j<tempWeak.length;j++)
{
System.out.print(tempSecWeak[j] + ", ");
}
}
Mutation Function:
public void mutation(int[] mutate)
{
if(this.blankData.size() > 2)
{
Blank blank = this.blankData.get(0);
int x = blank.getPosition();
Blank blank2 = this.blankData.get(1);
int y = blank2.getPosition();
Blank blank3 = this.blankData.get(2);
int z = blank3.getPosition();
int rando = random.nextInt(4) + 1;
if(rando == 2)
{
int rando2 = random.nextInt(4) + 1;
mutate[x] = rando2;
}
if(rando == 3)
{
int rando2 = random.nextInt(4) + 1;
mutate[y] = rando2;
}
if(rando==4)
{
int rando3 = random.nextInt(4) + 1;
mutate[z] = rando3;
}
}
The reason you see rapid convergence is that your methodology for "mating" is not very good. You are always producing two offspring from "mating" of the top two scoring individuals. Imagine what happens when one of the new offspring is the same as your top individual (by chance, no crossover and no mutation, or at least none that have an effect on the fitness). Once this occurs, the top two individuals are identical which eliminates the effectiveness of crossover.
A more typical approach is to replace EVERY individual on every generation. There are lots of possible variations here, but you might do a random choice of two parents weighted fitness.
Regarding population size: I don't know how hard of a problem sudoku is given your genetic representation and fitness function, but I suggest that you think about millions of individuals, not dozens.
If you are working on really hard problems, genetic algorithms are much more effective when you place your population on a 2-D grid and choosing "parents" for each point in the grid from the nearby individuals. You will get local convergence, but each locality will have converged on different solutions; you get a huge amount of variation produced from the borders between the locally-converged areas of the grid.
Another technique you might think about is running to convergence from random populations many times and store the top individual from each run. After you build up a bunch of different local minima genomes, build a new random population from those top individuals.
I think the Sudoku is a permutation problem. therefore i suggest you to use random permutation numbers for initializing population and use the crossover method which Compatible to permutation problems.

Apache Commons Math BicubicSplineInterpolator is returning strange interpolated values

The BicubicSplineInterpolator is returning some curious results for my input set.
Here is my test case:
double[] xValues = new double[] {36, 36.001, 36.002};
double[] yValues = new double[] {-108.00, -107.999, -107.998};
double[][] fValues = new double[][] {{1915, 1906, 1931},
{1877, 1889, 1894},
{1878, 1873, 1888}};
BicubicSplineInterpolator interpolator = new BicubicSplineInterpolator();
BicubicSplineInterpolatingFunction interpolatorFunction = interpolator.interpolate(xValues, yValues, fValues);
double[][] results = new double[9][9];
double x = 36;
int arrayIndexX = 0;
int arrayIndexY = 0;
while(x <= 36.002)
{
double y = -108;
arrayIndexY = 0;
while (y <= -107.998)
{
results[arrayIndexX][arrayIndexY] = interpolatorFunction.value(x, y);
System.out.println(results[arrayIndexX][arrayIndexY]);
y = y + 0.00025;
arrayIndexY++;
}
x = x + 0.00025;
arrayIndexX++;
}
After running this snippet of code, the interpolated values contained within the results array are:
1915.0
-3938.5937499822526
-1760.2500002294219
2246.2187497695777
1877.000000525819
250.9999999288558
1803.7499996906008
3403.374999905478
1889.0000007034323
-922.343750031719
390070.8886686283
320411.8593862744
91169.82228340462
3414.031240516051
140099.0224580196
124712.34376105569
48068.829113991116
2932.7499997298
-1277.0000000323469
335413.0390564674
264381.1250073778
61474.21095159976
2539.249988033902
335702.3671824192
264764.37503049
61763.88284085272
2547.749982131645
-37.90625000258933
112126.77147883564
76170.70312516135
2453.8925818554126
1336.3437417931855
362677.29393607465
272636.7187811567
46134.229521767236
1834.6249738819897
1877.0000000976995
-1228.312492238307
-1778.749983159687
-501.0624825709448
1877.9999996234117
304.4687496629192
1787.2500015275245
3316.9062529374487
1873.0000007069889
3414.031249990962
153858.71874489737
320991.32811795553
328540.929697798
236.59381305763964
49250.68456339003
124800.53124625524
139093.54200382315
1640.9687914999472
2539.249999955474
140423.82030525914
265019.87498830666
257740.9296891929
0.5000480143353343
140431.7734211699
265401.6249928146
258308.9765831194
5.500072199653914
1336.343749981772
56546.050777358614
76540.60936913849
58774.425778594334
701.9062589909881
161169.991191242
273494.90623999
249357.90724363495
-692.468683006271
For a set of f values that are between ~1800 and ~2000 as defined above, I'm not sure why there are negative values in the interpolation set. Additionally there values that are much greater than the largest value in the input set, such as 257740.9296891929 and 249357.90724363495.
I set up this input set in MatLab to compare my results using the interp2 cubic method and the results from MatLab are much more along the lines of what I would have expected. Here are the results for the same input set in MatLab:
1915
1901.84375000034
1891.12500000000
1882.84375000020
1877
1873.59375000003
1872.62499999999
1874.09375000004
1878
1909.56249999997
1900.16796875024
1892.21875000001
1885.71484375018
1880.65625000002
1877.04296875006
1874.87500000006
1874.15234375000
1874.87499999998
1906.24999999997
1899.57812500018
1893.62500000002
1888.39062500018
1883.87500000004
1880.07812500009
1877.00000000011
1874.64062499998
1872.99999999998
1905.06250000000
1900.07421875013
1895.34374999999
1890.87109375011
1886.65624999998
1882.69921875004
1879.00000000009
1875.55859374994
1872.37500000000
1906.00000000006
1901.65625000018
1897.37500000006
1893.15625000018
1889.00000000006
1884.90625000011
1880.87500000017
1876.90624999999
1873.00000000004
1909.06250000012
1904.32421875022
1899.71875000007
1895.24609375018
1890.90625000005
1886.69921875010
1882.62500000016
1878.68359375000
1874.87500000007
1914.25000000000
1908.07812500017
1902.37500000000
1897.14062500014
1892.37500000000
1888.07812500006
1884.25000000010
1880.89062499996
1878
1921.56250000000
1912.91796875023
1905.34375000000
1898.83984375017
1893.40625000000
1889.04296875005
1885.75000000008
1883.52734374998
1882.37500000000
1931
1918.84375000032
1908.62500000000
1900.34375000021
1894
1889.59375000005
1887.12500000004
1886.59375000001
1888
One other point of note. When the number of decimal points are reduced from 3 to 2 and 2 to 1 for the x and y values (such as 36.01 or 36.1), the interpolated results gravitate toward the "expected" realm (1800-2000). The negative numbers and extremely large numbers begin to disappear.
I am using version 3.3 of the commons math library.
Any insight as to why these values are being interpolated as such would be greatly appreciated. Thank you.

Visualizing Kmean Clustering

I'm doing a KMean clustering on a 12 dimensional matrix. I managed to get the result in K set of cluster. I want to show the result by plotting it into a 2D graph, but I can't figure it out how can I convert the 12 dimension data into 2 dimension.
Any suggestion on how can I do the conversion or any alternative ways on visualizing the result? I tried Multidimensional Scaling for Java (MDSJ) but it did not work.
The KMean algorithm I'm using was from the Java Machine Learning Library: Clustering basics.
I would do Principal Component Analysis (probably the easiest algorithm from Multidimensional scaling algorithms). (BTW PCA has nothing to do with KMeans, it is a general method for dimensionality reduction)
I assume variables are in columns, observations are in rows.
Standardize the data - convert variables to z-scores. That means: from each cell, subtract the mean of the column and devide the result by the std. deviation of the column. That way you get zero mean and unit variance. The former is obligatory, the latter, I would say, good to do. If you have zero variance, you calculate the eigen-vectors from the covariance matrix, otherwise have to use correlation matrix which kind of standardizes the data automatically. See this for explanation).
Calculate eigen-vectors and eigen-values of the covariance matrix. Sort the eigen-vectors by the eigen-values. (Many libraries already give you eigen-vectors sorted that way).
Use first two columns of the eigen-vector matrix and multiply the original matrix (converted to z-scores), visualize this data.
Using the colt library, you can do the following. It will be similar with other matrix libraries:
import cern.colt.matrix.DoubleMatrix1D;
import cern.colt.matrix.DoubleMatrix2D;
import cern.colt.matrix.doublealgo.Statistic;
import cern.colt.matrix.impl.SparseDoubleMatrix2D;
import cern.colt.matrix.linalg.Algebra;
import cern.colt.matrix.linalg.EigenvalueDecomposition;
import hep.aida.bin.DynamicBin1D;
public class Pca {
// to show matrix creation, it does not make much sense to calculate PCA on random data
public static void main(String[] x) {
double[][] data = {
{2.0,4.0,1.0,4.0,4.0,1.0,5.0,5.0,5.0,2.0,1.0,4.0},
{2.0,6.0,3.0,1.0,1.0,2.0,6.0,4.0,4.0,4.0,1.0,5.0},
{3.0,4.0,4.0,4.0,2.0,3.0,5.0,6.0,3.0,1.0,1.0,1.0},
{3.0,6.0,3.0,3.0,1.0,2.0,4.0,6.0,1.0,2.0,4.0,4.0},
{1.0,6.0,4.0,2.0,2.0,2.0,3.0,4.0,6.0,3.0,4.0,1.0},
{2.0,5.0,5.0,3.0,1.0,1.0,6.0,6.0,3.0,2.0,6.0,1.0}
};
DoubleMatrix2D matrix = new DenseDoubleMatrix2D(data);
DoubleMatrix2D pm = pcaTransform(matrix);
// print the first two dimensions of the transformed matrix - they capture most of the variance of the original data
System.out.println(pm.viewPart(0, 0, pm.rows(), 2).toString());
}
/** Returns a matrix in the space of principal components, take the first n columns */
public static DoubleMatrix2D pcaTransform(DoubleMatrix2D matrix) {
DoubleMatrix2D zScoresMatrix = toZScores(matrix);
final DoubleMatrix2D covarianceMatrix = Statistic.covariance(zScoresMatrix);
// compute eigenvalues and eigenvectors of the covariance matrix (flip needed since it is sorted by ascending).
final EigenvalueDecomposition decomp = new EigenvalueDecomposition(covarianceMatrix);
// Columns of Vs are eigenvectors = principal components = base of the new space; ordered by decreasing variance
final DoubleMatrix2D Vs = decomp.getV().viewColumnFlip();
// eigenvalues: ev(i) / sum(ev) is the percentage of variance captured by i-th column of Vs
// final DoubleMatrix1D ev = decomp.getRealEigenvalues().viewFlip();
// project the original matrix to the pca space
return Algebra.DEFAULT.mult(zScoresMatrix, Vs);
}
/**
* Converts matrix to a matrix of z-scores (by columns)
*/
public static DoubleMatrix2D toZScores(final DoubleMatrix2D matrix) {
final DoubleMatrix2D zMatrix = new SparseDoubleMatrix2D(matrix.rows(), matrix.columns());
for (int c = 0; c < matrix.columns(); c++) {
final DoubleMatrix1D column = matrix.viewColumn(c);
final DynamicBin1D bin = Statistic.bin(column);
if (bin.standardDeviation() == 0) { // use epsilon
for (int r = 0; r < matrix.rows(); r++) {
zMatrix.set(r, c, 0.0);
}
} else {
for (int r = 0; r < matrix.rows(); r++) {
double zScore = (column.get(r) - bin.mean()) / bin.standardDeviation();
zMatrix.set(r, c, zScore);
}
}
}
return zMatrix;
}
}
You could also use weka. I would first load your data into weka, then run PCA using the GUI (under attribute selection). You will see what classes are called with what parameters and then do the same thing from your code. The problem is you will need to convert/wrap your matrix into the data format weka works with.
A similar question has been discussed on CrossValidated2. The basic idea is to find an appropriate projection that separates these clusters (e.g., with discproj in R) and then to plot the projection on the clusters on the new space.
In addition to what the other answers suggest you should probably have a look at multidimensional scaling too.

Categories