|
|
<!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> |