yousanのメモ (original) (raw)
初めに
Flow MatchingとDiffusion Transformer(DiT)を基盤にした完全な非自己回帰型テキスト音声合成(TTS)である F5-TTSが公開されています
以下 ライブラリの詳細です( ReadMeより ChatGPTから生成したものです)
構成要素の概要
エンコーダー(Encoder)
エンコーダーは、テキスト入力を音声に変換するための特徴表現を生成する役割を果たします。このシステムでは、ConvNeXTブロックを使用して、テキスト入力を時間的に調整された音声特徴と一致させることができます。この部分は従来のTTSで使われていた複雑な設計(例: Duration Model, Text Encoder, Phoneme Alignment)を排除し、単にテキストに「Filler Tokens」をパディングして音声の長さに合わせるという簡単な手法を取っています。これにより、モデルはテキストと音声のアライメントを簡単に行えるようにしています。
デコーダー(Decoder)
デコーダーは、エンコーダーからの特徴表現を用いて最終的な音声を生成します。このシステムでは、DiTブロック(Diffusion Transformer)がその役割を担います。DiTブロックは、予測されたフローを基に音声を生成するための時間ステップごとのスケーリングや変換を行います。このプロセスでは、時間ステップ ( t \sim U[0,1] ) から始まり、入力データを次々と処理していく「拡散プロセス」が適用されます。
ボコーダー(Vocoder)
ボコーダーは、最終的に生成された音声スペクトログラムを実際の波形データに変換する部分です。このシステムでは、「ODE Solver」というプロセスを通じて、生成された音声メルスペクトログラムを波形データに変換します。これにより、生成されたメルスペクトログラムを直接人間の耳に聞こえる音声に変換する役割を果たします。
特徴的な部分
Sway Sampling
推論時に適用されるサンプリング戦略で、既存のFlow Matchingベースのモデルにも再トレーニングなしで適用可能です。これにより、効率と性能が大幅に向上します。推論リアルタイムファクター(RTF)は0.15と、従来の拡散ベースのTTSモデルと比較して大幅に改善されています。
ConvNeXT
入力テキストの特徴抽出にはConvNeXTブロックを使用し、これは近年の画像処理モデルで高い性能を示しているアーキテクチャです。このモデルは、テキストと音声の特徴表現を精緻に整列させる役割を果たし、従来のテキストエンコーダーよりも効率的です。
トレーニングと推論
トレーニングデータ
システムは100K時間の多言語データセットでトレーニングされており、その結果、高い自然性や表現力を持つ音声を生成できます。また、コードスイッチング(異なる言語間での切り替え)や速度制御も可能で、幅広い用途に対応できます。
非自己回帰型TTS
非自己回帰型TTSは、自己回帰型のモデルと異なり、推論時に音声フレームを一度に並列生成するため、速度が速くなるという利点があります。このF5-TTSシステムは、従来の自己回帰型モデルと比べて大幅な速度向上を実現しています。
環境
準備
ライブラリのインストール
公式のリポジトリだと動かなかったので、以下で修正したものがあります
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 uv pip install -r requirements.txt
事前学習モデルの配置
以下から各モデルをダウンロードして、画像のように配置します
実行
以下でttsの推論をすることができます
uv run .\test_infer_single.py
使用する事前学習モデルを変更する場合は、以下の箇所を変更します
exp_name = "E2TTS_Base"
推論時の参照音声および生成するテキストを変更するには、以下の変更します
ref_audio = "tests/ref_audio/test_en_1_ref_short.wav" ref_text = "Some call me nature, others call me mother nature." gen_text = "I don't really care what you call me. I've been a silent spectator, watching species evolve, empires rise and fall. But always remember, I am mighty and enduring. Respect me and I'll nurture you; ignore me and you shall face the consequences."
開発環境
詳細
crcmod(==1.7)をインストールする際に以下のエラーが出ました。
error: Failed to prepare distributions
Caused by: Failed to fetch wheel: crcmod==1.7
Caused by: Failed to run C:\Users\name\AppData\Local\uv\cache\builds-v0\.tmpv87Zlw\Scripts\python.exe
Caused by: stream did not contain valid UTF-8
以下で解決できます
$Env:PYTHONUTF8 = "1"
初めに
査読前の論文がアップロードされている arXivを気になったものを見ているものの気になるものを全て探すのは大変なので API経由で検索をしていきます
記事の内容のリポジトリは以下で公開しています
開発環境
- python 3.10
- uv
詳細
やりたいこと* 気になる特定のトピックの中から最新のものを探す * タイトルおよびSummaryを見る
以下で最新の内容からトピックを探してきます
import urllib.parse import feedparser
query = 'all:"LLM" OR all:"Text to Speech" OR all:"Speech to Text" OR all:"AI Character"'
encoded_query = urllib.parse.quote(query)
base_url = 'http://export.arxiv.org/api/query?'
params = {
'search_query': encoded_query,
'start': 0,
'max_results': 10,
'sortBy': 'submittedDate',
'sortOrder': 'descending',
}
query_string = '&'.join(f'{key}={value}' for key, value in params.items())
url = base_url + query_string
feed = feedparser.parse(url)
for entry in feed.entries:
title = entry.title
summary = entry.summary.replace('\n', ' ')
print(f'タイトル: {title}')
print(f'要約: {summary}')
print('-' * 80)
結果は以下のようになります
タイトル: Justice or Prejudice? Quantifying Biases in LLM-as-a-Judge 要約: LLM-as-a-Judge has been widely utilized as an evaluation method in various benchmarks and served as supervised rewards in model training. However, despite their excellence in many domains, potential issues are under-explored, undermining their reliability and the scope of their utility. Therefore, we identify 12 key potential biases and propose a new automated bias quantification framework-CALM-which systematically quantifies and analyzes each type of bias in LLM-as-a-Judge by using automated and principle-guided modification. Our experiments cover multiple popular language models, and the results indicate that while advanced models have achieved commendable overall performance, significant biases persist in certain specific tasks. Empirical results suggest that there remains room for improvement in the reliability of LLM-as-a-Judge. Moreover, we also discuss the explicit and implicit influence of these biases and give some suggestions for the reliable application of LLM-as-a-Judge. Our work highlights the need for stakeholders to address these issues and remind users to exercise caution in LLM-as-a-Judge applications.
タイトル: Adaptive Inference-Time Compute: LLMs Can Predict if They Can Do Better, Even Mid-Generation 要約: Inference-time computation is a powerful paradigm to enhance the performance of large language models (LLMs), with Best-of-N sampling being a widely used technique. However, this method is computationally expensive, requiring both (1) an external reward model and (2) the generation of multiple samples. In this work, we introduce a new generative self-evaluation scheme designed to adaptively reduce the number of generated samples while maintaining or even improving performance. We use a generative reward model formulation, allowing the LLM to predict mid-generation the probability that restarting the generation will yield a better response. These predictions are obtained without an external reward model and can be used to decide whether or not to generate more samples, prune unpromising samples early on, or to pick the best sample. This capability is very inexpensive as it involves generating a single predefined token. Trained using a dataset constructed with real unfiltered LMSYS user prompts, Llama 3.1 8B's win rate against GPT-4 on AlpacaEval increases from 21% to 34% with 16 samples and math performance on GSM8K improves from 84% to 91%. By sampling only when the LLM determines that it is beneficial to do so and adaptively adjusting temperature annealing, we demonstrate that 74% of the improvement from using 16 samples can be achieved with only 1.2 samples on average. We further demonstrate that 50-75% of samples can be pruned early in generation with minimal degradation in performance. Overall, our methods enable more efficient and scalable compute utilization during inference for LLMs.
はじめに
Singularity は、高パフォーマンスコンピューティング(HPC)環境でのコンテナ実行を可能にするコンテナプラットフォームです。WSL 上で Singularity を利用することで、Linux コンテナを Windows 環境で動作させることができます。
本記事では、WSL(Ubuntu 20.04)上で SingularityCE 4.2.1 をソースからビルドしてインストールする手順になります。
開発環境
- Windows 11
- WSL2
インストール方法
必要なパッケージのインストール
まず、Singularity のビルドに必要なパッケージをインストールします。
sudo apt-get update
sudo apt-get install -y
build-essential
libssl-dev
uuid-dev
libgpgme-dev
squashfs-tools
libseccomp-dev
wget
pkg-config
git
cryptsetup
libglib2.0-dev
libfuse-dev
libfuse3-dev
libjson-c-dev
Go 言語のインストール
既存の Go の削除(必要な場合)
sudo rm -rf /usr/local/go
最新の Go のダウンロードとインストール
wget https://go.dev/dl/go1.21.1.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz
rm go1.21.1.linux-amd64.tar.gz
環境変数を設定します
echo 'export GOPATH=${HOME}/go' >> ~/.bashrc echo 'export PATH=/usr/local/go/bin:${PATH}:${GOPATH}/bin' >> ~/.bashrc source ~/.bashrc
ここでインストールしたgoのversionを確認します
go version
以下の出力ができてきます
go version go1.21.1 linux/amd64
Singularity のソースコードのダウンロード
リポジトリからクローンします
git clone https://github.com/sylabs/singularity.git cd singularity
configの設定を使って処理を実行します
./mconfig
ビルドをしてインストールをします
make -C builddir sudo make -C builddir install
以下でインストール後の確認ができます
singularity --version
以下のような出力がされてたら成功です
singularity-ce version 4.2.1
エラー対応
- glib-2.0 headers are required to build conmon.
以下で追加のライブラリを入れます
sudo apt-get install libglib2.0-dev
参考サイト
参考
(この記事はとても参考になっています)
開発環境
- Windows 11
内容
requirements.txt
を使って ライブラリをインストールするときのメモ
pythonのversionの固定
以下で 特定のversionをインストールします
uv python install 3.9.20
以下で使用するversionを固定します
uv venv -p 3.9.20
ライブラリをインストール
以下で インストールをすることができます
uv pip sync requirements.txt
また以下をすることによってライブラリの依存を pyproject.toml
に記載してくれます
uv add -r requirements.txt
- 初めに
- 環境
- docker環境の作成
- 音声データセットの準備
- セマンティックトークンのバッチ抽出
- データセットをprotobufにパック
- LoRAの学習
- 学習後のLoRAの重みを変換
- 学習後のモデルを使って推論
- 備考
初めに
fish-speech v1.4がリリースされたので、改めて触ってみます。
Excited to introduce Fish Speech 1.4 - now open-source and more powerful than ever! 🎉 Our mission is to make cutting-edge voice tech accessible to everyone.
What's new:
- Trained on 700k hours of multilingual data (up from 200k)
- Now supports 8 languages: English, Chinese,… pic.twitter.com/A9vS1yGuRR— Fish Audio (@FishAudio) 2024年9月11日
前回 CLIで推論を行う記事を書いたので、今回は つくよみちゃん会話AI育成計画(会話テキストデータセット配布) を使って学習を進めていきます
環境
- Windows
- Docker Desktop
- fish-speech hash : b186c9881ad7c6dcf6e476bb7723b0b55b46be1e
- audio-preprocess v0.2.8
docker環境の作成
まずは fish-speechをcloneします。
https://github.com/fishaudio/fish-speech.git
docker環境が準備されているので、docker環境をビルドして立ち上げます。
docker-compose -f docker-compose.dev.yml up -d
ビルドしたdocker環境には以下のコマンドで入ることができます
docker exec -it fish-speech /bin/bash
音声データセットの準備
今回は つくよみちゃんデータセットを使うので、データセットをダウンロードしてきます。
次に 以下のようなフォルダ構成を作成します
/exp/ ├── data-raw/ │ ├── tsukuyomi-chan/
この中に音声ファイルを入れます。
ノーマライゼーション処理
はじめに 音声のノーマライゼーションを行います
fap loudness-norm data-raw data --clean
fapコマンドがない場合は、以下でインストールをします
pip install fish-audio-preprocess
(docker環境内でほかのライブラリと依存関係が一致しない場合は、docker外で別環境を作成してそちらでインストールを行うとうまく動きました。)
この処理が終わると /data
に処理後の音声が保存されます。
ファイルによってはうまく処理がされない場合があるので、以下の修正を行ったverを作成しました。
- ファイルのI/O処理のチャンク対応
- 音声のクリッピングの際に音声の長さの考慮
必要に応じてこちらをcloseして以下でインストールを行い処理をします。
pip install -e .
文字お越しファイルの作成
/data
の音声から それぞれの音声ファイルに対する .lab
ファイルを作成します。
以下のコードで つくよみちゃんの文字起こしのテキストファイルと音声ファイルを使って labファイルを作成します。
import re import os import argparse
def process_text_file(input_file, output_dir):
if not os.path.exists(output_dir):
os.makedirs(output_dir)
with open(input_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
if line.strip() == "":
continue
match = re.match(r'(VOICEACTRESS100_\d+):(.+)', line.strip())
if match:
file_name = match.group(1) + '.lab'
content = match.group(2).strip()
else:
file_name = f'line_{lines.index(line) + 1}.lab'
content = line.strip()
with open(os.path.join(output_dir, file_name), 'w', encoding='utf-8') as out_file:
out_file.write(content)
def main(): parser = argparse.ArgumentParser(description='Generate .lab files from input text file.') parser.add_argument('input_file', help='Path to the input text file') parser.add_argument('--output_dir', default='output', help='Path to the output directory (default: output)')
args = parser.parse_args()
process_text_file(args.input_file, args.output_dir)
if name == "main": main()
実行は以下のコマンドで実行することができます。
python generate_lab_files.py input_text.txt --output_dir custom_output
セマンティックトークンのバッチ抽出
VQGANの重みをダウンロードをダウンロードします。
huggingface-cli download fishaudio/fish-speech-1.4 --local-dir checkpoints/fish-speech-1.4
セマンティックトークンを抽出します。
python tools/vqgan/extract_vq.py data
--num-workers 1 --batch-size 16
--config-name "firefly_gan_vq"
--checkpoint-path "checkpoints/fish-speech-1.4/firefly-gan-vq-fsq-8x1024-21hz-generator.pth"
データセットをprotobufにパック
以下でデータセットからprotobufを生成します。
python tools/llama/build_dataset.py
--input "data"
--output "data/protos"
--text-extension .lab
--num-workers 16
LoRAの学習
LLAMAの重みをダウンロードします。
huggingface-cli download fishaudio/fish-speech-1.4 --local-dir checkpoints/fish-speech-1.4
docker環境で学習をする場合、shm_sizeが小さいとエラーになるため docker_compose.dev.yml
に以下を追加します。
shm_size: 30gb
追加後は以下にようになります
services: fish-speech: build: . container_name: fish-speech shm_size: 30gb
batchサイズやデータの並列処理部分のパラメータは text2semantic_finetune.yaml
の 以下で変更することができます。
num_workers: 2 batch_size: 4
学習時のステップ数や保存するタイミングは以下のパラメータになります。
max_steps: 5000 limit_val_batches: 1000 val_check_interval: 1000
以下でLoRAの学習を開始することができます。 my_voice_project
は任意のプロジェクト名を指定してください。
python fish_speech/train.py --config-name text2semantic_finetune
project=my_voice_project
+lora@model.model.lora_config=r_8_alpha_16
学習後のLoRAの重みを変換
学習が終わった後に生成されるファイルは .ckpt
というファイルになっているため、こちらを .pth
に変換する必要があります。
以下のコマンドで重みの変換を行います。
python tools/llama/merge_lora.py
--lora-config r_8_alpha_16
--base-weight checkpoints/fish-speech-1.4
--lora-weight results/$project/checkpoints/step_000000010.ckpt
--output checkpoints/fish-speech-1.4-yth-lora/
学習後のモデルを使って推論
音声推論をする場合は、CLIとWeb版などいくつか選ぶことができます。
CLIは以下を参考にしてください。
今回は視覚的にわかりやすいWeb版を立ち上げていきます。
まずは必要なモデルをダウンロードします。
huggingface-cli download fishaudio/fish-speech-1.4 --local-dir checkpoints/fish-speech-1.4
以下でWebUIを立ち上げることができます
python -m tools.webui
--llama-checkpoint-path "変換したLoRAの重みを保存したパス"
--decoder-checkpoint-path "checkpoints/fish-speech-1.4/firefly-gan-vq-fsq-8x1024-21hz-generator.pth"
--decoder-config-name firefly_gan_vq
備考
変更差分は以下にpushしています。
開発環境
モデルの構造確認
以下のコードでモデルの構造を確認できます
import torch from pathlib import Path import json from safetensors import safe_open import argparse
def load_model(model_path): if model_path.suffix == '.safetensors': with safe_open(model_path, framework="pt", device="cpu") as f: return {key: f.get_tensor(key) for key in f.keys()} elif model_path.suffix == '.pth': return torch.load(model_path, map_location='cpu') else: raise ValueError(f"Unsupported file format: {model_path.suffix}")
def analyze_model_structure(model_dict): sizes = set() important_shapes = {} for name, param in model_dict.items(): if isinstance(param, torch.Tensor): if len(param.shape) > 0: sizes.add(param.shape[-1]) if param.shape[-1] in [256, 512]: important_shapes[name] = param.shape return sizes, important_shapes
def analyze_models(model_paths, config_path): config_path = Path(config_path)
with open(config_path, 'r') as f:
config = json.load(f)
all_sizes = set()
all_important_shapes = {}
for model_path in model_paths:
model_path = Path(model_path)
print(f"\nAnalyzing {model_path.name}:")
model_dict = load_model(model_path)
if 'model' in model_dict:
model_dict = model_dict['model']
sizes, important_shapes = analyze_model_structure(model_dict)
all_sizes.update(sizes)
all_important_shapes.update(important_shapes)
print(f"Unique sizes found: {sorted(sizes)}")
print("Important shapes (256 or 512):")
for name, shape in important_shapes.items():
print(f" {name}: shape = {shape}")
print("\nOverall summary:")
print(f"All unique sizes found across models: {sorted(all_sizes)}")
print("\nImportant config information:")
print(f"Model name: {config.get('model_name', 'Not specified')}")
print(f"Version: {config.get('version', 'Not specified')}")
print(f"Gin channels: {config['model'].get('gin_channels', 'Not specified')}")
print(f"Hidden channels: {config['model'].get('hidden_channels', 'Not specified')}")
if name == "main": parser = argparse.ArgumentParser(description="Analyze VITS2 model files") parser.add_argument("config_path", type=str, help="Path to the config.json file") parser.add_argument("model_paths", type=str, nargs='+', help="Paths to the model files (.pth or .safetensors)")
args = parser.parse_args()
analyze_models(args.model_paths, args.config_path)
以下のようにモデルの構造を確認することができます
python .\analyze_vits2_model_structure.py .\model_assets\test\config.json .\model_assets\test\test_e1000_s25000.safetensors
Analyzing test_e1000_s25000.safetensors: Unique sizes found: [1, 2, 3, 5, 7, 8, 11, 16, 29, 32, 64, 96, 128, 192, 256, 384, 512, 768] Important shapes (256 or 512): dec.cond.bias: shape = torch.Size([512]) dec.conv_pre.bias: shape = torch.Size([512]) dec.resblocks.0.convs1.0.bias: shape = torch.Size([256]) dec.resblocks.0.convs1.1.bias: shape = torch.Size([256]) dec.resblocks.0.convs1.2.bias: shape = torch.Size([256]) dec.resblocks.0.convs2.0.bias: shape = torch.Size([256]) dec.resblocks.0.convs2.1.bias: shape = torch.Size([256]) dec.resblocks.0.convs2.2.bias: shape = torch.Size([256]) dec.resblocks.1.convs1.0.bias: shape = torch.Size([256]) dec.resblocks.1.convs1.1.bias: shape = torch.Size([256]) dec.resblocks.1.convs1.2.bias: shape = torch.Size([256]) dec.resblocks.1.convs2.0.bias: shape = torch.Size([256]) dec.resblocks.1.convs2.1.bias: shape = torch.Size([256]) dec.resblocks.1.convs2.2.bias: shape = torch.Size([256]) dec.resblocks.2.convs1.0.bias: shape = torch.Size([256]) dec.resblocks.2.convs1.1.bias: shape = torch.Size([256]) dec.resblocks.2.convs1.2.bias: shape = torch.Size([256]) dec.resblocks.2.convs2.0.bias: shape = torch.Size([256]) dec.resblocks.2.convs2.1.bias: shape = torch.Size([256]) dec.resblocks.2.convs2.2.bias: shape = torch.Size([256]) dec.ups.0.bias: shape = torch.Size([256]) dp.conv_1.bias: shape = torch.Size([256]) dp.conv_2.bias: shape = torch.Size([256]) dp.norm_1.beta: shape = torch.Size([256]) dp.norm_1.gamma: shape = torch.Size([256]) dp.norm_2.beta: shape = torch.Size([256]) dp.norm_2.gamma: shape = torch.Size([256]) emb_g.weight: shape = torch.Size([1, 512]) enc_p.encoder.spk_emb_linear.weight: shape = torch.Size([192, 512]) enc_p.style_proj.weight: shape = torch.Size([192, 256]) flow.flows.0.enc.spk_emb_linear.weight: shape = torch.Size([192, 512]) flow.flows.2.enc.spk_emb_linear.weight: shape = torch.Size([192, 512]) flow.flows.4.enc.spk_emb_linear.weight: shape = torch.Size([192, 512]) flow.flows.6.enc.spk_emb_linear.weight: shape = torch.Size([192, 512])
Overall summary: All unique sizes found across models: [1, 2, 3, 5, 7, 8, 11, 16, 29, 32, 64, 96, 128, 192, 256, 384, 512, 768]
Important config information: Model name: nadeko Version: 2.4.1-JP-Extra Gin channels: 512 Hidden channels: 192