File size: 12,358 Bytes
1b19efc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb5193e
1b19efc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69f60de
7043795
1b19efc
 
 
351e1a7
ef4c571
 
 
 
 
 
 
 
 
7bb6780
 
 
 
 
 
 
 
 
 
 
1b19efc
 
 
 
 
ef4c571
 
 
 
 
 
 
 
 
 
1b19efc
 
 
 
 
 
 
69f60de
1b19efc
 
 
ef4c571
dac4940
 
 
69f60de
dac4940
 
1b19efc
 
 
3f21703
 
0f7d93c
 
 
 
3f21703
 
1b19efc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69f60de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7043795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b19efc
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Build a 2D dataset and use SGD to train a classifier one step at a time." />
    <title>SGD Classifier Visualizer</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <main class="shell">
      <header class="page-header">
        <div>
          <!--p class="eyebrow">Interactive machine learning</p--!>
          <h1>SGD Classifier</h1>
          <p class="subtitle">Draw a dataset, then watch the decision boundary move one SGD step at a time.</p>
        </div>
        <div id="runtime-status" class="status loading"><span></span>Loading Python runtime…</div>
      </header>

      <section class="workspace">
        <div class="plot-card">
          <div class="plot-toolbar">
            <div>
              <h2>Decision boundary</h2>
              <!--p id="plot-instructions">Hover over a point to inspect its coordinates.</p--!>
            </div>
            <div class="legend" aria-label="Class legend">
              <span><i class="dot dot-a"></i>Class A (+)</span>
              <span><i class="dot dot-b"></i>Class B (-)</span>
              <span><i class="batch-ring"></i>Next batch</span>
            </div>
          </div>
          <div class="canvas-wrap">
            <canvas id="plot" aria-label="Interactive classifier decision boundary"></canvas>
            <div id="empty-hint" class="empty-hint">Select a class and click to place points</div>
          </div>
          <div class="plot-footer">
            <span id="point-count">0 points</span>
            <span id="step-count">Step 0</span>
            <span id="batch-summary">No batch selected</span>
          </div>
        </div>

        <aside class="control-card">
          <nav class="tabs" aria-label="Visualizer sections">
            <button id="configure-tab" class="tab active" type="button">Configure</button>
            <button id="train-tab" class="tab" type="button">Train</button>
            <button id="examples-tab" class="tab" type="button">Examples</button>
            <button id="usage-tab" class="tab" type="button">Usage</button>
          </nav>
          <div id="configure-panel" class="tab-panel active">
          <section class="control-section">
            <div class="section-heading"><span>1</span><h2>Specify data</h2></div>
            <div class="inline-field">
              <label for="dataset-select">Type</label>
              <select id="dataset-select">
                <option value="easy-linear">Builtin linearly separable data (easy)</option>
                <option value="hard-linear">Builtin linearly separable data (hard)</option>
                <option value="nonlinear">Builtin non-linearly separable data</option>
                <option value="custom">Custom data</option>
              </select>
            </div>
            <div id="custom-data-controls" hidden>
              <label>Point label</label>
              <div class="segment" role="group" aria-label="Point label">
                <button id="label-a" class="label-button active" type="button"><i class="dot dot-a"></i>Class A (+)</button>
                <button id="label-b" class="label-button" type="button"><i class="dot dot-b"></i>Class B (-)</button>
              </div>
              <div class="button-row data-buttons">
                <button id="undo" class="secondary" type="button">Undo</button>
                <button id="redo" class="secondary" type="button">Redo</button>
                <button id="clear" class="secondary danger" type="button">Clear</button>
              </div>
            </div>
          </section>

          <section class="control-section">
            <div class="section-heading"><span>2</span><h2>Configure model</h2></div>
            <div class="inline-field">
              <label for="loss">Loss</label>
              <select id="loss">
								<option>perceptron</option>
								<option>squared_error</option><option>log_loss</option>
                <option>hinge</option><option>squared_hinge</option>
                <option>huber</option><option>modified_huber</option>
								<option>epsilon_insensitive</option><option>squared_epsilon_insensitive</option>
              </select>
            </div>
            <div class="field-grid">
              <div><label for="learning-rate">Learning rate</label><input id="learning-rate" type="number" value="1" min="0.000001" step="0.01" /></div>
              <div><label for="batch-size">Batch size</label><input id="batch-size" type="number" value="1" min="1" step="1" /></div>
            </div>
            <label for="batch-selection">Mini-batch selection</label>
            <select id="batch-selection">
              <option value="random">Random subset</option>
              <option value="permutation">Permutation · non-overlapping</option>
            </select>
            <p id="sampling-help" class="help">Each point is used once before the dataset is shuffled again.</p>
          </section>
          <section class="control-section additional-options-section">
            <div class="section-heading"><span>3</span><h2>Additional options</h2></div>
            <div class="field-grid">
              <div><label for="random-seed">Random seed</label><input id="random-seed" type="number" value="42" min="0" max="4294967295" step="1" /></div>
              <div><label for="animation-speed">Animation speed</label><select id="animation-speed"><option value="200" selected>Fast</option><option value="900">Normal</option><option value="1500">Slow</option></select></div>
            </div>
          </section>
          </div>
          <div id="train-panel" class="tab-panel">
          <section class="control-section train-section">
            <div class="metrics-panel">
              <div class="metrics-heading"><h2>Metrics</h2><div><span class="metric-key loss-key"></span>Loss <span class="metric-key accuracy-key"></span>Accuracy</div></div>
              <div class="metrics-chart-wrap">
                <canvas id="metrics-chart" aria-label="Loss and accuracy over training steps"></canvas>
                <div id="metrics-tooltip" class="metrics-tooltip" role="tooltip" hidden></div>
              </div>
            </div>
            <div class="train-heading"><h2>Parameters</h2><span id="history-position">Step 0 of 0</span></div>
            <div class="parameter-panel" aria-live="polite">
              <div class="parameter-block">
                <span>Class A parameters</span><small>Weight vector and bias for the positive class</small>
                <code id="model-parameters">w_A = —<br>b_A = —</code>
              </div>
              <div class="parameter-block update-values">
                <span>Pending Class A update</span><small>Negative learning rate × derivatives</small>
                <code id="model-update">Δw_A = —<br>Δb_A = —</code>
              </div>
            </div>
            <div class="history-buttons">
              <button id="history-next" class="primary" type="button" disabled><span class="button-text">Next</span></button>
              <button id="history-prev" class="secondary" type="button">Previous</button>
              <button id="history-reset" class="secondary" type="button">Reset</button>
            </div>
            <div class="animation-buttons">
              <button id="animate" class="secondary" type="button">Animate</button>
              <button id="pause" class="secondary" type="button" disabled>Pause</button>
            </div>
            <p id="message" class="message">Add at least one point from each class to begin.</p>
          </section>
          </div>
          <div id="examples-panel" class="tab-panel">
            <section class="control-section examples-section">
              <h2>Example scenarios</h2>
              <p class="examples-intro">Load a scenario, then use Next or Animate in the Train tab to observe its behavior.</p>
              <article class="example-card">
                <button class="example-button" data-dataset="easy-linear" type="button">Perceptron – easy</button>
                <p>This uses the easy linearly separable dataset and the perceptron loss. The decision boundary eventually converges to one with zero loss and perfect classification accuracy on the data.</p>
              </article>
              <article class="example-card">
                <button class="example-button" data-dataset="hard-linear" type="button">Perceptron – hard</button>
                <p>This uses the perceptron loss and hard linearly separable dataset. The decision boundary eventually converges to one with zero loss and perfect classification accuracy on the data.</p>
              </article>
              <article class="example-card">
                <button class="example-button" data-dataset="nonlinear" type="button">Perceptron – nonseparable</button>
                <p>This uses the perceptron loss and the non-linearly separable dataset. The decision boundary does not converge.</p>
              </article>
              <article class="example-card">
                <button class="example-button" data-dataset="hard-linear" data-loss="squared_error" data-learning-rate="1" type="button">Adaline – hard (default learning rate)</button>
                <p>This uses squared error and the hard linearly separable dataset with the default learning rate of 1. The parameters diverge and the decision boundary does not converge.</p>
              </article>
              <article class="example-card">
                <button class="example-button" data-dataset="hard-linear" data-loss="squared_error" data-learning-rate="0.1" type="button">Adaline – hard (small learning rate)</button>
                <p>This uses squared error and the hard linearly separable dataset with a small learning rate of 0.1. 
								The parameters and decision boundary eventually fluctuates slightly around a perfect classifier.</p>
              </article>

              <article class="example-card"> <button class="example-button" data-dataset="hard-linear" data-loss="log_loss" data-learning-rate="1" type="button">Logistic regression – hard</button>
                <p>This uses log loss and the hard linearly separable dataset. 
								The parameters and decision boundary eventually fluctuates very slightly around a perfect classifer.</p>
              </article>
            </section>
          </div>
          <div id="usage-panel" class="tab-panel">
            <section class="control-section usage-section">
              <h2>Using the visualizer</h2>
              <ol>
                <li><strong>Choose data.</strong> Select a built-in dataset, or choose Custom data and click the plot to add Class A and Class B points.</li>
                <li><strong>Configure SGD.</strong> Select a loss, learning rate, mini-batch size, and selection strategy. A fixed random seed reproduces the same batch order.</li>
                <li><strong>Open Train.</strong> Points with amber rings form the mini-batch that will be used by the next update.</li>
                <li><strong>Step through training.</strong> Next performs one SGD step. Previous and Reset inspect earlier states without deleting later history.</li>
                <li><strong>Animate.</strong> Animate advances automatically at the configured speed; Pause stops it.</li>
              </ol>
              <h2>Reading the display</h2>
              <ul>
                <li>The solid line is the current decision boundary. The dotted line is the initial reference boundary.</li>
                <li>Background colors show the predicted class regions.</li>
                <li>The Parameters panel shows Class A's current weight and bias and its pending update.</li>
                <li>The Metrics chart evaluates loss and accuracy on the entire dataset. Larger outlined markers identify the step currently displayed.</li>
                <li>Hover over any point to inspect its class and coordinates.</li>
              </ul>
            </section>
          </div>
        </aside>
      </section>
    </main>
    <script type="module" src="app.js"></script>
  </body>
</html>