Этот пример демонстрирует подход машинного обучения, чтобы идентифицировать людей на основе функций, извлеченных из записанной речи. Функциями, использованными, чтобы обучить классификатор, является подача речевых сегментов речи и коэффициентов кепстра частоты mel (MFCC). Это - идентификация динамика замкнутого множества: аудио динамика под тестом сравнено со всеми доступными моделями динамика (конечное множество), и самое близкое соответствие возвращено.
Подход, используемый в этом примере для идентификации динамика, показывают в схеме.
Сделайте подачу и MFCC извлечены из речевых сигналов, зарегистрированных для 10 динамиков. Эти функции используются, чтобы обучить классификатор K - ближайших соседей (KNN). Затем новые речевые сигналы, которые должны быть классифицированы, проходят то же извлечение признаков. Обученный классификатор KNN предсказывает, какой из этих 10 динамиков является самым близким соответствием.
В этом разделе рассматриваются подачу и MFCC, две функции, которые используются, чтобы классифицировать динамики.
Тангаж
Речь может быть широко категоризирована, как озвучено и неречевая. В случае речевой речи воздух от легких модулируется голосовыми связками и результатами в квазипериодическом возбуждении. Получившийся звук во власти относительно низкочастотного колебания, называемого подачей. В случае неречевой речи воздух от легких проходит через сжатие в речевом тракте и становится турбулентным, подобным шуму возбуждением. В модели фильтра источника речи возбуждение упоминается как источник, и речевой тракт упоминается как фильтр. Охарактеризование источника является важной частью охарактеризования речевой системы.
Как пример речевой и неречевой речи, рассмотрите представление временного интервала слова "два" (/T UW/). Согласный/T/(неречевая речь) похож на шум, в то время как гласный/UW/(речевая речь) характеризуется сильной основной частотой.
[audioIn, fs] = audioread('Counting-16-44p1-mono-15secs.wav'); twoStart = 110e3; twoStop = 135e3; audioIn = audioIn(twoStart:twoStop); timeVector = linspace((twoStart/fs),(twoStop/fs),numel(audioIn)); sound(audioIn,fs) figure plot(timeVector,audioIn) axis([(twoStart/fs) (twoStop/fs) -1 1]) ylabel('Amplitude') xlabel('Time (s)') title('Utterance - Two')
Речевой сигнал является динамическим по своей природе и изменяется в зависимости от времени. Это принято, что речевые сигналы стационарные по кратковременным шкалам, и их обработка сделана в окнах 20-40 мс. Этот пример использует окно на 30 мс с перекрытием на 25 мс. Используйте pitch
функционируйте, чтобы видеть, как подача изменяется в зависимости от времени.
windowLength = round(0.03*fs); overlapLength = round(0.025*fs); f0 = pitch(audioIn,fs,'WindowLength',windowLength,'OverlapLength',overlapLength,'Range',[50,250]); figure subplot(2,1,1) plot(timeVector,audioIn) axis([(110e3/fs) (135e3/fs) -1 1]) ylabel('Amplitude') xlabel('Time (s)') title('Utterance - Two') subplot(2,1,2) timeVectorPitch = linspace((twoStart/fs),(twoStop/fs),numel(f0)); plot(timeVectorPitch,f0,'*') axis([(110e3/fs) (135e3/fs) min(f0) max(f0)]) ylabel('Pitch (Hz)') xlabel('Time (s)') title('Pitch Contour')
pitch
функционируйте оценивает значение подачи для каждой системы координат. Однако подача является только характеристической для источника в областях речевой речи. Самый простой метод, чтобы различать тишину и речь должен анализировать краткосрочную степень. Если степень в системе координат выше заданного порога, вы объявляете систему координат как речь.
pwrThreshold = -20;
[segments,~] = buffer(audioIn,windowLength,overlapLength,'nodelay');
pwr = pow2db(var(segments));
isSpeech = (pwr > pwrThreshold);
Самый простой метод, чтобы различать речевую и неречевую речь должен анализировать нулевой уровень пересечения. Большое количество нулевых пересечений подразумевает, что нет никакого доминирующего низкочастотного колебания. Если нулевой уровень пересечения для системы координат ниже заданного порога, вы объявляете его, как озвучено.
zcrThreshold = 300;
zeroLoc = (audioIn==0);
crossedZero = logical([0;diff(sign(audioIn))]);
crossedZero(zeroLoc) = false;
[crossedZeroBuffered,~] = buffer(crossedZero,windowLength,overlapLength,'nodelay');
zcr = (sum(crossedZeroBuffered,1)*fs)/(2*windowLength);
isVoiced = (zcr < zcrThreshold);
Объедините isSpeech
и isVoiced
определить, содержит ли система координат озвученную речь.
voicedSpeech = isSpeech & isVoiced;
Удалите области, которые не соответствуют речевой речи от оценки подачи и графику.
f0(~voicedSpeech) = NaN; figure subplot(2,1,1) plot(timeVector,audioIn) axis([(110e3/fs) (135e3/fs) -1 1]) axis tight ylabel('Amplitude') xlabel('Time (s)') title('Utterance - Two') subplot(2,1,2) plot(timeVectorPitch,f0,'*') axis([(110e3/fs) (135e3/fs) min(f0) max(f0)]) ylabel('Pitch (Hz)') xlabel('Time (s)') title('Pitch Contour')
Коэффициенты кепстра Mel-частоты (MFCC)
MFCC являются популярными функциями, извлеченными из речевых сигналов для использования в задачах распознавания. В модели фильтра источника речи MFCC, как изучают, представляют фильтр (речевой тракт). Частотная характеристика речевого тракта относительно является гладкой, тогда как источник речевой речи может быть смоделирован, когда импульс обучается. Результат состоит в том, что речевой тракт может быть оценен спектральным конвертом речевого сегмента.
Идея мотивации MFCC состоит в том, чтобы сжать информацию о речевом тракте (сглаживавший спектр) в небольшое количество коэффициентов на основе понимания улитки уха.
Несмотря на то, что нет никакого твердого стандарта для вычисления MFCC, основные шаги обрисованы в общих чертах схемой.
mel filterbank линейно располагает первые 10 треугольных фильтров с интервалами и логарифмически располагает остающиеся фильтры с интервалами. Отдельные полосы взвешиваются для даже энергии. График представляет типичный mel filterbank.
Этот пример использует mfcc
вычислить MFCC для каждого файла.
Этот пример использует Базу данных переписи (также известный как Базу данных AN4) от CMU Robust Speech Recognition Group [1]. Набор данных содержит записи участников эксперимента и участниц эксперимента, произносящих слова и числа. Функция помощника в этом разделе загружает его для вас и преобразует необработанные файлы в FLAC. Речевые файлы разделены в подкаталоги на основе меток, соответствующих динамикам. Если вы не можете загрузить его, можно загрузить таблицу функций от HelperAN4TrainingFeatures.mat
и перейдите непосредственно к разделу Training a Classifier. Функции были извлечены из того же набора данных.
Загрузите и извлеките речевые файлы для 10 динамиков (5 розеток и 5 штекеров) во временную директорию с помощью HelperAN4Download
функция.
dataDir = HelperAN4Download;
Создайте audioDatastore
объект управлять этой базой данных для обучения. Datastore позволяет вам собирать необходимые файлы формата файла и читать их.
ads = audioDatastore(dataDir,'IncludeSubfolders',true, ... 'FileExtensions','.flac', ... 'LabelSource','foldernames')
ads = audioDatastore with properties: Files: { ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\an36-fejs-b.flac'; ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\an37-fejs-b.flac'; ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\an38-fejs-b.flac' ... and 122 more } Folders: { 'C:\Users\bhemmat\AppData\Local\Temp\an4\wav\flacData' } Labels: [fejs; fejs; fejs ... and 122 more categorical] AlternateFileSystemRoots: {} OutputDataType: 'double' SupportedOutputFormats: ["wav" "flac" "ogg" "mp4" "m4a"] DefaultOutputFormat: "wav"
splitEachLabel
функция audioDatastore
разделяет datastore в два или больше хранилища данных. Получившиеся хранилища данных имеют заданную пропорцию звуковых файлов от каждой метки. В этом примере datastore разделен в две части. 80% данных для каждой метки используются для обучения, и остающиеся 20% используются для тестирования. countEachLabel
метод audioDatastore
используется, чтобы считать количество звуковых файлов на метку. В этом примере метка идентифицирует динамик.
[adsTrain, adsTest] = splitEachLabel(ads,0.8);
Отобразите datastore и количество динамиков в обучать datastore.
adsTrain
adsTrain = audioDatastore with properties: Files: { ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\an36-fejs-b.flac'; ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\an37-fejs-b.flac'; ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\an38-fejs-b.flac' ... and 94 more } Folders: { 'C:\Users\bhemmat\AppData\Local\Temp\an4\wav\flacData' } Labels: [fejs; fejs; fejs ... and 94 more categorical] AlternateFileSystemRoots: {} OutputDataType: 'double' SupportedOutputFormats: ["wav" "flac" "ogg" "mp4" "m4a"] DefaultOutputFormat: "wav"
trainDatastoreCount = countEachLabel(adsTrain)
trainDatastoreCount=10×2 table
Label Count
_____ _____
fejs 10
fmjd 10
fsrb 10
ftmj 10
fwxs 10
mcen 10
mrcb 10
msjm 10
msjr 10
msmn 7
Отобразите datastore и количество динамиков в тестовом datastore.
adsTest
adsTest = audioDatastore with properties: Files: { ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\cen6-fejs-b.flac'; ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\cen7-fejs-b.flac'; ' ...\bhemmat\AppData\Local\Temp\an4\wav\flacData\fejs\cen8-fejs-b.flac' ... and 25 more } Folders: { 'C:\Users\bhemmat\AppData\Local\Temp\an4\wav\flacData' } Labels: [fejs; fejs; fejs ... and 25 more categorical] AlternateFileSystemRoots: {} OutputDataType: 'double' SupportedOutputFormats: ["wav" "flac" "ogg" "mp4" "m4a"] DefaultOutputFormat: "wav"
testDatastoreCount = countEachLabel(adsTest)
testDatastoreCount=10×2 table
Label Count
_____ _____
fejs 3
fmjd 3
fsrb 3
ftmj 3
fwxs 2
mcen 3
mrcb 3
msjm 3
msjr 3
msmn 2
Чтобы предварительно просмотреть содержимое вашего datastore, считайте файл примера и проигрывайте его с помощью аудио устройства по умолчанию.
[sampleTrain, dsInfo] = read(adsTrain); sound(sampleTrain,dsInfo.SampleRate)
Чтение от обучать datastore продвигает указатель чтения так, чтобы можно было выполнить итерации через базу данных. Сбросьте обучать datastore, чтобы возвратить указатель чтения на запуск для следующего извлечения признаков.
reset(adsTrain)
Извлеките подачу и функции MFCC от каждой системы координат, которая соответствует речевой речи в учебном datastore. Функция поддержки, isVoicedSpeech, выполняет обнаружение озвучивания, обрисованное в общих чертах в описании извлечения признаков подачи.
fs = dsInfo.SampleRate; windowLength = round(0.03*fs); overlapLength = round(0.025*fs); features = []; labels = []; while hasdata(adsTrain) [audioIn,dsInfo] = read(adsTrain); melC = mfcc(audioIn,fs,'Window',hamming(windowLength,'periodic'),'OverlapLength',overlapLength); f0 = pitch(audioIn,fs,'WindowLength',windowLength,'OverlapLength',overlapLength); feat = [melC,f0]; voicedSpeech = isVoicedSpeech(audioIn,fs,windowLength,overlapLength); feat(~voicedSpeech,:) = []; label = repelem(dsInfo.Label,size(feat,1)); features = [features;feat]; labels = [labels,label]; end
Сделайте подачу и MFCC не находятся по той же шкале. Это сместит классификатор. Нормируйте функции путем вычитания среднего значения и деления стандартного отклонения.
M = mean(features,1); S = std(features,[],1); features = (features-M)./S;
Теперь, когда вы собрали функции всех 10 динамиков, можно обучить классификатор на основе их. В этом примере вы используете классификатор K - ближайших соседей (KNN). KNN является методом классификации, которому естественно удовлетворяют для классификации мультиклассов. Гиперпараметры для самого близкого соседнего классификатора включают количество самых близких соседей, метрика расстояния использовалась для расчета расстояния до соседей и веса метрики расстояния. Гиперпараметры выбраны, чтобы оптимизировать точность валидации и эффективность на наборе тестов. В этом примере номер соседей определяется к 5, и метрика для выбранного расстояния является взвешенным Евклидовым расстоянием в квадрате обратным. Для получения дополнительной информации о классификаторе, обратитесь к fitcknn
(Statistics and Machine Learning Toolbox).
Обучите классификатор и распечатайте точность перекрестной проверки. crossval
(Statistics and Machine Learning Toolbox) и kfoldLoss
(Statistics and Machine Learning Toolbox) используется для расчета точность перекрестной проверки в классификаторе KNN.
Задайте все опции классификатора и обучите классификатор.
trainedClassifier = fitcknn( ... features, ... labels, ... 'Distance','euclidean', ... 'NumNeighbors',5, ... 'DistanceWeight','squaredinverse', ... 'Standardize',false, ... 'ClassNames',unique(labels));
Выполните перекрестную проверку.
k = 5; group = labels; c = cvpartition(group,'KFold',k); % 5-fold stratified cross validation partitionedModel = crossval(trainedClassifier,'CVPartition',c);
Вычислите точность валидации.
validationAccuracy = 1 - kfoldLoss(partitionedModel,'LossFun','ClassifError'); fprintf('\nValidation accuracy = %.2f%%\n', validationAccuracy*100);
Validation accuracy = 97.50%
Визуализируйте график беспорядка.
validationPredictions = kfoldPredict(partitionedModel); figure cm = confusionchart(labels,validationPredictions,'title','Validation Accuracy'); cm.ColumnSummary = 'column-normalized'; cm.RowSummary = 'row-normalized';
Можно также использовать Classification Learner (Statistics and Machine Learning Toolbox) приложение, чтобы испытать и сравнить различные классификаторы с вашей таблицей функций.
В этом разделе вы тестируете обученный классификатор KNN с речевыми сигналами от каждого из 10 докладчиков, чтобы видеть, как хорошо это ведет себя с сигналами, которые не использовались, чтобы обучить его.
Считайте файлы, извлеките функции из набора тестов и нормируйте их.
features = []; labels = []; numVectorsPerFile = []; while hasdata(adsTest) [audioIn,dsInfo] = read(adsTest); melC = mfcc(audioIn,fs,'Window',hamming(windowLength,'periodic'),'OverlapLength',overlapLength); f0 = pitch(audioIn,fs,'WindowLength',windowLength,'OverlapLength',overlapLength); feat = [melC,f0]; voicedSpeech = isVoicedSpeech(audioIn,fs,windowLength,overlapLength); feat(~voicedSpeech,:) = []; numVec = size(feat,1); label = repelem(dsInfo.Label,numVec); numVectorsPerFile = [numVectorsPerFile,numVec]; features = [features;feat]; labels = [labels,label]; end features = (features-M)./S;
Предскажите метку (динамик) для каждой системы координат путем вызова predict
на trainedClassifier
.
prediction = predict(trainedClassifier,features); prediction = categorical(string(prediction));
Визуализируйте график беспорядка.
figure('Units','normalized','Position',[0.4 0.4 0.4 0.4]) cm = confusionchart(labels,prediction,'title','Test Accuracy (Per Frame)'); cm.ColumnSummary = 'column-normalized'; cm.RowSummary = 'row-normalized';
Для данного файла предсказания сделаны для каждой системы координат. Определите режим предсказаний для каждого файла и затем постройте график беспорядка.
r2 = prediction(1:numel(adsTest.Files)); idx = 1; for ii = 1:numel(adsTest.Files) r2(ii) = mode(prediction(idx:idx+numVectorsPerFile(ii)-1)); idx = idx + numVectorsPerFile(ii); end figure('Units','normalized','Position',[0.4 0.4 0.4 0.4]) cm = confusionchart(adsTest.Labels,r2,'title','Test Accuracy (Per File)'); cm.ColumnSummary = 'column-normalized'; cm.RowSummary = 'row-normalized';
Предсказанные динамики совпадают с ожидаемыми динамиками для всех файлов под тестом.
Эксперимент был повторен с помощью внутренне разработанного набора данных. Набор данных состоит из 20 динамиков с каждым динамиком, говорящим несколько предложений из списка [2] предложений Гарварда. Для 20 динамиков, точность валидации 89%.
function voicedSpeech = isVoicedSpeech(x,fs,windowLength,overlapLength) pwrThreshold = -40; [segments,~] = buffer(x,windowLength,overlapLength,'nodelay'); pwr = pow2db(var(segments)); isSpeech = (pwr > pwrThreshold); zcrThreshold = 1000; zeroLoc = (x==0); crossedZero = logical([0;diff(sign(x))]); crossedZero(zeroLoc) = false; [crossedZeroBuffered,~] = buffer(crossedZero,windowLength,overlapLength,'nodelay'); zcr = (sum(crossedZeroBuffered,1)*fs)/(2*windowLength); isVoiced = (zcr < zcrThreshold); voicedSpeech = isSpeech & isVoiced; end
[1] "CMU Sphinx Group - Аудио Базы данных". Полученный доступ 19 декабря 2019. http://www.speech.cs.cmu.edu/databases/an4/.
[2] "Предложения Гарварда". Википедия, 27 августа 2019. Википедия, https://en.wikipedia.org/w/index.php? title=Harvard_sentences&oldid=912785385.