You are on page 1of 10

SOURE CODE

Chúng tôi sẽ dùng Matlab để phát triển hệ nhận dạng của mình.

Matlab (Matrix Laboratory) là một môi trường trợ giúp tính toán và hiển
thị rất mạnh được hãng MathWorks phát triển. Mức phát triển của Matlab ngày
nay đã chứng tỏ Matlab là một phần mềm có giao diện cực mạnh cùng nhiều lợi
thế trong kĩ thuật lập trình để giải quyết những vấn đề đa dạng trong nghiên cứu
Khoa học kỹ thuật

Phần tử tính toán cơ bản của Matlab là các ma trận. Giao diện cơ sở
của Matlab là các dòng lệnh. Ngoài thư viện các hàm tính toán, vào-ra, đồ
hoạ… cơ bản, Matlab còn có các toolbox là các thư viện cho từng lĩnh vực
cụ thể. Ví dụ có toolbox cho xử lí tín hiệu (Signal Processing), mô phỏng mô
hình (SimulLink), logic mờ (Fuzzy Logic), mạng nơron (NNet), … thậm chí
cho cả thiết kế máy bay (Aerospace) hay giải phương trình vi phân (PDE)…

Matlab cũng hỗ trợ lập trình và cho phép tích hợp thư viện do người
dùng xây dựng. Câu lệnh của Matlab được viết rất sát các mô tả kĩ thuật nên
lập trình trên Matlab nhanh và đơn giản hơn so với các ngôn ngữ thông dụng
như Pascal, Fortran… Cú pháp lập trình của Matlab giống C nên không quá
khó học. Đặc biệt Matlab còn có các giao thức để liên kết với các môi
trường lập trình khác, nhất là VC++, chẳng hạn cho phép dịch các hàm trong
Matlab thành các chương trình nguồn C/C++ hoặc hỗ trợ các thư viện DLL
từ bên ngoài.

Quá trình nhận dạng mẫu (cả ở pha huấn luyện hay pha nhận dạng)
đều trải qua bước giai đoạn là trích chọn đặc trưng (feature extraction). Bước
này thực hiện các phân tích phổ (spectral analysis) nhằm xác định các thông
tin quan trọng, đặc trưng, ổn định của tín hiệu tiếng nói, tối thiểu hoá ảnh
hưởng của nhiễu; xúc cảm, trạng thái, cách phát âm của người nói; giảm
khối lượng dữ liệu cần xử lí...

Mặc dù không mang tính quyết định nhưng giai đoạn trích chọn đặc
trưng ảnh hưởng rất lớn đến hiệu năng nhận dạng. Vì vậy việc lựa chọn đặc
trưng cho tín hiệu tiếng nói rất quan trọng.

Có nhiều phương pháp trích chọn đặc trưng đã và đang được sử dụng
(FBA, MFCC, LPC, PLP...). Mỗi phương pháp có những ưu điểm và nhược
điểm riêng. Hiện nay MFCC (Mel-scale Frequency Cepstral Coefficient)
được sử dụng phổ biến nhất.

Các hệ nhận dạng tiếng nói thường tách đặc trưng từ tín hiệu bằng
cách: chia tín hiệu thành các đoạn độ dài 5-15 ms, mỗi đoạn gọi là một
khung (frame). Trong khoảng thời gian ngắn như vậy, phổ của tín hiệu đủ ổn
định để tiến hành tách đặc trưng. Mỗi frame sẽ cho đặc trưng là một vector
và đặc trưng của toàn bộ tín hiệu sẽ là một dãy vector.

MFCC là phương pháp trích đặc trưng dựa trên đặc điểm cảm thụ tần
số âm của tai người: tuyến tính đối với tần số nhỏ hơn 1kHz và phi tuyến đối
với tần số trên 1kHz (theo thang tần số mel, không phải theo Hz). Vì lẽ đó
rất nhiều hệ thống nhận dạng tiếng nói sử dụng MFCC làm đặc trưng.

Thu thập và tiền xử lí tín hiệu tiếng nói ở giai đoạn huấn luyện được
thực hiện bằng phương pháp thủ công: sử dụng phần mềm ghi âm, lọc nhiễu
và cắt thành các từ riêng rẽ, mỗi từ ghi vào một file (tên file ghi từ tương
ứng).
Bộ dữ liệu do chúng tôi tự xây dựng gồm:
• file wav 16 bit 8kHz, mỗi file là phát âm của một từ.
• từ là các chữ số tiếng Việt từ đến . (Mặc dù “mười” không phải là chữ
số nhưng vẫn cần trong hệ nhận dạng chữ số vì có các số phát âm là
“mười một”, “mười hai”...)

Ở giai đoạn nhận dạng, việc thu thập và tiền xử lí (cắt các vùng không
chứa tín hiệu tiếng nói) được thực hiện bởi các lệnh sau

x = wavrecord(10000,8000); %tần số lấy mẫu 8kHz


x = x'; % ghi âm chừng hơn 1s
y = endcut(x, 64, 1.5E-3);

Hàm endcut dùng cắt các khoảng lặng không chứa tín hiệu âm:

function y = endcut(x, n, es)


% cat khoang lang ra khoi x.
% n là độ dài frame, es là ngưỡng năng lượng.
x = x - mean(x);
if nargin < 3

es = 2E-3;
end;
if nargin < 2

n = 128;
end;
y=[];
t=x(1:n);
e=mean(t.^2);
i=n+1;ln = length(x) - n+1;
while i<=ln

t=x(i:i+n-1);
e1=mean(t.^2);
if ~( (e1<es) | (abs(e1-e)<es) )

y = [y t];
end;
i=i+n;

end;

Bộ dữ liệu huấn luyện có 11 từ nên chúng tôi chia toàn bộ vector đặc
trưng thành 11 lớp, mỗi vector ứng với lớp của từ tương ứng. (Từ “một”
thuộc lớp 1, từ “hai” thuộc lớp 2,... từ “không” thuộc lớp 11).

Các dữ liệu trên lại tiếp tục được chia làm 2 phần: một phần dành cho
huấn luyện và một phần để kiểm tra.

Phân chia bộ dữ liệu và phân lớp cũng được thực hiện thủ công: danh
sách các file được đưa vào Excel, thông tin về chỉ số lớp của mỗi file được
đưa vào tương ứng. Mỗi file cũng được xếp vào một trong 2 nhóm: train và
test.
Nạp file Excel bằng Matlab để tạo thành 2 biến: biến file mô tả tên
file, và biến list mô tả thông tin phân lớp. Sau đó dùng các lệnh sau:

numid=list(:,1);
train=find(list(:,2)==1);
test=find(list(:,2)==0);

Mô tả chỉ số lớp tương ứng với mỗi từ; là danh sách các từ thuộc bộ
dữ liệu huấn luyện và kiểm tra. Mỗi file âm thanh được trích chọn đặc trưng
MFCC thành một dãy các vector MFCC bằng hàm wave2mfcc:

function mfcc = wave2mfcc(wav, fs, p);


if nargin < 3 % mặc định lấy vector MFCC 8pt

p = 8;
end;
if nargin < 2 % mặc định tần số lấy mẫu = 8kHz

fs = 8000;
end;
if isstr(wav) % nếu wav là tên file thì đọc

[wav fs] = wavread(wav);


end;
% chuẩn hoá để max(wav)=1.
mx = max(wav);
wav = wav ./ mx;
% tính vector MFCC p phần tử, gồm cả năng lượng
mfcc = melcepst(wav,fs,'e',p-1);

Vì các file wav có độ dài ngắn khác nhau nên dãy các vector đặc trưng
MFCC tương ứng cũng không có cùng số phần tử. Nhưng đầu vào của mạng
nơron MLP lại phải cố định. Do đó chúng tôi thực hiện một biện pháp đơn
giản là chia dãy đặc trưng thành 5 phần đều nhau, tính trung bình của từng
phần được 5 vector rồi ghép lại thành một vector. Kết quả đầu vào của mạng
nơron là một vector 40 thành phần. Hàm tính đầu vào của mạng:

function x = VecAvr(ft,k);
% trích ft thành k phần chia trung bình.

n = length(ft); m = floor(n/k); x=[];


i=0;t=1;
while i<k

i=i+1;
f=sum(ft(t:t+m-1,:))./m;
x=[x f];
t=t+m;
end;

Toàn bộ dữ liệu huấn luyện được đọc vào Matlab qua hàm:

function [x,t,z]=MakeDataANN(file, train, numid,test)


N=length(train);
i=0; x=[]; t=[];
while i<N
i = i + 1; j=train(i)
str = file{j};
mfc = wave2mfcc(str); % trích MFCC từ file wav
xi = vecavr(mfc,5);

% chia 5 phần
ti = zeros(1,11); ti(numid(j))=1; % tính target
x = [x; xi];
% ghép xi vào cuối của x

t = [t; ti];
end;
N=length(test);
i=0; z=[];

while i<N
i = i + 1;
str = file{test(i)};
mfc = wave2mfcc(str);
xi = vecavr(mfc,5);
z = [z; xi];

end;

Trong đó: x, z là đầu vào cho mạng của tương ứng với dữ liệu huấn
luyện và kiểm tra. t là đầu ra mong muốn (target) dành cho huấn luyện.
Đầu ra mong muốn của dữ liệu huấn luyện xác định rất đơn giản: là
một vector 11 thành phần (ứng với 11 lớp mẫu). Nếu file tương ứng trong bộ
dữ liệu huấn luyện thuộc lớp k, thì thành phần thứ k của vector bằng 1, các
thành phần còn lại bằng 0.

Xây dựng và huấn luyện và thử nghiệm các mạng có cấu trúc khác
nhau (về số nơron ẩn, kiểu hàm kích hoạt) được tiến hành bằng script sau

clc;
hnode=0; kq=[]; mac=0; i=0;
while hnode<150

hnode=hnode+5 % tăng hnode theo bước 5


main
% thử nghiệm mạng
if mac < ac
% ghi nhận mạng tốt hơn
mac = ac;

best = net;
end;
i=i+1;
netkq{i} = net; % ghi lại tất cả các mạng

end;

Trong đó script thực hiện khởi tạo, huấn luyện và kiểm tra mạng

net = mlp(inode, hnode, onode, func, anpha); % tạo


MLP
[net err]=mlptrain(net, xtrain, target, loop);%
train
ytest = mlpfwd(net, xtest);
% tính đầu ra bộ test
ac = TestANN(ytest, numid(test)); % tính độ chính xác
kq =[kq; ac];

Các tham số mạng như (kiểu hàm kích hoạt), (cận khởi tạo trọng số),
(số vòng lặp huấn luyện) được thay đổi theo mỗi cấu trúc mạng. Hàm
TestANN dùng tính số từ được nhận dạng chính xác dựa trên đầu ra tương
ứng với đầu vào của bộ bộ dữ liệu kiểm tra.

function [ac, qt] = TestANN(yte, numid)


qt=[]; ac=0; i=0;

while i<length(yte)
i=i+1;
kc = yte(i,:);
[mi id] = max(kc); % xác định lớp xác suất cao

nhất if id == numid(i) % nếu là chỉ số lớp tương ứng


ac = ac + 1;
% => nhận dạng đúng
end;
qt = [qt; i id numid(i) mi ac kc];
end;
ac = ac / length(yte); %độ chính xác=số từ đúng/tổng

Hàm ANNrecognize thực hiện nhận dạng với đầu vào cho trước:

function [id, xs, out] = ANNrecognize(wav,net);


mfc = wave2mfcc(wav); % trích MFCC
vec = vecavr(mfc,5);% tính đầu vào
out = mlpfwd(net,vec);% tính đầu ra của mạng
[xs id] = max(out);% đưa ra lớp cao nhất

You might also like