В цикле for языка Python не могу получить ожидаемое значение счетчика
Проект по распознаванию спикера с помощью модуля resemblyzer. Структура папок такова: есть директория speakers, в которой лежат папки spk1, spk2 и т.д. В каждой из папок - по нескольку записей отдельных спикеров (одна папка - один говорящий). В ходе обработки сделал словарь, в котором ключи - те самые директории spk1, spk2 и проч., а их значения - эмбединги (представления) записей спикеров.
Далее я хочу сравнить попарно записи каждого спикера, чтобы посчитать метрику accuracy (как часто система ошибается). На этом первом этапе приводимого ниже скрипта делаю следующее: создаю попарные комбинации с тем, чтобы перебрать все возможные сочетания записей всякого говорящего внутри "его" папки.
Второй этап - поместить эмбединги записей в матрицы подобия и сравнить их посредством косинусного сходства.
В финале (третий этап) считаем accuracy. Видим: перебрали 46 комбинаций, но почему-то получили 0 совпадений. Хотя если распечатать матрицы подобия, очевидно, что совпадения наличествуют. Что не так в цикле for?
Ранее схожая проблема возникала, когда ту же задачу я решал с помощью библиотеки speechbrain. Тогда ошибка счета была связана с тензорным типом данных, генерирующим логические ответы True либо False. Здесь, как мне представляется, иной случай.
Код:
!pip install resemblyzer
! pip install umap
import numpy as np
from itertools import combinations
num_true=0
num_total=0
# 1 этап - ради сравнения перебираем значения словаря (т.е. эмбединги записей спикеров) и создаем список всех возможных комбинаций:
# (спикер 1 запись 1 - спикер 1 запись 2), (спикер 1 запись 1 - спикер 1 запись 3) и т.д.
for elems in speaker_wavs.values():
# print(elems[0])
tuples = list(combinations(elems, 2)) # получаем перебор всех комбинаций
# 2 этап - создаем эмбединги записей
for single in tuples: # идем по каждой комбинации в списке
# функция .embed_utterance() создает эмбединги голосов
embeds = (np.array( [encoder.embed_utterance(single[0]) ] ), np.array([encoder.embed_utterance(single[1]) ] ) )
num_total+=1
# Вычислим матрицу подобия. Сходство двух эмбедингов - это просто их точечное произведение,
# потому что метрикой сходства является косинусное сходство, а эмбединги уже нормированы по L2.
# Короткая версия:
utt_sim_matrix = np.inner(embeds[0], embeds[1]) # Внутреннее произведение двух массивов.
# print('Матрица_1', utt_sim_matrix) # распечатать, если надо наглядно сравнить эмбединги
# Длинная, подробная версия:
utt_sim_matrix2 = np.zeros( (len(embeds[0]), len(embeds[1]) ) )
for i in range(len(embeds[0])):
for j in range(len(embeds[1])):
# Обозначение @ эквивалентно np.dot(embedds_a[i], embedds_b[i])
utt_sim_matrix2[i, j] = embeds[0][i] @ embeds[1][j]
# print('Матрица_2', utt_sim_matrix2) # распечатать, если надо наглядно сравнить эмбединги
# Возвращает True, если два массива равны по элементам в пределах допуска
if np.allclose(utt_sim_matrix, utt_sim_matrix2) == 'True':
num_true+=1
# print(num_true) # сейчас получаем 0
# print(num_total) # сейчас получаем 46
# Этап 3 - считаем метрику accuracy:
if num_total !=0:
accuracy = num_true/num_total
print(accuracy)
else:
print('На ноль делить нельзя')
Ответы (1 шт):
numpy.allclose() возвращает или True или False, поэтому надо сравнивать не со строкой, а с этими значениями. Да и на самом деле даже сравнивать не требуется, потому что достаточно и
if np.allclose(utt_sim_matrix, utt_sim_matrix2): # т.к. тут или True или False, то и сравнивать не нужно
num_true+=1