随机森林实验报告Word下载.docx
- 文档编号:19219061
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:13
- 大小:95.49KB
随机森林实验报告Word下载.docx
《随机森林实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《随机森林实验报告Word下载.docx(13页珍藏版)》请在冰豆网上搜索。
例如对于某条记录,这26个二叉树的结果按序号排列为{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...1,0},那么这条记录的分类应该为25。
要将一个26维的0,1序列变回
一个索弓I,我们只需要找出这个序列中值最大的元素的索弓I,这个索引即是序列号。
我们将上面的26棵分别对26个索引做是否判断的二分类树视为一个整体,在多线程的
环境下,构造多个这样的整体,然后进行求和运算,最后取出每个结果序列中值最大的元素
的下标作为分类值,那么久得到了我们想要的结果,随机森林完成。
三.算法流程:
1.读入训练集trainset,测试集testset
2.将训练集分割为输入trainln,输出trainOut
3.这里假设类别数N为26,将trainOut[记录条数]映射为transformTrainOut[训练记录
数][26]
4.初始化transformTestOut[测试记录数][26]全部为0
i=1:
ForestSize:
策树
在这里,我们每一次26分类是由26棵CART共同完成的,CART的costfunction采
用的是gini系数,CART的最大层数为7分裂停止条件为当前节点GINI为0或者当前节点
所在层数到达了7.
2.随机森林
a.随机森林每次循环的训练集采样为原训练集的
b.对于森林中每一棵决策树每一次分割点的选取,对属性进行了打乱抽样,抽样数为
25,即每次分割只在25个属性中寻找最合适的值。
并且对于每个选取的属性,我们进行了行采样。
即如果这个属性所拥有的属性值数大于30,我们选取其中30个作为分割候选,如
果小于30,则全部纳入分割候选。
四•代码详解
1.训练集/测试集的读入
a.在中定义了:
寸crilw.ii;
I■ii-519A.]:
:
/,.-.!
1:
“-|-.
hdefina6239//100第燎他誌农
理afiiwtntwtNum//W试删记*•
'
■o:
c11n?
■pI.■■20:
1.■i
200,.O...-ir^.*.:
;
:
训练集记录列数numparametres(ID
(1)+参数数量(617)+输出
(1)=619)训练集记录条数transetNum
测试集记录条数testsetNum
分类类型数typesNum而在中,我们声明了全局变量
doubletrainlnf?
-|[-■】-一=-“=*1=7.-<
]•JI:
七■-
doubletr^inOut[-|[L]'
►double■-■■■■■■it][、-y.2];
|//..
|讨0ub|年testOutlteH辑tiMlimI;
"
淑怖供输出
IiMtrainlDLisetNumt//训Wife每一行记录的ID・進个看宴画慨兄也眾右谢攻肚
Lintte$tlD[tc3t$«
tNum];
1u[倉的【D
trainln用于装载训练集输入,trainOut用于装载训练集的输出(这里trainOut是二维数
组是出于模型如果泛化,那么输出值不一定只有一个的情况,在本次实验中并未派上什么真
正用场,可以将trainOut看作一个普通一维数组)。
trainID用于装载训练集中每一行的第
一列ID号。
testln,testlD则对应测试集的输入和ID号。
这里注意,没有testOut的原因
是测试集的结果理论上应该是不存在的。
然后通过自己编写的读入函数
readDataC'
train.csv'
\'
"
testcsv"
);
读入测试集合训练集,这个函数将分别装载我们在前面提到的trainin、trainOut、trainID
testIn、testID。
这个函数使用的fstream逐行读入的方法,这里不做详述。
2.训练集输出转化为对应的26维01数组transformOut[typesNum]
在中,我们定义了分类类别数typesNum:
在中,我们定义了全局变量transformOut[typesNum]
inttransformOutftrainsetNum][typesNum+1|=f0};
//类S!
l数
这里的transformOut是用于储存将trainOut每行的值映射为一行对应的26维01序列后所
产生的结果。
这里面的对应关系是:
例如trainOut[10]中的值是13那么transformOut[10][13]=
1,transformOut[10][除13外其他列]=0;
如果值是14,那么14列为1,其他列为0,行号代表的是它们对应的是第几条记录;
trainOut[10]和transformOut[10]都表示的是第
10行的分类值为某个值,只是表达方式不同。
前者用数字表示,后者将对应下标的值置1
表示。
转换接口由中的函数
定义,它的输入参数依次为转换输出的承接容器transformres,盛放原始输出的容器orges。
它所做的事情是将transformres[i][orges[i]]的值置1
3.并行构建随机森林
在中,我们构建了
doubletrainInPerTime[p:
rH丨严pm:
-:
-2]:
doubletrainlnPerTimeTlftN..r][2];
doubletrainJnPerTimeT2[?
r_ir^eNum][numparanne1re52LdoubletrainlnPerTimeT3|perTinneNum][numparamelres-2];
doubletrainInPerTimeT4[r_ir-eNwm][numparameires-2];
int1ransformOutPerlime[p&
rTiineNur][二_」…+1J={0|;
in:
transformOutPerTimeTlfperTimeNurn][type5Num+1)=(Qh
inttransformOutPerTimeT2[;
'
ii]|ivt-1)-(Q|;
inttransformOutPerTimeT3[perTimeNum)[typesNum+1|={0
inttransformOutPerTimeT4[TipesNi-m+1]={0};
doubletransformTestOutT1[:
estsetrml[t匚esNum+1]=(0hdoubletransformTestOutT2[testsetr丄\\pesNur+1]=(0doubletransformTestOirtTJIt^^rsetNn-r|(t/p^sNum+1]={0};
doubletransfcrmTestOutT4(tfstsetNu](typesNum+1](0};
trainlnperTime代表的是随机森林算法中经过采样步骤后选取的训练输入,
TransformOutPerTime代表的是与trainlnperTime对应的转换输出
transformtestOut是承接本支线程的所有CART树的决策值之和的结构,这与算法思路是对
应的,我们将所有CART树的预测结果在意个转换输出容器上累加,然后对于每行取该行最
大列的下标,即可得到由随机森林得到的分类结果。
我们可以看出,这几个变量都是只有最后的TX有区别,实际上,重复的创建相似的变量只
是为了方便多线程操作不会冲突。
多线程入口:
dvcjo-il&
tasd=Treel,
i.tt.i:
thread1(niainlnThitad.IransformOutPerTimeTl,trainlnPedimeTl,transformTeitOu订枚Tr舅Lj,
lscdthredd2[mjirJnThredd.lranjformOutPerTirr«
T2PtramlnPerTimeT2.t(ansformT«
tOdtT2P8iTree2\t---p.-.cthread3(mainhThread.TrsnjformOutPerTirneTi廿和巾“弘订咐韋T玄trantformTestOuxTJ,a(Tre#3);
t-cthread4;
mairJnThread..transformOutPerTimeT4..trainJnPerlimeT4,transformTestOdtT4r&
Tree4i;
这里使用的是C++11的<
thread>
库,简单好用。
每一个线程的随机森林框架定义在的
TRAIN.nlnPerTimeftransformOutPerTimertransfcrmTestOut.Tree);
中进行一轮决策树的训练,这一轮训练将会生成26棵CART树,对应26个分类值。
这里输
入的参数Tree就是我们所用的决策树容器,这里注意,我们一个线程中只需要公用一个决
策树结构即足够了
4.一轮训练26棵树
因为26棵CART树才能完整的等价于一棵26分类树,因此我们将构建这26棵CART树的过
程看成是一个整体。
这个过程由函数
TRAINf.iPerTimeftransformOutPerTimeFtransfcrmTestOutfTree);
,对应的转换训
实现。
它的输入依次是本轮的训练输入(经过了下采样,随机森林要求的)
练输出,以及一个决策树容器Tree。
决策树的定义我们将在下文中描述。
这个函数有一个栈
stack<
int>
trace;
//HJiiPi'
■"
■:
孃.这里曲门佚㈢:
]的星先根遍比
并且有一个从1:
26的循环
for(inttypesN=1;
typesN<
=:
ypesNum;
typesN十十){
每次循环会建立一棵关于对应的分类值得CART树,CART树的构造是由栈trace维护的,
trace维护的是一个先序的遍历顺序。
当循环完成后,将会计算本轮的转换输出结果的变更:
for(inti=0;
i<
testsetNur^i;
+ii){//testresPerTime[i][typesN]—Tree,computeRes(testln[i]);
transformlestOut[i][typesN]+二(*Tree).computeRes(testIn[i]);
5.每科CART树的构造
CART树的数据结构如下:
structd«
isionTree[
doubletrain[n[p«
rliiymNum][numparanwtrws*2];
in:
trainOutl],
Nod«
s(iI;
/ZU脚时K要便用的可用书竹至刁
in:
us,ableNod^
trainlntrainOut对应于输入该树的输入输出集,Nodes表示的是节点序列,在这里我们的
树的构造使用的是数组,且树的节点间的索引是通过索引值维护的,这颗树非常紧密(如果只看NODE是看不出节点间的层级关系的)
它有如下成员函数:
deciiicnTrwy:
|;
voidutD«
asionTr«
»
(doublttrainiIh_IJ[r^jmpirimvtnsboolgetPartiticmimindex,i'
itcontainer|]).
doublecomputeGini(irrtindex,ntlabel,doublevalue),/ydcublecomputeNcMieGini(intindex):
doubkcomputer■2]);
s/oidgetNodesSequ已rK贺[]};
打初始化風
;
Qidinitializef-'
o.uele)d
//5J于毎个菩点的一些磔件
voidgetNodeAttrfErtor<
irt>
selectedCols,intindex:
voidcomputePerNodeGini(intindex);
voidcomputeNodeValuetintindex);
J;
setDecisionTree用于给trainln和trainOut赋值
getNodeSequence(node1[])本来是用来输出节点参数的,这里不做详述initialize用于初始化决策树。
getNodeAttr用于得到某一节点的备选属性分割值
computePerNodeGini用于计算某一节点的GINI值,这在停止节点分割时有用
computeNodeValue是用于计算某一叶子节点的拟合值的。
我们再说一下Nodes节点,它的结构如下
veckgintAdMaliKfex;
/厝于袈该书点创数耗的容器
//rarie戒机就分簸
■-ctDdouble>
attributes!
wj;
intleftchildrightchild.
〃了节点的】ode*
intisLeaf;
//Q.A于山部书点,]
L裏示的部节凉
irit^phtLabel.
匚录当前的分割H性的位Hi
doublelabelvalue
doublevalue;
谏节,巨的平t勺悄.d亓
耳于拟台时的远君
intlayer;
用Ties所廿融
doublegini:
〃当前节总的GIN【怕
Attrbutes[selectedColumns]是用于存放候选的分割值的容器
其余变量的功能见图片中的文字注释
这里我们用dataIndex存放对应记录所在索引的方法取代了直接存放记录,这里是一个巨大
的改进,将程序的执行速度提高了至少10倍。
在构造一棵决策树时,当train函数对应的trace栈的栈顶非空时,我们会不断的取出栈顶元素,对其进行
boolgetPartitionOntindex,mtcontainer[|j;
.j/'
■■/JI
操作,Index指的是节点所在的索引值,container用于存放这个节点的左右叶子索引,由
于树的构建是由外部栈维护的,所以这个container是必不可少的,在当前节点分割完成后,
我们会将这个节点的索引值出栈,如果container[0]的值不是-1,我们会将
container[0],container[1]入栈。
建树的对应模块在下的train函数中的
trace.push(uj;
//树的初始化(插入头节点)完成后”正式尸始决策狗的构建while(Itrace,emptyO){
intcurrent_node-tracetop[);
trace.popO:
intcontainerf2]-{0};
(*Tree).getPartition(current_nodercontainer);
斯当前节点是否成功分割
if(gjnt引noJOj匚匚1){trace.push(container[l]);
trace,pusli(container[0]);
1
训练完成’计算输出
F面再重点说一下函数:
这个函数是单棵决策树构造的核心,调用这个函数,如果当前节点的
Gini值已经为0,那
么这个函数会计算当前节点的拟合值:
$1山爭丄:
世七imjj]]]Im
if(Nodes;
rHp;
0ni==0|Ncbdesfir-|layerJ..--||「-,-mr-:
一=:
■■)(
Nodes!
=1;
//UM叶干节点
doubleturn=0;
for■m:
i0;
Nod«
^[]datllndtxjiitQ;
*+i)(
轧》巾2帕1"
0叽凶讯电厂'
1.<
1航亦|4訶|]|;
■■■■■--I
I
NodesIiJt'
j.vjlueSuM/NCdvilmc:
IdatalndrM.^izrO,
conuinerlQI-CDntain«
r[L]■1;
retun
结束条件是gini==0||层数等于10
如果当前节点不满足结束分割条件,那么函数将对属性进行抽样,抽样的方法是打乱后取前
selectedColumns列。
然后调用getNodeAttr(s,index)获取当前节点的备选分割值,这里的s是抽取的属性的列号的集合。
/域得ITB后的寿I・幷选取前面盟25^^作为选职的列眄蠡引*传谨跆幻etAttr.载得所需栗的分裁侑.■'
rTr-<
■■->
sequence^'
t:
一or-crc;
-2);
srand{(Jn;
grcrvtime'
J):
for{i=0;
sequence,sizefl;
++i){
sequence[i].ind«
K=i;
s«
qutirKfl[i].valuerand^;
J
ltd:
sort(sequencebeginO,sequence.erid),.cmp);
for(iqti0;
iwStzCclu;
*^0(
s[i|3equflFKe[i]index,
)
d电tNo占电AttWMitid电乂丫
在得到备选的属性分割值后,将进入循环,寻找最优分割点
/,,rNocip-.]Indlek[grtA11ributi.
for(i■0,i<
St-eiIrjClum;
*+i){
■/r<
dpuble>
i4:
i-cursor
for(cursor=NodesLiddattributes[i]begrnO;
cursor>
=N©
d«
[d■attfibutes[i].endOi<
-+cur»
r){tenip_gini=computeGiiii(index.s[i[,'
cursor];
if(min_gini>
temp_gmi){
mingim=tempginiparlabel=s[i);
parvalue=Cursor;
6.最终结果计算
在main函数中,我们将四个线程所得的transformOutT相加,最后遍历取每一行最大值的
下标,即可得到最终结果。
五•算法优化
1.应用了数组+栈建树取代了普通的函数递归建树,加快了建树速度。
2.在传递每个节点的节点数据集时,使用了传递数据集的索引而非数据本身,这样做的好处
是,原来如果传递一条数据需要复制617个double类型的数量,而现在只需要传递一个Int型的索引,这种快了617倍的数据集传递方式使程序运行效率提高了10倍以上。
3.在每个属性中选择备选分割值的时候,采用了一种下采样的策略。
即:
如果该节点的数据
集大小小于某一数值,则将这个数据集的这个属性的所有值都纳入候选分割值列表。
但是如
果大于了这个阈值,则将属性所对应的列进行排序后再进行等间距采样得到样本数等于阈值
的子集作为候选分割集。
代码详见getPartition().这样做的好处是需要计算的分割gini
值大大减少了(本人取的采样阈值时100,相比原数据集,样本空间缩小了尽30倍),这里
也再一次加速了程序运行。
但是这个优化随机而来的一个问题是:
有可能每次分割都不是最
佳分割。
4.使用了C++11的<thread>库进行了并行实现,开出4个线程,程序相比单线程加速了4
倍。
六•并行实现
C++11<thread>库创建线程,为每个线程赋予独立的数据容器,并将随机森林分成等量的4
部分(因为我使用的是4个线程)。
即,每个线程中执行的函数承担1/4规模的随机森林的
构造,实现代码如下:
t仆」lthread1imainlliThread.rtsformOutPerTumeTl,.trainlnP^rTinrieTLtranificiirmT«
tOutTlb&
Tree1J;
n”thread2(mainrriThread.transformOutPerTurneT2,trsairuInFerTirneTi..tran&
forimTwtOutTS.&
Tree2);
…i-」lthread3imamirThread.tranj5f
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 随机 森林 实验 报告