使用神经网络进行词性标注
在有了第一个版本的network的基础上,我们将output层修改为softmax,改掉原来使用的sigmoid。代码修改完之后却发现运行的时候报出overflow的错误,在纠结了许久之后,在导师的帮助下,发现了程序的两个bug:一个是softmax的激活函数,分子上的e次方忘记了加;另外一个就是在feedforward的过程中,把hidden layer的activation直接输出到softmax()中,没有使用z = w * a + b。代码的错误还是很无语的,总结:千万不要在头脑昏昏的时候敲代码,越敲越乱。下面对使用了softmax作为output layer的神经网络做一个准确率的总结。
对hidden layer神经元数量的调参
hidden layer neuron数量 | 最好的正确率(mini batch size = 10, eta = 4.0) | best epoch |
---|---|---|
50 | 81.86% | 85 |
60 | 82.29% | 124 |
70 | 81.73% | 100 |
80 | 82.28% | 138 |
90 | 82.50% | 109 |
100 | 81.17% | 105 |
注:–表示结果还没有跑出来
这里的结果是偏低的,因为我首先调参的是hidden layer neuron的数量,没有首先调试c(eta)的值。
我使用小数据量的数据进行过粗略的测试(2000个training_data,300个test_data),当eta = 0.1(上述表格中的eta = 4.0)的时候,准确率就可以达到81%.
当我使用全部数据进行测试的时候,结果就可以达到89.67%,程序还没有跑完。等三个超参数全部调试完,我想结果应该可以上90%。
对c(eta)的调参
c | 最好的正确率(mini batch size = 10, hidden layer neuron数量 = 60) | best epoch |
---|---|---|
0.0001 | 90.79% | 491 |
0.0005 | 91.13% | 107 |
0.001 | 90.93% | 52 |
0.005 | 90.82% | 24 |
0.01 | 90.60% | 17 |
0.05 | 90.44% | 21 |
0.1 | 89.95% | 60 |
1.0 | 87.81% | 117 |
2.0 | 84.07% | 81 |
3.0 | 82.12% | 109 |
4.0 | 78.37% | 63 |
5.0 | 75.52% | 53 |
总结:因为首先调试的参数hidden layer,但是结果并不是很好,所以此处我们对c调参,然后根据c的结果,下一步对hidden layer neuron数目进行调参。
从结果我们可以看到,当c = 0.001的时候,结果是最好的。所以,下面我们就是用c = 0.001对hidden layer neuron数目进行调参
2016.1.11补充
在发现c = 0.001还有增长空间的时候,我们又进行了两个测试,发现当c = 0.0005的时候,正确率是最高的,等于91.13%
对hidden layer neuron数目的调参
hidden layer neuron数量 | 最好的正确率(mini batch size = 10, eta = 0.001) | best epoch |
---|---|---|
40 | 90.66% | 80 |
50 | 90.86% | 65 |
60 | 91.22% | 62 |
70 | 91.24% | 43 |
80 | 91.52% | 50 |
90 | 91.75% | 43 |
100 | 91.93% | 37 |
110 | 91.98%(eta = 0.0005) | 83 |
120 | 92.07%(eta = 0.0005) | 88 |
130 | 92.06%(eta = 0.0005) | 80 |
为什么表格最后三个的eta和上述的eta不一样呢,因为在上面的hidden layer neuron数目进行测试的时候,我并没有测试当eta = 0.0001 和eta = 0.0005的情况,当我测试完成之后,我发现当eta = 0.0005的时候,测试出来的准确率是最高的,所以,在我发现当hidden layer neuron数目 > 100的时候,仍然有增长空间的时候,我就进行第二轮测试,使用eta = 0.0005的hyper parameter。经过测试我们发现,当hidden layer neuron数目 = 120的时候,得到的正确率是最好的92.07%
对mini batch size的调参
mini batch size | 最好的正确率(hidden layer neuron数目 = 120, eta = 0.0005) | best epoch |
---|---|---|
5 | 90.38% | 68 |
10 | 90.65% | 23 |
15 | 90.85% | 22 |
20 | 90.99% | 13 |
30 | 91.35% | 3 |
40 | 91.32% | 5 |
50 | 91.57% | 5 |
额,貌似有一点问题,为什么在eta = 0.0005的时候,最好的正确率反而不如当eta = 0.001的时候呢?有必要用eta = 0.001的时候再测试一遍。。。
增加了tanh激活函数后的粗略调参
eta | 最好的正确率(hidden layer neuron数目 = 120, mini batch size = 10) | best epoch |
---|---|---|
0.001 | 91.70% | 17 |
0.01 | 90.98% | 6 |
0.1 | 89.88% | 69 |
1.0 | 79.15% | 123 |
2.0 | 68.98% | 41 |
3.0 | 68.73% | 107 |
5.0 | 62.35% | 66 |
从这个里面我们可以看出来,我们添加了tanh激活函数之后,进行了粗调,eta的准确率还是可以上升的,因为我不想把太多的时间放在这个上面,所以并没有继续调试下去,等待以后network完成以后,再进行细调。
增加了dropout和adagrad的网络调参 (2016-1-14 更新)
其他参数的情况:hidden layer neuron number = 120, mini batch size = 10, without L2 regularization
eta | 最好的正确率/best epoch (dropout, adagrad) | no dropout, adagrad | dropout, no adagrad | no dropout, no adagrad |
---|---|---|---|---|
0.0001 | 77.03%/393 | —– | 88.78%/84 | 92.04%/98 |
0.0005 | 88.08%/363 | —– | 89.14%/38 | 91.85%/24 |
0.001 | 89.51%/366 | —– | 89.63%/35 | 91.88%/16 |
0.005 | 90.91%/185 | —– | 89.69%/17 | 91.38%/2 |
0.05 | 88.49%/84 | —– | ||
0.01 | 90.93%/128 | —– | 89.66%/33 | 91.08%/5 |
0.1 | 87.42%/109 | —– | 87.46%/39 | 89.72%/44 |
1.0 | 85.57%/253 | —– | 72.67%/55 | 75.73%/57 |
不要在意eta的次序~~
2016-1-17更新 调整了一下hidden-layer-neuron数目,然后发现
由于目前卡在了添加了dropout这部分,各种改正发现效果并不好,然后今天晚间突然有个想法,试试调整一下hidden-layer-neuron数目试试看,然后将hidden-layer-neuron的数目调整到了240,然后神奇的事情发生了,正确率居然提高了,提高了还不少,就目前来看,比当hidden-layer-neuron = 120的时候好,将目前的数据记录如下(程序还没有跑完)
eta | 最好的正确率/best epoch(dropout each input, no adagrad) | (dropout each batch, no adagrad) |
---|---|---|
0.1 | 84.29%/29 | |
0.01 | 89.51%/25 | 89.16%/24 |
0.05 | 87.11%/46 | 86.68%/30 |
0.001 | 91.12%/33 | 90.95%/59 |
0.005 | 90.28%/25 | 90.25%/31 |
0.0001 | 90.29%/103 | |
0.0005 | 91.14%/60 | 91.09%/66 |
根据以上的数据,我觉得,实现的dropout可能是正确的,但是参数需要重新调试,那么问题来了,是不是每次加入一个新的方法,并且当需要看一下准确率的时候,我们都需要进行调参?
tanh, softmax, dropout神经网络对hidden layer neuron数目调参
因为上述得到的结果,是否使用dropout的时候,hidden layer neuron的数目对正确率有比较重要的影响,所以在此对hidden layer neuron进行调参,看看结果有何影响。
hidden layer neuron数目 | 最好的正确率/best epoch(eta = 0.001, mini batch size = 10) |
---|---|
240 | 91.13%/34 |
260 | 91.35%/57 |
280 | 91.39%/47 |
300 | 91.47%/56 |
320 | 91.55%/49(中断) |
350 | 91.51%/24(中断) |
380 | 91.62%/22(中断) |
400 | 91.61%/22(中断) |
中断的原因是,我们发现,dropout的实现是没有错的,但是在本实验中,效果不佳,我们决定弃用。
2016-1-19更新,对tanh激活函数,softmax output layer神经网络对adagrad的测试
eta | 最好的正确率/best epoch(hidden layer neuron number = 120, mini batch size = 10) |
---|---|
1.0 | 87.84%/103 |
0.1 | 88.82%/17 |
0.5 | 88.16%/99 |
0.01 | 91.96%/19 |
0.05 | 89.53%/19 |
0.001 | 91.81%/402 |
0.005 | 92.05%/57 |
0.0001 | 86.28%/499 |
0.0005 | 91.23%/487 |
mini batch size | 最好的正确率/best epoch(hidden layer neuron number = 240, eta = 0.01) |
---|---|
1 | 92.21%/9 |
5 | 92.46%/12 |
10 | 92.33%/17 |
20 | 92.35%/13 |
50 | 92.52/%12 |
2016-1-24更新,regularization
昨天离开实验室之前,将regularization加入到神经网络中去,简单的测试了一下,但是效果好像并不太好,可能因为需要重新调参的原因,也有可能我们的任务并不需要regularization,现将测试的一些结果记录下来,以备使用
因为代码有一点点问题,以下是错误的数据,不删了,就放在这个地方吧
lambda | 最好的正确率/best epoch(hidden layer neuron number = 240, mini batch size = 50, eta = 0.01) |
---|---|
1 | 91.99%/19 |
1e-3 | 91.89%/14 |
1e-4 | 91.85%/31 |
1e-5 | 91.86%/21 |
1e-6 | 92.06%/16 |
由此可见,增加regularization可能和dropout一样,并没有什么显著的用处,所以我接下的工作就是增加更新input layer的功能
2016-1-25更新
今天测试了以下regularization,将相关的数据记录下来(每一个实例使用regularization)
lambda | 最好的正确率/best epoch(hidden layer neuron number = 240, mini batch size = 50, eta = 0.01) |
---|---|
1 | 92.39%/9 |
1e-1 | 92.54%/19 |
1e-2 | 92.50%/12 |
1e-3 | 92.53%/12 |
1e-4 | 92.40%/8 |
1e-5 | 92.40%/7 |
1e-6 | 92.27%/11 |
由此可见,当lambda = 1e-1的时候,准确率可以达到92.54%,是目前最好的准确率
如果对每一个batch,进行一次regularization,效果如何?
lambda | 最好的正确率/best epoch(hidden layer neuron number = 240, mini batch size = 50, eta = 0.01) |
---|---|
1 | 92.60%/9 |
1e-1 | 92.51%/11 |
1e-2 | 92.39%/12 |
1e-3 | 92.60%/13 |
1e-4 | 92.52%/15 |
1e-5 | 92.36%/7 |
1e-6 | 92.66%/14 |
我们可以从这一组数据当中看出来,我们的准确率可以达到更到!当lambda = 1e-6的时候,我们的准确率可以达到92.66%,这个是目前最好的正确率
2016-1-24下午更新,今天老冷啊,冻死宝宝了
找到bug在什么地方了,在读取数据的时候,有一个数组是用来存放所有的vector的,可以根据词所在的下标index,查找到词所对应的vector,在进行前两个词的index定位的时候,我把左边一个词的index,l_index写成了i_index,找了半天才发现这个错误。其实我对这个错误老早就有了防范之心,在初始化ll_index,l_index,等index的时候,我把这些值都赋值为-1,这样子,如果有一个值没有被赋值成功,或者错位什么的,应该跑程序的时候,会报错的啊,但是呢,老夫忘了,python里面-1代表一个数组的最后一个元素!!!那怎么办呢,随便赋值一个比数组长度长的就好了,或者无穷大。
2016-2-22中午更新
因为博客放在实验室的台式机上面,放假的时间就没有更新,现在将update x的相关测试补充一下,我们可以看到,准确率达到了93.08%
lambda | 最好的正确率/best epoch(hidden layer neuron number = 240, mini batch size = 50, eta = 0.01) |
---|---|
1 | 93.08%/22 |
1e-1 | 93.05%/22 |
1e-3 | 92.86%/22 |
1e-4 | 92.90%/26 |
1e-5 | 92.95%/19 |
1e-6 | 92.99%/13 |
因为之前测试的时候,都是使用的测试集(train),应该使用开发集(dev),现在我使用开发集做测试,试试效果如何:
lambda | 最好的正确率/best epoch(hidden layer neuron number = 240, mini batch size = 50, eta = 0.01) |
---|---|
1 | 92.87%/14 |
1e-1 | 92.62%/13 |
1e-2 | 92.73%/43 |
1e-3 | 92.75%/20 |
1e-4 | 92.57%/15 |
1e-5 | 92.78%/17 |
1e-6 | 92.73%/14 |
从结果我们看到,使用dev进行测试的结果比使用test的结果要低一点,我是这么认为的,因为dev(25029)的数据量比test(33228)的数据量要小。