From fcd3b936cfb2ffba3e3573765ce0b984cb0245b7 Mon Sep 17 00:00:00 2001 From: Serge Zaigraeff Date: Tue, 4 Mar 2025 22:10:20 +0300 Subject: [PATCH] add merge tools --- config.json | 4 +- tools/whisper_merge.sh | 367 +++++++++++++++++++++++++++++++++++ tools/whisper_merge_guide.md | 288 +++++++++++++++++++++++++++ 3 files changed, 657 insertions(+), 2 deletions(-) create mode 100755 tools/whisper_merge.sh create mode 100644 tools/whisper_merge_guide.md diff --git a/config.json b/config.json index 7f7f0f9..ec85d90 100644 --- a/config.json +++ b/config.json @@ -1,9 +1,9 @@ { "service_port": 5042, - "model_path": "/mnt/cloud/llm/whisper/whisper-large-v3-russian", + "model_path": "/mnt/cloud/llm/whisper/whisper-large-v3-russian-ties-podlodka", "language": "russian", "enable_history": true, - "chunk_length_s": 22, + "chunk_length_s": 25, "batch_size": 20, "max_new_tokens": 384, "return_timestamps": false, diff --git a/tools/whisper_merge.sh b/tools/whisper_merge.sh new file mode 100755 index 0000000..f8e5701 --- /dev/null +++ b/tools/whisper_merge.sh @@ -0,0 +1,367 @@ +#!/bin/bash + +# Имя окружения conda +CONDA_ENV_NAME="whisper-merge" + +# Директории для моделей +MODEL_A="/mnt/cloud/llm/whisper/whisper-large-v3-russian" +MODEL_B="/mnt/cloud/llm/whisper/whisper-large-v3-ru-podlodka" +OUTPUT_DIR="/mnt/cloud/llm/whisper/whisper-large-v3-russian+podlodka" + +# Флаг обновления (по умолчанию false) +UPDATE_ENV=false + +# Метод слияния (по умолчанию all) +MERGE_METHOD="all" + +# Дополнительные параметры (по умолчанию) +SLERP_T=0.5 +TIES_DENSITY=0.8 +ENCODER_WEIGHTS="0.6,0.4" +DECODER_WEIGHTS="0.4,0.6" +DIRECT_ALPHA=0.5 + +# Проверка аргументов +while [[ "$#" -gt 0 ]]; do + case $1 in + --update) UPDATE_ENV=true ;; + --method) MERGE_METHOD="$2"; shift ;; + --slerp-t) SLERP_T="$2"; shift ;; + --ties-density) TIES_DENSITY="$2"; shift ;; + --encoder-weights) ENCODER_WEIGHTS="$2"; shift ;; + --decoder-weights) DECODER_WEIGHTS="$2"; shift ;; + --direct-alpha) DIRECT_ALPHA="$2"; shift ;; + *) echo "⚠️ Неизвестный параметр: $1"; exit 1 ;; + esac + shift +done + +# Проверка наличия conda +if ! command -v conda &> /dev/null; then + echo "❌ Conda не установлен. Пожалуйста, установите conda и попробуйте снова." + exit 1 +fi + +# Создание окружения conda, если оно не существует +if ! conda env list | grep -q "$CONDA_ENV_NAME"; then + echo "🔹 Создание окружения conda: $CONDA_ENV_NAME" + conda create -n "$CONDA_ENV_NAME" python=3.12 -y +else + echo "✅ Окружение conda '$CONDA_ENV_NAME' уже существует." +fi + +# Получение пути к conda +CONDA_PATH=$(which conda) + +# Проверка, что путь к conda найден +if [ -z "$CONDA_PATH" ]; then + echo "❌ Не удалось найти путь к conda." + exit 1 +fi + +# Активация окружения conda +echo "🔹 Активация окружения conda: $CONDA_ENV_NAME" +source $(dirname "$CONDA_PATH")/../etc/profile.d/conda.sh +conda activate "$CONDA_ENV_NAME" + +# Если флаг --update установлен, обновляем зависимости +if [[ "$UPDATE_ENV" == true ]]; then + echo "🔹 Установка и обновление зависимостей" + pip install --upgrade pip wheel + pip install torch torchaudio + pip install transformers datasets evaluate accelerate + pip install soundfile librosa tqdm +fi + +# Проверка установки torch и transformers +if ! python -c "import torch, transformers" &> /dev/null; then + echo "❌ PyTorch или Transformers не установлены. Запустите с опцией --update." + exit 1 +fi + +# Создание временного Python-скрипта для слияния +cat > merge_models.py << EOL +#!/usr/bin/env python3 + +import argparse +import os +import torch +from transformers import WhisperForConditionalGeneration, WhisperProcessor +from tqdm import tqdm + +def direct_merge(model_a_path, model_b_path, output_path, alpha=0.5): + """Простое прямое слияние весов моделей с коэффициентом alpha""" + print(f"🔹 Запуск прямого слияния с alpha={alpha}") + + print(f"📂 Загрузка модели A из {model_a_path}") + model_a = WhisperForConditionalGeneration.from_pretrained(model_a_path) + + print(f"📂 Загрузка модели B из {model_b_path}") + model_b = WhisperForConditionalGeneration.from_pretrained(model_b_path) + + # Создаем новую модель для хранения объединенных весов + print("🔄 Объединение весов моделей...") + merged_model = WhisperForConditionalGeneration.from_pretrained(model_a_path) + + # Подсчет общего количества параметров + param_count = len(list(merged_model.named_parameters())) + + # Объединение весов + with torch.no_grad(): + for i, (param_name, param) in enumerate(tqdm(merged_model.named_parameters(), total=param_count, desc="Слияние параметров")): + if param_name in model_a.state_dict() and param_name in model_b.state_dict(): + # Объединяем веса с учетом коэффициента альфа + merged_param = alpha * model_a.state_dict()[param_name] + (1 - alpha) * model_b.state_dict()[param_name] + param.copy_(merged_param) + + # Создаем директорию для выходных данных, если она не существует + os.makedirs(output_path, exist_ok=True) + + # Сохраняем объединенную модель + print(f"💾 Сохранение объединенной модели в {output_path}") + merged_model.save_pretrained(output_path) + + # Сохраняем процессор из модели A + print("💾 Сохранение процессора") + processor = WhisperProcessor.from_pretrained(model_a_path) + processor.save_pretrained(output_path) + + print("✅ Прямое слияние успешно завершено!") + return merged_model + +def slerp_weights(model_a, model_b, t): + """Выполняет SLERP (Spherical Linear Interpolation) между весами моделей""" + # Получаем словари состояний моделей + state_dict_a = model_a.state_dict() + state_dict_b = model_b.state_dict() + + # Создаем новый словарь для смешанных весов + mixed_weights = {} + + for key in tqdm(state_dict_a.keys(), desc="SLERP слияние"): + if key in state_dict_b: + # Получаем веса для текущего параметра + weight_a = state_dict_a[key].float() + weight_b = state_dict_b[key].float() + + # Выполняем SLERP + # Нормализуем веса + norm_a = torch.norm(weight_a) + norm_b = torch.norm(weight_b) + + # Если норма близка к нулю, используем линейную интерполяцию + if norm_a < 1e-6 or norm_b < 1e-6: + mixed_weights[key] = (1 - t) * weight_a + t * weight_b + continue + + weight_a_normalized = weight_a / norm_a + weight_b_normalized = weight_b / norm_b + + # Вычисляем косинус угла между векторами + cos_theta = torch.sum(weight_a_normalized * weight_b_normalized) + cos_theta = torch.clamp(cos_theta, -1.0, 1.0) + + # Вычисляем угол + theta = torch.acos(cos_theta) + + # Если угол близок к 0 или π, используем линейную интерполяцию + if abs(theta) < 1e-6 or abs(theta - torch.pi) < 1e-6: + mixed_weights[key] = (1 - t) * weight_a + t * weight_b + else: + # SLERP формула: (sin((1-t)*theta) / sin(theta)) * weight_a + (sin(t*theta) / sin(theta)) * weight_b + sin_theta = torch.sin(theta) + mixed_weights[key] = (torch.sin((1 - t) * theta) / sin_theta) * weight_a + (torch.sin(t * theta) / sin_theta) * weight_b + + # Проверка на NaN + if torch.isnan(mixed_weights[key]).any(): + # Если появились NaN, используем линейную интерполяцию + mixed_weights[key] = (1 - t) * weight_a + t * weight_b + + return mixed_weights + +def slerp_merge(model_a_path, model_b_path, output_path, t=0.5): + """Слияние методом SLERP, реализованное напрямую без использования mergekit""" + print(f"🔹 Запуск слияния методом SLERP с t={t}") + + print(f"📂 Загрузка модели A из {model_a_path}") + model_a = WhisperForConditionalGeneration.from_pretrained(model_a_path) + + print(f"📂 Загрузка модели B из {model_b_path}") + model_b = WhisperForConditionalGeneration.from_pretrained(model_b_path) + + # Создаем новую модель для хранения смешанных весов + print("🔄 Применение метода SLERP...") + merged_model = WhisperForConditionalGeneration.from_pretrained(model_a_path) + + # Получаем смешанные веса + mixed_weights = slerp_weights(model_a, model_b, t) + + # Загружаем смешанные веса в модель + merged_model.load_state_dict(mixed_weights) + + # Создаем директорию для выходных данных + os.makedirs(output_path, exist_ok=True) + + # Сохраняем объединенную модель + print(f"💾 Сохранение объединенной модели в {output_path}") + merged_model.save_pretrained(output_path) + + # Сохраняем процессор из модели A + processor = WhisperProcessor.from_pretrained(model_a_path) + processor.save_pretrained(output_path) + + print("✅ Слияние методом SLERP успешно завершено!") + return merged_model + +def ties_merge(model_a_path, model_b_path, output_path, density=0.8, encoder_weights=(0.6, 0.4), decoder_weights=(0.4, 0.6)): + """Слияние, реализованное по принципу TIES без использования mergekit""" + print(f"🔹 Запуск слияния по принципу TIES с плотностью {density}") + print(f" Веса кодировщика: {encoder_weights}, веса декодера: {decoder_weights}") + + print(f"📂 Загрузка модели A из {model_a_path}") + model_a = WhisperForConditionalGeneration.from_pretrained(model_a_path) + + print(f"📂 Загрузка модели B из {model_b_path}") + model_b = WhisperForConditionalGeneration.from_pretrained(model_b_path) + + # Создаем новую модель для хранения смешанных весов + print("🔄 Применение метода TIES...") + merged_model = WhisperForConditionalGeneration.from_pretrained(model_a_path) + + # Получаем словари состояний моделей + state_dict_a = model_a.state_dict() + state_dict_b = model_b.state_dict() + + # Создаем словарь для смешанных весов + mixed_weights = {} + + # Для каждого параметра + for key in tqdm(state_dict_a.keys(), desc="TIES слияние"): + if key in state_dict_b: + # Определение типа слоя (кодировщик или декодер) + if "encoder" in key: + w_a, w_b = encoder_weights + elif "decoder" in key: + w_a, w_b = decoder_weights + else: + # Для других параметров используем среднее + w_a = (encoder_weights[0] + decoder_weights[0]) / 2 + w_b = (encoder_weights[1] + decoder_weights[1]) / 2 + + # Получаем веса для текущего параметра + weight_a = state_dict_a[key] + weight_b = state_dict_b[key] + + # Вычисляем абсолютную разницу между весами + abs_diff = torch.abs(weight_a - weight_b) + + # Создаем маску для топ-k% элементов с наибольшей разницей + # если density=0.8, то мы сохраняем 80% элементов с наибольшей разницей + k = int((1 - density) * abs_diff.numel()) + if k > 0: + threshold = torch.kthvalue(abs_diff.flatten(), k).values + mask = abs_diff >= threshold + else: + mask = torch.ones_like(abs_diff, dtype=torch.bool) + + # Создаем смешанные веса: + # Для элементов с большой разницей используем веса w_a и w_b + # Для остальных используем среднее арифметическое + mixed = torch.zeros_like(weight_a) + mixed[mask] = w_a * weight_a[mask] + w_b * weight_b[mask] + mixed[~mask] = (weight_a[~mask] + weight_b[~mask]) / 2 + + mixed_weights[key] = mixed + + # Загружаем смешанные веса в модель + merged_model.load_state_dict(mixed_weights) + + # Создаем директорию для выходных данных + os.makedirs(output_path, exist_ok=True) + + # Сохраняем объединенную модель + print(f"💾 Сохранение объединенной модели в {output_path}") + merged_model.save_pretrained(output_path) + + # Сохраняем процессор из модели A + processor = WhisperProcessor.from_pretrained(model_a_path) + processor.save_pretrained(output_path) + + print("✅ Слияние по принципу TIES успешно завершено!") + return merged_model + +def main(): + parser = argparse.ArgumentParser(description="Объединение моделей Whisper методами SLERP и TIES") + parser.add_argument("--model-a", default="$MODEL_A", + help="Путь к первой модели") + parser.add_argument("--model-b", default="$MODEL_B", + help="Путь к второй модели") + parser.add_argument("--output-dir", default="$OUTPUT_DIR", + help="Директория для сохранения результатов") + parser.add_argument("--method", choices=["slerp", "ties", "direct", "all"], default="$MERGE_METHOD", + help="Метод слияния: slerp, ties, direct или all") + + # Параметры для SLERP + parser.add_argument("--slerp-t", type=float, default=$SLERP_T, + help="Коэффициент интерполяции для SLERP (0-1)") + + # Параметры для TIES + parser.add_argument("--ties-density", type=float, default=$TIES_DENSITY, + help="Плотность смешивания для TIES (0-1)") + parser.add_argument("--encoder-weights", type=str, default="$ENCODER_WEIGHTS", + help="Веса для кодировщика в формате '0.6,0.4'") + parser.add_argument("--decoder-weights", type=str, default="$DECODER_WEIGHTS", + help="Веса для декодера в формате '0.4,0.6'") + + # Параметры для прямого слияния + parser.add_argument("--direct-alpha", type=float, default=$DIRECT_ALPHA, + help="Коэффициент альфа для прямого слияния (0-1)") + + args = parser.parse_args() + + # Разбор весов для TIES + encoder_weights = tuple(map(float, args.encoder_weights.split(','))) + decoder_weights = tuple(map(float, args.decoder_weights.split(','))) + + # Создание выходной директории + os.makedirs(args.output_dir, exist_ok=True) + + # Выполнение слияния выбранным методом + if args.method == "direct" or args.method == "all": + direct_output = os.path.join(args.output_dir, "direct") + direct_merge(args.model_a, args.model_b, direct_output, args.direct_alpha) + + if args.method == "slerp" or args.method == "all": + slerp_output = os.path.join(args.output_dir, "slerp") + try: + slerp_merge(args.model_a, args.model_b, slerp_output, args.slerp_t) + except Exception as e: + print(f"❌ Ошибка при слиянии методом SLERP: {e}") + print("⚠️ Используется прямое слияние вместо SLERP.") + direct_merge(args.model_a, args.model_b, slerp_output, args.slerp_t) + + if args.method == "ties" or args.method == "all": + ties_output = os.path.join(args.output_dir, "ties") + try: + ties_merge(args.model_a, args.model_b, ties_output, args.ties_density, encoder_weights, decoder_weights) + except Exception as e: + print(f"❌ Ошибка при слиянии методом TIES: {e}") + print("⚠️ Используется прямое слияние вместо TIES.") + alpha = (encoder_weights[0] + decoder_weights[0]) / 2 + direct_merge(args.model_a, args.model_b, ties_output, alpha) + + print("\n✅ Все операции слияния успешно завершены!") + print(f"📂 Результаты сохранены в {args.output_dir}") + +if __name__ == "__main__": + main() +EOL + +# Запуск Python-скрипта +python merge_models.py + +# Удаление временного скрипта +rm merge_models.py + +echo "" +echo "✅ Процесс слияния завершен. Результаты сохранены в $OUTPUT_DIR" diff --git a/tools/whisper_merge_guide.md b/tools/whisper_merge_guide.md new file mode 100644 index 0000000..bf0cb40 --- /dev/null +++ b/tools/whisper_merge_guide.md @@ -0,0 +1,288 @@ +# Полное руководство по объединению моделей Whisper + +## Содержание +1. [Введение](#введение) +2. [Установка и подготовка](#установка-и-подготовка) +3. [Базовое использование](#базовое-использование) +4. [Детальные настройки](#детальные-настройки) + - [Методы слияния](#методы-слияния) + - [Параметры для метода Direct](#параметры-для-метода-direct) + - [Параметры для метода SLERP](#параметры-для-метода-slerp) + - [Параметры для метода TIES](#параметры-для-метода-ties) +5. [Практические рекомендации](#практические-рекомендации) +6. [Тестирование и оценка](#тестирование-и-оценка) +7. [Устранение неполадок](#устранение-неполадок) + +## Введение + +Скрипт `whisper_merge.sh` позволяет объединять две модели Whisper, обученные на разных датасетах, для получения комбинированной модели с улучшенными характеристиками. Особенно полезно для моделей, обученных на разных типах данных одного языка (например, разные диалекты русского языка, формальная/неформальная речь и т.д.). + +## Установка и подготовка + +1. **Убедитесь, что Conda установлена** в вашей системе. +2. **Скачайте скрипт `whisper_merge.sh`** и сделайте его исполняемым: + ```bash + chmod +x whisper_merge.sh + ``` +3. **Подготовьте модели для слияния**. По умолчанию скрипт ищет модели по следующим путям: + - Модель A: `/mnt/cloud/llm/whisper/whisper-large-v3-russian` + - Модель B: `/mnt/cloud/llm/whisper/whisper-large-v3-ru-podlodka` + - Директория для результатов: `/mnt/cloud/llm/whisper/whisper-large-v3-russian+podlodka` + + Пути можно изменить, отредактировав переменные `MODEL_A`, `MODEL_B` и `OUTPUT_DIR` в начале скрипта. + +## Базовое использование + +### Первый запуск + +Для первого запуска рекомендуется использовать флаг `--update` для установки всех зависимостей: + +```bash +./whisper_merge.sh --update +``` + +Это создаст окружение conda с именем `whisper-merge` и установит необходимые пакеты. + +### Стандартное слияние + +Для выполнения слияния с настройками по умолчанию: + +```bash +./whisper_merge.sh +``` + +По умолчанию будут использованы следующие параметры: +- Метод слияния: `all` (все методы) +- SLERP t: `0.5` +- TIES density: `0.8` +- Encoder weights: `0.6,0.4` +- Decoder weights: `0.4,0.6` +- Direct alpha: `0.5` + +## Детальные настройки + +### Методы слияния + +Скрипт поддерживает три метода слияния моделей: + +1. **Direct** (`--method direct`) — простое линейное смешивание весов: + ```bash + ./whisper_merge.sh --method direct + ``` + - **Преимущества**: простота, надежность, меньшие вычислительные требования + - **Недостатки**: может не сохранять геометрию пространства весов + - **Когда использовать**: для быстрого тестирования или когда модели очень близки + +2. **SLERP** (`--method slerp`) — сферическая линейная интерполяция: + ```bash + ./whisper_merge.sh --method slerp + ``` + - **Преимущества**: лучше сохраняет геометрию пространства весов + - **Недостатки**: требует больше вычислений, может не работать корректно для некоторых моделей + - **Когда использовать**: для моделей, где важно сохранение пространственных отношений между параметрами + +3. **TIES** (`--method ties`) — алгоритм Task Induced Expert Selection: + ```bash + ./whisper_merge.sh --method ties + ``` + - **Преимущества**: позволяет индивидуально настраивать веса для кодировщика и декодера + - **Недостатки**: более сложный, требует тонкой настройки параметров + - **Когда использовать**: для продвинутого слияния, когда известно, что одна модель лучше работает с определенными аспектами (например, фонетикой или грамматикой) + +4. **All** (`--method all`) — применяет все три метода и сохраняет результаты в отдельные подпапки: + ```bash + ./whisper_merge.sh --method all + ``` + - **Преимущества**: позволяет сравнить результаты всех методов + - **Недостатки**: требует больше времени и дискового пространства + - **Когда использовать**: при первоначальном тестировании для выбора оптимального метода + +### Параметры для метода Direct + +#### Direct Alpha (`--direct-alpha`) + +Определяет вес первой модели в процессе слияния: + +```bash +./whisper_merge.sh --method direct --direct-alpha 0.7 +``` + +- **Диапазон**: от 0.0 до 1.0 +- **По умолчанию**: 0.5 (равный вес обеих моделей) +- **Влияние**: + - `0.0` — полностью использует веса второй модели (MODEL_B) + - `0.5` — равный вклад обеих моделей + - `1.0` — полностью использует веса первой модели (MODEL_A) +- **Рекомендации**: + - Если MODEL_A лучше справляется с задачей: увеличьте alpha (`0.6` — `0.8`) + - Если MODEL_B лучше справляется с задачей: уменьшите alpha (`0.2` — `0.4`) + - Для тонкой настройки изменяйте значение с шагом 0.05 + +### Параметры для метода SLERP + +#### SLERP t (`--slerp-t`) + +Определяет соотношение весов при сферической интерполяции: + +```bash +./whisper_merge.sh --method slerp --slerp-t 0.3 +``` + +- **Диапазон**: от 0.0 до 1.0 +- **По умолчанию**: 0.5 (равный вклад) +- **Влияние**: + - `0.0` — полностью вес на MODEL_A + - `1.0` — полностью вес на MODEL_B + - Промежуточные значения дают нелинейную интерполяцию между моделями +- **Рекомендации**: + - В отличие от direct alpha, здесь значение `0` соответствует MODEL_A, а `1` соответствует MODEL_B + - SLERP обычно дает более гладкое слияние, чем direct + - Для русских моделей обычно хорошо работают значения `0.4` — `0.6` + +### Параметры для метода TIES + +#### TIES Density (`--ties-density`) + +Определяет долю параметров, которые будут смешаны индивидуально, а не усреднены: + +```bash +./whisper_merge.sh --method ties --ties-density 0.85 +``` + +- **Диапазон**: от 0.0 до 1.0 +- **По умолчанию**: 0.8 +- **Влияние**: + - `0.0` — все параметры усредняются + - `1.0` — все параметры смешиваются индивидуально по заданным весам + - Промежуточные значения определяют процент параметров с наибольшей разницей, которые будут смешаны индивидуально +- **Рекомендации**: + - Более высокие значения (`0.8` — `0.9`) лучше сохраняют индивидуальные особенности каждой модели + - Более низкие значения (`0.5` — `0.7`) дают более стабильный результат + - Для русских моделей рекомендуется `0.85`, что позволяет сохранить уникальные особенности обеих моделей + +#### Encoder Weights (`--encoder-weights`) + +Определяет веса моделей для кодировщика (отвечает за обработку аудиосигнала): + +```bash +./whisper_merge.sh --method ties --encoder-weights "0.7,0.3" +``` + +- **Формат**: два числа, разделенные запятой, сумма должна равняться 1.0 +- **По умолчанию**: "0.6,0.4" +- **Влияние**: + - Первое число — вес MODEL_A для кодировщика + - Второе число — вес MODEL_B для кодировщика +- **Рекомендации**: + - Если MODEL_A лучше распознает фонетические особенности речи: увеличьте её вес (e.g., "0.7,0.3") + - Если MODEL_B лучше распознает акценты или диалекты: увеличьте её вес (e.g., "0.4,0.6") + - Для русских моделей, если одна из них лучше обрабатывает различные диалекты, дайте ей больший вес в кодировщике + +#### Decoder Weights (`--decoder-weights`) + +Определяет веса моделей для декодера (отвечает за формирование текста): + +```bash +./whisper_merge.sh --method ties --decoder-weights "0.3,0.7" +``` + +- **Формат**: два числа, разделенные запятой, сумма должна равняться 1.0 +- **По умолчанию**: "0.4,0.6" +- **Влияние**: + - Первое число — вес MODEL_A для декодера + - Второе число — вес MODEL_B для декодера +- **Рекомендации**: + - Если MODEL_A лучше справляется с грамматикой: увеличьте её вес (e.g., "0.6,0.4") + - Если MODEL_B имеет лучший языковой контекст: увеличьте её вес (e.g., "0.3,0.7") + - Для русских моделей, если одна модель лучше обрабатывает грамматические конструкции, дайте ей больший вес в декодере + +## Практические рекомендации + +### Для слияния русских моделей + +1. **Общее правило**: начинайте с метода TIES с близкими к равным весами. + +2. **Если модели обучены на разных типах данных**: + ```bash + ./whisper_merge.sh --method ties --ties-density 0.85 --encoder-weights "0.6,0.4" --decoder-weights "0.5,0.5" + ``` + Это даст больший приоритет первой модели в распознавании звуков, но обе модели будут равно влиять на грамматику. + +3. **Если одна модель лучше с формальной речью, а другая с разговорной**: + ```bash + ./whisper_merge.sh --method ties --ties-density 0.9 --encoder-weights "0.5,0.5" --decoder-weights "0.6,0.4" + ``` + Высокая плотность (0.9) позволит сохранить уникальные особенности обеих моделей. + +4. **Для моделей, где первая модель имеет высокое качество, но вторая содержит специфичные улучшения**: + ```bash + ./whisper_merge.sh --method slerp --slerp-t 0.3 + ``` + Это сохранит основу первой модели (70%) и добавит 30% особенностей второй. + +### Для наилучших результатов + +Рекомендуется выполнить несколько экспериментов с разными настройками и сравнить результаты: + +```bash +# Эксперимент 1: TIES с приоритетом первой модели +./whisper_merge.sh --method ties --ties-density 0.85 --encoder-weights "0.65,0.35" --decoder-weights "0.6,0.4" + +# Эксперимент 2: SLERP с уклоном к первой модели +./whisper_merge.sh --method slerp --slerp-t 0.4 + +# Эксперимент 3: Прямое слияние +./whisper_merge.sh --method direct --direct-alpha 0.6 +``` + +## Тестирование и оценка + +После слияния моделей важно оценить результаты: + +1. **Подготовьте тестовый набор данных**, включающий: + - Формальную речь + - Разговорную речь + - Различные диалекты + - Различные шумовые условия + - Различные темпы речи + +2. **Выполните транскрипцию** с помощью объединенной модели и сравните с исходными моделями. + +3. **Оцените результаты** по следующим критериям: + - Word Error Rate (WER) + - Character Error Rate (CER) + - Обработка специфичных для русского языка особенностей (падежи, ударения) + - Скорость обработки + +## Устранение неполадок + +### Проблемы со слиянием SLERP или TIES + +Если возникают ошибки при использовании методов SLERP или TIES, скрипт автоматически откатывается к методу Direct. Для решения проблем: + +1. **Проверьте совместимость моделей**: + - Модели должны иметь одинаковую архитектуру + - Версии Whisper должны быть совместимы + +2. **Увеличьте объем памяти**: + - SLERP и TIES требуют больше оперативной памяти + - Попробуйте запустить на машине с большим объемом RAM + +3. **Проверьте логи** для определения конкретной проблемы + +### Проблемы с окружением Conda + +Если возникают проблемы с созданием или активацией окружения: + +1. **Обновите Conda**: + ```bash + conda update -n base conda + ``` + +2. **Удалите и пересоздайте окружение**: + ```bash + conda env remove -n whisper-merge + ./whisper_merge.sh --update + ``` + +3. **Проверьте пути к моделям** и убедитесь, что они корректны