format short format compact echo on % Read in Peterson-Barney Data: fid = fopen('pb.Table1'); PB = textscan(fid, '%s %s %d %s %s %f %f %f %f', 10000); fclose(fid); % % 1: m = man, w=woman, c=child % 2: m=male, f=female % 3: N=speaker number % 4: V=vowel name (heed/iy, hid/ih, head/eh, had/ae, hod/aa, hawed/ao, hood/uh, who'd/uw, hud/ah, heard/er) % 5: IPA % 6: F0 in Hz % 7: F1 % 8: F2 % 9: F3 % pause % Convert column 1 (man, woman, child) from cell array to string array: MWC=char(PB{1}); % Make some useful binary vectors: isman=(MWC=='m'); iswoman=(MWC=='w'); ischild=(MWC=='c'); % man/woman/child as values from 1 to 3: MWCints = isman + 2*iswoman + 3*ischild; % Convert column 2 (male, female) to string array: MF=char(PB{2}); % More useful binary vectors: ismale=(MF=='m'); isfemale=(MF=='f'); % Convert column 4 (vowel ID) to integers 1:10 in VID array % Note that options are 'iy','ih','eh', 'ae','aa','ao','uh','uw','ah','er' VID=zeros(length(isman),1); VID = VID + strcmp('iy',PB{4}); VID = VID + 2*strcmp('ih',PB{4}); VID = VID + 3*strcmp('eh',PB{4}); VID = VID + 4*strcmp('ae',PB{4}); VID = VID + 5*strcmp('aa',PB{4}); VID = VID + 6*strcmp('ao',PB{4}); VID = VID + 7*strcmp('uh',PB{4}); VID = VID + 8*strcmp('uw',PB{4}); VID = VID + 9*strcmp('ah',PB{4}); VID = VID + 10*strcmp('er',PB{4}); % pause % Make matrix whose rows are vowels, and % columns are F0, F1, F2, F3: F0123 = [PB{6} PB{7} PB{8} PB{9}]; % Make mean vectors and covariance matrices for man vs. woman vs. child: MWCmeans = zeros(3,4); MWCcov = cell(3,1); for c=1:3 MWCmeans(c,:) = mean(F0123(MWCints==c,:)); MWCcov{c} = inv(cov(F0123(MWCints==c,:))); end % pause % Calculate MWC distances for all 1520 vowels: MWCdist = zeros(1520,3); MWCminvals = zeros(1520,1); MWCchoice = zeros(1520,1); echo off for v=1:1520 for c=1:3 f = F0123(v,:)-MWCmeans(c,:); MWCdist(v,c) = sqrt(f*MWCcov{c}*f'); end [MWCminvals(v), MWCchoice(v)] = min(MWCdist(v,:)); end echo on % Make confusion matrix: MWCconfusion = zeros(3); for v=1:1520 i=MWCints(v); j=MWCchoice(v); MWCconfusion(i,j) = MWCconfusion(i,j)+1; end % % Show confusion matrix: MWCconfusion % What's the proportion correct? sum(diag(MWCconfusion))/1520 pause % Make mean vectors and covariance matrices for vowels: Vmeans = zeros(10,4); Vcov = cell(10,1); for v=1:10 Vmeans(v,:) = mean(F0123(VID==v,:)); Vcov{v} = inv(cov(F0123(VID==v,:))); end % Calculate V distances for all 1520 vowels: Vdist = zeros(1520,10); Vminvals = zeros(1520,1); Vchoice = zeros(1520,1); echo off for testv=1:1520 for refv=1:10 f = F0123(testv,:)-Vmeans(refv,:); Vdist(testv,refv) = sqrt(f*Vcov{refv}*f'); end [Vminvals(testv), Vchoice(testv)] = min(Vdist(testv,:)); end echo on % Make confusion matrix Vconfusion = zeros(10); for v=1:1520 i=VID(v); j=Vchoice(v); Vconfusion(i,j) = Vconfusion(i,j)+1; end % Show confusion matrix -- % 1='iy' 2='ih' 3='eh' 4='ae' 5='aa' 6='ao' 7='uh' 8='uw' 9='ah' 10='er' Vconfusion % Proportion correct? sum(diag(Vconfusion))/1520 pause % % Now divide data matrix into training and testing sets. % There are 76 speakers, IDs 1 to 76: SID = PB{3}; % 33 men (1:33), 28 women (34:61), 15 children (62:76) % Since there are 20 vowels per speaker, % the start of the nth speaker's data is row (n-1)*20 + 1 % and the end of the nth speaker's data is row n*20 % The corresponding rows in F0123 are: % men 1 to 33*20 = 1 to 660 % women 33*20 + 1 to 61*20 = 661 to 1240 % children 62*20 + 1 to 76*20 = 1241 to 1520 % % If we assign the last two men, the last two women, and the last child % to the test set, we get: istrainman=zeros(1520,1); istestman=zeros(1520,1); istrainwoman=zeros(1520,1); istestwoman=zeros(1520,1); istrainchild=zeros(1520,1); istestchild=zeros(1520,1); % istrainman(1:(31*20)) = 1; % 1 to 31 istestman((31*20+1):(33*20))=1; % 32 to 33 % istrainwoman((33*20+1):(59*20)) = 1; % 34 to 59 istestwoman((59*20+1):(61*20)) = 1; % 60 to 61 % istrainchild((61*20+1):(74*20)) = 1; % 62 to 74 istestchild((74*20+1):(76*20)) = 1; % 75 to 76 % istrain = istrainman | istrainwoman | istrainchild; istest = istestman | istestwoman | istestchild; MWCtints = MWCints(istest); VIDt = VID(istest); pause % Make mean vectors and covariance matrices for man vs. woman vs. child, % this time only from "training" data: MWCtmeans = zeros(3,4); MWCtcov = cell(3,1); for c=1:3 which = (MWCints==c) & istrain; MWCtmeans(c,:) = mean(F0123(which,:)); MWCtcov{c} = inv(cov(F0123(which,:))); end % pause % Calculate MWC distances for 100 test vowels: MWCtdist = zeros(100,3); MWCtminvals = zeros(100,1); MWCtchoice = zeros(100,1); F0123t = F0123(istest,:); echo off for v=1:100 for c=1:3 f = F0123t(v,:)-MWCtmeans(c,:); MWCtdist(v,c) = sqrt(f*MWCtcov{c}*f'); end [MWCtminvals(v), MWCtchoice(v)] = min(MWCtdist(v,:)); end echo on % Make confusion matrix: MWCtconfusion = zeros(3); for v=1:100 i=MWCtints(v); j=MWCtchoice(v); MWCtconfusion(i,j) = MWCtconfusion(i,j)+1; end % % Show confusion matrix: MWCtconfusion % What's the proportion correct? sum(diag(MWCtconfusion))/100 pause % Make mean vectors and covariance matrices for vowels, % this time only from "training" set: Vttmeans = zeros(10,4); Vcov = cell(10,1); for v=1:10 which = (VID==v) & istrain; Vtmeans(v,:) = mean(F0123(which,:)); Vtcov{v} = inv(cov(F0123(which,:))); end % Calculate V distances for 100 test vowels: Vtdist = zeros(1520,10); Vtminvals = zeros(1520,1); Vtchoice = zeros(1520,1); echo off for testv=1:100 for refv=1:10 f = F0123t(testv,:)-Vmeans(refv,:); Vtdist(testv,refv) = sqrt(f*Vtcov{refv}*f'); end [Vtminvals(testv), Vtchoice(testv)] = min(Vtdist(testv,:)); end echo on % Make confusion matrix Vtconfusion = zeros(10); for v=1:100 i=VIDt(v); j=Vtchoice(v); Vtconfusion(i,j) = Vtconfusion(i,j)+1; end % Show confusion matrix -- % 1='iy' 2='ih' 3='eh' 4='ae' 5='aa' 6='ao' 7='uh' 8='uw' 9='ah' 10='er' Vtconfusion % Proportion correct? sum(diag(Vtconfusion))/100 pause