书接上文,切割后的文件转换特征为MFCC(细节不表了,网搜的代码)。声音的特征和识别最好的组合绝对不是MFCC+SVM(后面我会讲为什么),我只是怎么怎么方便怎么来,看到这的准备做声音识别的同学请果断变道。
有了特征值就可以作为训练素材了,Emgucv版本更新快,不同版本的分类器参数设置方式不一样,这可以参见我以前的类似博客。
以下将走过的坑分享一下:
1.不定长声音的MFCC也不定长(废话),解决不定长,我用了人工指定的方式,即指定MFCC特征的个数,多的丢,少的补零。仅个人实践表明,特征越多分类效果越好,所以,多补零吧。
string[] MFCCa = MFCCs.Split(',');
for (int j = 0; j < chanum; j++)
{
if (j > MFCCa.Length - 2)//存的时候多了个“,”,所以回退一位
{
trainDate[i, j] = 0;
}
else
{
trainDate[i, j] = Convert.ToSingle(MFCCa[j]);
}
trainLab[i, 0] = 1;
}
2.Emgucv3.×以上的训练结果文件(.XML)的读存请自行修改下,直接save和load似乎不行。半公开的秘密,代码如下:
private static void saveSVMtoFile(SVM model,String path)
{
if (File.Exists(path))
File.Delete(path);
FileStorage fs = new FileStorage(path, FileStorage.Mode.Write);
model.Write(fs);
fs.ReleaseAndGetString();
}
private static SVM loadSVMtoFile(String path)
{
SVM svm = new SVM();
FileStorage fs = new FileStorage(path, FileStorage.Mode.Read);
svm.Read(fs.GetRoot());
fs.ReleaseAndGetString();
return svm;
}
3.Emgucv的SVM和BP之间细微的差别
本以为只是改改训练器,几行代码的事情,但报了一堆错,全是小细节。
3.1 SVM的分类标签可以是int或者float,但BP一定一定要是float
Matrix trainDate = new Matrix(allnum, chanum);
Matrix trainLab = new Matrix(allnum,1);
Matrix trainData = new Matrix(allnum, chanum);
Matrix trainClasses = new Matrix(allnum, 1);
3.2 SVM可以直接给出预测结果(即标签),BP给出的不知道是什么(大概是到你定的标签范围内的落点,我定了1和-1,但有时候超出了1和-1,所以很奇怪,有真懂的同学留言教我一下),还要自己判断一下。
Matrix preDate = new Matrix(1, chaNum);
getPerDate(preDate, OutfileName[j], chaNum);
float kinds=svm.Predict(preDate);
Matrix preDate = new Matrix(1, chaNum);
Matrix prediction = new Matrix(1, 1);
getPerDate(preDate, OutfileName[j], chaNum);
network.Predict(preDate, prediction);
float kinds = prediction.Data[0, 0];
3.3 SVM(线性核函数)+MFCC我做出来50%上下,几乎没什么意义。BP效果不错,起码70以上,一般水准在80%上下。
悲伤的补一句,样本数量还可以且分类数量很小的情况下,最短路径的效果其实很好。
新开博客,目的为学习交流,本人QQ:273651820。