聊天視窗

從零到偶像:生成式 AI 與虛擬人物的跨域實踐 - 第 4 章

第 4 章 數據收集與模型微調

發布於 2026-03-02 19:24

# 第 4 章 數據收集與模型微調 ## 4.1 為什麼要微調? 在虛擬偶像的開發過程中,**通用模型**(如 LLaMA、Stable Diffusion、RVC)提供了強大的基礎能力,但若直接套用,往往會出現以下問題: 1. **角色語氣不一致**:模型的預設風格與偶像的設定(可愛、冷酷、青春)不匹配。 2. **專屬詞彙缺失**:偶像的專屬梗、粉絲稱呼、品牌口號等不在語料庫中。 3. **視覺與聲音的個性化不足**:生成的立繪或聲線缺乏獨特性,難以形成辨識度。 透過 **微調(Fine‑Tuning)** 或 **參數高效微調(Parameter‑Efficient Fine‑Tuning)**,我們可以在保留基礎模型能力的同時,注入角色專屬的語言、圖像與聲音特徵,快速產出符合品牌定位的 AI 產出。 --- ## 4.2 資料蒐集策略 微調的品質直接受 **資料品質** 影響。以下提供三大類型的資料蒐集要點與工具推薦。 ### 4.2.1 文本語料 | 來源 | 內容 | 收集工具 | 注意事項 | |------|------|----------|----------| | 官方劇本、劇情大綱 | 角色對話、情節敘述 | `scrapy`、`beautifulsoup4` | 確認版權,過濾敏感詞 | | 社群貼文(Twitter、Discord) | 粉絲互動、梗圖文字 | `twarc`、`discord.py` | 需去除噪聲、去重 | | 角色設定檔(CSV/JSON) | 人格特質、口頭禪 | 手動整理或 `pandas` | 統一格式、標註情緒 | **實作小技巧**: - 使用 **正則表達式** 切除表情符號與 URL。 - 將文字全部 `lowercase` 後再做 **分詞(tokenization)**,便於後續統計。 ### 4.2.2 影像素材 | 來源 | 說明 | 建議工具 | 版權備註 | |------|------|----------|----------| | 官方官方概念稿、插畫 | 高解析度角色正面/側面/表情 | `wget`、`rclone` | 自行擁有版權或已授權 | | 網路公開資料庫 (Pixiv、DeviantArt) | 同風格參考圖 | `pixivpy` API | 需取得作者同意或使用 CC0 素材 | | 3D 模型渲染圖 | 動作帧、光照變化 | Blender Python API | 內部製作 → 自有版權 | **圖像前處理**: - **統一尺寸**(512×512 或 768×768) - **色彩標準化**(均值 0.5、標準差 0.5) - **去除水印**(若有授權,使用 `inpaint`) ### 4.2.3 音頻資料 | 來源 | 內容 | 采集方式 | 需要的前處理 | |------|------|----------|--------------| | 原始配音、歌唱錄音 | 語音、歌聲 | Audacity、Reaper 錄製 | 44.1kHz、16‑bit PCM | | 粉絲語音抽樣 | 粉絲喊話、ASMR | Discord 錄音機器人 | 轉成單聲道、去雜訊 | | 公開音源 (Freesound) | 背景音效、環境聲 | `freesound` API | 轉為 .wav、標註情緒 | **音頻清理**: - `sox` 進行 **降噪**(`sox input.wav output.wav noisered profile 0.21`) - 使用 **RVC** 前先切分成 4‑8 秒的片段,並在檔名中加入情緒標籤(`happy_01.wav`)。 --- ## 4.3 數據清洗與標註 > **目標**:讓資料在訓練時「可讀」且「可解」 ### 4.3.1 文本清理流程 ```python import re, unicodedata def clean_text(txt: str) -> str: txt = unicodedata.normalize('NFKC', txt) # 統一全形/半形 txt = re.sub(r'https?://\S+', '', txt) # 去除 URL txt = re.sub(r'[@#]\w+', '', txt) # 去除社群標記 txt = re.sub(r'\s+', ' ', txt).strip() # 合併連續空白 return txt ``` - **分詞**:使用 `jieba`、`tokenizers`(BPE)產生 token 序列。 - **情緒標註**:利用 `snownlp` 或手動標記,加入 `[POSITIVE]`、`[NEGATIVE]` 標籤,以輔助情緒控制。 ### 4.3.2 圖像清洗與標籤 1. **去重**:利用 **感知哈希(pHash)** 判斷相似度 > 0.95 的圖像視為重複,刪除。 2. **自動標籤**:使用 `BLIP`、`CLIP` 產生 5‑10 個關鍵詞(`prompt_tags.txt`)。 3. **手動校正**:建議每 200 張圖抽樣 10 張,人工確認標籤正確性,形成 **校正集**。 ```bash # pHash 去重示例 (Python) from imagehash import phash from PIL import Image import os hashes = {} for f in os.listdir('raw_images'): img = Image.open(os.path.join('raw_images', f)) h = phash(img) if h in hashes: print('duplicate:', f, '->', hashes[h]) else: hashes[h] = f ``` ### 4.3.3 音頻清理與情緒標籤 | 步驟 | 工具 | 範例指令 | |------|------|----------| | 切割 | `pydub` | `AudioSegment.from_wav(...).split_to_mono()` | | 降噪 | `sox` | `sox input.wav output.wav noisered profile 0.15` | | 標籤 | 手動或 `praat` | `happy_01.wav`、`sad_02.wav` | --- ## 4.4 常見微調技術概覽 | 技術 | 核心概念 | 典型應用 | 主要優勢 | |------|----------|----------|-----------| | **LoRA** (Low‑Rank Adaptation) | 只在部分權重矩陣上加入低秩矩陣 | 文本、圖像的角色化微調 | 訓練成本 ≈ 1/10,容易合併多個 LoRA | | **DreamBooth** | 用少量正向/負向樣本讓模型記住 *特定實體* | 角色立繪、專屬服裝、場景 | 可在 3‑5 張圖完成角色專屬化 | | **Textual Inversion** | 為新概念學習嵌入向量(token) | 新詞彙、專屬道具 | 嵌入僅 1‑2 MB,易於部署 | | **PEFT (Adapter, Prefix Tuning)** | 在 transformer 前/中插入小型適配層 | 大型 LLM 的語氣微調 | 訓練快速、兼容性高 | --- ## 4.5 LoRA 微調實作步驟 (以 Stable Diffusion 為例) ### 4.5.1 環境建置 ```bash # 建議使用 conda 管理環境 conda create -n lora python=3.10 -y conda activate lora # 安裝核心套件 pip install torch==2.0.1+cu118 torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu118 pip install diffusers==0.25.0 accelerate==0.25.0 transformers==4.34.0 pip install safetensors==0.4.0 ``` > 若使用 GPU,確保 CUDA 驅動 ≥ 11.8。若資源有限,可改用 **Colab** 或 **Kaggle** 提供的 T4 GPU。 ### 4.5.2 資料準備 1. **資料夾結構** ``` training_data/ ├─ images/ # 512×512 PNG/JPG │ ├─ 0001.png │ └─ ... └─ metadata.csv # 每行: filename, caption ``` 2. **產生 caption**(建議使用 CLIP‑BLIP) ```python from transformers import BlipProcessor, BlipForConditionalGeneration import pandas as pd, os processor = BlipProcessor.from_pretrained('Salesforce/blip-image-captioning-base') model = BlipForConditionalGeneration.from_pretrained('Salesforce/blip-image-captioning-base') rows = [] for f in os.listdir('training_data/images'): img_path = os.path.join('training_data/images', f) raw_image = Image.open(img_path).convert('RGB') inputs = processor(images=raw_image, return_tensors='pt') out = model.generate(**inputs) caption = processor.decode(out[0], skip_special_tokens=True) rows.append([f, caption]) pd.DataFrame(rows, columns=['filename','caption']).to_csv('training_data/metadata.csv', index=False) ``` 3. **加入角色專屬 Tag**(如 `[CHARACTER]`) ```csv filename,caption 0001.png,"[CHARACTER] 站在星空下,微笑,金色長髮" ``` ### 4.5.3 訓練指令 > 下面的範例採用 `accelerate launch`,可以自動分配多卡或單卡。 ```bash accelerate launch \ train_lora_sd.py \ --pretrained_model_name_or_path=stabilityai/stable-diffusion-2-1-base \ --train_data_dir=training_data/images \ --caption_column=caption \ --resolution=512 \ --train_batch_size=4 \ --gradient_accumulation_steps=2 \ --learning_rate=5e-5 \ --lr_scheduler="constant" \ --num_train_epochs=5 \ --output_dir=./lora_character \ --logging_dir=./logs \ --mixed_precision="fp16" ``` **主要參數說明**: | 參數 | 說明 | |------|------| | `--learning_rate` | LoRA 的學習率通常較低,5e-5~1e-4 為常見範圍。 | | `--train_batch_size` | 受 GPU 記憶體限制,建議 2~8。 | | `--num_train_epochs` | 依素材量調整;少量圖(≈30 張) 3‑5 epoch 已足夠。 | | `--mixed_precision` | 使用 `fp16` 能節省 50% 記憶體。 | ### 4.5.4 監控與驗證 - **TensorBoard**:`tensorboard --logdir logs`,觀察 loss 曲線與學習率。 - **驗證腳本**:在 `validation/` 放入 5 張未見圖,使用以下指令檢查生成效果。 ```bash python infer_lora.py \ --model_path=stabilityai/stable-diffusion-2-1-base \ --lora_path=./lora_character/lora.safetensors \ --prompt="[CHARACTER] 在海邊玩耍,夕陽" \ --output_dir=./samples ``` - **評估指標**:使用 **FID**(Fréchet Inception Distance)比較微調前後分布差異。 --- ## 4.6 DreamBooth 微調流程(圖像 & 聲音) ### 4.6.1 圖像 DreamBooth 1. **準備 3‑5 張正向影像**(不同姿勢、光線),以及 10‑15 張負向樣本(不含目標角色)。 2. **使用 `diffusers` 官方腳本**: ```bash accelerate launch train_dreambooth.py \ --pretrained_model_name_or_path=runwayml/stable-diffusion-v1-5 \ --instance_data_dir=./instance_images \ --class_data_dir=./class_images \ --output_dir=./dreambooth_character \ --instance_prompt="a photo of <char>" \ --class_prompt="a photo of a person" \ --resolution=512 \ --train_batch_size=1 \ --gradient_accumulation_steps=1 \ --learning_rate=5e-6 \ --lr_scheduler="constant" \ --max_train_steps=800 \ --checkpointing_steps=200 ``` 3. **驗證**:`python generate.py --prompt "a photo of <char> in a futuristic city"` ### 4.6.2 聲音 DreamBooth(RVC) 1. **收集 10‑20 秒的乾淨說話樣本**(同一位說話者,語速、情緒多樣)。 2. **切割**為 4‑8 秒片段,放入 `rvc/dataset/target`。 3. **使用 `rvc-train`**(基於 `torch`): ```bash python train.py \ --exp_name=char_voice \ --data_path=./rvc/dataset/target \ --pretrained_path=./rvc/pretrained/v2 \ --epoch=1200 \ --batch_size=8 \ --lr=0.0001 ``` 4. **測試**: ```bash python inference.py --model_path=./rvc/weights/char_voice.pth \ --input=./test_sentence.wav \ --output=./synthesized.wav ``` --- ## 4.7 多模態微調策略 | 需求 | 推薦組合 | 實作建議 | |------|----------|----------| | **角色語言 + 立繪** | LoRA(文字) + DreamBooth(圖像) | 先完成文字 LoRA,確保對話風格;再以 DreamBooth 加入角色視覺特徵,兩者分別儲存於 `./lora_text`、`./dreambooth_img`。 | | **語音+口型同步** | RVC 微調 + 3D Blendshape 生成 | RVC 產出語音,利用 `face2face` 或 `wav2lip` 產生對應口型動畫。 | | **跨平台即時互動** | LoRA + LoRA‑tuned TTS | 在 Discord 機器人中,先用 LLM(LoRA)產生回覆文字,再交給微調過的 TTS(RVC)播放。 | **統一管理**:將所有 LoRA / DreamBooth 權重放在 `./weights/`,並在 `config.yaml` 中記錄對應的 `prompt_tag`,方便部署時自動載入。 --- ## 4.8 成效評估指標 | 類型 | 指標 | 計算方式 | 目標值 (建議) | |------|------|----------|---------------| | 文本 | **BLEU / ROUGE** | 與人工撰寫範例比對 | BLEU > 0.45、ROUGE‑L > 0.60 | | 文本 | **情緒一致性** | 透過情感分析模型(BERT‑Emotion) | 正確率 > 85% | | 圖像 | **FID** | 產生圖與真實圖特徵分布比較 | FID < 30(小樣本) | | 圖像 | **CLIP 相似度** | `CLIPScore` | > 0.30 | | 聲音 | **MOS (Mean Opinion Score)** | 人工聽感評分(1‑5) | MOS ≥ 4.0 | | 聲音 | **Pitch RMSE** | 合成聲與原聲的 pitch 差異 | < 30 Hz | --- ## 4.9 常見問題與排錯 | 問題 | 可能原因 | 解決方案 | |------|----------|----------| | 訓練時 `CUDA out of memory` | Batch 太大、模型未使用 `fp16` | 降低 `train_batch_size`、開啟 `mixed_precision`、使用 `gradient_checkpointing` | | 生成圖像中仍出現原始基礎模型的樣式 | LoRA 過小或學習率過低 | 提升 `rank`(默認 4 → 8)或適度提高學習率至 `1e-4` | | 文字微調後出現「忘記角色名稱」 | 訓練資料缺少足夠的角色 tag | 在每條 caption 前加入固定 token(`[CHAR]`)並在 LLM 提示詞中使用同樣 token | | RVC 合成聲音有雜音、斷斷續續 | 訓練資料太短或噪聲未清除 | 增加每段長度至 6‑8 秒,使用 `sox` 進行前置降噪 | | DreamBooth 產生的圖像失真 | 迭代次數不足或負樣本過少 | 增加 `max_train_steps` 至 1500,或擴充 `class_data_dir` 以提供更廣泛的背景資訊 | --- ## 4.10 案例研究:打造專屬虛擬偶像「星瀾」的語言模型 | 步驟 | 操作 | 成果 | |------|------|------| | 1️⃣ 收集語料 | 2,300 條粉絲聊天、官方劇本、品牌口號 | 總計約 1.1M token | | 2️⃣ 清理與標註 | 去除廣告、加入 `[STARL]` 角色標籤、情緒標記 | `cleaned_starland.csv` | 3️⃣ 微調模型 | 使用 `LLaMA‑7B` + LoRA(rank=8),學習率 5e-5,10 epoch | LoRA 權重 `starlora.safetensors` | 4️⃣ 評估 | BLEU 0.52、情緒正確率 87% | 超過內部基準 | 5️⃣ 部署 | 透過 `vLLM` 以 `--tensor-parallel-size 2` 部署於 Nvidia A100 | 延遲 < 120ms,支援 500 QPS | **關鍵技巧**: - 在每個回答開頭加入固定 token `[STARL]`,保證角色語氣一致。 - 使用 **adapter‑fusion** 把不同 LoRA(粉絲互動、劇情敘事)合併,讓模型能在不同情境自動切換。 --- ## 4.11 小結與實作清單 1. **完成資料蒐集**:文本 2k+ 條、圖像 100+ 張、音頻 30+ 段。 2. **完成清洗與標註**,產出 `cleaned_text.csv`、`metadata.csv`、`audio_labels.csv`。 3. **選擇微調技術**(LoRA / DreamBooth / RVC),在 `04_Tech_Selection.md` 中記錄決策過程。 4. **執行微調**,保存權重於 `weights/`,同時產出測試樣本於 `samples/`。 5. **評估指標**:確保所有指標均達到章節 4.8 中的目標值。 6. **撰寫微調手冊**(`README_MICRO_TUNE.md`),包括環境、指令、常見錯誤、最佳實踐。 完成以上六項,即可進入第 5 章 **「視覺形象的自動生成與後製」**,開始利用已微調的模型產出高品質的角色立繪與動畫素材。