From e6cd11b615ff2c5a0555a9f827043090e400296f Mon Sep 17 00:00:00 2001 From: zin Date: Wed, 6 May 2026 19:10:25 +0000 Subject: [PATCH] Integrated Music_engine and update Debug UI --- src/main.py | 132 +++++++++++++++++------------- src/music_engine/matcher.py | 53 ++++++------ src/music_engine/va_regressor.pkl | Bin 0 -> 67011 bytes src/scripts/train_regressor.py | 68 +++++++-------- 4 files changed, 135 insertions(+), 118 deletions(-) create mode 100644 src/music_engine/va_regressor.pkl diff --git a/src/main.py b/src/main.py index 7a809f9..b3e606a 100644 --- a/src/main.py +++ b/src/main.py @@ -31,39 +31,41 @@ LABELS_CSV = DATA_ROOT / "labels.csv" EMBEDDINGS_PATH = Path("./src/emoset_test_embeddings.npy") LABELS_PATH = Path("./src/emoset_test_labels.npy") -# Параметры эксперимента NUM_CHOICES = 6 TOTAL_ROUNDS = 10 -st.set_page_config(page_title="EmoSet & Music Recommendation Demo", layout="wide") +# Словарь для расшифровки меток (алфавитный порядок EmoSet) +EMO_NAMES = { + 0: "amusement (веселье)", + 1: "anger (гнев)", + 2: "awe (трепет)", + 3: "contentment (удовлетворение)", + 4: "disgust (отвращение)", + 5: "excitement (возбуждение)", + 6: "fear (страх)", + 7: "sadness (грусть)" +} + +st.set_page_config(page_title="Debug Mode: EmoSet & Music", layout="wide") -# Инициализация музыкального движка с кэшированием @st.cache_resource def load_music_engine(): - # Путь относительно src: ../dataset/DEAM/music_db.csv - db_path = Path(__file__).parent.parent / "dataset" / "DEAM" / "music_db.csv" - if not db_path.exists(): - return None - return MusicMatcher(db_path) + base_dir = Path(__file__).resolve().parent + db_path = base_dir.parent / "dataset" / "DEAM" / "music_db.csv" + model_path = base_dir / "music_engine" / "va_regressor.pkl" + if not db_path.exists(): return None + return MusicMatcher(db_path=db_path, model_path=model_path) matcher = load_music_engine() -# ---------------------------- -# 2️⃣ Загрузка данных EmoSet -# ---------------------------- @st.cache_data def load_emoset_data(): - if not IMAGES_DIR.exists() or not EMBEDDINGS_PATH.exists(): + if not IMAGES_DIR.exists() or not EMBEDDINGS_PATH.exists() or not LABELS_CSV.exists(): return None, None, None - - image_files = sorted([f.name for f in IMAGES_DIR.glob("*.jpg")]) + df = pd.read_csv(LABELS_CSV) + image_files = df['filename'].tolist() embeddings = np.load(EMBEDDINGS_PATH) labels_array = np.load(LABELS_PATH) - - if len(image_files) != len(embeddings) or len(image_files) != len(labels_array): - st.error("Размеры массивов данных не совпадают!") - st.stop() - return image_files, embeddings, labels_array image_files, embeddings, labels_array = load_emoset_data() @@ -72,69 +74,81 @@ image_files, embeddings, labels_array = load_emoset_data() # 3️⃣ Логика приложения # ---------------------------- if image_files is None: - st.error("Данные EmoSet не найдены. Проверьте папку dataset.") + st.error("Данные не найдены.") else: if 'round' not in st.session_state: st.session_state.round = 1 st.session_state.chosen_indices = [] st.session_state.current_options = random.sample(range(len(image_files)), NUM_CHOICES) - st.title("Выбор эмоциональных образов") - st.write(f"Раунд {st.session_state.round} из {TOTAL_ROUNDS}. Выберите изображение, которое больше всего соответствует вашему настроению.") - + st.title("🧪 Отладка эмоционального маппинга") + if st.session_state.round <= TOTAL_ROUNDS: - # Отображение сетки изображений + st.write(f"**Раунд {st.session_state.round} из {TOTAL_ROUNDS}**") + + # Сетка выбора с отладочной информацией cols = st.columns(3) for i, idx in enumerate(st.session_state.current_options): with cols[i % 3]: img_path = IMAGES_DIR / image_files[idx] img = Image.open(img_path) st.image(img, use_container_width=True) - if st.button(f"Выбрать {i+1}", key=f"btn_{idx}"): + + # --- ИНФОРМАЦИЯ ДЛЯ ОТЛАДКИ --- + if matcher: + v, a = matcher.predict_va(embeddings[idx]) + label_id = labels_array[idx] + label_name = EMO_NAMES.get(label_id, "Unknown") + + st.caption(f"**Класс:** {label_name}") + st.caption(f"**Прогноз:** V: {v:.2f} | A: {a:.2f}") + # ------------------------------ + + if st.button(f"Выбрать образ {i+1}", key=f"btn_{idx}", use_container_width=True): st.session_state.chosen_indices.append(idx) st.session_state.round += 1 if st.session_state.round <= TOTAL_ROUNDS: st.session_state.current_options = random.sample(range(len(image_files)), NUM_CHOICES) st.rerun() else: - # ФИНАЛЬНЫЙ ЭТАП: Анализ и Музыка - st.success("Анализ завершен! Ваш эмоциональный профиль сформирован.") + # ФИНАЛЬНЫЙ ЭТАП + st.success("✅ Профиль сформирован!") - # Расчет среднего вектора пользователя - chosen_embeddings = embeddings[st.session_state.chosen_indices] - user_vector = np.mean(chosen_embeddings, axis=0) - - # РАЗДЕЛ МУЗЫКАЛЬНЫХ РЕКОМЕНДАЦИЙ - st.divider() - st.header("🎵 Рекомендованный плейлист") + # Считаем итог + chosen_embs = embeddings[st.session_state.chosen_indices] + all_v, all_a = [], [] + for emb in chosen_embs: + v, a = matcher.predict_va(emb) + all_v.append(v) + all_a.append(a) - if matcher is None: - st.warning("База данных DEAM (music_db.csv) не найдена. Подбор музыки недоступен.") - else: - with st.spinner("Сопоставляем визуальный профиль с музыкальной базой..."): - target_v, target_a, playlist = matcher.get_playlist(user_vector, top_k=5) - - # Визуализация VA-метрик пользователя - m1, m2, m3 = st.columns(3) - m1.metric("Позитивность (Valence)", f"{target_v:.2f}", help="Шкала 1-9") - m2.metric("Энергия (Arousal)", f"{target_a:.2f}", help="Шкала 1-9") - m3.metric("Найдено треков", len(playlist)) + target_v, target_a = np.mean(all_v), np.mean(all_a) + + # Вывод результатов + col1, col2 = st.columns([2, 1]) + + with col1: + st.header("🎵 Ваш плейлист") + distances = np.sqrt((matcher.music_db['valence'] - target_v)**2 + (matcher.music_db['arousal'] - target_a)**2) + playlist = matcher.music_db.copy() + playlist['distance'] = distances + st.table(playlist.sort_values(by='distance').head(5)[['song_id', 'valence', 'arousal', 'distance']]) - # Таблица с результатами - st.subheader("Топ-5 подходящих композиций") - st.table(playlist[['song_id', 'valence', 'arousal', 'distance']]) - - st.info("💡 Вы можете найти эти треки по ID в папке audio датасета DEAM.") - - # Визуализация вектора (графики) + with col2: + st.header("📊 Профиль") + st.metric("Valence (Итог)", f"{target_v:.2f}") + st.metric("Arousal (Итог)", f"{target_a:.2f}") + + # Показываем, что именно выбрал пользователь st.divider() - st.subheader("Визуализация эмоционального вектора") - fig, ax = plt.subplots(figsize=(10, 3)) - ax.plot(user_vector[:100]) # Показываем первые 100 измерений для наглядности - ax.set_title("Эмбеддинг вашего настроения (фрагмент)") - st.pyplot(fig) + st.subheader("Выбранные вами образы и их веса:") + sum_cols = st.columns(5) + for i, idx in enumerate(st.session_state.chosen_indices): + with sum_cols[i % 5]: + v_i, a_i = matcher.predict_va(embeddings[idx]) + st.image(Image.open(IMAGES_DIR / image_files[idx]), use_container_width=True) + st.write(f"V:{v_i:.1f} A:{a_i:.1f}") if st.button("Начать заново"): - for key in list(st.session_state.keys()): - del st.session_state[key] + for key in list(st.session_state.keys()): del st.session_state[key] st.rerun() \ No newline at end of file diff --git a/src/music_engine/matcher.py b/src/music_engine/matcher.py index c789427..cefa65c 100644 --- a/src/music_engine/matcher.py +++ b/src/music_engine/matcher.py @@ -1,53 +1,52 @@ import numpy as np import pandas as pd from pathlib import Path +import joblib class MusicMatcher: - def __init__(self, db_path: Path): + def __init__(self, db_path: Path | str, model_path: Path | str): + # 1. Загрузка базы музыки self.music_db = pd.read_csv(db_path) - # Убедимся, что данные числовые self.music_db['valence'] = pd.to_numeric(self.music_db['valence'], errors='coerce') self.music_db['arousal'] = pd.to_numeric(self.music_db['arousal'], errors='coerce') self.music_db = self.music_db.dropna() + + # 2. Загрузка обученного регрессора + if Path(model_path).exists(): + self.regressor = joblib.load(model_path) + print("✅ Регрессионная модель успешно загружена.") + else: + self.regressor = None + print("⚠️ ВНИМАНИЕ: Модель va_regressor.pkl не найдена!") def predict_va(self, embedding: np.ndarray): """ - Умный хак для демо: используем статистику вектора. - Мрачные картинки имеют меньшую среднюю активацию. + Использование обученной ML-модели (Ridge) для маппинга + эмбеддингов в пространство Valence-Arousal. """ - # 1. Средняя сила активации (прокси для Valence) - mean_act = float(np.mean(embedding)) - - # 2. Разреженность вектора (прокси для Arousal) - # Чем больше нулей или близких к нулю значений, тем "спокойнее" картинка - sparsity = float(np.mean(embedding < 0.1)) - - # Масштабируем: если средняя активация низкая (мрачное), уводим Valence вниз - # (Типичный mean_act для ResNet обычно от 0.2 до 0.8) - v = np.interp(mean_act, [0.2, 0.6], [2.0, 8.0]) - - # Если много нулей (пустота/мрак), Arousal падает. - # Если нулей мало (пестрый мусор) - Arousal растет. - a = np.interp(sparsity, [0.3, 0.8], [8.0, 2.0]) # Обратная зависимость - - # Добавляем "соль" из суммы вектора, чтобы избежать одинаковых результатов - # для похожих, но разных наборов картинок - salt = (float(np.sum(embedding)) % 2.0) - 1.0 - v += salt - a += salt - + if self.regressor is not None: + # Модель ожидает двумерный массив (batch_size, features) + emb_2d = embedding.reshape(1, -1) + prediction = self.regressor.predict(emb_2d)[0] # Получаем [Valence, Arousal] + + v, a = prediction[0], prediction[1] + else: + # Fallback на случай, если файл модели потеряется + v, a = 5.0, 5.0 + return np.clip(v, 1.0, 9.0), np.clip(a, 1.0, 9.0) def get_playlist(self, user_vector: np.ndarray, top_k: int = 5): + # 1. Предсказываем координаты через ML-модель target_v, target_a = self.predict_va(user_vector) - # Считаем Евклидово расстояние от пользователя до всех треков + # 2. Считаем Евклидово расстояние (L2-норма) до треков в базе distances = np.sqrt( (self.music_db['valence'] - target_v)**2 + (self.music_db['arousal'] - target_a)**2 ) - # Добавляем дистанцию, сортируем по возрастанию (чем меньше, тем ближе) + # 3. Формируем финальную выдачу df_result = self.music_db.copy() df_result['distance'] = distances playlist = df_result.sort_values(by='distance').head(top_k) diff --git a/src/music_engine/va_regressor.pkl b/src/music_engine/va_regressor.pkl new file mode 100644 index 0000000000000000000000000000000000000000..3b8697e79aa0117d4a778540ce300c12687e5df4 GIT binary patch literal 67011 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 M?f(BKCc^B00i*t{X8-^I literal 0 HcmV?d00001 diff --git a/src/scripts/train_regressor.py b/src/scripts/train_regressor.py index 9179c52..9953a17 100644 --- a/src/scripts/train_regressor.py +++ b/src/scripts/train_regressor.py @@ -1,61 +1,65 @@ import numpy as np import pandas as pd from pathlib import Path -from sklearn.linear_model import Ridge +from sklearn.linear_model import RidgeCV from sklearn.multioutput import MultiOutputRegressor +from sklearn.preprocessing import StandardScaler +from sklearn.pipeline import Pipeline from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score import joblib -# 1. Эталонный маппинг EmoSet -> Valence/Arousal (шкала 1-9) -# Убедись, что индексы ключей (0-7) совпадают с тем, как они размечены в твоем labels.npy -# Стандартный порядок EmoSet: +# 1. Алфавитный маппинг EmoSet EMO_VA_MAP = { - 0: (7.5, 6.5), # amusement (радость/веселье) - позитивно, средне-активно - 1: (6.5, 5.0), # awe (трепет/восхищение) - позитивно, спокойно - 2: (7.0, 3.0), # contentment (удовлетворение) - позитивно, очень спокойно - 3: (8.0, 8.0), # excitement (возбуждение) - очень позитивно, очень активно - 4: (2.0, 8.0), # anger (гнев) - негативно, очень активно - 5: (3.0, 6.0), # disgust (отвращение) - негативно, средне-активно - 6: (2.5, 7.5), # fear (страх) - негативно, очень активно - 7: (2.0, 2.0), # sadness (грусть) - негативно, пассивно + 0: (7.5, 6.5), # amusement + 1: (2.0, 8.0), # anger + 2: (6.5, 5.0), # awe + 3: (7.0, 3.0), # contentment + 4: (3.0, 6.0), # disgust + 5: (8.0, 8.0), # excitement + 6: (2.5, 7.5), # fear + 7: (2.0, 2.0), # sadness } -# 2. Загрузка данных -# Укажи пути к твоим эмбеддингам и меткам (можно взять train или test, для демо не так критично) -EMBEDDINGS_PATH = Path("../emoset_test_embeddings.npy") -LABELS_PATH = Path("../emoset_test_labels.npy") +BASE_DIR = Path(__file__).resolve().parent.parent +EMBEDDINGS_PATH = BASE_DIR / "emoset_test_embeddings.npy" +LABELS_PATH = BASE_DIR / "emoset_test_labels.npy" print("Загрузка данных...") X = np.load(EMBEDDINGS_PATH) y_labels = np.load(LABELS_PATH) -# Преобразуем дискретные метки в целевые координаты V-A -print("Формирование целевых координат (Valence, Arousal)...") y_va = np.array([EMO_VA_MAP[label] for label in y_labels]) - -# Разделение на train/val X_train, X_test, y_train, y_test = train_test_split(X, y_va, test_size=0.2, random_state=42) -# 3. Обучение модели -print("Обучение Ridge регрессора...") -# Ridge отлично справляется с многомерными эмбеддингами, избегая переобучения -base_estimator = Ridge(alpha=1.0) -model = MultiOutputRegressor(base_estimator) +# 2. НОВАЯ, ПРАВИЛЬНАЯ АРХИТЕКТУРА (Pipeline) +print("Обучение масштабатора и RidgeCV регрессора...") +# Pipeline гарантирует, что при предсказании в main.py новые векторы тоже будут масштабированы +model = Pipeline([ + ('scaler', StandardScaler()), + ('regressor', MultiOutputRegressor(RidgeCV(alphas=[0.1, 1.0, 10.0, 100.0, 1000.0]))) +]) model.fit(X_train, y_train) -# 4. Оценка +# 3. Диагностика и Оценка y_pred = model.predict(X_test) + mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) -print(f"Обучение завершено!") -print(f"MSE (Среднеквадратичная ошибка): {mse:.4f}") -print(f"R^2 Score (Коэффициент детерминации): {r2:.4f}") +print(f"\n[УСПЕХ] Обучение завершено!") +print(f"MSE: {mse:.4f}") +print(f"R^2 Score: {r2:.4f}") -# 5. Сохранение -output_model_path = Path("../src/music_engine/va_regressor.pkl") +# === ТОТ САМЫЙ ТЕСТ НА КОЛЛАПС === +print("\n--- ДИАГНОСТИКА РАЗБРОСА ПРЕДСКАЗАНИЙ ---") +print(f"Valence: от {y_pred[:, 0].min():.2f} до {y_pred[:, 0].max():.2f} (Эталон: 2.0 - 8.0)") +print(f"Arousal: от {y_pred[:, 1].min():.2f} до {y_pred[:, 1].max():.2f} (Эталон: 2.0 - 8.0)") +# =============================================== + +# 4. Сохранение (Pipeline сохраняется целиком со StandardScaler) +output_model_path = BASE_DIR / "music_engine" / "va_regressor.pkl" output_model_path.parent.mkdir(parents=True, exist_ok=True) joblib.dump(model, output_model_path) -print(f"Модель сохранена в: {output_model_path}") \ No newline at end of file +print(f"\nМодель сохранена в: {output_model_path}") \ No newline at end of file