📄 bsomdemo1.java
字号:
/* * @(#)BsomDemo1.java 1.3 12 Nov 1996 Akio Utsugi */import java.applet.Applet;import java.awt.*;import java.lang.Math;import java.lang.Double;import Slider;/** * BsomDemo1 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) * @version 1.3 12 Nov 1996 * @author <a href="http://www.aist.go.jp/NIBH/~b0616/"> Akio Utsugi </a> * This applet uses Matrix.class(1.3) and Slider.class(reformed version). */public class BsomDemo1 extends java.applet.Applet{ DrawArea drawArea; AlphaSlider alphaSlider; BetaSlider betaSlider; WidthSlider widthSlider; HeightSlider heightSlider; PhaseSlider phaseSlider; NoiseSlider noiseSlider; Button initButton; Checkbox learnButton; Checkbox autoButton; Checkbox densityButton; TextField unitNumberText; int xd, yd; double scale; int n_data, n_unit; int dstep; 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; double alpha_min_power, alpha_max_power; double beta_min_power, beta_max_power; double initial_alpha, initial_beta; public void init() { String p; /* Get parameters. */ 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); 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.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 Panel controlPanel = new Panel(); // Button panel Panel buttonPanel = new Panel(); Panel unitNumberPanel; buttonPanel.setLayout(new GridLayout(5, 1)); learnButton = new Checkbox("learn"); autoButton = new Checkbox("auto"); densityButton = new Checkbox("density"); initButton = new Button("init"); unitNumberPanel = new Panel(); unitNumberPanel.setLayout(new GridLayout(1, 2)); unitNumberText = new TextField(""+n_unit, 2); Label unitNumberLabel = new Label("#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 Panel alphaSliderPanel = new Panel(); 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 Panel betaSliderPanel = new Panel(); 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 Panel dataPanel1 = new Panel(); dataPanel1.setLayout(new GridLayout(2, 1)); Panel widthSliderPanel = new Panel(); widthSliderPanel.setLayout(new BorderLayout()); widthSlider = new WidthSlider(drawArea, width_range); Label wlabel = new Label("width"); widthSliderPanel.add("Center", widthSlider); widthSliderPanel.add("South", wlabel); Panel heightSliderPanel = new Panel(); 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 Panel dataPanel2 = new Panel(); dataPanel2.setLayout(new GridLayout(2, 1)); Panel phaseSliderPanel = new Panel(); phaseSliderPanel.setLayout(new BorderLayout()); phaseSlider = new PhaseSlider(drawArea, phase_range); Label label5 = new Label("phase"); phaseSliderPanel.add("Center", phaseSlider); phaseSliderPanel.add("South", label5); Panel noiseSliderPanel = new Panel(); 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 stop() { drawArea.stop(); } public synchronized boolean action(Event evt, Object what) { if(evt.target == learnButton){ drawArea.learn = learnButton.getState(); if(!drawArea.learn && drawArea.auto_learn){ drawArea.auto_learn = false; autoButton.setState(false); } return true; } if(evt.target == autoButton){ drawArea.auto_learn = autoButton.getState(); if(!drawArea.learn && drawArea.auto_learn){ drawArea.learn = true; learnButton.setState(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.getState()){ 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; } 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.setState(false); learnButton.setState(false); alphaSlider.setValueOfSlider(initial_alpha); betaSlider.setValueOfSlider(initial_beta); showStatus(" "); repaint(); }}/** * 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; 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; g.drawOval(x, y, diameter, diameter); } } /** * 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, r; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -