alexdatamed's picture
Upload app.js
2bd6c65 verified
// Дані про робочий процес науки про дані
const workflowData = {
"title": "Робочий процес науки про дані",
"introduction": "Кожен проект з науки про дані включає кілька важливих етапів. Ця інтерактивна панель допоможе вам зрозуміти кожен етап робочого процесу та його важливість.",
"steps": [
{
"id": 1,
"title": "Формулювання проблеми",
"shortTitle": "Проблема",
"description": "Кожен проект з науки про дані починається з визначення проблеми. Незалежно від того, чи це прогнозування результатів пацієнтів або оптимізація бізнес-операцій, переклад реальної проблеми у питання, що базується на даних, є вирішальним.",
"keyPoints": [
"Визначення конкретної проблеми, яку потрібно вирішити",
"Формулювання питань, на які потрібно відповісти за допомогою даних",
"Вибір підходу до вирішення (машинне навчання, статистичний аналіз тощо)"
],
"example": "У галузі охорони здоров'я, прогнозування часу відновлення пацієнта на основі медичної історії. Формулювання проблеми: лікарям потрібен інструмент для прогнозування тривалості відновлення пацієнта після лікування.",
"tips": [
"Завжди консультуйтеся з експертами в предметній області",
"Переконайтеся, що проблема може бути вирішена за допомогою даних",
"Визначте чіткі критерії успіху"
],
"quiz": [
{
"question": "Що є першим кроком у проекті науки про дані?",
"options": [
"Збір даних",
"Визначення проблеми",
"Побудова моделі",
"Оцінка результатів"
],
"answer": 1
}
]
},
{
"id": 2,
"title": "Збір даних",
"shortTitle": "Дані",
"description": "Наступним кроком є збір відповідних даних з надійних джерел. Це може включати бази даних, публічні набори даних або дані, зібрані через сенсори та додатки.",
"keyPoints": [
"Визначення потрібних даних для вирішення проблеми",
"Ідентифікація джерел даних",
"Розуміння регуляторних вимог та етичних міркувань"
],
"example": "Збір клінічних записів з баз даних охорони здоров'я для аналізу часу відновлення пацієнтів.",
"tips": [
"Переконайтеся, що ви маєте дозвіл на використання даних",
"Перевірте якість та надійність джерел даних",
"Зберігайте дані безпечно та відповідно до норм"
],
"quiz": [
{
"question": "Що Ендрю Нг назвав 'їжею для ШІ'?",
"options": [
"Алгоритми",
"Дані",
"Обчислювальні потужності",
"Програмний код"
],
"answer": 1
}
]
},
{
"id": 3,
"title": "Підготовка даних",
"shortTitle": "Підготовка",
"description": "Сирі дані часто містять невідповідності, відсутні значення або викиди. Підготовка даних забезпечує, що дані чисті та стандартизовані.",
"keyPoints": [
"Очищення даних від невідповідностей",
"Обробка відсутніх значень",
"Нормалізація та стандартизація даних"
],
"example": "Очищення клінічних даних для забезпечення послідовності в аналізі.",
"tips": [
"Документуйте всі зміни, внесені до вихідних даних",
"Використовуйте автоматизовані інструменти для очищення великих наборів даних",
"Перевірте дані після очищення, щоб переконатися, що вони все ще відображають реальність"
],
"quiz": [
{
"question": "Які проблеми вирішує етап підготовки даних?",
"options": [
"Невідповідності, відсутні значення, викиди",
"Формулювання проблеми та вибір алгоритму",
"Вибір метрик оцінки",
"Розгортання моделі в виробництво"
],
"answer": 0
}
]
},
{
"id": 4,
"title": "Моделювання",
"shortTitle": "Модель",
"description": "Вибір правильного алгоритму є критичним. В залежності від проблеми, ми можемо використовувати регресію, класифікацію або кластеризацію, тощо.",
"keyPoints": [
"Вибір алгоритму на основі типу проблеми",
"Оцінка доступних даних (кількість та якість)",
"Врахування обчислювальних ресурсів та часу навчання"
],
"example": "Вибір алгоритму машинного навчання для прогнозування часу відновлення пацієнта на основі історичних даних.",
"tips": [
"Почніть з простих моделей перед переходом до складніших",
"Розділіть дані на тренувальні та тестові набори",
"Експериментуйте з різними алгоритмами для порівняння результатів"
],
"quiz": [
{
"question": "Які фактори слід враховувати при виборі алгоритму?",
"options": [
"Тільки тип проблеми",
"Тільки обчислювальні ресурси",
"Тип проблеми, доступні дані та обчислювальні ресурси",
"Тільки розмір набору даних"
],
"answer": 2
}
]
},
{
"id": 5,
"title": "Оцінювання",
"shortTitle": "Оцінка",
"description": "Після навчання, оцінка моделі є важливою для забезпечення точності та надійності.",
"keyPoints": [
"Вибір відповідних метрик для оцінки моделі",
"Порівняння результатів з бізнес-цілями",
"Виявлення областей для покращення"
],
"example": "Оцінка моделі для виявлення ранніх симптомів захворювання за допомогою метрик точності, чутливості та специфічності.",
"tips": [
"Використовуйте метрики, що відповідають бізнес-цілям",
"Проведіть крос-валідацію для надійності оцінки",
"Порівняйте результати з базовими моделями"
],
"quiz": [
{
"question": "Які метрики можуть використовуватися для оцінки моделі?",
"options": [
"Тільки точність (accuracy)",
"Точність, повнота, F1-оцінка та інші",
"Тільки час навчання",
"Тільки розмір моделі"
],
"answer": 1
}
]
},
{
"id": 6,
"title": "Розгортання",
"shortTitle": "Розгортання",
"description": "Розгортання — це процес інтеграції навченої моделі в виробниче середовище, роблячи її доступною для реального використання. Цей крок є вирішальним для забезпечення того, щоб прогнози моделі були постійно доступні та надійні для кінцевих користувачів або автоматизованих систем.",
"keyPoints": [
"Контейнеризація моделі для портативності",
"Створення API для доступу до моделі",
"Налаштування безперервної інтеграції та доставки (CI/CD)",
"Забезпечення масштабованості та доступності"
],
"example": "Розгортання моделі прогнозування часу відновлення пацієнта в хмарній платформі (AWS, Azure) та інтеграція з системою електронних медичних карт через API.",
"tips": [
"Тестуйте модель в середовищі, подібному до виробничого",
"Впровадіть моніторинг для відстеження продуктивності",
"Плануйте для масштабування від початку"
],
"quiz": [
{
"question": "Що таке контейнеризація в контексті розгортання моделі?",
"options": [
"Упаковка моделі в фізичний контейнер для транспортування",
"Упаковка моделі, залежностей і середовища в програмний контейнер (як Docker)",
"Обмеження доступу до моделі",
"Зменшення розміру моделі"
],
"answer": 1
}
]
},
{
"id": 7,
"title": "Моніторинг та підтримка",
"shortTitle": "Моніторинг",
"description": "Моделі потребують постійного моніторингу, щоб залишатися точними та ефективними. Зміни в розподілі даних можуть погіршити продуктивність з часом.",
"keyPoints": [
"Відстеження продуктивності моделі в реальному часі",
"Виявлення зміщення даних (data drift)",
"Регулярне перенавчання моделі з новими даними",
"Автоматизація розгортання оновлених моделей"
],
"example": "Використання інструментів моніторингу, таких як Prometheus і Grafana, для відстеження точності моделі прогнозування часу відновлення пацієнта та виявлення будь-яких змін у розподілі даних.",
"tips": [
"Встановіть сповіщення для виявлення зниження продуктивності",
"Плануйте регулярні огляди моделі",
"Документуйте всі зміни та оновлення"
],
"quiz": [
{
"question": "Чому важливий моніторинг моделі після розгортання?",
"options": [
"Він не важливий, якщо модель добре навчена",
"Тільки для задоволення регуляторних вимог",
"Для виявлення зміщення даних та підтримки продуктивності моделі",
"Тільки для економії обчислювальних ресурсів"
],
"answer": 2
}
]
}
]
};
// Глобальні змінні стану
let currentStepId = null;
let visitedSteps = new Set();
let selectedQuizOption = null;
let quizAnswered = false;
// Іконки для етапів
const stepIcons = {
1: '❓',
2: '📊',
3: '🔧',
4: '🤖',
5: '📈',
6: '🚀',
7: '👁️'
};
// Ініціалізація додатка
document.addEventListener('DOMContentLoaded', function() {
initializeApp();
setupEventListeners();
});
function initializeApp() {
// Встановлення заголовку та вступу
document.getElementById('introText').textContent = workflowData.introduction;
// Рендер бічної панелі
renderSidebar();
// Рендер візуалізації робочого процесу
renderWorkflowDiagram();
// Оновлення прогресу
updateProgress();
// Приховати деталі етапу спочатку
document.getElementById('stepDetailsSection').classList.remove('active');
}
function setupEventListeners() {
// Кнопки навігації
document.getElementById('nextStepBtn').addEventListener('click', () => navigateStep(1));
document.getElementById('prevStepBtn').addEventListener('click', () => navigateStep(-1));
// Кнопка скидання прогресу
document.getElementById('resetProgressBtn').addEventListener('click', resetProgress);
// Кнопка перевірки відповіді
document.getElementById('checkAnswerBtn').addEventListener('click', checkQuizAnswer);
}
function renderSidebar() {
const sidebarList = document.getElementById('sidebarStepsList');
sidebarList.innerHTML = '';
workflowData.steps.forEach(step => {
const listItem = document.createElement('li');
const link = document.createElement('a');
link.href = '#';
link.className = 'step-link';
link.dataset.stepId = step.id;
const stepNumber = document.createElement('span');
stepNumber.className = 'step-number';
stepNumber.textContent = step.id;
const stepTitle = document.createElement('span');
stepTitle.textContent = step.shortTitle;
link.appendChild(stepNumber);
link.appendChild(stepTitle);
link.addEventListener('click', (e) => {
e.preventDefault();
showStepDetails(step.id);
});
listItem.appendChild(link);
sidebarList.appendChild(listItem);
});
}
function renderWorkflowDiagram() {
const diagram = document.getElementById('workflowDiagram');
diagram.innerHTML = '';
workflowData.steps.forEach(step => {
const stepElement = document.createElement('div');
stepElement.className = 'workflow-step';
stepElement.dataset.stepId = step.id;
const icon = document.createElement('div');
icon.className = 'step-icon';
icon.textContent = stepIcons[step.id] || '⚡';
const title = document.createElement('h3');
title.textContent = step.shortTitle;
stepElement.appendChild(icon);
stepElement.appendChild(title);
stepElement.addEventListener('click', () => {
showStepDetails(step.id);
});
diagram.appendChild(stepElement);
});
}
function showStepDetails(stepId) {
const step = workflowData.steps.find(s => s.id === stepId);
if (!step) return;
currentStepId = stepId;
visitedSteps.add(stepId);
// Оновити активний стан
updateActiveStates();
// Заповнити деталі етапу
document.getElementById('stepTitle').textContent = step.title;
document.getElementById('stepDescription').textContent = step.description;
// Ключові моменти
const keyPointsList = document.getElementById('stepKeyPoints');
keyPointsList.innerHTML = '';
step.keyPoints.forEach(point => {
const li = document.createElement('li');
li.textContent = point;
keyPointsList.appendChild(li);
});
// Приклад
document.getElementById('stepExample').textContent = step.example;
// Поради
const tipsList = document.getElementById('stepTips');
tipsList.innerHTML = '';
step.tips.forEach(tip => {
const li = document.createElement('li');
li.textContent = tip;
tipsList.appendChild(li);
});
// Вікторина
setupQuiz(step.quiz[0]);
// Показати панель деталей
document.getElementById('introSection').style.display = 'none';
document.getElementById('stepDetailsSection').classList.add('active');
// Оновити кнопки навігації
updateNavigationButtons();
// Оновити прогрес
updateProgress();
// Прокрутити до верху
document.getElementById('stepDetailsSection').scrollIntoView({ behavior: 'smooth' });
}
function updateActiveStates() {
// Оновити бічну панель
document.querySelectorAll('.step-link').forEach(link => {
const stepId = parseInt(link.dataset.stepId);
link.classList.remove('active');
if (visitedSteps.has(stepId)) {
link.classList.add('visited');
}
if (stepId === currentStepId) {
link.classList.add('active');
}
});
// Оновити діаграму
document.querySelectorAll('.workflow-step').forEach(step => {
const stepId = parseInt(step.dataset.stepId);
step.classList.remove('active');
if (visitedSteps.has(stepId)) {
step.classList.add('visited');
}
if (stepId === currentStepId) {
step.classList.add('active');
}
});
}
function setupQuiz(quiz) {
document.getElementById('quizQuestion').textContent = quiz.question;
const optionsContainer = document.getElementById('quizOptions');
optionsContainer.innerHTML = '';
quiz.options.forEach((option, index) => {
const optionElement = document.createElement('div');
optionElement.className = 'quiz-option';
optionElement.textContent = option;
optionElement.dataset.index = index;
optionElement.addEventListener('click', () => {
if (quizAnswered) return;
document.querySelectorAll('.quiz-option').forEach(opt => {
opt.classList.remove('selected');
});
optionElement.classList.add('selected');
selectedQuizOption = index;
});
optionsContainer.appendChild(optionElement);
});
// Скинути стан вікторини
selectedQuizOption = null;
quizAnswered = false;
document.getElementById('quizResult').classList.remove('show', 'correct', 'incorrect');
document.getElementById('checkAnswerBtn').style.display = 'block';
}
function checkQuizAnswer() {
if (selectedQuizOption === null) {
alert('Будь ласка, оберіть відповідь');
return;
}
const step = workflowData.steps.find(s => s.id === currentStepId);
const quiz = step.quiz[0];
const isCorrect = selectedQuizOption === quiz.answer;
// Показати результат
const resultElement = document.getElementById('quizResult');
resultElement.classList.add('show');
if (isCorrect) {
resultElement.classList.add('correct');
resultElement.textContent = '✅ Правильно! Відмінна робота!';
} else {
resultElement.classList.add('incorrect');
resultElement.textContent = `❌ Неправильно. Правильна відповідь: ${quiz.options[quiz.answer]}`;
}
// Підсвітити правильну та неправильну відповіді
document.querySelectorAll('.quiz-option').forEach((option, index) => {
if (index === quiz.answer) {
option.classList.add('correct');
} else if (index === selectedQuizOption && !isCorrect) {
option.classList.add('incorrect');
}
});
quizAnswered = true;
document.getElementById('checkAnswerBtn').style.display = 'none';
}
function navigateStep(direction) {
if (!currentStepId) return;
const currentIndex = workflowData.steps.findIndex(s => s.id === currentStepId);
const newIndex = currentIndex + direction;
if (newIndex >= 0 && newIndex < workflowData.steps.length) {
showStepDetails(workflowData.steps[newIndex].id);
}
}
function updateNavigationButtons() {
const currentIndex = workflowData.steps.findIndex(s => s.id === currentStepId);
document.getElementById('prevStepBtn').disabled = currentIndex === 0;
document.getElementById('nextStepBtn').disabled = currentIndex === workflowData.steps.length - 1;
}
function updateProgress() {
const totalSteps = workflowData.steps.length;
const completedSteps = visitedSteps.size;
const percentage = (completedSteps / totalSteps) * 100;
document.getElementById('progressFill').style.width = `${percentage}%`;
document.getElementById('progressText').textContent = `${completedSteps}/${totalSteps} етапів вивчено`;
}
function resetProgress() {
if (confirm('Ви впевнені, що хочете скинути свій прогрес?')) {
visitedSteps.clear();
currentStepId = null;
// Приховати деталі етапу та показати вступ
document.getElementById('stepDetailsSection').classList.remove('active');
document.getElementById('introSection').style.display = 'block';
// Оновити стани
updateActiveStates();
updateProgress();
// Прокрутити до верху
window.scrollTo({ top: 0, behavior: 'smooth' });
}
}