| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Advanced Neural Network Visualizer | Model Fine-Tuning</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
| <style> |
| .neuron { |
| width: 40px; |
| height: 40px; |
| border-radius: 50%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| font-weight: bold; |
| position: relative; |
| box-shadow: 0 2px 4px rgba(0,0,0,0.2); |
| transition: all 0.3s ease; |
| } |
| |
| .layer { |
| display: flex; |
| flex-direction: column; |
| gap: 20px; |
| align-items: center; |
| position: relative; |
| } |
| |
| .connection { |
| position: absolute; |
| background: rgba(156, 163, 175, 0.3); |
| transform-origin: 0 0; |
| z-index: -1; |
| transition: all 0.3s ease; |
| } |
| |
| .connection.active { |
| background: rgba(16, 185, 129, 0.6); |
| height: 2px; |
| } |
| |
| .code-editor { |
| font-family: 'Courier New', monospace; |
| font-size: 14px; |
| line-height: 1.5; |
| tab-size: 4; |
| } |
| |
| .sidebar-item:hover { |
| background-color: rgba(55, 65, 81, 0.5); |
| } |
| |
| .jupyter-cell { |
| border-left: 4px solid #3b82f6; |
| } |
| |
| .jupyter-output { |
| background-color: rgba(31, 41, 55, 0.7); |
| } |
| |
| .draggable { |
| cursor: move; |
| } |
| |
| .resizable { |
| resize: horizontal; |
| overflow: auto; |
| } |
| |
| @keyframes pulse { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0.5; } |
| } |
| |
| .animate-pulse { |
| animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; |
| } |
| |
| .model-card { |
| transition: all 0.2s ease; |
| } |
| |
| .model-card:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3); |
| } |
| |
| .model-card.selected { |
| border-color: #3b82f6; |
| background-color: rgba(59, 130, 246, 0.1); |
| } |
| |
| .language-tag { |
| transition: all 0.2s ease; |
| } |
| |
| .language-tag:hover { |
| transform: scale(1.05); |
| } |
| |
| .language-tag.selected { |
| background-color: #3b82f6; |
| color: white; |
| } |
| |
| .param-slider::-webkit-slider-thumb { |
| -webkit-appearance: none; |
| appearance: none; |
| width: 18px; |
| height: 18px; |
| border-radius: 50%; |
| background: #3b82f6; |
| cursor: pointer; |
| } |
| |
| .param-slider::-moz-range-thumb { |
| width: 18px; |
| height: 18px; |
| border-radius: 50%; |
| background: #3b82f6; |
| cursor: pointer; |
| } |
| |
| .tab-button { |
| transition: all 0.2s ease; |
| } |
| |
| .tab-button.active { |
| border-bottom: 2px solid #3b82f6; |
| color: #3b82f6; |
| } |
| |
| .activation-node { |
| width: 12px; |
| height: 12px; |
| border-radius: 50%; |
| position: absolute; |
| bottom: -6px; |
| left: 50%; |
| transform: translateX(-50%); |
| } |
| </style> |
| </head> |
| <body class="bg-gray-900 text-gray-200 h-screen flex flex-col overflow-hidden"> |
| |
| <div class="bg-gray-800 px-4 py-2 flex items-center justify-between border-b border-gray-700"> |
| <div class="flex items-center space-x-4"> |
| <span class="font-bold text-blue-400 flex items-center"> |
| <i class="fas fa-brain mr-2"></i> |
| <span>Neural Visualizer Pro</span> |
| </span> |
| <div class="flex space-x-2 text-sm"> |
| <button class="px-2 py-1 hover:bg-gray-700 rounded">File</button> |
| <button class="px-2 py-1 hover:bg-gray-700 rounded">Edit</button> |
| <button class="px-2 py-1 hover:bg-gray-700 rounded">View</button> |
| <button class="px-2 py-1 hover:bg-gray-700 rounded">Run</button> |
| <button class="px-2 py-1 hover:bg-gray-700 rounded">Help</button> |
| </div> |
| </div> |
| <div class="flex items-center space-x-3"> |
| <span class="text-xs text-gray-400">Interactive Mode</span> |
| <div class="w-3 h-3 rounded-full bg-green-500 animate-pulse"></div> |
| <button class="text-xs px-3 py-1 bg-blue-600 rounded hover:bg-blue-700"> |
| <i class="fas fa-cloud-upload-alt mr-1"></i> Save Model |
| </button> |
| </div> |
| </div> |
| |
| <div class="flex flex-1 overflow-hidden"> |
| |
| <div class="w-16 bg-gray-800 flex flex-col items-center py-4 border-r border-gray-700"> |
| <button class="sidebar-item w-12 h-12 rounded-lg flex items-center justify-center mb-4 bg-gray-700 text-blue-400"> |
| <i class="fas fa-project-diagram text-xl"></i> |
| </button> |
| <button class="sidebar-item w-12 h-12 rounded-lg flex items-center justify-center mb-4 hover:text-blue-400"> |
| <i class="fas fa-layer-group text-xl"></i> |
| </button> |
| <button class="sidebar-item w-12 h-12 rounded-lg flex items-center justify-center mb-4 hover:text-blue-400"> |
| <i class="fas fa-sliders-h text-xl"></i> |
| </button> |
| <button class="sidebar-item w-12 h-12 rounded-lg flex items-center justify-center mb-4 hover:text-blue-400"> |
| <i class="fas fa-chart-line text-xl"></i> |
| </button> |
| <button class="sidebar-item w-12 h-12 rounded-lg flex items-center justify-center mb-4 hover:text-blue-400"> |
| <i class="fas fa-language text-xl"></i> |
| </button> |
| <div class="mt-auto"> |
| <button class="sidebar-item w-12 h-12 rounded-lg flex items-center justify-center mb-4 hover:text-blue-400"> |
| <i class="fas fa-cog text-xl"></i> |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="flex-1 flex overflow-hidden"> |
| |
| <div class="w-1/2 flex flex-col border-r border-gray-700"> |
| <div class="bg-gray-800 px-4 py-2 flex items-center justify-between"> |
| <div class="flex items-center space-x-2"> |
| <i class="fas fa-file-code text-blue-400"></i> |
| <span class="text-sm">model_config.py</span> |
| </div> |
| <div class="flex space-x-2"> |
| <button class="text-xs px-2 py-1 bg-blue-600 rounded hover:bg-blue-700"> |
| <i class="fas fa-play mr-1"></i> Run |
| </button> |
| <button class="text-xs px-2 py-1 bg-gray-700 rounded hover:bg-gray-600"> |
| <i class="fas fa-terminal mr-1"></i> Console |
| </button> |
| </div> |
| </div> |
| |
| <div class="flex-1 overflow-auto bg-gray-900 p-4 code-editor"> |
| |
| <div class="flex border-b border-gray-700 mb-4"> |
| <button class="tab-button px-4 py-2 text-sm font-medium active" data-tab="config"> |
| <i class="fas fa-cog mr-2"></i>Configuration |
| </button> |
| <button class="tab-button px-4 py-2 text-sm font-medium" data-tab="training"> |
| <i class="fas fa-running mr-2"></i>Training |
| </button> |
| <button class="tab-button px-4 py-2 text-sm font-medium" data-tab="fine-tuning"> |
| <i class="fas fa-magic mr-2"></i>Fine-Tuning |
| </button> |
| </div> |
| |
| |
| <div id="config-tab" class="tab-content"> |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-green-400"># Model Configuration</div> |
| <div class="text-gray-500"># Select a base model and customize parameters</div> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-purple-400">from</div> <div class="text-gray-200">transformers</div> <div class="text-purple-400">import</div> <div class="text-gray-200">AutoModelForSequenceClassification</div> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-yellow-400 mb-2"># Available Models (click to select)</div> |
| <div class="grid grid-cols-3 gap-4 mb-4"> |
| <div class="model-card p-4 border border-gray-700 rounded-lg cursor-pointer bg-gray-800 selected" data-model="llama-2"> |
| <div class="flex items-center mb-2"> |
| <i class="fas fa-robot text-blue-400 mr-2"></i> |
| <span class="font-medium">LLaMA 2</span> |
| </div> |
| <div class="text-xs text-gray-400">7B parameters</div> |
| <div class="text-xs text-gray-400">Context: 4096</div> |
| </div> |
| <div class="model-card p-4 border border-gray-700 rounded-lg cursor-pointer bg-gray-800" data-model="gpt-3"> |
| <div class="flex items-center mb-2"> |
| <i class="fas fa-brain text-purple-400 mr-2"></i> |
| <span class="font-medium">GPT-3.5</span> |
| </div> |
| <div class="text-xs text-gray-400">175B parameters</div> |
| <div class="text-xs text-gray-400">Context: 4096</div> |
| </div> |
| <div class="model-card p-4 border border-gray-700 rounded-lg cursor-pointer bg-gray-800" data-model="bert"> |
| <div class="flex items-center mb-2"> |
| <i class="fas fa-shield-alt text-green-400 mr-2"></i> |
| <span class="font-medium">BERT</span> |
| </div> |
| <div class="text-xs text-gray-400">340M parameters</div> |
| <div class="text-xs text-gray-400">Context: 512</div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-yellow-400 mb-2"># Model Parameters</div> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Learning Rate</label> |
| <div class="flex items-center space-x-4"> |
| <input type="range" min="0.0001" max="0.01" step="0.0001" value="0.001" class="param-slider w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <span class="text-xs bg-gray-800 px-2 py-1 rounded">0.001</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Batch Size</label> |
| <div class="flex items-center space-x-4"> |
| <input type="range" min="8" max="128" step="8" value="32" class="param-slider w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <span class="text-xs bg-gray-800 px-2 py-1 rounded">32</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Epochs</label> |
| <div class="flex items-center space-x-4"> |
| <input type="range" min="1" max="50" step="1" value="10" class="param-slider w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <span class="text-xs bg-gray-800 px-2 py-1 rounded">10</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Dropout Rate</label> |
| <div class="flex items-center space-x-4"> |
| <input type="range" min="0" max="0.5" step="0.05" value="0.1" class="param-slider w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <span class="text-xs bg-gray-800 px-2 py-1 rounded">0.1</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="training-tab" class="tab-content hidden"> |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-green-400"># Training Configuration</div> |
| <div class="text-gray-500"># Set up your training parameters and data</div> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-yellow-400 mb-2"># Dataset Selection</div> |
| <select class="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm mb-4"> |
| <option>Custom Dataset</option> |
| <option>GLUE Benchmark</option> |
| <option>SQuAD 2.0</option> |
| <option>IMDB Reviews</option> |
| <option>Swahili News Dataset</option> |
| </select> |
| |
| <div class="text-sm text-gray-400 mb-2">Or upload your own dataset:</div> |
| <div class="border-2 border-dashed border-gray-700 rounded-lg p-4 text-center cursor-pointer hover:bg-gray-800 mb-4"> |
| <i class="fas fa-cloud-upload-alt text-2xl text-blue-400 mb-2"></i> |
| <div class="text-sm">Click to upload or drag and drop</div> |
| <div class="text-xs text-gray-500 mt-1">CSV, JSON, or TXT files</div> |
| </div> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-yellow-400 mb-2"># Training Options</div> |
| <div class="space-y-3"> |
| <label class="flex items-center space-x-2 cursor-pointer"> |
| <input type="checkbox" class="form-checkbox text-blue-500 rounded" checked> |
| <span class="text-sm">Use mixed precision training</span> |
| </label> |
| <label class="flex items-center space-x-2 cursor-pointer"> |
| <input type="checkbox" class="form-checkbox text-blue-500 rounded"> |
| <span class="text-sm">Enable gradient checkpointing</span> |
| </label> |
| <label class="flex items-center space-x-2 cursor-pointer"> |
| <input type="checkbox" class="form-checkbox text-blue-500 rounded" checked> |
| <span class="text-sm">Use learning rate scheduling</span> |
| </label> |
| <label class="flex items-center space-x-2 cursor-pointer"> |
| <input type="checkbox" class="form-checkbox text-blue-500 rounded"> |
| <span class="text-sm">Enable early stopping</span> |
| </label> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="fine-tuning-tab" class="tab-content hidden"> |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-green-400"># Fine-Tuning Options</div> |
| <div class="text-gray-500"># Customize for specific languages or domains</div> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-yellow-400 mb-2"># Language Specialization</div> |
| <div class="flex flex-wrap gap-2 mb-4"> |
| <div class="language-tag px-3 py-1 bg-gray-800 rounded-full text-xs cursor-pointer selected" data-lang="en"> |
| <i class="fas fa-check-circle mr-1"></i> English |
| </div> |
| <div class="language-tag px-3 py-1 bg-gray-800 rounded-full text-xs cursor-pointer" data-lang="sw"> |
| <i class="fas fa-globe-africa mr-1"></i> Swahili |
| </div> |
| <div class="language-tag px-3 py-1 bg-gray-800 rounded-full text-xs cursor-pointer" data-lang="fr"> |
| <i class="fas fa-baguette mr-1"></i> French |
| </div> |
| <div class="language-tag px-3 py-1 bg-gray-800 rounded-full text-xs cursor-pointer" data-lang="es"> |
| <i class="fas fa-sun mr-1"></i> Spanish |
| </div> |
| <div class="language-tag px-3 py-1 bg-gray-800 rounded-full text-xs cursor-pointer" data-lang="de"> |
| <i class="fas fa-landmark mr-1"></i> German |
| </div> |
| <div class="language-tag px-3 py-1 bg-gray-800 rounded-full text-xs cursor-pointer" data-lang="zh"> |
| <i class="fas fa-yin-yang mr-1"></i> Chinese |
| </div> |
| </div> |
| |
| <div class="text-sm text-gray-400 mb-2">Custom tokenizer for selected language:</div> |
| <textarea class="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm h-20 mb-4" placeholder="Add special tokens or vocabulary for your language..."></textarea> |
| </div> |
| |
| <div class="jupyter-cell mb-4 pl-2"> |
| <div class="text-yellow-400 mb-2"># Domain Adaptation</div> |
| <select class="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm mb-4"> |
| <option>General Language</option> |
| <option>Medical</option> |
| <option>Legal</option> |
| <option>Financial</option> |
| <option>Technical</option> |
| <option>News</option> |
| </select> |
| |
| <div class="text-sm text-gray-400 mb-2">Domain-specific vocabulary:</div> |
| <textarea class="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm h-20" placeholder="Add domain-specific terms..."></textarea> |
| </div> |
| </div> |
| </div> |
| |
| <div class="bg-gray-800 px-4 py-2 border-t border-gray-700"> |
| <div class="flex items-center space-x-2 text-xs"> |
| <span>Python 3.10.6</span> |
| <span class="text-gray-500">•</span> |
| <span>PyTorch 2.0.1</span> |
| <span class="text-gray-500">•</span> |
| <span>Transformers 4.30.2</span> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="w-1/2 flex flex-col"> |
| <div class="bg-gray-800 px-4 py-2 flex items-center justify-between"> |
| <div class="flex items-center space-x-2"> |
| <i class="fas fa-project-diagram text-blue-400"></i> |
| <span class="text-sm">Model Visualization & Training</span> |
| </div> |
| <div class="flex space-x-2"> |
| <button class="text-xs px-2 py-1 bg-gray-700 rounded hover:bg-gray-600"> |
| <i class="fas fa-sync-alt mr-1"></i> Refresh |
| </button> |
| <button class="text-xs px-2 py-1 bg-gray-700 rounded hover:bg-gray-600"> |
| <i class="fas fa-expand mr-1"></i> Fullscreen |
| </button> |
| <button class="text-xs px-2 py-1 bg-blue-600 rounded hover:bg-blue-700"> |
| <i class="fas fa-rocket mr-1"></i> Deploy |
| </button> |
| </div> |
| </div> |
| |
| <div class="flex-1 overflow-auto bg-gray-900 p-8 flex flex-col"> |
| |
| <div class="mb-8"> |
| <div class="text-lg font-medium mb-4 flex items-center"> |
| <i class="fas fa-network-wired text-blue-400 mr-2"></i> |
| <span>Model Architecture</span> |
| </div> |
| <div class="bg-gray-800 rounded-lg p-6"> |
| <div class="flex items-center justify-center space-x-8" id="network-container"> |
| |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="mb-8"> |
| <div class="text-lg font-medium mb-4 flex items-center"> |
| <i class="fas fa-running text-green-400 mr-2"></i> |
| <span>Training Controls</span> |
| </div> |
| <div class="bg-gray-800 rounded-lg p-6"> |
| <div class="grid grid-cols-3 gap-6 mb-6"> |
| <div> |
| <label class="block text-sm text-gray-400 mb-2">Current Epoch</label> |
| <div class="text-2xl font-bold text-center">0</div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-2">Training Loss</label> |
| <div class="text-2xl font-bold text-center">-</div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-2">Validation Loss</label> |
| <div class="text-2xl font-bold text-center">-</div> |
| </div> |
| </div> |
| |
| <div class="flex space-x-4"> |
| <button class="flex-1 py-2 bg-green-600 rounded hover:bg-green-700 flex items-center justify-center"> |
| <i class="fas fa-play mr-2"></i> Start Training |
| </button> |
| <button class="flex-1 py-2 bg-yellow-600 rounded hover:bg-yellow-700 flex items-center justify-center" disabled> |
| <i class="fas fa-pause mr-2"></i> Pause |
| </button> |
| <button class="flex-1 py-2 bg-red-600 rounded hover:bg-red-700 flex items-center justify-center" disabled> |
| <i class="fas fa-stop mr-2"></i> Stop |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="mb-8"> |
| <div class="text-lg font-medium mb-4 flex items-center"> |
| <i class="fas fa-chart-line text-purple-400 mr-2"></i> |
| <span>Training Metrics</span> |
| </div> |
| <div class="grid grid-cols-2 gap-6"> |
| <div class="bg-gray-800 rounded-lg p-4"> |
| <canvas id="training-chart" height="200"></canvas> |
| </div> |
| <div class="bg-gray-800 rounded-lg p-4"> |
| <canvas id="metrics-chart" height="200"></canvas> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div> |
| <div class="text-lg font-medium mb-4 flex items-center"> |
| <i class="fas fa-magic text-pink-400 mr-2"></i> |
| <span>Fine-Tuning Progress</span> |
| </div> |
| <div class="bg-gray-800 rounded-lg p-6"> |
| <div class="mb-4"> |
| <div class="flex justify-between text-sm mb-1"> |
| <span>Language Adaptation (Swahili)</span> |
| <span>0%</span> |
| </div> |
| <div class="w-full bg-gray-700 rounded-full h-2"> |
| <div class="bg-blue-500 h-2 rounded-full" style="width: 0%"></div> |
| </div> |
| </div> |
| <div class="mb-4"> |
| <div class="flex justify-between text-sm mb-1"> |
| <span>Domain Specialization</span> |
| <span>0%</span> |
| </div> |
| <div class="w-full bg-gray-700 rounded-full h-2"> |
| <div class="bg-purple-500 h-2 rounded-full" style="width: 0%"></div> |
| </div> |
| </div> |
| <div class="text-sm text-gray-400"> |
| <i class="fas fa-info-circle mr-2"></i> |
| Fine-tuning will begin after initial training completes |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="bg-gray-800 px-4 py-2 border-t border-gray-700 flex justify-between items-center"> |
| <div class="flex items-center space-x-4"> |
| <button class="text-xs px-3 py-1 bg-blue-600 rounded hover:bg-blue-700"> |
| <i class="fas fa-play mr-1"></i> Train Model |
| </button> |
| <div class="flex items-center space-x-2 text-xs"> |
| <span>GPU:</span> |
| <span class="px-2 py-1 bg-gray-700 rounded">NVIDIA A100</span> |
| </div> |
| <div class="flex items-center space-x-2 text-xs"> |
| <span>Memory:</span> |
| <span class="px-2 py-1 bg-gray-700 rounded">32GB</span> |
| </div> |
| </div> |
| <div class="text-xs text-gray-400"> |
| <i class="fas fa-circle text-green-500 mr-1"></i> Ready |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const layers = [4, 8, 8, 4]; |
| const colors = ['bg-blue-500', 'bg-purple-500', 'bg-pink-500', 'bg-green-500']; |
| const activations = ['sigmoid', 'relu', 'tanh', 'linear']; |
| |
| |
| drawNetwork(layers, colors, activations); |
| |
| |
| initTrainingChart(); |
| initMetricsChart(); |
| |
| |
| const editorPanel = document.querySelector('.w-1/2'); |
| editorPanel.classList.add('resizable'); |
| |
| |
| makeNeuronsDraggable(); |
| |
| |
| setupTabs(); |
| |
| |
| setupModelSelection(); |
| |
| |
| setupLanguageSelection(); |
| |
| |
| updateSliderValues(); |
| |
| |
| simulateTraining(); |
| }); |
| |
| function drawNetwork(layers, colors, activations) { |
| const container = document.getElementById('network-container'); |
| container.innerHTML = ''; |
| |
| |
| const maxNeurons = Math.max(...layers); |
| const layerSpacing = 200; |
| const neuronSpacing = 60; |
| |
| |
| layers.forEach((neuronCount, layerIndex) => { |
| const layerDiv = document.createElement('div'); |
| layerDiv.className = 'layer'; |
| |
| |
| const verticalOffset = ((maxNeurons - neuronCount) * neuronSpacing) / 2; |
| |
| |
| for (let i = 0; i < neuronCount; i++) { |
| const neuron = document.createElement('div'); |
| neuron.className = `neuron ${colors[layerIndex]} draggable`; |
| neuron.textContent = `${layerIndex+1}.${i+1}`; |
| neuron.dataset.layer = layerIndex; |
| neuron.dataset.neuron = i; |
| neuron.style.top = `${verticalOffset + i * neuronSpacing}px`; |
| neuron.style.left = `${layerIndex * layerSpacing}px`; |
| |
| |
| const activationNode = document.createElement('div'); |
| activationNode.className = `activation-node bg-${getActivationColor(activations[layerIndex])}`; |
| activationNode.title = activations[layerIndex]; |
| neuron.appendChild(activationNode); |
| |
| layerDiv.appendChild(neuron); |
| } |
| |
| |
| const layerLabel = document.createElement('div'); |
| layerLabel.className = 'text-xs mt-2 text-gray-400'; |
| |
| if (layerIndex === 0) { |
| layerLabel.textContent = 'Input Layer'; |
| } else if (layerIndex === layers.length - 1) { |
| layerLabel.textContent = 'Output Layer'; |
| } else { |
| layerLabel.textContent = `Hidden Layer ${layerIndex}`; |
| } |
| |
| layerDiv.appendChild(layerLabel); |
| container.appendChild(layerDiv); |
| }); |
| |
| |
| if (layers.length > 1) { |
| for (let l = 0; l < layers.length - 1; l++) { |
| const currentLayerCount = layers[l]; |
| const nextLayerCount = layers[l + 1]; |
| |
| for (let i = 0; i < currentLayerCount; i++) { |
| for (let j = 0; j < nextLayerCount; j++) { |
| const startNeuron = document.querySelector(`[data-layer="${l}"][data-neuron="${i}"]`); |
| const endNeuron = document.querySelector(`[data-layer="${l+1}"][data-neuron="${j}"]`); |
| |
| if (startNeuron && endNeuron) { |
| const startRect = startNeuron.getBoundingClientRect(); |
| const endRect = endNeuron.getBoundingClientRect(); |
| const containerRect = container.getBoundingClientRect(); |
| |
| const startX = startRect.left + startRect.width/2 - containerRect.left; |
| const startY = startRect.top + startRect.height/2 - containerRect.top; |
| const endX = endRect.left + endRect.width/2 - containerRect.left; |
| const endY = endRect.top + endRect.height/2 - containerRect.top; |
| |
| const length = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2)); |
| const angle = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI; |
| |
| const connection = document.createElement('div'); |
| connection.className = 'connection'; |
| connection.style.width = `${length}px`; |
| connection.style.height = '1px'; |
| connection.style.left = `${startX}px`; |
| connection.style.top = `${startY}px`; |
| connection.style.transform = `rotate(${angle}deg)`; |
| |
| |
| if (Math.random() < 0.3) { |
| connection.classList.add('active'); |
| } |
| |
| container.appendChild(connection); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| function getActivationColor(activation) { |
| switch(activation) { |
| case 'relu': return 'red-500'; |
| case 'sigmoid': return 'blue-500'; |
| case 'tanh': return 'purple-500'; |
| case 'linear': return 'green-500'; |
| default: return 'gray-500'; |
| } |
| } |
| |
| function initTrainingChart() { |
| const ctx = document.getElementById('training-chart').getContext('2d'); |
| const chart = new Chart(ctx, { |
| type: 'line', |
| data: { |
| labels: Array.from({length: 20}, (_, i) => i * 5), |
| datasets: [ |
| { |
| label: 'Training Loss', |
| data: [2.5, 2.1, 1.8, 1.5, 1.2, 0.9, 0.7, 0.5, 0.4, 0.3, 0.25, 0.2, 0.18, 0.16, 0.15, 0.14, 0.13, 0.12, 0.11, 0.1], |
| borderColor: 'rgb(99, 102, 241)', |
| backgroundColor: 'rgba(99, 102, 241, 0.1)', |
| tension: 0.4, |
| fill: true |
| }, |
| { |
| label: 'Validation Loss', |
| data: [2.6, 2.3, 2.0, 1.7, 1.4, 1.1, 0.9, 0.7, 0.6, 0.5, 0.45, 0.4, 0.38, 0.36, 0.35, 0.34, 0.33, 0.32, 0.31, 0.3], |
| borderColor: 'rgb(236, 72, 153)', |
| backgroundColor: 'rgba(236, 72, 153, 0.1)', |
| tension: 0.4, |
| fill: true |
| } |
| ] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| title: { |
| display: true, |
| text: 'Training Loss', |
| color: '#E5E7EB' |
| }, |
| legend: { |
| labels: { |
| color: '#E5E7EB' |
| } |
| } |
| }, |
| scales: { |
| x: { |
| title: { |
| display: true, |
| text: 'Epoch', |
| color: '#9CA3AF' |
| }, |
| ticks: { |
| color: '#9CA3AF' |
| }, |
| grid: { |
| color: 'rgba(55, 65, 81, 0.5)' |
| } |
| }, |
| y: { |
| title: { |
| display: true, |
| text: 'Loss', |
| color: '#9CA3AF' |
| }, |
| ticks: { |
| color: '#9CA3AF' |
| }, |
| grid: { |
| color: 'rgba(55, 65, 81, 0.5)' |
| } |
| } |
| } |
| } |
| }); |
| } |
| |
| function initMetricsChart() { |
| const ctx = document.getElementById('metrics-chart').getContext('2d'); |
| const chart = new Chart(ctx, { |
| type: 'line', |
| data: { |
| labels: Array.from({length: 20}, (_, i) => i * 5), |
| datasets: [ |
| { |
| label: 'Accuracy', |
| data: [0.2, 0.3, 0.35, 0.4, 0.5, 0.6, 0.65, 0.7, 0.75, 0.78, 0.8, 0.82, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91], |
| borderColor: 'rgb(16, 185, 129)', |
| backgroundColor: 'rgba(16, 185, 129, 0.1)', |
| tension: 0.4, |
| fill: true |
| }, |
| { |
| label: 'F1 Score', |
| data: [0.15, 0.25, 0.3, 0.35, 0.45, 0.55, 0.6, 0.65, 0.7, 0.73, 0.76, 0.78, 0.8, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88], |
| borderColor: 'rgb(245, 158, 11)', |
| backgroundColor: 'rgba(245, 158, 11, 0.1)', |
| tension: 0.4, |
| fill: true |
| } |
| ] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| title: { |
| display: true, |
| text: 'Performance Metrics', |
| color: '#E5E7EB' |
| }, |
| legend: { |
| labels: { |
| color: '#E5E7EB' |
| } |
| } |
| }, |
| scales: { |
| x: { |
| title: { |
| display: true, |
| text: 'Epoch', |
| color: '#9CA3AF' |
| }, |
| ticks: { |
| color: '#9CA3AF' |
| }, |
| grid: { |
| color: 'rgba(55, 65, 81, 0.5)' |
| } |
| }, |
| y: { |
| title: { |
| display: true, |
| text: 'Score', |
| color: '#9CA3AF' |
| }, |
| ticks: { |
| color: '#9CA3AF' |
| }, |
| grid: { |
| color: 'rgba(55, 65, 81, 0.5)' |
| } |
| } |
| } |
| } |
| }); |
| } |
| |
| function makeNeuronsDraggable() { |
| const neurons = document.querySelectorAll('.draggable'); |
| let isDragging = false; |
| let currentNeuron = null; |
| let offsetX, offsetY; |
| |
| neurons.forEach(neuron => { |
| neuron.addEventListener('mousedown', function(e) { |
| isDragging = true; |
| currentNeuron = this; |
| offsetX = e.clientX - this.getBoundingClientRect().left; |
| offsetY = e.clientY - this.getBoundingClientRect().top; |
| |
| |
| this.style.zIndex = '10'; |
| this.classList.add('ring-2', 'ring-blue-400'); |
| }); |
| }); |
| |
| document.addEventListener('mousemove', function(e) { |
| if (!isDragging || !currentNeuron) return; |
| |
| const container = document.getElementById('network-container'); |
| const containerRect = container.getBoundingClientRect(); |
| |
| let x = e.clientX - containerRect.left - offsetX; |
| let y = e.clientY - containerRect.top - offsetY; |
| |
| |
| x = Math.max(0, Math.min(x, containerRect.width - currentNeuron.offsetWidth)); |
| y = Math.max(0, Math.min(y, containerRect.height - currentNeuron.offsetHeight)); |
| |
| currentNeuron.style.left = `${x}px`; |
| currentNeuron.style.top = `${y}px`; |
| |
| |
| redrawConnections(); |
| }); |
| |
| document.addEventListener('mouseup', function() { |
| if (currentNeuron) { |
| currentNeuron.style.zIndex = ''; |
| currentNeuron.classList.remove('ring-2', 'ring-blue-400'); |
| } |
| isDragging = false; |
| currentNeuron = null; |
| }); |
| } |
| |
| function redrawConnections() { |
| |
| const connections = document.querySelectorAll('.connection'); |
| connections.forEach(conn => conn.remove()); |
| |
| |
| const neurons = document.querySelectorAll('.neuron'); |
| const container = document.getElementById('network-container'); |
| const containerRect = container.getBoundingClientRect(); |
| |
| |
| const layers = {}; |
| neurons.forEach(neuron => { |
| const layer = parseInt(neuron.dataset.layer); |
| if (!layers[layer]) layers[layer] = []; |
| layers[layer].push(neuron); |
| }); |
| |
| const layerIndices = Object.keys(layers).sort(); |
| |
| for (let i = 0; i < layerIndices.length - 1; i++) { |
| const currentLayer = layers[layerIndices[i]]; |
| const nextLayer = layers[layerIndices[i+1]]; |
| |
| currentLayer.forEach(startNeuron => { |
| nextLayer.forEach(endNeuron => { |
| const startRect = startNeuron.getBoundingClientRect(); |
| const endRect = endNeuron.getBoundingClientRect(); |
| |
| const startX = startRect.left + startRect.width/2 - containerRect.left; |
| const startY = startRect.top + startRect.height/2 - containerRect.top; |
| const endX = endRect.left + endRect.width/2 - containerRect.left; |
| const endY = endRect.top + endRect.height/2 - containerRect.top; |
| |
| const length = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2)); |
| const angle = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI; |
| |
| const connection = document.createElement('div'); |
| connection.className = 'connection'; |
| connection.style.width = `${length}px`; |
| connection.style.height = '1px'; |
| connection.style.left = `${startX}px`; |
| connection.style.top = `${startY}px`; |
| connection.style.transform = `rotate(${angle}deg)`; |
| |
| |
| if (Math.random() < 0.3) { |
| connection.classList.add('active'); |
| } |
| |
| container.appendChild(connection); |
| }); |
| }); |
| } |
| } |
| |
| function setupTabs() { |
| const tabButtons = document.querySelectorAll('.tab-button'); |
| const tabContents = document.querySelectorAll('.tab-content'); |
| |
| tabButtons.forEach(button => { |
| button.addEventListener('click', function() { |
| |
| tabButtons.forEach(btn => btn.classList.remove('active')); |
| |
| this.classList.add('active'); |
| |
| |
| tabContents.forEach(content => content.classList.add('hidden')); |
| |
| const tabId = this.getAttribute('data-tab') + '-tab'; |
| document.getElementById(tabId).classList.remove('hidden'); |
| }); |
| }); |
| } |
| |
| function setupModelSelection() { |
| const modelCards = document.querySelectorAll('.model-card'); |
| |
| modelCards.forEach(card => { |
| card.addEventListener('click', function() { |
| |
| modelCards.forEach(c => c.classList.remove('selected')); |
| |
| this.classList.add('selected'); |
| |
| |
| const model = this.getAttribute('data-model'); |
| updateNetworkForModel(model); |
| }); |
| }); |
| } |
| |
| function updateNetworkForModel(model) { |
| let layers, colors, activations; |
| |
| switch(model) { |
| case 'llama-2': |
| layers = [4, 8, 8, 4]; |
| colors = ['bg-blue-500', 'bg-purple-500', 'bg-pink-500', 'bg-green-500']; |
| activations = ['sigmoid', 'relu', 'tanh', 'linear']; |
| break; |
| case 'gpt-3': |
| layers = [4, 12, 12, 4]; |
| colors = ['bg-blue-500', 'bg-purple-500', 'bg-pink-500', 'bg-green-500']; |
| activations = ['relu', 'relu', 'tanh', 'linear']; |
| break; |
| case 'bert': |
| layers = [4, 8, 4]; |
| colors = ['bg-blue-500', 'bg-purple-500', 'bg-green-500']; |
| activations = ['tanh', 'relu', 'linear']; |
| break; |
| default: |
| layers = [4, 8, 8, 4]; |
| colors = ['bg-blue-500', 'bg-purple-500', 'bg-pink-500', 'bg-green-500']; |
| activations = ['sigmoid', 'relu', 'tanh', 'linear']; |
| } |
| |
| drawNetwork(layers, colors, activations); |
| } |
| |
| function setupLanguageSelection() { |
| const languageTags = document.querySelectorAll('.language-tag'); |
| |
| languageTags.forEach(tag => { |
| tag.addEventListener('click', function() { |
| |
| this.classList.toggle('selected'); |
| |
| |
| if (this.getAttribute('data-lang') === 'sw' && this.classList.contains('selected')) { |
| showSwahiliMessage(); |
| } |
| }); |
| }); |
| } |
| |
| function showSwahiliMessage() { |
| const fineTuningTab = document.getElementById('fine-tuning-tab'); |
| const message = document.createElement('div'); |
| message.className = 'bg-blue-900 text-blue-200 p-3 rounded-lg text-sm mb-4 flex items-start'; |
| message.innerHTML = ` |
| <i class="fas fa-info-circle mt-1 mr-2"></i> |
| <div> |
| <strong>Kumbuka:</strong> Unachagua kufanya fine-tuning kwa lugha ya Kiswahili. |
| Hii itahitaji data ya ziada ya Kiswahili kwa matokeo bora. |
| <div class="mt-1">Tafadhali hakikisha una dataset ya kutosha.</div> |
| </div> |
| `; |
| |
| fineTuningTab.insertBefore(message, fineTuningTab.firstChild.nextSibling); |
| |
| |
| setTimeout(() => { |
| message.remove(); |
| }, 10000); |
| } |
| |
| function updateSliderValues() { |
| const sliders = document.querySelectorAll('.param-slider'); |
| |
| sliders.forEach(slider => { |
| const valueDisplay = slider.nextElementSibling; |
| |
| |
| valueDisplay.textContent = slider.value; |
| |
| |
| slider.addEventListener('input', function() { |
| valueDisplay.textContent = this.value; |
| }); |
| }); |
| } |
| |
| function simulateTraining() { |
| const startButton = document.querySelector('.bg-green-600'); |
| const pauseButton = document.querySelector('.bg-yellow-600'); |
| const stopButton = document.querySelector('.bg-red-600'); |
| const epochDisplay = document.querySelector('.text-2xl.font-bold.text-center'); |
| const trainingLossDisplay = document.querySelectorAll('.text-2xl.font-bold.text-center')[1]; |
| const valLossDisplay = document.querySelectorAll('.text-2xl.font-bold.text-center')[2]; |
| const progressBars = document.querySelectorAll('.bg-gray-700 .rounded-full > div'); |
| |
| let isTraining = false; |
| let isPaused = false; |
| let currentEpoch = 0; |
| let animationId; |
| |
| startButton.addEventListener('click', function() { |
| if (!isTraining) { |
| isTraining = true; |
| currentEpoch = 0; |
| startButton.disabled = true; |
| pauseButton.disabled = false; |
| stopButton.disabled = false; |
| |
| |
| startButton.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Training...'; |
| |
| |
| simulateEpoch(); |
| } |
| }); |
| |
| pauseButton.addEventListener('click', function() { |
| if (isTraining && !isPaused) { |
| isPaused = true; |
| cancelAnimationFrame(animationId); |
| pauseButton.innerHTML = '<i class="fas fa-play mr-2"></i> Resume'; |
| startButton.innerHTML = '<i class="fas fa-spinner mr-2"></i> Training Paused'; |
| } else if (isTraining && isPaused) { |
| isPaused = false; |
| pauseButton.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause'; |
| startButton.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Training...'; |
| simulateEpoch(); |
| } |
| }); |
| |
| stopButton.addEventListener('click', function() { |
| isTraining = false; |
| isPaused = false; |
| cancelAnimationFrame(animationId); |
| |
| startButton.disabled = false; |
| pauseButton.disabled = true; |
| stopButton.disabled = true; |
| |
| startButton.innerHTML = '<i class="fas fa-play mr-2"></i> Start Training'; |
| pauseButton.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause'; |
| |
| |
| progressBars.forEach(bar => { |
| bar.style.width = '0%'; |
| }); |
| }); |
| |
| function simulateEpoch() { |
| if (!isTraining || isPaused) return; |
| |
| currentEpoch++; |
| |
| |
| epochDisplay.textContent = currentEpoch; |
| |
| |
| const trainingLoss = Math.max(0.1, 2.5 - (currentEpoch * 0.12)); |
| const valLoss = Math.max(0.15, 2.6 - (currentEpoch * 0.115)); |
| |
| trainingLossDisplay.textContent = trainingLoss.toFixed(4); |
| valLossDisplay.textContent = valLoss.toFixed(4); |
| |
| |
| if (currentEpoch >= 5) { |
| const progress = Math.min(100, (currentEpoch - 5) * 10); |
| progressBars.forEach(bar => { |
| bar.style.width = `${progress}%`; |
| }); |
| } |
| |
| |
| if (currentEpoch < 20) { |
| animationId = requestAnimationFrame(simulateEpoch); |
| } else { |
| isTraining = false; |
| startButton.disabled = false; |
| pauseButton.disabled = true; |
| stopButton.disabled = true; |
| |
| startButton.innerHTML = '<i class="fas fa-play mr-2"></i> Start Training'; |
| |
| |
| const message = document.createElement('div'); |
| message.className = 'bg-green-900 text-green-200 p-3 rounded-lg text-sm mb-4 flex items-center absolute bottom-4 right-4'; |
| message.innerHTML = ` |
| <i class="fas fa-check-circle mr-2"></i> |
| <div>Training completed successfully!</div> |
| `; |
| |
| document.querySelector('.flex-1.overflow-auto').appendChild(message); |
| |
| |
| setTimeout(() => { |
| message.remove(); |
| }, 5000); |
| } |
| } |
| } |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Bur3hani/neuralv" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |