Александр Иванов – Python в аудио-спецэффектах. Как работают нейросети изнутри. (страница 6)
Полносвязная сеть для классификации звуков.
4 входных признака -> 16 скрытых нейронов -> 8 скрытых нейронов -> 3 класса
"""
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(4, 16) # входной слой -> скрытый слой 1
self.fc2 = nn.Linear(16, 8) # скрытый слой 1 -> скрытый слой 2
self.fc3 = nn.Linear(8, 3) # скрытый слой 2 -> выходной слой (3 класса)
self.relu = nn.ReLU() # функция активации ReLU
self.softmax = nn.Softmax(dim=1) # для получения вероятностей
def forward(self, x):
x = self.relu(self.fc1(x))
x = self.relu(self.fc2(x))
x = self.softmax(self.fc3(x))
return x
# Создаём модель, функцию потерь и оптимизатор
model = SoundClassifier()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
print("Модель создана:")
print(model)
print(f"\nКоличество параметров: {sum(p.numel() for p in model.parameters())}")
Наша сеть принимает четыре признака для каждого аудиофрейма: среднюю громкость, частоту пересечений нуля, спектральный центроид и спектральный спад. Частота пересечений нуля показывает, насколько сигнал колеблется — у шума она высокая, у музыки средняя, у речи низкая. Спектральный центроид показывает, где сосредоточена энергия спектра — у шипящих звуков он высокий, у басовых — низкий. Спектральный спад показывает, насколько спектр сконцентрирован — у тональных звуков он низкий, у шумовых — высокий.
Сеть состоит из трёх слоёв. Первый слой принимает четыре признака и выдаёт шестнадцать скрытых представлений. Второй сжимает их до восьми. Третий выдаёт три числа — вероятности для каждого класса: речь, музыка, шум. Функция активации ReLU оставляет положительные значения без изменений и обнуляет отрицательные — это простая нелинейность, которая хорошо работает на практике.
Обучение классификатора
Теперь нам нужны данные для обучения. В идеале — тысячи размеченных аудиофрагментов. Для демонстрации мы создадим синтетические данные: сгенерируем признаки, похожие на те, что бывают у реальной речи, музыки и шума.
python
def generate_synthetic_data(n_samples=500):
"""
Генерирует синтетические данные для демонстрации обучения.
В реальном проекте здесь была бы загрузка реальных аудиофайлов.
"""
np.random.seed(42)
data = []
labels = []
for _ in range(n_samples):
# Класс 0: Речь
data.append([
np.random.normal(0.3, 0.1), # rms: умеренная громкость
np.random.normal(0.15, 0.05), # zcr: низкая частота пересечений нуля
np.random.normal(0.8, 0.2), # centroid: низкий центроид
np.random.normal(0.6, 0.3), # rolloff: умеренный спад
])
labels.append(0)
# Класс 1: Музыка
data.append([
np.random.normal(0.4, 0.15), # rms: средняя громкость
np.random.normal(0.25, 0.08), # zcr: средняя
np.random.normal(1.5, 0.5), # centroid: средний
np.random.normal(2.0, 1.0), # rolloff: выше
])
labels.append(1)
# Класс 2: Шум
data.append([
np.random.normal(0.2, 0.1), # rms: низкая громкость
np.random.normal(0.45, 0.1), # zcr: высокая
np.random.normal(2.5, 1.0), # centroid: высокий
np.random.normal(3.0, 1.5), # rolloff: высокий
])
labels.append(2)
# Перемешиваем
data = np.array(data, dtype=np.float32)
labels = np.array(labels)
shuffle_idx = np.random.permutation(len(data))
return data[shuffle_idx], labels[shuffle_idx]