对于函数而言,在将张量参数传递给函数之前,请将其移到CUDA设备上。
例如:
cuda = torch.device("cuda")
waveform = waveform.to(cuda)
spectrogram = torchaudio.functional.spectrogram(waveform)
支持CUDA的类是通过torch.nn.Module()实现的。在传递CUDA张量之前,也需要将实例移动到CUDA设备上。
例如:
cuda = torch.device("cuda")
resampler = torchaudio.transforms.Resample(8000, 16000)
resampler.to(cuda)
waveform.to(cuda)
resampled = resampler(waveform)
神经网络的训练分为两个步骤:
前向传播:在前向传播中,神经网络对于正确的输出进行最佳猜测。它通过将输入数据通过每个函数来运行,从而进行这个猜测。
反向传播:在反向传播中,神经网络根据其猜测的误差调整其参数。它通过从输出开始向后遍历,收集误差对于函数参数的导数(梯度),并使用梯度下降来优化参数。
在PyTorch中的使用
我们加载一个预训练的resnet18模型(来自torchvision)。
我们创建一个随机数据张量,表示一个拥有3个通道、高度和宽度为64的单个图像,以及相应的标签,初始值为一些随机值。预训练模型中的标签形状为(1,1000)。
注意:
这个教程只在CPU上工作,在GPU设备上不工作(即使张量被移动到CUDA)。
import torch
from torchvision.models import resnet18, ResNet18_Weights
model = resnet18(weights=ResNet18_Weights.DEFAULT)
data = torch.rand(1, 3, 64, 64)
labels = torch.rand(1, 1000)
接下来,我们将输入数据通过模型的每个层进行运算,以进行预测。这称为前向传播。
prediction = model(data) # 前向传播
我们使用模型的预测结果和相应的标签来计算误差(损失)。
下一步是将此误差通过网络进行反向传播。
当我们在误差张量上调用 .backward() 时,反向传播开始。
然后Autograd计算并存储每个模型参数的梯度在参数的 .grad 属性中。
loss = (prediction - labels).sum()
loss.backward() # 反向传播
接下来,我们加载一个优化器,本例中使用学习率为0.01和动量为0.9的SGD。我们在优化器中注册模型的所有参数。
optim = torch.optim.SGD(model.parameters(), lr=1e-2, momentum=0.9)
最后,我们调用 .step() 来启动梯度下降。优化器通过其在 .grad 中存储的梯度来调整每个参数。
optim.step() #梯度下降
此时,你已经拥有训练神经网络所需的一切。
torch.autograd跟踪所有requires_grad标志设置为True的张量的操作。对于不需要梯度的张量,将该属性设置为False将其排除在梯度计算DAG之外。
即使只有一个输入张量的requires_grad=True,操作的输出张量也将需要梯度。
x = torch.rand(5, 5)
y = torch.rand((5, 5), requires_grad=True)
在神经网络中,不计算梯度的参数通常被称为冻结参数。如果事先知道不需要这些参数的梯度,将其部分“冻结”在模型中是很有用的(这样可以通过减少自动求导计算来提高性能)。
在微调中,我们通常冻结大部分模型,只修改分类器层以便对新标签进行预测。我们加载一个预训练的resnet18模型,并将所有参数冻结。
from torch import nn, optim
model = resnet18(weights=ResNet18_Weights.DEFAULT)
#冻结网络中的所有参数
for param in model.parameters():
param.requires_grad = False
假设我们想在一个有10个标签的新数据集上微调模型。在resnet中,分类器是最后一个线性层model.fc。
我们可以简单地用一个新的线性层(默认情况下未冻结)替换它,作为我们的分类器。
model.fc = nn.Linear(512, 10)
现在,模型中除了model.fc的参数之外,所有参数都被冻结。只有模型的权重和偏置需要计算梯度。
# 只优化分类器
optimizer = optim.SGD(model.parameters(), lr=1e-2, momentum=0.9) 请注意,尽管我们将所有参数都注册到了优化器中,但只有分类器的权重和偏置会计算梯度(因此在梯度下降中更新)。
torch.no_grad()也提供了同样的排除功能,可以作为上下文管理器使用。
###################################################################################################
import torch
import torchaudio
from torchaudio.utils import download_asset
SAMPLE_WAV = download_asset("tutorial-assets/Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav")
# 查询音频元数据
metadata = torchaudio.info(SAMPLE_WAV) print(metadata)
# 查询类似文件的对象
url = "https://download.pytorch.org/torchaudio/tutorial-assets/steam-train-whistle-daniel_simon.wav"
with requests.get(url, stream=True) as response:
metadata = torchaudio.info(response.raw)
print(metadata)
加载音频数据:要加载音频数据,可以使用torchaudio.load()函数。该函数接受类似路径的对象或类似文件的对象作为输入。
返回的值是一个元组,包含波形(Tensor)和采样率(int)。默认情况下,返回的Tensor对象的dtype是torch.float32,数值范围是[-1.0, 1.0]。
import matplotlib.pyplot as plt
waveform, sample_rate = torchaudio.load(SAMPLE_WAV)
def plot_waveform(waveform, sample_rate):
waveform = waveform.numpy()
num_channels, num_frames = waveform.shape
time_axis = torch.arange(0, num_frames) / sample_rate # 一维张量
figure, axes = plt.subplots(num_channels, 1) #
num_channels*1的图
if num_channels == 1:
axes = [axes]
for c in range(num_channels):
axes[c].plot(time_axis, waveform[c], linewidth=1)
axes[c].grid(True)
if num_channels > 1:
axes[c].set_ylabel(f"Channel {c+1}")
figure.suptitle("waveform")
plt.show(block=False)
plot_waveform(waveform, sample_rate)
def plot_specgram(waveform, sample_rate, title="Spectrogram"):
waveform = waveform.numpy()
num_channels, num_frames = waveform.shape
figure, axes = plt.subplots(num_channels, 1)
if num_channels == 1:
axes = [axes]
for c in range(num_channels):
axes[c].specgram(waveform[c], Fs=sample_rate)
if num_channels > 1:
axes[c].set_ylabel(f"Channel {c+1}")
figure.suptitle(title)
plt.show(block=False)
plot_specgram(waveform, sample_rate)
# 切片
方法一
waveform1 = waveform1[:, frame_offset : frame_offset + num_frames]
print(f" - 已获取 {response.raw.tell()} 字节")
方法二
waveform2, sample_rate2 = torchaudio.load(response.raw, frame_offset=frame_offset, num_frames=num_frames)
print(f" - 已获取 {response.raw.tell()} 字节")
print("检查生成的波形数据 ... ", end="")
assert (waveform1 == waveform2).all()
print("匹配!")
要将音频数据保存为常见应用程序可读取的格式,您可以使用torchaudio.save()函数。
###################################################################################################
要获取音频信号随时间变化的频谱图,可以使用 torchaudio.transforms.Spectrogram()
函数。
SPEECH_WAVEFORM, SAMPLE_RATE = torchaudio.load(SAMPLE_SPEECH)
n_fft = 1024 win_length = None hop_length = 512 # Define transform spectrogram = T.Spectrogram( n_fft=n_fft, win_length=win_length, hop_length=hop_length, center=True, pad_mode="reflect", power=2.0, )
# Perform transform spec = spectrogram(SPEECH_WAVEFORM)
要从频谱图恢复出波形信号,可以使用 Griffin-Lim 算法(GriffinLim)
torch.random.manual_seed(0) n_fft = 1024 win_length = None hop_length = 512 spec = T.Spectrogram( n_fft=n_fft, win_length=win_length, hop_length=hop_length, )(SPEECH_WAVEFORM)
griffin_lim = T.GriffinLim( n_fft=n_fft, win_length=win_length, hop_length=hop_length, )
reconstructed_waveform = griffin_lim(spec)
Mel频谱图的生成涉及到生成频谱图并进行Mel标度转换。在torchaudio
中,torchaudio.transforms.MelSpectrogram()
提供了这个功能。
n_fft = 1024 win_length = None hop_length = 512 n_mels = 128 mel_spectrogram = T.MelSpectrogram( sample_rate=sample_rate, n_fft=n_fft, win_length=win_length, hop_length=hop_length, center=True, pad_mode="reflect", power=2.0, norm="slaney", onesided=True, n_mels=n_mels, mel_scale="htk", ) melspec = mel_spectrogram(SPEECH_WAVEFORM)
MFCC:
n_fft = 2048 win_length = None hop_length = 512 n_mels = 256 n_mfcc = 256 mfcc_transform = T.MFCC( sample_rate=sample_rate, n_mfcc=n_mfcc, melkwargs={ "n_fft": n_fft, "n_mels": n_mels, "hop_length": hop_length, "mel_scale": "htk", }, ) mfcc = mfcc_transform(SPEECH_WAVEFORM)
LFCC:
n_fft = 2048 win_length = None hop_length = 512 n_lfcc = 256 lfcc_transform = T.LFCC( sample_rate=sample_rate, n_lfcc=n_lfcc, speckwargs={ "n_fft": n_fft, "win_length": win_length, "hop_length": hop_length, }, ) lfcc = lfcc_transform(SPEECH_WAVEFORM)
Pitch:音高
pitch = F.detect_pitch_frequency(SPEECH_WAVEFORM, SAMPLE_RATE)
音频特征增强:
import torchaudio.transforms as T
SpecAugment是一种常用的频谱增强技术(改变速度、)
torchaudio实现了torchaudio.transforms.TimeStretch()、torchaudio.transforms.TimeMasking()和torchaudio.transforms.FrequencyMasking()。
spec = get_spectrogram(power=None) stretch = T.TimeStretch() rate = 1.2 spec_ = stretch(spec, rate)
时间掩码:
torch.random.manual_seed(4) spec = get_spectrogram()
masking = T.TimeMasking(time_mask_param=80) spec = masking(spec)
频域掩码:
torch.random.manual_seed(4) spec = get_spectrogram()
masking = T.FrequencyMasking(freq_mask_param=80) spec = masking(spec)
使用wav2vec2提取声学特征:在torchaudio.pipelines中有多个预训练模型可用。
bundle = torchaudio.pipelines.WAV2VEC2_ASR_BASE_960H #(960小时)
model = bundle.get_model().to(device)
waveform, sample_rate = torchaudio.load(SPEECH_FILE) waveform = waveform.to(device) if sample_rate != bundle.sample_rate: waveform = torchaudio.functional.resample(waveform, sample_rate, bundle.sample_rate)
with torch.inference_mode(): features, _ = model.extract_features(waveform)
Wav2Vec2模型提供了一步完成特征提取和分类的方法。
使用torch.inference_mode():
emission, _ = model(waveform)
emission[0].T,此时的横轴为帧,纵轴为类别
============================================================================
spectrogram(从原始音频信号创建一个或一批频谱图)
inverse_spectrogram(从所提供的复值频谱图创建一个或一批反频谱图)
griffinlim(使用 Griffin-Lim 变换从线性幅度谱图计算波形)
phase_vocoder(给定一个 STFT 张量,通过一个速度因子在时间上加速而不改变音高)
pitch_shift(将波形的音高调整 n_steps 步)
compute_deltas(计算张量(通常为频谱图)的增量系数)
detect_pitch_frequency(检测音高频率)
sliding_window_cmn(对每个utterance应用滑动窗口倒谱均值(和可选的方差)归一化)
compute_kaldi_pitch(提取音高)
spectral_centroid(计算每个通道沿时间轴的频谱中心)
标签:sample,TorchAudio,torchaudio,torch,rate,学习,waveform,length,2.0 From: https://www.cnblogs.com/yuyongzhen-98/p/17722926.html