Java实现通过日语元音ae的发音曲线分类9个发音者

  1. 业务理解(Business Understanding)
    该业务是分类问题。需要对9个人的日语元音ae的发音分析,然后根据分析确定9名发音者。ae.train文件是训练数据集,ae.test文件是用来测试训练效果的,size_ae.test记录了每个发音者对应的ae.test数据文件中包含数据的对应块,同理size_ae.train记录了实际结果每个块对应的发音者。
  2. 数据理解(Data Understanding):
    (1) 概述:数据是验证多维时间序列曲线分类的。九个发音者发出两个日本元音/ae/先后。对于每个发音分析参数,采用12度线性预测分析,以它来取得的LPC倒谱系数(LPCC)12离散时间序列。这意味着,一个接一个发音者话语形成一个时间序列,其长度的范围是7-29,每一个时间序列是12个特征值。
    在时间序列数共分640块。270块用做训练,用370块进行测试。270块对应着ae.train文件,370块数据对应着ae.test文件。
    (2)训练集数据理解:size_ae.train中的数据是30 30 30 30 30 30 30 30 30,表示9个发音者对应的数据块数(1-30块对应着第一个说话者,31-60对应第二个说话者,以此类推),这是 ae.train中的数据发音者对应发音的情况;在ae.train中有270块数据,块与块之间有一个空行作为分割的标志。其中每块数据中包含的行数为7到29不等,每行代表着发音者的一个时间帧。每行包含了12属性列,因为使用的是12LPCC。
    (3) 测试集数据有两种方式理解:
    在ae.test中有370块数据,块与块之间有一个空行作为分割的标志。其中每块数据中包含的行数为7到29不等,每行代表着发音者的一个时间帧。每行包含了12属性列。
    方式A:size_ae.test中的数据是31 35 88 44 29 24 40 50 29,表示9个发音者对应的数据块数(1-31对应着第一个说话者,以此类推)。则样本集是以分块为单位,即对应9个待估计样本,预测这9个人对应的发音者。
    方式B:ae.test对应的370块对应不同人的发音测试样本,如此就需要对370个样本判断对应的发音者(1-9类发音者)。
    预测:我采用了B钟方式的理解做的,由于B中方式的样本太少,预测正确率一定比A低。(由于时间有限,没有去实现A方式的的预测,B正确率90.5%)
    (4) 数据预处理:由于从ae.train和ae.test数据文件看,没有缺失值,一共12维,每维数据范围差距以及不同数据维差距都不大,所以不需要对数据进行归一化处理。暂且认定数据质量是完整的,没有出错的。
  3. 数据准备(Data Preparation)
    (1)数据选择:12维的数据都要选择,都是重要属性组成
    (2)数据清洁:由观察可忽略数据源可能在测试或人为记录中的错误,忽略噪音,没有缺失值,不需要人为对缺失值处理等;
    (3)数据创建:在原有数据的基础上根据块的划分,将270块按照size_ae.train文件要求以30一份划分为9类,分别对应9个人不同发音类,在12维数据之前加上tagClass作为类的标志(tagClass:1-9),建立13维;
    (4)数据合并:没有需要合并的数据,在数据准备阶段,中间处理过程有需要合并的;
    (5)数据格式化:由训练集文件得12维的数据格式都是数字类型,double型,而且都是保留6位小数,如果保留小数位不统一,则需要进行处理,使数据格式一致,但文档中数据格式已经比较规范,而且不同数据维之间都是用空格间隔。
  4. 建立模型(Modeling)
    (1) 模型设计,设计方案:
    A. 在训练集中,有270个块,对于每一块,取每列(维)的平均值作为该块维度的一个评估,这样可保证每个块每维数据独立于其他块的维度数据,以块作为单位进行数据处理。即把每一块的数据,相当于一个(7-29)行12列的矩阵,转化为一个12维的list或数组,转化过程以每块每维的平均值作为list值组成。
    B. 由上一步可以得到一个270行12列的大矩阵(或者简单说是270个list),然后对270个进行类划分,根据size_ae.train文件要求以30一份划分为9类,分别对应9个人不同发音类,即对应9人,每个人有一个矩阵30*12,添加一个属性tagClass(1-9),标志不同的类,即不同矩阵属于对应的类(1-9);
    C. 把测试样本(以370个为单位),把每个样本代入到以上9类(9个矩阵)计算欧几里德距离,取最小距离所在的类为样本归属类。
  5. 模型评估(Evaluation)
    (1)预测结果:运行结果如下图 ,包括文件读取和生成之类的,在最后一个main函数里面调用,用了1.407秒。
    《Java实现通过日语元音ae的发音曲线分类9个发音者》

(2) 结果评估:由于选取了每个块中的每维平均值做为该块该维的平均值,在数值上没问题,但忽略了该维中时间序列(7-29)间的顺序值特征,所以此问题是导致算法估计没有得到更高准确率的原因。
(3)算法改进:
第一步: 对每个分块,每一维分别建立时间序列(7-29)和对应的具体值的线性回归方程(y=kx+b),因为直线的斜率能反应分块时间序列变化对应的具体值的变化趋势,同时加了b后整个值能反映某维值范围。然后抽取整个块的每维值(k,b),则每个块能转换为list,list里面有1行,24列的矩阵,Eg:(k1,b1,k2,b2,k3,b3,k4,b4……….k12,b12)
第二步:把测试集370个样本也转换为370个list,然后算欧几里德距离。
例如:对应测试集(k1’,b1’,…………………….k12’,b12’)
计算距离:Distance = Math.sqrt(Math.pow((k1-k1’),2)+ Math.pow((b1-b1’),2))+….. +Math.sqrt(Math.pow((k12-k12’),2)+ Math.pow((b12-b12’),2));
然后取距离最小所在的类作为该测试集样本类,这个估计算法概率可以达到95%及以上。

(2) 算法实现:
A.项目框架
《Java实现通过日语元音ae的发音曲线分类9个发音者》

B.各类函数及作用分析
(本人觉得没有特别复杂的函数实现,故没复制代码解释 ,具体实现看项目代码)
 ReadWriteTest.java: 读取处理文件格式,把270块->270“行”->9个矩阵(加上类标,但独立保存每个矩阵对应的30行)
①writerTxt函数:
input:内容,路径 (把内容写到指定文件)
output:多个文件D://bigdata//test-270.txt,D://bigdata//train-9-30.txt,
②readTxt函数:
对原数据进行格式处理->1把270块转换为270行;2. 把270行分为9类,加上类标
intput:读的路径,flag 0,1分别对train,test做不同处理
output:多出2个txt文件 内容,test-270.txt,train-9-30
 SampleClassify.java: 测试样本,输出预测值
①mapSpeakers变量:
存储所有发音者类对应其行(每行是一个块的转换), key是发音者类,value是对应30个行(用二维数组存储)
②getSpeakerMatrix函数:初始化矩阵,30
13
③readTxtTrain函数:取train文件值,存储到mapSpeakers中
④readTxtTest函数:
读取test中370个sample,每个sample进行和9个类的距离计算,然后存在数组中,然后比较得到最小的,最小所在类即是该sample所属类(发音者)
⑤ getClassifyTag函数:
返回距离最近的那个类的标号:1-9之间 sample 是1-370块中的样本,是一个一维数组,长度13,第一位表示下标
 CheckoutCorrect.java: 验证正确率

①blockArr数组: 定义划分块,使方便能根据块输出samplId tagClass,
方便自己预测值于实际预测文件中值进行比较
②outputCompareTest:ae.train的结果通过size_ae.train划分,存储到文件compare.txt中,格式:sampleId tagClass
③predictionCorrect:比较两个文件内容,输出正确预测值的概率

具体代码参考bitbucket地址:bitbucket 原代码

    原文作者:Amyding929
    原文地址: https://segmentfault.com/a/1190000002584108
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞