對抗性音訊範例
Expert4 min readUpdated 2026-03-13
打造對抗音訊擾動的技術,含心理聲學隱藏、頻域攻擊,以及 over-the-air 對抗音訊。
對抗音訊定式
對抗音訊問題:給定來源音訊訊號 x 與目標轉錄 y_target,尋找擾動 delta 使:
ASR(x + delta) = y_target
須滿足:delta 對人類不可察覺
與影像以 Lp 範數衡量「不可察覺」不同,音訊的不可察覺由人類聽覺系統的遮蔽特性決定。
心理聲學隱藏
聽覺遮蔽
兩類遮蔽使對抗音訊成為可能:
同時遮蔽:某頻率上的響亮聲音使鄰近較安靜的頻率變得聽不見。1kHz 的響亮音,會遮蔽 800Hz–1.2kHz 間低於某門檻的聲音。
時序遮蔽:響亮聲音會使前(後向遮蔽,約 5ms)與後(前向遮蔽,約 50–200ms)之聲音暫時不可聞。
import numpy as np
from scipy.signal import stft
def compute_masking_threshold(
audio: np.ndarray,
sample_rate: int = 16000,
frame_size: int = 512
) -> np.ndarray:
"""
計算簡化之心理聲學遮蔽門檻。
回傳:每 frame 各頻率 bin 的門檻。
低於此門檻的擾動對人耳不可聞。
"""
# 計算 STFT
f, t, Zxx = stft(audio, fs=sample_rate, nperseg=frame_size)
power_spectrum = np.abs(Zxx) ** 2
# 簡化遮蔽模型(Schroeder spreading function)
num_freq_bins = power_spectrum.shape[0]
masking_threshold = np.zeros_like(power_spectrum)
for frame_idx in range(power_spectrum.shape[1]):
frame_power = power_spectrum[:, frame_idx]
for i in range(num_freq_bins):
if frame_power[i] < 1e-10:
continue
# 將遮蔽擴散至鄰近頻率
for j in range(num_freq_bins):
bark_diff = abs(i - j) * (sample_rate / frame_size) / 100
# 簡化擴散函式(dB)
spread = max(
-100,
15.81 + 7.5 * (bark_diff + 0.474)
- 17.5 * np.sqrt(1 + (bark_diff + 0.474) ** 2)
)
masking_threshold[j, frame_idx] += (
frame_power[i] * 10 ** (spread / 10)
)
return masking_threshold
def psychoacoustic_perturbation(
perturbation: np.ndarray,
masking_threshold: np.ndarray,
sample_rate: int = 16000,
frame_size: int = 512
) -> np.ndarray:
"""
將擾動縮放至遮蔽門檻以下。
此舉使擾動不可聞,同時最大化其量級。
"""
f, t, pert_stft = stft(perturbation, fs=sample_rate, nperseg=frame_size)
pert_power = np.abs(pert_stft) ** 2
# 將各頻率 bin 縮放以低於遮蔽門檻
scale = np.ones_like(pert_power)
exceeds = pert_power > masking_threshold
scale[exceeds] = np.sqrt(
masking_threshold[exceeds] / (pert_power[exceeds] + 1e-10)
)
scaled_stft = pert_stft * scale
# 反 STFT 以取得時域擾動
from scipy.signal import istft
_, scaled_perturbation = istft(scaled_stft, fs=sample_rate, nperseg=frame_size)
return scaled_perturbation[:len(perturbation)]頻域攻擊
於頻域(頻譜空間)而非時域作業,對音訊對抗攻擊有數項優勢。
頻譜擾動
由於 ASR 模型通常作用於 mel 頻譜上,直接於頻譜空間擾動更為直接:
import torch
import torchaudio
def spectrogram_attack(
model,
audio: torch.Tensor,
target_ids: torch.Tensor,
num_steps: int = 500,
step_size: float = 0.01
) -> torch.Tensor:
"""
於 mel 頻譜空間進行攻擊以提高最佳化效率。
"""
# 轉為 mel 頻譜
mel_transform = torchaudio.transforms.MelSpectrogram(
sample_rate=16000, n_fft=400, n_mels=80
)
mel = mel_transform(audio)
mel_delta = torch.zeros_like(mel, requires_grad=True)
optimizer = torch.optim.Adam([mel_delta], lr=step_size)
for step in range(num_steps):
perturbed_mel = mel + mel_delta
# 自 mel 特徵起前向通過模型
logits = model.encoder(perturbed_mel)
logits = model.decoder(logits, target_ids[:, :-1])
loss = torch.nn.functional.cross_entropy(
logits.view(-1, logits.size(-1)),
target_ids[:, 1:].reshape(-1)
)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 限制擾動量級
with torch.no_grad():
mel_delta.data = torch.clamp(mel_delta.data, -2.0, 2.0)
return (mel + mel_delta).detach()頻帶限制擾動
將擾動限於特定頻帶可提升不可察覺性:
def band_limited_attack(
perturbation: np.ndarray,
sample_rate: int = 16000,
low_freq: float = 4000, # 人類於 4kHz 以上較不敏感
high_freq: float = 8000
) -> np.ndarray:
"""將對抗擾動限於特定頻帶。"""
from scipy.signal import butter, filtfilt
nyquist = sample_rate / 2
low = low_freq / nyquist
high = high_freq / nyquist
b, a = butter(4, [low, high], btype='band')
filtered = filtfilt(b, a, perturbation)
return filteredOver-the-Air 穩健性
實用音訊攻擊的最大挑戰:撐過實體播放。
房間脈衝響應模擬
訓練對抗音訊以對房間聲學具穩健性:
def simulate_room_impulse(
audio: np.ndarray,
room_size: tuple = (5, 4, 3), # 公尺
source_pos: tuple = (2, 1, 1.5),
mic_pos: tuple = (3, 3, 1.5),
sample_rate: int = 16000
) -> np.ndarray:
"""
以 image source 法模擬房間聲學。
於對抗最佳化期間使用以提升穩健性。
"""
# 簡化:以合成之房間脈衝響應做卷積
# 實務上請用 pyroomacoustics 做準確模擬
rt60 = 0.4 # 混響時間(秒)
num_samples = int(rt60 * sample_rate)
# 指數衰減雜訊近似房間脈衝
rir = np.random.randn(num_samples)
rir *= np.exp(-np.arange(num_samples) / (rt60 * sample_rate / 6.9))
rir[0] = 1.0 # 直接路徑
rir /= np.max(np.abs(rir))
return np.convolve(audio, rir, mode='same')
def robust_adversarial_optimization(
model,
audio: torch.Tensor,
target_ids: torch.Tensor,
num_rooms: int = 5,
num_steps: int = 1000
) -> torch.Tensor:
"""
最佳化對抗音訊,使其對多種模擬房間條件皆具穩健性
(Expectation over Transformation)。
"""
delta = torch.zeros_like(audio, requires_grad=True)
for step in range(num_steps):
total_loss = 0
for _ in range(num_rooms):
# 隨機房間模擬
room_audio = apply_random_room_sim(audio + delta)
logits = model(room_audio)
loss = compute_target_loss(logits, target_ids)
total_loss += loss / num_rooms
total_loss.backward()
with torch.no_grad():
delta.data -= 0.001 * delta.grad.sign()
delta.data = torch.clamp(delta.data, -0.02, 0.02)
delta.grad.zero_()
return (audio + delta).detach()各攻擊做法比較
| 做法 | 不可察覺性 | 數位成功 | OTA 成功 | 算力 |
|---|---|---|---|---|
| 時域 PGD | 低 | 高 | 低 | 中 |
| 心理聲學 PGD | 高 | 高 | 低—中 | 高 |
| 頻譜攻擊 | 中 | 高 | 低 | 中 |
| 頻帶限制 | 中高 | 中 | 中 | 中 |
| 房間穩健(EoT) | 中 | 中高 | 中高 | 非常高 |
相關主題
- 語音辨識攻擊 -- 較高層次的 ASR 攻擊策略
- VLM 的對抗性影像範例 -- 視覺領域的平行概念
- 實驗:打造音訊對抗範例 -- 動手練習
參考資料
- "Audio Adversarial Examples: Targeted Attacks on Speech-to-Text" - Carlini & Wagner(2018)- 目標式對抗音訊攻擊方法論的奠基作
- "Imperceptible, Robust, and Targeted Adversarial Examples for Automatic Speech Recognition" - Qin et al.(2019)- 以心理聲學遮蔽產生不可察覺音訊攻擊
- "Robust Audio Adversarial Example for a Physical Attack" - Yakura & Sakuma(2019)- 以 Expectation over Transformation 達成房間穩健之對抗音訊
- "AdvPulse: Universal, Synchronization-free, and Targeted Audio Adversarial Attacks via Subsecond Perturbations" - Li et al.(2020)- 通用對抗音訊擾動技術
Knowledge Check
為什麼心理聲學遮蔽對對抗音訊攻擊很重要?