[Home] Restricted access for guests. The link to Java source code is disabled
Java source code of 'jhplot.bsom.BsomDemo'
package jhplot.bsom;
import java.awt.*;
import java.lang.Math; // import Slider;
import java.util.Hashtable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.lang.Math;
/**
* BsomDemo is an applet for the demonstration of Bayesian Self-Organizing Maps.
* The following parameters are used: 'data' is the number of data points. (def.
* 100) 'unit' is the number of inner units (weight points). (def. 20) 'amin' is
* the power of 10 for minimum alpha. (def. 0.) 'amax' is the power of 10 for
* maximum alpha. (def. 5.) 'bmin' is the power of 10 for minimum beta. (def.
* 0.) 'bmax' is the power of 10 for maximum beta. (def. 5.) 'init_weight' is
* the size of initial random weights. (def. 0.1) (xd, yd) is the position of
* origin of mathematical space in display. (def. 210, 150) 'scale' is the scale
* factor from mathematical space to display. (def. 70) 'dstep' is the size of a
* cell for density calculation. (def. 10)
*
* @author A.Utsugi and S.Chekanov
*/
public class BsomDemo extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
protected DrawArea drawArea;
protected AlphaSlider alphaSlider;
protected BetaSlider betaSlider;
protected WidthSlider widthSlider;
protected HeightSlider heightSlider;
protected PhaseSlider phaseSlider;
protected NoiseSlider noiseSlider;
protected JButton initButton;
protected JCheckBox learnButton;
protected JCheckBox autoButton;
protected JCheckBox densityButton;
protected JTextField unitNumberText;
protected int xd, yd;
protected double scale;
protected int n_data, n_unit;
protected int dstep;
public static double delta=0.000001;
double width_range = 2.;
double height_range = 2.;
double phase_range = 0.5;
double noise_range = 0.5;
double initial_width = 2.;
double initial_height = 1.;
double initial_noise_level = 0.2;
double initial_phase = 0.;
double initial_weight_level = 0.1;
protected double alpha_min_power, alpha_max_power;
protected double beta_min_power, beta_max_power;
protected double initial_alpha, initial_beta;
public void init() {
String p;
/* Get parameters. */
n_data = 100;
n_unit = 20;
alpha_min_power = 0.0;
alpha_max_power = 5.0;
beta_min_power = 0;
beta_max_power = 5.0;
/*
*
* p = getParameter("data"); if(p == null){ p = "100"; } n_data =
* Integer.valueOf(p).intValue();
*
* p = getParameter("unit"); if(p == null){ p = "20"; } n_unit =
* Integer.valueOf(p).intValue();
*
* p = getParameter("amin"); if(p == null){ p = "0."; } alpha_min_power
* = Double.valueOf(p).doubleValue();
*
* p = getParameter("amax"); if(p == null){ p = "5."; } alpha_max_power
* = Double.valueOf(p).doubleValue();
*
* p = getParameter("bmin"); if(p == null){ p = "0."; } beta_min_power =
* Double.valueOf(p).doubleValue();
*
* p = getParameter("bmax"); if(p == null){ p = "5."; } beta_max_power =
* Double.valueOf(p).doubleValue();
*/
initial_alpha = Math.pow(10., alpha_max_power);
initial_beta = Math.pow(10., beta_min_power);
xd = 210;
yd = 150;
scale = 70;
dstep = 10;
initial_weight_level = 0.1;
/*
* p = getParameter("xd"); if(p == null){ p = "210"; } xd =
* Integer.valueOf(p).intValue();
*
* p = getParameter("yd"); if(p == null){ p = "150"; } yd =
* Integer.valueOf(p).intValue();
*
* p = getParameter("scale"); if(p == null){ p = "70"; } scale =
* (double)Integer.valueOf(p).intValue();
*
* p = getParameter("dstep"); if(p == null){ p = "10"; } dstep =
* Integer.valueOf(p).intValue();
*
*
* p = getParameter("init_weight"); if(p == null){ p = "0.1"; }
* initial_weight_level = Double.valueOf(p).doubleValue();
*/
/* Layout */
setLayout(new BorderLayout());
// Draw area
drawArea = new DrawArea(this, xd, yd, scale);
drawArea.setBackground(Color.white);
drawArea.setSize(new Dimension(600, 400));
drawArea.n_data = n_data;
drawArea.n_unit = n_unit;
drawArea.dstep = dstep;
drawArea.width = initial_width;
drawArea.height = initial_height;
drawArea.noise_level = initial_noise_level;
drawArea.phase = initial_phase;
drawArea.initial_weight_level = initial_weight_level;
drawArea.alpha = initial_alpha;
drawArea.beta = initial_beta;
add("Center", drawArea);
// Control panel
JPanel controlPanel = new JPanel();
// Button panel
JPanel buttonPanel = new JPanel();
JPanel unitNumberPanel;
buttonPanel.setLayout(new GridLayout(5, 1));
learnButton = new JCheckBox("learn");
learnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
drawArea.learn = learnButton.isSelected();
if (!drawArea.learn && drawArea.auto_learn) {
drawArea.auto_learn = false;
autoButton.setSelected(false);
}
}
});
autoButton = new JCheckBox("auto");
autoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
drawArea.auto_learn = autoButton.isSelected();
if (!drawArea.learn && drawArea.auto_learn) {
drawArea.learn = true;
learnButton.setSelected(true);
}
}
});
densityButton = new JCheckBox("density");
densityButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (densityButton.isSelected()) {
drawArea.stop();
drawArea.density_mode = true;
drawArea.repaint();
} else {
drawArea.density_mode = false;
drawArea.start();
}
}
});
initButton = new JButton("init");
initButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
n_unit = Integer.parseInt(unitNumberText.getText());
resetUnitNumber(n_unit);
drawArea.W.init();
if (drawArea.auto_learn) {
alphaSlider.setValueOfSlider(initial_alpha);
betaSlider.setValueOfSlider(initial_beta);
drawArea.alpha = initial_alpha;
drawArea.beta = initial_beta;
}
}
});
unitNumberPanel = new JPanel();
unitNumberPanel.setLayout(new GridLayout(1, 2));
unitNumberText = new JTextField(Integer.toString(n_unit), 2);
unitNumberText.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
n_unit = Integer.parseInt(unitNumberText.getText());
resetUnitNumber(n_unit);
}
});
JLabel unitNumberLabel = new JLabel("#unit");
unitNumberPanel.add(unitNumberLabel);
unitNumberPanel.add(unitNumberText);
buttonPanel.add(learnButton);
buttonPanel.add(autoButton);
buttonPanel.add(densityButton);
buttonPanel.add(initButton);
buttonPanel.add(unitNumberPanel);
controlPanel.add(buttonPanel);
// Weight panel
Panel weightPanel = new Panel();
weightPanel.setLayout(new GridLayout(2, 1));
// Alpha slider panel
JPanel alphaSliderPanel = new JPanel();
alphaSliderPanel.setLayout(new BorderLayout());
alphaSlider = new AlphaSlider(drawArea, alpha_min_power,
alpha_max_power);
Label alabel = new Label("alpha");
alphaSliderPanel.add("Center", alphaSlider);
alphaSliderPanel.add("South", alabel);
weightPanel.add(alphaSliderPanel);
// Beta slider panel
JPanel betaSliderPanel = new JPanel();
betaSliderPanel.setLayout(new BorderLayout());
betaSlider = new BetaSlider(drawArea, beta_min_power, beta_max_power);
Label blabel = new Label("beta");
betaSliderPanel.add("Center", betaSlider);
betaSliderPanel.add("South", blabel);
weightPanel.add(betaSliderPanel);
controlPanel.add(weightPanel);
// First data parameter panel
JPanel dataPanel1 = new JPanel();
dataPanel1.setLayout(new GridLayout(2, 1));
JPanel widthSliderPanel = new JPanel();
widthSliderPanel.setLayout(new BorderLayout());
widthSlider = new WidthSlider(drawArea, width_range);
JLabel wlabel = new JLabel("width");
widthSliderPanel.add("Center", widthSlider);
widthSliderPanel.add("South", wlabel);
JPanel heightSliderPanel = new JPanel();
heightSliderPanel.setLayout(new BorderLayout());
heightSlider = new HeightSlider(drawArea, height_range);
Label hlabel = new Label("height");
heightSliderPanel.add("Center", heightSlider);
heightSliderPanel.add("South", hlabel);
dataPanel1.add(widthSliderPanel);
dataPanel1.add(heightSliderPanel);
// Second data parameter panel
JPanel dataPanel2 = new JPanel();
dataPanel2.setLayout(new GridLayout(2, 1));
JPanel phaseSliderPanel = new JPanel();
phaseSliderPanel.setLayout(new BorderLayout());
phaseSlider = new PhaseSlider(drawArea, phase_range);
Label label5 = new Label("phase");
phaseSliderPanel.add("Center", phaseSlider);
phaseSliderPanel.add("South", label5);
JPanel noiseSliderPanel = new JPanel();
noiseSliderPanel.setLayout(new BorderLayout());
noiseSlider = new NoiseSlider(drawArea, noise_range);
Label label6 = new Label("noise level");
noiseSliderPanel.add("Center", noiseSlider);
noiseSliderPanel.add("South", label6);
dataPanel2.add(phaseSliderPanel);
dataPanel2.add(noiseSliderPanel);
controlPanel.add(dataPanel1);
controlPanel.add(dataPanel2);
add("South", controlPanel);
// Set initial values of sliders.
alphaSlider.setValueOfSlider(initial_alpha);
betaSlider.setValueOfSlider(initial_beta);
widthSlider.setValueOfSlider(initial_width);
heightSlider.setValueOfSlider(initial_height);
phaseSlider.setValueOfSlider(initial_phase);
noiseSlider.setValueOfSlider(initial_noise_level);
drawArea.init();
repaint();
}
public void start() {
if (!drawArea.density_mode) {
drawArea.start();
}
}
public void startNoThread() {
drawArea.runNoThread();
}
public void stop() {
drawArea.stop();
}
/**
* Set learn mode
*/
public void learn() {
drawArea.learn = true;
drawArea.auto_learn = false;
}
/**
* Set auto mode
*/
public void auto() {
drawArea.auto_learn = true;
drawArea.learn = true;
}
public synchronized boolean action(Event evt, Object what) {
if (evt.target == learnButton) {
drawArea.learn = learnButton.isSelected();
if (!drawArea.learn && drawArea.auto_learn) {
drawArea.auto_learn = false;
autoButton.setSelected(false);
}
return true;
}
if (evt.target == autoButton) {
drawArea.auto_learn = autoButton.isSelected();
if (!drawArea.learn && drawArea.auto_learn) {
drawArea.learn = true;
learnButton.setSelected(true);
}
return true;
}
if (evt.target == initButton) {
drawArea.W.init();
if (drawArea.auto_learn) {
alphaSlider.setValueOfSlider(initial_alpha);
betaSlider.setValueOfSlider(initial_beta);
drawArea.alpha = initial_alpha;
drawArea.beta = initial_beta;
}
return true;
}
if (evt.target == densityButton) {
if (densityButton.isSelected()) {
drawArea.stop();
drawArea.density_mode = true;
drawArea.repaint();
} else {
drawArea.density_mode = false;
drawArea.start();
}
return true;
}
if (evt.target == unitNumberText) {
resetUnitNumber(Integer.valueOf((String) what).intValue());
return true;
}
return false;
}
/**
* Set alpha and beta for learning
*/
public void setAlphaBeta(double alpha, double beta) {
// alphaSlider.setValueOfSlider(alpha);
// betaSlider.setValueOfSlider(beta);
drawArea.alpha = alpha;
drawArea.beta = beta;
}
public void resetUnitNumber(int r) {
int rmax = 99;
if (r > rmax) {
showStatus("Too many units.");
return;
} else if (r < 2) {
showStatus("Too few units.");
return;
} else {
// showStatus("Unit number is now changed.");
}
drawArea.alpha = initial_alpha;
drawArea.beta = initial_beta;
drawArea.auto_learn = false;
drawArea.learn = false;
drawArea.n_unit = r;
drawArea.initWeight();
autoButton.setSelected(false);
learnButton.setSelected(false);
alphaSlider.setValueOfSlider(initial_alpha);
betaSlider.setValueOfSlider(initial_beta);
// showStatus(" ");
repaint();
}
/**
* Generate error message
*
* @param a
* Message
*/
private void showStatus(String a) {
JOptionPane dialogError = new JOptionPane();
JOptionPane.showMessageDialog(dialogError, a, "Error",
JOptionPane.ERROR_MESSAGE);
}
}
/**
* A Visible2DPointArray has two-dimensional points and can plot them on
* display.
*/
class Visible2DPointArray extends Matrix {
int radius; // of a circle expressing a point.
double scale;
int dxo, dyo; // the position of origin on display
private int diameter; // of a circle expressing a point.
final double xo = 0, yo = 0; // the position of origin in mathematical space
/**
* Construct a Visible2DPointArray.
*
* @param n
* The number of points.
* @param scale
* Scale factor from mathematical space to display.
* @param radius
* The radius of a circle expressing a point.
* @param x
* , y The position of origin on display.
*/
public Visible2DPointArray(int n, double scale, int radius, int x, int y) {
super(n, 2);
this.radius = radius;
this.scale = scale;
radius = 2;
if (radius > 0)
diameter = radius * 2;
else
diameter = 1;
dxo = x;
dyo = y;
}
/**
* Draw points as circles.
*
* @param g
* Graphics of the drawn object.
*/
public void draw(Graphics g) {
int i, x, y;
for (i = 0; i < row; i++) {
x = (int) (scale * (value[i][0] - xo)) + dxo - radius;
y = (int) (-scale * (value[i][1] - yo)) + dyo - radius;
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Ellipse2D.Float(x, y, diameter, diameter));
g2.fill(new Ellipse2D.Float(x, y, diameter, diameter));
// g.drawOval(x, y, diameter, diameter);
// g.fillOval(Color.black);
}
}
/**
* Draw points as linked circles on a graphic object.
*
* @param g
* Graphics of the drawn object.
*/
public void drawCurve(Graphics g) {
int i, x, y;
int xp, yp;
xp = (int) (scale * (value[0][0] - xo)) + dxo;
yp = (int) (-scale * (value[0][1] - yo)) + dyo;
for (i = 1; i < row; i++) {
x = (int) (scale * (value[i][0] - xo)) + dxo;
y = (int) (-scale * (value[i][1] - yo)) + dyo;
g.drawLine(xp, yp, x, y);
xp = x;
yp = y;
}
}
int index(int x, int y)
// Return the index of the point specified by a position (x, y).
{
int i;
for (i = 0; i < row; i++) {
if (Math.abs(x - (int) (scale * (value[i][0] - xo)) - dxo) <= radius
&& Math.abs(y - (int) (-scale * (value[i][1] - yo)) - dyo) <= radius)
return i;
}
return -1;
}
void move(int id, int ix, int iy)
// Move a point specified by ID to a position (ix, iy).
{
value[id][0] = (ix - dxo) / scale + xo;
value[id][1] = -(iy - dyo) / scale + yo;
}
}
/**
* A data object consists of points made by adding Gaussian perturbation (noise)
* to points on a sin curve. The width, height and phase of the curve and the
* magnitude of noise can be changed afterward.
*/
class Data extends Visible2DPointArray {
double width, height, noise_level, phase;
private Matrix noise;
public Data(int n, double scale, int radius, int x, int y, double width,
double height, double phase, double noise_level) {
super(n, scale, radius, x, y);
noise = Matrix.random(row, col);
this.width = width;
this.height = height;
this.phase = phase;
this.noise_level = noise_level;
this.remake();
}
synchronized public void remake() {
int i;
double x;
int n = row;
for (i = 0; i < n; i++) {
x = i;
value[i][0] = width * (2 * x / n - 1);
value[i][1] = height * Math.sin(2 * Math.PI * (x / n + phase));
}
this.updateLinearConv(1., noise_level, noise);
}
}
/**
* A weight object consists of weight points (centroids) of a BSOM model, which
* are initialized randomly and updated by an EM algorithm.
*/
class Weight extends Visible2DPointArray {
Matrix Ds, P;
double initial_level;
int seed = 1;
public Weight(int r, double scale, int radius, int x, int y,
double initial_level) {
super(r, scale, radius, x, y);
this.initial_level = initial_level;
this.init();
}
/**
* Initialize by Gaussian random numbers.
*/
synchronized public void init() {
Matrix noise;
noise = Matrix.random(row, col, seed);
this.updateLinearConv(0., initial_level, noise);
seed++;
}
/**
* Update by an EM algorithm.
*/
synchronized public void update(Data X, Matrix M, double alpha,
double beta, int grabed_unit) {
Matrix Z, N, Ki, Xm, Wn;
double c = 1;
// Soft competition
Ds = this.crossSqDistance(X); // Make squared Euclidean distances
// between data points and weights.
P = Ds.multipliedBy(-beta / 2.);
P.updateExp(); // Convert into 'Boltzmann Factors'.
Z = P.verticalSum(); // Make partition function.
dealZeroZ(Z, P, Ds); // Though this is not necessary in many cases, ....
P.updateDivideByRowVector(Z); // Convert into fuzzy membership
// (posterior selection probabilities).
// Update weights by EM algorithm.
N = P.horizontalSum(); // estimated numbers of members
N = N.diagonal(); // Convert into a diagonal matrix.
Ki = M.linearConv(alpha / beta, 1., N); // inverse lateral interaction
Xm = P.multipliedBy(X); // data weighted by fuzzy membership
Wn = Ki.dividedBy(Xm, 5); // new temporary estimates of weights
// A point grabbed by mouse is escaped from weight-update.
if (grabed_unit >= 0) {
Wn.value[grabed_unit][0] = value[grabed_unit][0];
Wn.value[grabed_unit][1] = value[grabed_unit][1];
}
this.updateLinearConv(1. - c, c, Wn); // If c=1 this is EM update.
// Otherwise GEM update.
}
/**
* If an entry of Z is zero, normal weight-updating is broken down. This do
* not occur theoretically but occur actually, due to the underflow in the
* calculation of Z. In such a case, the associating column of P is
* calculated by hard competition and the entry of Z is set to 1.
*/
void dealZeroZ(Matrix z, Matrix P, Matrix D) {
int i, j, imin;
for (j = 0; j < P.col; j++) {
if (z.value[0][j] <= 0.) {
P.value[0][j] = 1;
imin = 0;
for (i = 1; i < P.row; i++) {
if (D.value[i][j] < D.value[imin][j]) {
P.value[imin][j] = 0;
P.value[i][j] = 1;
imin = i;
} else
P.value[i][j] = 0;
}
z.value[0][j] = 1;
}
}
}
/**
* Calculate Number of Good Parameters.
*/
public double ngp(int n, double alpha, double beta, Matrix lmd) {
int i;
double gamma = 0;
double betad = beta * n / row;
for (i = 0; i < row; i++) {
gamma += betad / (betad + alpha * lmd.value[0][i]);
}
gamma -= 2;
return gamma;
}
public double updateAlpha(Matrix D, double gamma) {
double alpha;
Matrix R = D.multipliedBy(this);
alpha = (gamma * col) / R.sumSqrEntries();
return alpha;
}
public double updateBeta(int n, double gamma) {
double beta;
Matrix PD = P.mulipliedEntriesWith(Ds);
beta = ((n - gamma - 2) * col) / PD.sumEntries();
return beta;
}
public Matrix makeDensity(Matrix pos, double beta) {
int k;
Matrix Ds, P, Z, density;
Ds = this.crossSqDistance(pos);
P = Ds.multipliedBy(-beta / 2.);
P.updateExp();
Z = P.verticalSum();
double zmax = 0;
for (k = 0; k < Z.col; k++) {
if (Z.value[0][k] > zmax) {
zmax = Z.value[0][k];
}
}
density = Z.multipliedBy(1. / zmax);
return density;
}
}
/**
* A DrawArea is an area where data and weight points are plotted. This also
* makes a thread for learning.
*/
class DrawArea extends Canvas implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
BsomDemo demo;
int xd, yd;
double scale;
int ntot = 0;
int n_data, n_unit; // Number of points
double alpha, beta; // Hyperparameters
double width, height, noise_level, phase; // Parameters for data
// distribution
double initial_weight_level;
int dstep;
boolean density_mode = false;
Data X; // Data
Weight W; // Weights (centroid parameters)
Matrix D; // Discrete Laplacian matrix
Matrix M; // Hesse matrix of log prior (M = D'D)
Matrix lmd; // Eigenvalues of M
Thread thread;
int wait_time = 100;
boolean learn = false;
boolean auto_learn = false;
int grabed_unit = -1;
/**
* Construct a DrawArea on a demonstration applet.
*
* @param demo
* Demonstration applet
*/
public DrawArea(BsomDemo demo, int xd, int yd, double scale) {
this.demo = demo;
this.xd = xd;
this.yd = yd;
this.scale = scale;
}
/**
* Initialize learning by making data (X), weights (W) and Hesse matrix of
* prior (M).
*/
public void init() {
initWeight();
initData();
}
void initWeight() {
W = new Weight(n_unit, scale, 2, xd, yd, initial_weight_level);
makePriorHessian(n_unit);
}
void initData() {
X = new Data(n_data, scale, 0, xd, yd, width, height, phase,
noise_level);
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void stop() {
thread.stop();
}
// run without thread
public void runNoThread() {
double ini_gam = 0;
grabed_unit = -1;
ntot = 0;
for (;;) {
// System.out.println("learn="+Boolean.toString(learn));
// System.out.println("auto="+Boolean.toString(auto_learn));
if (learn) {
W.update(X, M, alpha, beta, grabed_unit);
if (auto_learn) {
double gamma = W.ngp(n_data, alpha, beta, lmd);
alpha = W.updateAlpha(D, gamma);
beta = W.updateBeta(n_data, gamma);
// System.out.println("gamma="+Double.toString(gamma));
// System.out.println("alpha="+Double.toString(alpha));
// System.out.println("beta="+Double.toString(beta));
if (Math.abs(gamma - ini_gam) < BsomDemo.delta)
break;
ini_gam = gamma;
}
}
ntot++;
// if (i>max) break;
}
// System.out.println("Total iterations="+Integer.toString(i));
}
/**
* Learn and plot if 'learn' is true. If 'auto_learn' is true,
* hyperparameters are tuned.
*/
public void run() {
ntot = 0;
try {
for (;;) {
thread.sleep(wait_time);
if (learn) {
W.update(X, M, alpha, beta, grabed_unit);
if (auto_learn) {
double gamma = W.ngp(n_data, alpha, beta, lmd);
alpha = W.updateAlpha(D, gamma);
beta = W.updateBeta(n_data, gamma);
alpha = demo.alphaSlider.setValueOfSlider(alpha);
beta = demo.betaSlider.setValueOfSlider(beta);
// System.out.println("gamma="+Double.toString(gamma));
// System.out.println("alpha="+Double.toString(alpha));
// System.out.println("beta="+Double.toString(beta));
}
}
repaint();
ntot++;
// if (i>ntot) break;
}
} catch (InterruptedException e) {
}
// System.out.println("Total iterations="+Integer.toString(i));
}
/* Double-buffering is used for drawing objects. */
Graphics offgraphics;
Dimension offscreensize;
Image offscreen;
public synchronized void update(Graphics g) {
Dimension d = size();
if ((offscreen == null) || (d.width != offscreensize.width)
|| (d.height != offscreensize.height)) {
offscreen = createImage(d.width, d.height);
offscreensize = d;
offgraphics = offscreen.getGraphics();
}
if (!density_mode) {
offgraphics.setColor(getBackground());
offgraphics.fillRect(0, 0, d.width, d.height);
offgraphics.setColor(Color.black);
} else {
g.drawString("Now, density is calculated.", 0, 10);
drawDensity(offgraphics);
offgraphics.setColor(Color.red);
offgraphics.drawString("a=" + alpha, 0, 10);
offgraphics.drawString("b=" + beta, 0, 20);
offgraphics.setColor(Color.green);
}
X.draw(offgraphics);
offgraphics.setColor(Color.blue);
W.draw(offgraphics);
W.drawCurve(offgraphics);
paint(g);
}
public void paint(Graphics g) {
if (offscreen != null)
g.drawImage(offscreen, 0, 0, null);
}
/*
* A weight-point can be moved directly by mouse.
*/
public synchronized boolean mouseDown(Event evt, int ix, int iy) {
grabed_unit = W.index(ix, iy);
return true;
}
public synchronized boolean mouseDrag(Event evt, int ix, int iy) {
if (grabed_unit >= 0) {
W.move(grabed_unit, ix, iy);
return true;
}
return false;
}
public synchronized boolean mouseUp(Event evt, int ix, int iy) {
grabed_unit = -1;
return true;
}
void makePriorHessian(int r) {
int i, j;
int rep_limit = 1000;
double eps = 0.00001;
// Make a discrete Laplacian matrix.
D = new Matrix(r - 2, r);
for (i = 0; i < r - 2; i++) {
for (j = 0; j < r; j++) {
if (j == i + 1)
D.value[i][j] = -2;
if (j == i || j == i + 2)
D.value[i][j] = 1;
}
}
Matrix Dt = D.transpose();
M = Dt.multipliedBy(D); // M = D'*D
lmd = M.eigenvalues(eps, rep_limit);
// Fix the two smallest eigenvalues to zeros.
double lmd_min1, lmd_min2, lmd_max;
int i1 = 0, i2 = 0;
lmd_min1 = lmd_max = lmd.value[0][0];
for (i = 1; i < r; i++) {
if (lmd.value[0][i] < lmd_min1) {
lmd_min1 = lmd.value[0][i];
i1 = i;
}
if (lmd.value[0][i] > lmd_max) {
lmd_max = lmd.value[0][i];
}
}
lmd.value[0][i1] = 0.;
lmd_min2 = lmd_max;
for (i = 0; i < r; i++) {
if (lmd.value[0][i] > 0. && lmd.value[0][i] < lmd_min2) {
lmd_min2 = lmd.value[0][i];
i2 = i;
}
}
lmd.value[0][i2] = 0.;
}
public void drawDensity(Graphics g) {
int i, j;
float c;
int k;
double x, y;
Dimension s = this.size();
int nx = s.width / dstep;
int ny = s.height / dstep;
Matrix pos = new Matrix(nx * ny, 2);
k = 0;
for (i = 0; i < nx; i++) {
for (j = 0; j < ny; j++) {
x = (i + 0.5) * dstep;
y = (j + 0.5) * dstep;
pos.value[k][0] = (double) ((x - xd) / scale);
pos.value[k][1] = (double) (-(y - yd) / scale);
k++;
}
}
Matrix density = W.makeDensity(pos, beta);
k = 0;
for (i = 0; i < nx; i++) {
for (j = 0; j < ny; j++) {
c = (float) (density.value[0][k]);
g.setColor(new Color(c, c, c));
g.fillRect(i * dstep, j * dstep, dstep, dstep);
k++;
}
}
}
}
/*
* SLIDERS
*/
/**
* Slider for setting hyperparameter. This slider is on log scale. Also, while
* dragging auto-learn is suppressed.
*/
class HpSlider extends JSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
static final double LOG10 = Math.log(10.);
protected DrawArea drawArea;
protected double min_power, max_power;
protected boolean stored_mode;
protected boolean dragged = false;
private int value;
private double range;
HpSlider(DrawArea p, double min_power, double max_power) {
super();
setMajorTickSpacing(20);
// setMinorTickSpacing(4);
setPaintTicks(true);
Hashtable labelTable = new Hashtable();
labelTable.put(new Integer(0), new JLabel("0"));
labelTable.put(new Integer(20), new JLabel("1"));
labelTable.put(new Integer(40), new JLabel("2"));
labelTable.put(new Integer(60), new JLabel("3"));
labelTable.put(new Integer(80), new JLabel("4"));
labelTable.put(new Integer(100), new JLabel("5"));
setLabelTable(labelTable);
setPaintLabels(true);
drawArea = p;
this.min_power = min_power;
this.max_power = max_power;
range = max_power - min_power;
// Register a change listener
addChangeListener(new ChangeListener() {
// This method is called whenever the slider's value is changed
public void stateChanged(ChangeEvent evt) {
JSlider slider = (JSlider) evt.getSource();
if (!slider.getValueIsAdjusting()) {
// Get new value
value = slider.getValue();
stored_mode = drawArea.auto_learn;
drawArea.auto_learn = false;
dragged = true;
}
}
});
addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent arg0) {
stored_mode = drawArea.auto_learn;
drawArea.auto_learn = false;
dragged = true;
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
value = getValue();
drawArea.auto_learn = stored_mode;
dragged = false;
setValueBySlider();
// System.out.println(value);
}
public void mousePressed(MouseEvent e) {
}
});
}
public void Motion() {
if (!dragged) {
stored_mode = drawArea.auto_learn;
drawArea.auto_learn = false;
}
dragged = true;
setValueBySlider();
}
public void Release() {
setValueBySlider();
drawArea.auto_learn = stored_mode;
dragged = false;
}
public void setValueBySlider() {
}
double getValueFromSlider() {
double power = value / 100. * range + min_power;
double v = Math.pow(10., power);
return v;
}
public double setValueOfSlider(double x) {
int v = (int) ((Math.log(x) / LOG10 - min_power) / range * 100);
if (v < 1) {
v = 1;
x = Math.pow(10., 1. / 100. * range + min_power);
} else if (v > 100) {
v = 100;
x = Math.pow(10., 1. * range + min_power);
}
setValue(v);
return x;
}
}
/**
* Slider for setting alpha
*/
class AlphaSlider extends HpSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
AlphaSlider(DrawArea p, double min_power, double max_power) {
super(p, min_power, max_power);
}
public void setValueBySlider() {
drawArea.alpha = getValueFromSlider();
}
}
/**
* Slider for setting beta.
*/
class BetaSlider extends HpSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
BetaSlider(DrawArea p, double min_power, double max_power) {
super(p, min_power, max_power);
}
public void setValueBySlider() {
drawArea.beta = getValueFromSlider();
}
}
/**
* Slider for setting data parameters
*/
class DataSlider extends JSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
DrawArea drawArea;
double range;
DataSlider(DrawArea p, double range) {
super();
drawArea = p;
this.range = range;
}
public void Motion() {
setValueBySlider();
drawArea.X.remake();
}
public void Release() {
setValueBySlider();
drawArea.X.remake();
}
void setValueBySlider() {
}
double getValueFromSlider() {
return getValue() / 100. * range;
}
public double setValueOfSlider(double x) {
int v = (int) (x / range * 100);
if (v < 1) {
v = 1;
x = 1. / 100. * range;
} else if (v > 100) {
v = 100;
x = range;
}
setValue(v);
return x;
}
}
/**
* Slider for setting the width of data range
*/
class WidthSlider extends DataSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
WidthSlider(DrawArea p, double range) {
super(p, range);
}
void setValueBySlider() {
drawArea.X.width = getValueFromSlider();
}
}
/**
* Slider for setting the height of data range
*/
class HeightSlider extends DataSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
HeightSlider(DrawArea p, double range) {
super(p, range);
}
void setValueBySlider() {
drawArea.X.height = getValueFromSlider();
}
}
/**
* Slider for setting the phase of sin data
*/
class PhaseSlider extends DataSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
PhaseSlider(DrawArea p, double range) {
super(p, range);
}
void setValueBySlider() {
drawArea.X.phase = getValueFromSlider();
}
}
/**
* Slider for noise level
*/
class NoiseSlider extends DataSlider {
/**
*
*/
private static final long serialVersionUID = 1L;
NoiseSlider(DrawArea p, double range) {
super(p, range);
}
void setValueBySlider() {
drawArea.X.noise_level = getValueFromSlider();
}
}