iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0
生成式 AI

AI 情感偵測:從聲音到表情的多模態智能應用系列 第 4

【🎙️ 情緒測謊機 | 讓 AI 聽懂你語音的真心話】

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250924/20178322rZg5QJL03t.jpg
🧩 專案目標
我們平常聽朋友講話,有時會覺得「他嘴角在笑,但聲音怪怪的,好像有點生氣?」
AI 也能做到類似的事情:分析「聲音特徵」來推測說話者的情緒。
本專案會帶你一步一步:
下載情緒語音資料集
用 librosa 把聲音轉換成數字特徵(MFCC)
用 RNN/LSTM 建立模型
訓練並測試
做一個小 Demo → 你講一句話,AI 回覆「你聽起來很開心 😃」或「你其實有點生氣 😡」

🔧 專案步驟(學生版 + 專家補充)

1. 準備資料集

👉 我們需要有人「帶情緒」的聲音檔。最常用的是 RAVDESS dataset。
特色:由 24 位演員錄音,有 8 種情緒(開心、悲傷、生氣、害怕、驚訝、厭惡、冷靜、中性)。
下載:RAVDESS dataset

📌補充
為什麼要用公開資料集?
因為這些數據已經有人幫你「標好情緒」了(就像考卷上有答案),模型才有東西可以學。
如果只用我們錄的隨機聲音,AI 根本不知道「這句聲音應該是快樂還是悲傷」。

**2. 特徵擷取 **

我們要把聲音「轉換成數字」。
最常見的方法是 MFCC
人類的耳朵對不同頻率的聲音敏感度不一樣(對中頻特別敏感)。
MFCC 就是模擬人耳的聽覺,把聲音轉換成一組「代表性數字」。

import librosa
import numpy as np

def extract_features(file_path):
    y, sr = librosa.load(file_path, duration=3, offset=0.5)  # 取3秒音訊
    mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=40)       # 40維 MFCC
    return np.mean(mfcc.T, axis=0)  # 壓縮成一個向量

📌補充
為什麼要「取平均」?
因為原始聲音是一段時間序列(每毫秒都有特徵),數據量太大。
取平均相當於「濃縮」成摘要,讓模型更快學習。
(進階版:可以不取平均,直接丟整段序列給 LSTM → 模型能捕捉聲音隨時間變化的細節,但計算量會更大)

3. 建立模型:RNN / LSTM

聲音是一種「時間序列資料」 → 適合用 RNN (Recurrent Neural Network) 或 LSTM (Long Short-Term Memory)。

import torch
import torch.nn as nn

class EmotionRNN(nn.Module):
    def __init__(self, input_dim=40, hidden_dim=128, num_classes=7):
        super(EmotionRNN, self).__init__()
        self.lstm = nn.LSTM(input_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, num_classes)
    
    def forward(self, x):
        out, _ = self.lstm(x)    # LSTM 輸出序列
        out = out[:, -1, :]      # 取最後一個時間點
        return self.fc(out)      # 丟進全連接層輸出分類結果

** 📌 補充**
為什麼用 LSTM?
普通 RNN 容易「忘記」前面的聲音訊息,而 LSTM 有「記憶單元」,能保留比較長的時間關聯。
這裡的輸入是 40 維 MFCC,每段聲音是一個序列(像是 3 秒 × 100 個時間步 × 40 維特徵)

4. 訓練模型

輸入:聲音的 MFCC 特徵序列
輸出:對應的情緒標籤(0=快樂, 1=悲傷,等等)
Loss:CrossEntropyLoss(分類常用)
Optimizer:Adam(比較穩定,學生最常用)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(20):
    for X_batch, y_batch in dataloader:
        outputs = model(X_batch)
        loss = criterion(outputs, y_batch)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    print(f"Epoch {epoch}, Loss={loss.item():.4f}")

5. 小 Demo:做一個情緒測謊機

讓同學輪流講一句話,AI 直接判斷情緒。

import sounddevice as sd
import wavio

def record_voice(filename="test.wav", duration=3, sr=16000):
    print("🎙️ 開始錄音…")
    recording = sd.rec(int(duration * sr), samplerate=sr, channels=1)
    sd.wait()
    wavio.write(filename, recording, sr, sampwidth=2)
    print("✅ 錄音完成")

錄完後 → 抽取 MFCC → 丟進模型 → AI 輸出結果。
輸出範例:
「你聽起來很開心 😃」
「你嘴角在笑,但聲音有火 🔥😡」

故事化應用
課堂展示:同學輪流說「我很開心」,AI 有時會判斷「聽起來其實很累」,超好玩。
客服場景:AI 幫客服分析顧客語氣:「雖然講得很客氣,但怒氣值 80%」。
延伸挑戰:加上 Webcam 表情辨識 → 多模態「情緒測謊機」。


這次我做的專案叫 「情緒測謊機」,核心想法是:讓 AI 不只聽懂我們「說什麼」,還能揣摩我們「心情怎麼樣」。
我先用公開的 RAVDESS 語音情緒資料集,因為裡面已經有人幫忙標好情緒(像是快樂、生氣、悲傷)。接著用 librosa 擷取聲音特徵(MFCC),這一步就好像是把聲音轉成「AI 能看懂的數字」。
模型部分,我選了 LSTM,因為它比一般 RNN 更能記住聲音的時間序列變化,適合處理語音這種有「連續性」的資料。最後,我寫了一個小 Demo:用麥克風錄 3 秒聲音 → AI 判斷 → 輸出像是「你聽起來很開心 😃」或「你嘴角在笑,但聲音有火 🔥😡」。
這個專案讓我更直觀地體驗到 AI 怎麼從原始音訊一路走到「情感判斷」:從感測器錄音、特徵提取、模型訓練,再到最後的互動測試。
對我來說,這不只是一個技術練習,更像是一個 把 AI 拉近到人類感官的嘗試。因為人類本來就是透過眼睛、耳朵一起判斷情緒,而現在 AI 也能做到類似的事。未來如果加上影像辨識,就能做成更完整的「多模態情緒偵測」。


上一篇
【🚀人臉辨識打卡機實作 | 臉部關鍵點、CNN、ViT 應用 】
下一篇
【貓也要打卡 | AI 的貓臉辨識】
系列文
AI 情感偵測:從聲音到表情的多模態智能應用7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言