📄 bsomdemo1.java
字号:
* 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 i, j, k; double x, y; 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{ BsomDemo1 demo; int xd, yd; double scale; 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(BsomDemo1 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(); } /** * Learn and plot if 'learn' is true. * If 'auto_learn' is true, hyperparameters are tuned. */ public void run() { 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); } } repaint(); } } catch(InterruptedException e){} } /* 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 Slider { static final double LOG10 = Math.log(10.); DrawArea drawArea; double min_power, max_power; boolean stored_mode; boolean dragged = false; private double range; HpSlider(DrawArea p, double min_power, double max_power) { super(); drawArea = p; this.min_power = min_power; this.max_power = max_power; range = max_power - min_power; } 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 = GetValue()/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 { 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 { 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 Slider { 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 { 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 { 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 { PhaseSlider(DrawArea p, double range) { super(p, range); } void setValueBySlider() { drawArea.X.phase = getValueFromSlider(); }}/** * Slider for noise level */class NoiseSlider extends DataSlider { NoiseSlider(DrawArea p, double range) { super(p, range); } void setValueBySlider() { drawArea.X.noise_level = getValueFromSlider(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -