33< head >
44 < meta charset ="UTF-8 ">
55 < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6- < title > Neural Layer Visualizer</ title >
6+ < title > Retro-Futuristic Neural Layer Visualizer</ title >
77 < script src ="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.24.2/plotly.min.js "> </ script >
8- < link href ="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700 &display=swap " rel ="stylesheet ">
8+ < link href ="https://fonts.googleapis.com/css2?family=VT323 &display=swap " rel ="stylesheet ">
99 < style >
10+ : root {
11+ --bg-color : # 001a33 ;
12+ --text-color : # 00ffcc ;
13+ --border-color : # 00ffcc ;
14+ --slider-bg : # 005f73 ;
15+ }
1016 body {
11- font-family : 'Roboto' , sans-serif;
17+ font-family : 'VT323' , monospace;
18+ background-color : var (--bg-color );
19+ color : var (--text-color );
1220 max-width : 800px ;
1321 margin : 0 auto;
1422 padding : 20px ;
15- background-color : # 2c3e50 ;
16- color : # ecf0f1 ;
17- }
18- h1 {
19- text-align : center;
2023 }
2124 # plot {
2225 width : 100% ;
2326 height : 400px ;
24- background-color : rgba (255 , 255 , 255 , 0.1 );
25- border-radius : 8 px ;
27+ background-color : rgba (0 , 26 , 51 , 0.5 );
28+ border : 2 px solid var ( --border-color ) ;
2629 overflow : hidden;
2730 margin-bottom : 20px ;
31+ box-shadow : 0 0 20px rgba (0 , 255 , 204 , 0.2 );
2832 }
2933 .controls {
3034 display : flex;
3539 .column {
3640 flex : 1 ;
3741 min-width : 200px ;
38- background-color : rgba (255 , 255 , 255 , 0.1 );
42+ background-color : rgba (0 , 26 , 51 , 0.5 );
3943 padding : 15px ;
40- border-radius : 8px ;
44+ border : 1px solid var (--border-color );
45+ }
46+ .column h3 {
47+ margin-top : 0 ;
48+ margin-bottom : 15px ;
49+ color : var (--text-color );
50+ text-shadow : 0 0 5px rgba (0 , 255 , 204 , 0.5 );
4151 }
4252 label {
4353 display : inline-block;
4454 margin-right : 10px ;
4555 font-weight : 300 ;
4656 }
47- # neuronCount {
48- width : 60px ;
49- padding : 5px ;
50- border : none;
51- border-radius : 4px ;
52- background-color : # 34495e ;
53- color : # ecf0f1 ;
54- }
55- # activationFunction {
56- width : 150px ;
57+ # neuronCount , # activationFunction {
58+ width : 100px ;
5759 padding : 5px ;
58- border : none;
59- border-radius : 4px ;
60- background-color : # 34495e ;
61- color : # ecf0f1 ;
60+ border : 1px solid var (--border-color );
61+ background-color : var (--bg-color );
62+ color : var (--text-color );
63+ font-family : 'VT323' , monospace;
64+ font-size : 16px ;
6265 }
6366 .slider-container {
6467 display : flex;
7174 -webkit-appearance : none;
7275 width : 100% ;
7376 height : 5px ;
74- border-radius : 5px ;
75- background : # 34495e ;
77+ background : var (--slider-bg );
7678 outline : none;
7779 }
7880 input [type = "range" ]::-webkit-slider-thumb {
7981 -webkit-appearance : none;
8082 appearance : none;
8183 width : 15px ;
8284 height : 15px ;
83- border-radius : 50% ;
84- background : # 3498db ;
85+ cursor : pointer;
86+ }
87+ input [type = "range" ]::-moz-range-thumb {
88+ width : 15px ;
89+ height : 15px ;
90+ cursor : pointer;
91+ }
92+ input [type = "range" ]::-ms-thumb {
93+ width : 15px ;
94+ height : 15px ;
8595 cursor : pointer;
8696 }
8797 .value-input {
8898 width : 60px ;
8999 padding : 5px ;
90100 margin-left : 10px ;
91- border : 1px solid # 3498db ;
92- border-radius : 4px ;
93- background-color : # 34495e ;
94- color : # ecf0f1 ;
101+ border : 1px solid var (--border-color );
102+ background-color : var (--bg-color );
103+ color : var (--text-color );
95104 text-align : center;
105+ font-family : 'VT323' , monospace;
106+ font-size : 16px ;
96107 }
97108 .network-config-container {
98- background-color : rgba (255 , 255 , 255 , 0.1 );
99- padding : 15px ;
100- border-radius : 8px ;
101- margin-bottom : 20px ;
102109 display : flex;
103110 justify-content : space-between;
104111 align-items : center;
112+ margin-bottom : 20px ;
113+ }
114+ .network-config-item {
115+ display : flex;
116+ align-items : center;
117+ }
118+ # formula {
119+ text-align : center;
120+ font-size : 1.2em ;
121+ font-family : 'VT323' , monospace;
122+ white-space : pre-wrap;
123+ text-shadow : 0 0 5px rgba (0 , 255 , 204 , 0.5 );
124+ margin-bottom : 20px ;
125+ }
126+ .latex-label {
127+ min-width : 30px ;
128+ display : inline-block;
105129 }
106130 </ style >
107131</ head >
108132< body >
109- < h1 > Neural Layer Visualizer </ h1 >
133+ < div id =" formula " > </ div >
110134 < div id ="plot "> </ div >
111135 < div class ="network-config-container ">
112- < div >
136+ < div class =" network-config-item " >
113137 < label for ="neuronCount "> Number of neurons:</ label >
114138 < input type ="number " id ="neuronCount " min ="1 " max ="10 " value ="3 ">
115139 </ div >
116- < div >
140+ < div class =" network-config-item " >
117141 < label for ="activationFunction "> Activation Function:</ label >
118142 < select id ="activationFunction ">
119143 < option value ="relu " selected > ReLU</ option >
@@ -144,65 +168,114 @@ <h1>Neural Layer Visualizer</h1>
144168 } ;
145169
146170 let currentActivation = activationFunctions . relu ;
171+ let currentActivationName = 'ReLU' ;
147172
148173 const networkOutput = ( x , params ) =>
149- params . w . reduce ( ( sum , wi , i ) => sum + wi * currentActivation ( x + params . b [ i ] ) , 0 ) ;
174+ params . w . reduce ( ( sum , wi , i ) => sum + currentActivation ( wi * x + params . b [ i ] ) , 0 ) ;
150175
151176 const xValues = Array . from ( { length : 201 } , ( _ , i ) => - 10 + i * 0.1 ) ;
177+
178+ const randomInitialize = count => Array . from ( { length : count } , ( ) => parseFloat ( ( Math . random ( ) * 4 - 2 ) . toFixed ( 2 ) ) ) ;
179+
152180 let params = {
153- w : [ - 0.81 , 1.89 , - 2.70 ] ,
154- b : [ 8.44 , 3.03 , - 5.07 ]
181+ w : randomInitialize ( 3 ) ,
182+ b : randomInitialize ( 3 )
155183 } ;
156- const colors = [ '#3498db' , '#2ecc71' , '#e74c3c' , '#f39c12' , '#9b59b6' ] ;
184+
185+ const colors = [ '#ff8c00' , '#ff00ff' , '#00ff00' , '#00ffff' , '#ff1493' , '#7fff00' , '#ff69b4' , '#1e90ff' ] ;
186+
187+ function updateFormula ( ) {
188+ const neuronCount = params . w . length ;
189+ let formulaStr = `<span style="color: ${ colors [ 0 ] } ">y(x) = </span>` ;
190+ for ( let i = 0 ; i < neuronCount ; i ++ ) {
191+ const color = colors [ ( i + 1 ) % colors . length ] ;
192+ formulaStr += `<span style="color: ${ color } ">${ currentActivationName } (w${ i + 1 } *x + b${ i + 1 } )</span>` ;
193+ if ( i < neuronCount - 1 ) formulaStr += ' + ' ;
194+ }
195+ document . getElementById ( 'formula' ) . innerHTML = formulaStr ;
196+ }
157197
158198 function updatePlot ( ) {
159199 const traces = [
160200 {
161201 x : xValues ,
162202 y : xValues . map ( x => networkOutput ( x , params ) ) ,
163- name : 'Layer Output ' ,
203+ name : 'y ' ,
164204 line : { color : colors [ 0 ] , width : 3 }
165205 } ,
166206 ...params . w . map ( ( _ , i ) => ( {
167207 x : xValues ,
168- y : xValues . map ( x => params . w [ i ] * currentActivation ( x + params . b [ i ] ) ) ,
208+ y : xValues . map ( x => currentActivation ( params . w [ i ] * x + params . b [ i ] ) ) ,
169209 name : `Neuron ${ i + 1 } ` ,
170210 line : { color : colors [ ( i + 1 ) % colors . length ] , dash : 'dash' , width : 2 }
171211 } ) )
172212 ] ;
173213
174214 Plotly . react ( 'plot' , traces , {
175- paper_bgcolor : 'rgba(0,0,0,0)' ,
176- plot_bgcolor : 'rgba(0,0,0,0)' ,
177- xaxis : { title : 'Input' , range : [ - 10 , 10 ] , gridcolor : '#888' , zerolinecolor : '#888' } ,
178- yaxis : { title : 'Output' , range : [ - 10 , 10 ] , gridcolor : '#888' , zerolinecolor : '#888' } ,
215+ paper_bgcolor : 'rgba(0,26,51,0)' ,
216+ plot_bgcolor : 'rgba(0,26,51,0)' ,
217+ xaxis : {
218+ title : 'Input' ,
219+ range : [ - 10 , 10 ] ,
220+ gridcolor : '#005f73' ,
221+ zerolinecolor : '#005f73' ,
222+ dtick : 1
223+ } ,
224+ yaxis : {
225+ title : 'Output' ,
226+ range : [ - 2 , 8 ] ,
227+ gridcolor : '#005f73' ,
228+ zerolinecolor : '#005f73' ,
229+ dtick : 1
230+ } ,
179231 showlegend : true ,
180232 legend : { orientation : 'h' , yanchor : 'bottom' , y : 1.02 , xanchor : 'right' , x : 1 } ,
181- font : { color : '#ecf0f1' }
233+ font : { color : '#00ffcc' , family : 'VT323, monospace' } ,
234+ margin : { t : 10 , b : 40 , l : 50 , r : 10 }
182235 } ) ;
236+
237+ updateFormula ( ) ;
183238 }
184239
185- function createSlider ( container , id , min , max , value , label ) {
240+ function createSlider ( container , id , min , max , value , label , color ) {
186241 const sliderContainer = document . createElement ( 'div' ) ;
187242 sliderContainer . className = 'slider-container' ;
188243 sliderContainer . innerHTML = `
189- <label for=" ${ id } ">${ label } :</label >
244+ <span class="latex- label" style="color: ${ color } ">${ label } :</span >
190245 <input type="range" id="${ id } " min="${ min } " max="${ max } " step="0.01" value="${ value } ">
191- <input type="text" class="value-input" id="${ id } -input" value="${ value } ">
246+ <input type="text" class="value-input" id="${ id } -input" value="${ value } " style="color: ${ color } " >
192247 ` ;
193248 container . appendChild ( sliderContainer ) ;
194249
195250 const inputRange = sliderContainer . querySelector ( 'input[type="range"]' ) ;
196251 const inputText = sliderContainer . querySelector ( '.value-input' ) ;
197252
198- function updateValue ( newValue ) {
253+ // Set the color of the slider button
254+ const style = document . createElement ( 'style' ) ;
255+ style . textContent = `
256+ #${ id } ::-webkit-slider-thumb {
257+ background-color: ${ color } ;
258+ box-shadow: 0 0 5px ${ color } ;
259+ }
260+ #${ id } ::-moz-range-thumb {
261+ background-color: ${ color } ;
262+ box-shadow: 0 0 5px ${ color } ;
263+ }
264+ #${ id } ::-ms-thumb {
265+ background-color: ${ color } ;
266+ box-shadow: 0 0 5px ${ color } ;
267+ }
268+ ` ;
269+ document . head . appendChild ( style ) ;
270+
271+ const updateValue = newValue => {
199272 const value = parseFloat ( newValue ) . toFixed ( 2 ) ;
200273 inputRange . value = value ;
201274 inputText . value = value ;
202275 const [ type , index ] = id . split ( '-' ) ;
203276 params [ type ] [ index ] = parseFloat ( value ) ;
204277 updatePlot ( ) ;
205- }
278+ } ;
206279
207280 inputRange . oninput = ( ) => updateValue ( inputRange . value ) ;
208281 inputText . onchange = ( ) => updateValue ( inputText . value ) ;
@@ -225,15 +298,14 @@ <h1>Neural Layer Visualizer</h1>
225298 params . b = params . b . slice ( 0 , count ) ;
226299
227300 while ( params . w . length < count ) {
228- params . w . push ( parseFloat ( ( Math . random ( ) * 2 - 1 ) . toFixed ( 2 ) ) ) ;
229- }
230- while ( params . b . length < count ) {
231- params . b . push ( parseFloat ( ( Math . random ( ) * 2 - 1 ) . toFixed ( 2 ) ) ) ;
301+ params . w . push ( parseFloat ( ( Math . random ( ) * 4 - 2 ) . toFixed ( 2 ) ) ) ;
302+ params . b . push ( parseFloat ( ( Math . random ( ) * 4 - 2 ) . toFixed ( 2 ) ) ) ;
232303 }
233304
234305 for ( let i = 0 ; i < count ; i ++ ) {
235- createSlider ( weightColumn , `w-${ i } ` , - 10 , 10 , params . w [ i ] , `w${ i + 1 } ` ) ;
236- createSlider ( biasColumn , `b-${ i } ` , - 10 , 10 , params . b [ i ] , `b${ i + 1 } ` ) ;
306+ const color = colors [ ( i + 1 ) % colors . length ] ;
307+ createSlider ( weightColumn , `w-${ i } ` , - 10 , 10 , params . w [ i ] , `w${ i + 1 } ` , color ) ;
308+ createSlider ( biasColumn , `b-${ i } ` , - 10 , 10 , params . b [ i ] , `b${ i + 1 } ` , color ) ;
237309 }
238310
239311 slidersDiv . appendChild ( weightColumn ) ;
@@ -245,6 +317,7 @@ <h1>Neural Layer Visualizer</h1>
245317 document . getElementById ( 'neuronCount' ) . addEventListener ( 'input' , updateNeuronCount ) ;
246318 document . getElementById ( 'activationFunction' ) . addEventListener ( 'change' , function ( ) {
247319 currentActivation = activationFunctions [ this . value ] ;
320+ currentActivationName = this . options [ this . selectedIndex ] . text ;
248321 updatePlot ( ) ;
249322 } ) ;
250323
0 commit comments