forked from exacity/deeplearningbook-chinese
-
Notifications
You must be signed in to change notification settings - Fork 1
/
sequence_modeling_rnn.tex
1262 lines (1082 loc) · 95.7 KB
/
sequence_modeling_rnn.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% !Mode:: "TeX:UTF-8"
% Translator: Shenjian Zhao
\chapter{序列建模:循环和递归网络}
\label{chap:sequence_modeling_recurrent_and_recursive_nets}
\firstgls{RNN}或~\glssymbol{RNN}~\citep{RHW}是一类用于处理序列数据的\gls{NN}。
就像\gls{convolutional_network}是专门用于处理网格化数据$\TSX$(如一个图像)的\gls{NN},\gls{RNN}是专门用于处理序列$\Vx^{(1)}, \dots, \Vx^{(\tau)}$的\gls{NN}。
正如\gls{convolutional_network}可以很容易地扩展到具有很大宽度和高度的图像,以及处理大小可变的图像,\gls{recurrent_network}可以扩展到更长的序列(比不基于序列的特化网络长得多)。
大多数\gls{recurrent_network}也能处理可变长度的序列。
从多层网络出发到\gls{recurrent_network},我们需要利用上世纪80年代\gls{ML}和统计模型早期思想的优点:在模型的不同部分共享参数。
\gls{parameter_sharing}使得模型能够扩展到不同形式的样本(这里指不同长度的样本)并进行泛化。
如果我们在每个时间点都有一个单独的参数,我们不但不能泛化到训练时没有见过序列长度,也不能在时间上共享不同序列长度和不同位置的统计强度。
当信息的特定部分会在序列内多个位置出现时,这样的共享尤为重要。
例如,考虑这两句话:``I went to Nepal in 2009''和``In 2009, I went to Nepal.''
如果我们让一个\gls{ML}模型读取这两个句子,并提取叙述者去\ENNAME{Nepal}的年份,无论``2009年''是作为句子的第六个单词还是第二个单词出现,我们都希望模型能认出``2009年''作为相关资料片段。
假设我们要训练一个处理固定长度句子的\gls{feedforward_network}。
传统的全连接\gls{feedforward_network}会给每个输入特征分配一个单独的参数,所以需要分别学习句子每个位置的所有语言规则。
相比之下,\gls{RNN}在几个\gls{time_step}内共享相同的权重,不需要分别学习句子每个位置的所有语言规则。
% -- 363 --
一个相关的想法是在1维时间序列上使用卷积。
这种卷积方法是\gls{TDNNs}的基础\citep{Lang+Hinton88,Waibel89b,lang1990time}。
卷积操作允许网络跨时间共享参数,但是浅层的。
卷积的输出是一个序列,其中输出中的每一项是相邻几项输入的函数。
\gls{parameter_sharing}的概念体现在每个\gls{time_step}中使用的相同卷积核。
\gls{RNN}以不同的方式共享参数。
输出的每一项是前一项的函数。
输出的每一项对先前的输出应用相同的更新规则而产生。
这种循环方式导致参数通过很深的\gls{computational_graph}共享。
为简单起见,我们说的~\glssymbol{RNN}~是指在序列上的操作,并且该序列在时刻$t$(从1到$\tau$)包含向量$\Vx^{(t)}$。
在实际情况中,\gls{recurrent_network}通常在序列的\gls{minibatch}上操作,并且\gls{minibatch}的每项具有不同序列长度$\tau$。
我们省略了\gls{minibatch}索引来简化记号。
此外,\gls{time_step}索引不必是字面上现实世界中流逝的时间。
有时,它仅表示序列中的位置。
\glssymbol{RNN}~也可以应用于跨越两个维度的空间数据(如图像)。
当应用于涉及时间的数据,并且将整个序列提供给网络之前就能观察到整个序列时,该网络可具有关于时间向后的连接。
本章将\gls{computational_graph}的思想扩展到包括循环。
这些周期代表变量自身的值在未来某一\gls{time_step}对自身值的影响。
这样的\gls{computational_graph}允许我们定义\gls{RNN}。
然后,我们描述许多构建、训练和使用\gls{RNN}的不同方式。
本章将简要介绍\gls{RNN},为获取更多详细信息,我们建议读者参考~\cite{Graves-book2012}的著作。
% -- 364 --
\section{\glsentrytext{unfolding}\glsentrytext{computational_graph}}
\label{sec:unfolding_computational_graphs}
\gls{computational_graph}是形式化一组计算结构的方式,如那些涉及将输入和参数映射到输出和损失的计算。
综合的介绍请参考\secref{sec:computational_graphs}。
本节,我们对\firstgls{unfolding}递归或循环计算得到的重复结构进行解释,这些重复结构通常对应于一个事件链。
\firstgls{unfolding}这个计算图将导致深度网络结构中的\gls{parameter_sharing}。
例如,考虑动态系统的经典形式:
\begin{align}
\label{eq:101s}
\Vs^{(t)} = f(\Vs^{(t-1)}; \Vtheta),
\end{align}
其中$ \Vs^{(t)}$称为系统的状态。
$\Vs$在时刻$t$的定义需要参考时刻$t-1$时同样的定义,因此\eqnref{eq:101s}是循环的。
对有限\gls{time_step}~$\tau$, $\tau-1$次应用这个定义可以展开这个图。
例如$\tau = 3$,我们对\eqnref{eq:101s}展开,可以得到:
\begin{align}
\Vs^{(3)} &= f(\Vs^{(2)}; \Vtheta) \\
& = f(f(\Vs^{(1)}; \Vtheta) ; \Vtheta).
\label{eq:103s}
\end{align}
以这种方式重复应用定义,\gls{unfolding}等式,就能得到不涉及循环的表达。
现在我们可以使用传统的有向无环\gls{computational_graph}呈现这样的表达。
\eqnref{eq:101s}和\eqnref{eq:103s}的\gls{unfolding}\gls{computational_graph}如\figref{fig:chap10_unfolded_dynsys}所示。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/unfolded_dynsys}}
\fi
\caption{将\eqnref{eq:101s}描述的经典动态系统表示为展开的计算图。
每个节点表示在某个时刻$t$的状态,并且函数$f$将$t$处的状态映射到$t+1$处的状态。
所有\gls{time_step}都使用相同的参数(用于参数化$f$的相同$\Vtheta$值)。
}
\label{fig:chap10_unfolded_dynsys}
\end{figure}
% -- 365 --
作为另一个例子,让我们考虑由外部信号$\Vx^{(t)}$驱动的动态系统,
\begin{align}
\label{eq:104s}
\Vs^{(t)} = f(\Vs^{(t-1)}, \Vx^{(t)} ; \Vtheta),
\end{align}
我们可以看到,当前状态包含了整个过去序列的信息。
\gls{RNN}可以通过许多不同的方式建立。
就像几乎所有函数都可以被认为是\gls{feedforward_network},本质上任何涉及循环的函数都可以被认为是一个\gls{RNN}。
很多\gls{RNN}使用\eqnref{eq:105h}或类似的公式定义\gls{hidden_unit}的值。
为了表明状态是网络的\gls{hidden_unit},我们使用变量$\Vh$代表状态重写\eqnref{eq:104s}:
\begin{align}
\label{eq:105h}
\Vh^{(t)} = f(\Vh^{(t-1)}, \Vx^{(t)} ; \Vtheta),
\end{align}
如\figref{fig:chap10_rnn_circuit_unfolded}所示,典型~\glssymbol{RNN}~会增加额外的架构特性,如读取状态信息$\Vh$进行预测的输出层。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/rnn_circuit_unfolded}}
\fi
\caption{没有输出的\gls{recurrent_network}。
此\gls{recurrent_network}只处理来自输入$\Vx$的信息,将其合并到经过时间向前传播的状态$\Vh$。
\emph{(左)}回路原理图。 黑色方块表示单个\gls{time_step}的延迟。
\emph{(右)}同一网络被视为展开的计算图,其中每个节点现在与一个特定的时间实例相关联。
}
\label{fig:chap10_rnn_circuit_unfolded}
\end{figure}
当训练\gls{recurrent_network}根据过去预测未来时,网络通常要学会使用$\Vh^{(t)}$作为过去序列(直到$t$)与任务相关方面的有损摘要。
此摘要一般而言一定是有损的,因为其映射任意长度的序列$(\Vx^{(t)},\Vx^{(t-1)}, \Vx^{(t-2)},\dots,\Vx^{(2)}, \Vx^{(1)})$到一固定长度的向量$\Vh^{(t)}$。
根据不同的训练\gls{criterion},摘要可能选择性地精确保留过去序列的某些方面。
例如,如果在统计语言建模中使用的~\glssymbol{RNN},通常给定前一个词预测下一个词,可能没有必要存储时刻$t$前输入序列中的所有信息;而仅仅存储足够预测句子其余部分的信息。
最苛刻的情况是我们要求$\Vh^{(t)}$足够丰富,并能大致恢复输入序列,如\gls{AE}框架(\chapref{chap:autoencoders})。
% -- 366 --
\eqnref{eq:105h}可以用两种不同的方式来绘制。
一种绘制~\glssymbol{RNN}~的方式是用循环图,对于可能存在于模型的物理实现中的每个组件,都在图中包含其对应的节点。这种方式的一个示例是生物神经网络。
在这种视角下,网络定义了实时操作的回路,如\figref{fig:chap10_rnn_circuit_unfolded}的左侧,其当前状态可以影响其未来的状态。
在本章中,我们使用回路图中的黑色方块表示单个\gls{time_step}延时所发生的交互,即从时刻$t$的状态到时刻$t+1$的状态的变化。
另一种绘制~\glssymbol{RNN}~的方式是用展开的\gls{computational_graph},其中每一个组件由许多不同的变量表示,每个\gls{time_step}一个变量,用来表示组件在该时间点的状态。
每个\gls{time_step}的每个变量绘制为\gls{computational_graph}的一个独立节点,如\figref{fig:chap10_rnn_circuit_unfolded}的右侧。
我们所说的\gls{unfolding}是将左图中的回路映射为右图中包含重复组件的\gls{computational_graph}的操作。
这样,\gls{unfolded_graph}的大小取决于序列长度。
我们可以用一个函数$g^{(t)}$代表经$t$步展开后的循环:
\begin{align}
\label{eq:106}
\Vh^{(t)} &=g^{(t)}(\Vx^{(t)},\Vx^{(t-1)}, \Vx^{(t-2)},\dots,\Vx^{(2)}, \Vx^{(1)}) \\
& = f(\Vh^{(t-1)}, \Vx^{(t)} ; \Vtheta) .
\end{align}
函数$g^{(t)}$将全部的过去序列$(\Vx^{(t)},\Vx^{(t-1)}, \Vx^{(t-2)},\dots,\Vx^{(2)}, \Vx^{(1)})$作为输入来生成当前状态,但是展开的循环架构允许我们将$g^{(t)}$分解为函数$f$的重复应用。
因此,展开过程引入两个主要优点:
\begin{enumerate}
\item 无论序列的长度,学成的模型始终具有相同的输入大小,因为它指定的是从一种状态到另一种状态的\gls{transition}, 而不是在可变长度的历史状态上操作。
\item 我们可以在每个\gls{time_step}使用相同参数的\emph{相同}\gls{transition}函数$f$。
\end{enumerate}
这两个因素使得学习在所有\gls{time_step}和所有序列长度上操作单一的模型$f$是可能的,而不需要在所有可能\gls{time_step}学习独立的模型$g^{(t)}$。
学习单一的共享模型允许泛化到没有见过的序列长度(没有出现在训练集中),并且估计模型所需的训练样本远远少于不带\gls{parameter_sharing}的模型。
% -- 367 --
无论是循环图和\gls{unfolded_graph}都有其用途。
循环图简洁。
\gls{unfolded_graph}能够明确描述其中的计算流程。
\gls{unfolded_graph}还通过显式的信息流动路径帮助说明信息在时间上向前(计算输出和损失)和向后(计算\gls{gradient})的思想。
\section{\glsentrytext{RNN}}
\label{sec:recurrent_neural_networks}
基于\secref{sec:unfolding_computational_graphs}中的图展开和\gls{parameter_sharing}的思想,我们可以设计各种\gls{RNN}。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/hidden_recurrence_rnn}}
\fi
\caption{计算\gls{recurrent_network}(将$\Vx$值的输入序列映射到输出值$\Vo$的对应序列)训练损失的计算图。
损失$L$衡量每个$\Vo$与相应的训练目标$\Vy$的距离。
当使用softmax输出时,我们假设$\Vo$是未归一化的对数概率。
损失$L$内部计算$\hat{\Vy} = \text{softmax}(\Vo)$,并将其与目标$\Vy$比较。
\glssymbol{RNN}输入到隐藏的连接由权重矩阵$\MU$参数化,隐藏到隐藏的循环连接由权重矩阵$\MW$参数化以及隐藏到输出的连接由权重矩阵$\MV$参数化。
\eqnref{eq:108a}定义了该模型中的前向传播。
\emph{(左)}使用循环连接绘制的~\glssymbol{RNN}~和它的损失。
\emph{(右)}同一网络被视为展开的计算图,其中每个节点现在与一个特定的时间实例相关联。
}
\label{fig:chap10_hidden_recurrence_rnn}
\end{figure}
\gls{RNN}中一些重要的设计模式包括以下几种:
\begin{enumerate}
\item 每个\gls{time_step}都有输出,并且\gls{hidden_unit}之间有循环连接的\gls{recurrent_network},如\figref{fig:chap10_hidden_recurrence_rnn}所示。
\item 每个\gls{time_step}都产生一个输出,只有当前时刻的输出到下个时刻的\gls{hidden_unit}之间有循环连接的\gls{recurrent_network},如\figref{fig:chap10_output_recurrence_rnn}所示。
\item \gls{hidden_unit}之间存在循环连接,但读取整个序列后产生单个输出的\gls{recurrent_network},如\figref{fig:chap10_single_output_rnn}所示。
\end{enumerate}
\figref{fig:chap10_hidden_recurrence_rnn}是非常具有代表性的例子,我们将会在本章大部分涉及这个例子。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/output_recurrence_rnn}}
\fi
\caption{此类~\glssymbol{RNN}~的唯一循环是从输出到隐藏层的反馈连接。
在每个\gls{time_step}~$t$,输入为$\Vx_t$,\gls{hidden_layer}激活为$\Vh^{(t)}$,输出为$\Vo^{(t)}$,目标为$\Vy^{(t)}$,损失为$L^{(t)}$。
\emph{(左)}回路原理图。
\emph{(右)}展开的计算图。
这样的~\glssymbol{RNN}~没有\figref{fig:chap10_hidden_recurrence_rnn}表示的RNN那样强大(只能表示更小的函数集合)。
\figref{fig:chap10_hidden_recurrence_rnn}中的~\glssymbol{RNN}~可以选择将其想要的关于过去的任何信息放入隐藏表示$\Vh$中并且将$\Vh$传播到未来。
该图中的~\glssymbol{RNN}~被训练为将特定输出值放入$\Vo$中,并且$\Vo$是允许传播到未来的唯一信息。
此处没有从$\Vh$前向传播的直接连接。
之前的$\Vh$仅通过产生的预测间接地连接到当前。
$\Vo$通常缺乏过去的重要信息,除非它非常高维且内容丰富。
这使得该图中的~\glssymbol{RNN}~不那么强大,但是它更容易训练,因为每个\gls{time_step}可以与其他\gls{time_step}分离训练,允许训练期间更多的并行化,如\secref{sec:teacher_forcing_and_networks_with_output_recurrence}所述。
}
\label{fig:chap10_output_recurrence_rnn}
\end{figure}
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/single_output_rnn}}
\fi
\caption{关于时间展开的\gls{RNN},在序列结束时具有单个输出。
这样的网络可以用于概括序列并产生用于进一步处理的固定大小的表示。
在结束处可能存在目标(如此处所示),或者通过更下游模块的反向传播来获得输出$\Vo^{(t)}$上的梯度。
}
\label{fig:chap10_single_output_rnn}
\end{figure}
任何图灵可计算的函数都可以通过这样一个有限维的\gls{recurrent_network}计算,在这个意义上\figref{fig:chap10_hidden_recurrence_rnn}和\eqnref{eq:108a}的\gls{RNN}是万能的。
\glssymbol{RNN}~经过若干\gls{time_step}后读取输出,这与由图灵机所用的\gls{time_step}是渐近线性的,与输入长度也是渐近线性的\citep{Siegelmann+Sontag-1991,Siegelmann-1995,Siegelmann+Sontag-1995,Hyotyniemi-1996}。
由图灵机计算的函数是离散的,所以这些结果都是函数的具体实现,而不是近似。
\glssymbol{RNN}~作为图灵机使用时,需要一个二进制序列作为输入,其输出必须离散化以提供二进制输出。
利用单个有限大小的特定~\glssymbol{RNN}~计算在此设置下的所有函数是可能的(~\cite{Siegelmann+Sontag-1995}用了886个单元)。
图灵机的``输入''是要计算函数的详细说明(specification),所以模拟此图灵机的相同网络足以应付所有问题。
用于证明的理论~\glssymbol{RNN}~可以通过激活和权重(由无限精度的有理数表示)来模拟无限堆栈。
% -- 368 --
现在我们研究\figref{fig:chap10_hidden_recurrence_rnn}中~\glssymbol{RNN}~的\gls{forward_propagation}公式。
这个图没有指定\gls{hidden_unit}的激活函数。
我们假设使用双曲正切激活函数。
此外,图中没有明确指定何种形式的输出和\gls{loss_function}。
我们假定输出是离散的,如用于预测词或字符的~\glssymbol{RNN}。
表示离散变量的常规方式是把输出$\Vo$作为每个离散变量可能值的非标准化对数概率。
然后,我们可以应用~\gls{softmax}~后续处理后,获得标准化后概率的输出向量$\hat \Vy$。
\glssymbol{RNN}~从特定的初始状态$\Vh^{(0)}$开始\gls{forward_propagation}。
从$t= 1$到$t = \tau$的每个\gls{time_step},我们应用以下更新方程:
\begin{align}
\label{eq:108a}
\Va^{(t)} &= \Vb + \MW \Vh^{(t-1)} + \MU \Vx^{(t)}, \\
\Vh^{(t)} &= \tanh(\Va^{(t)} ), \\
\Vo^{(t)} &= \Vc + \MV \Vh^{(t)}, \\
\hat \Vy^{(t)} &= \text{softmax}(\Vo^{(t)}),
\end{align}
其中的参数的\gls{bias_aff}向量$\Vb$和$\Vc$连同权重矩阵$\MU$、$\MV$和$\MW$,分别对应于输入到隐藏、隐藏到输出和隐藏到隐藏的连接。
这个\gls{recurrent_network}将一个输入序列映射到相同长度的输出序列。
与$\Vx$序列配对的$\Vy$的总损失就是所有\gls{time_step}的损失之和。
例如,$L^{(t)}$为给定的$\Vx^{(1)}, \dots, \Vx^{(t)}$后$\Vy^{(t)}$的负对数似然,则
\begin{align} \label{eq:1012L}
& L\big( \{ \Vx^{(1)}, \dots, \Vx^{(\tau)} \}, \{ \Vy^{(1)}, \dots, \Vy^{(\tau)} \} \big) \\
& = \sum_t L^{(t)} \\
& = - \sum_t \log p_{\text{model}} \big( y^{(t)} \mid \{ \Vx^{(1)}, \dots, \Vx^{(t)} \} \big) ,
\end{align}
其中$p_{\text{model}} \big( y^{(t)} \mid \{ \Vx^{(1)}, \dots, \Vx^{(t)} \} \big) $需要读取模型输出向量$\hat \Vy^{(t)}$中对应于$y^{(t)}$的项。
关于各个参数计算这个\gls{loss_function}的\gls{gradient}是计算成本很高的操作。
\gls{gradient}计算涉及执行一次\gls{forward_propagation}(如在\figref{fig:chap10_hidden_recurrence_rnn}\gls{unfolded_graph}中从左到右的传播),接着是由右到左的\gls{backward_propagation}。
运行时间是$\CalO(\tau)$,并且不能通过并行化来降低,因为\gls{forward_propagation}图是固有循序的;每个\gls{time_step}只能一前一后地计算。
\gls{forward_propagation}中的各个状态必须保存,直到它们\gls{backward_propagation}中被再次使用,因此内存代价也是$\CalO(\tau)$。
应用于\gls{unfolded_graph}且代价为$\CalO(\tau)$的\gls{backward_propagation}算法称为\firstall{BPTT},将在\secref{sec:computing_the_gradient_in_a_recurrent_neural_network}进一步讨论。
因此\gls{hidden_unit}之间存在循环的网络非常强大但训练代价也很大。
我们是否有其他选择呢?
% -- 371 --
\subsection{\glsentrytext{teacher_forcing}和输出\glsentrytext{recurrent_network}}
\label{sec:teacher_forcing_and_networks_with_output_recurrence}
仅在一个\gls{time_step}的输出和下一个\gls{time_step}的\gls{hidden_unit}间存在循环连接的网络(示于\figref{fig:chap10_output_recurrence_rnn})确实没有那么强大(因为缺乏隐藏到隐藏的循环连接)。
例如,它不能模拟通用图灵机。
因为这个网络缺少隐藏到隐藏的循环,它要求输出单元捕捉用于预测未来的关于过去的所有信息。
因为输出单元明确地训练成匹配训练集的目标,它们不太能捕获关于过去输入历史的必要信息,除非用户知道如何描述系统的全部状态,并将它作为训练目标的一部分。
消除隐藏到隐藏循环的优点在于,任何基于比较时刻$t$的预测和时刻$t$的训练目标的\gls{loss_function}中的所有\gls{time_step}都解耦了。
因此训练可以并行化,即在各时刻$t$分别计算\gls{gradient}。
因为训练集提供输出的理想值,所以没有必要先计算前一时刻的输出。
由输出反馈到模型而产生循环连接的模型可用\firstgls{teacher_forcing}进行训练。
\gls{teacher_forcing}一个源自于最大似然\gls{criterion}的过程,在训练模型时的时刻$t+1$接收真实值$y^{(t)}$作为输入。
我们可以通过检查两个\gls{time_step}的序列得知这一点。
条件最大似然\gls{criterion}是
\begin{align}
&\log p(\Vy^{(1)},\Vy^{(2)} \mid \Vx^{(1)}, \Vx^{(2)} ) \\
&= \log p(\Vy^{(2)} \mid \Vy^{(1)}, \Vx^{(1)}, \Vx^{(2)} ) + \log p(\Vy^{(1)} \mid \Vx^{(1)}, \Vx^{(2)}) .
\end{align}
% -- 372 --
在这个例子中,\emph{同时}给定迄今为止的$\Vx$序列和来自训练集的前一$\Vy$值,我们可以看到在时刻$t=2$时,模型被训练为最大化$\Vy^{(2)}$的条件概率。
因此最大似然在训练时指定正确反馈,而不是将自己的输出反馈到模型。
如\figref{fig:chap10_teacher_forcing}所示。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/teacher_forcing}}
\fi
\caption{\gls{teacher_forcing}的示意图。
\gls{teacher_forcing}是一种训练技术,适用于输出与下一\gls{time_step}的隐藏状态存在连接的~\glssymbol{RNN}。
\emph{(左)}训练时,我们将训练集中\emph{正确}的输出$\Vy^{(t)}$反馈到$\Vh^{(t+1)}$。
\emph{(右)}当模型部署后,真正的输出通常是未知的。
在这种情况下,我们用模型的输出$\Vo^{(t)}$近似正确的输出$\Vy^{(t)}$,并反馈回模型。
}
\label{fig:chap10_teacher_forcing}
\end{figure}
我们使用\gls{teacher_forcing}的最初动机是为了在缺乏隐藏到隐藏连接的模型中避免\gls{BPTT}。
只要模型一个\gls{time_step}的输出与下一\gls{time_step}计算的值存在连接,\gls{teacher_forcing}仍然可以应用到这些存在隐藏到隐藏连接的模型。
然而,只要\gls{hidden_unit}成为较早\gls{time_step}的函数,\glssymbol{BPTT}~算法是必要的。
因此训练某些模型时要同时使用\gls{teacher_forcing}和~\glssymbol{BPTT}。
% -- 373 --
如果之后网络在\textbf{开环}(open-loop)模式下使用,即网络输出(或输出分布的样本)反馈作为输入,那么完全使用\gls{teacher_forcing}进行训练的缺点就会出现。
在这种情况下,训练期间该网络看到的输入与测试时看到的会有很大的不同。
减轻此问题的一种方法是同时使用\gls{teacher_forcing}和自由运行的输入进行训练,例如在展开循环的输出到输入路径上预测几个步骤的正确目标值。
通过这种方式,网络可以学会考虑在训练时没有接触到的输入条件(如自由运行模式下,自身生成自身),以及将状态映射回使网络几步之后生成正确输出的状态。
另外一种方式\citep{SamyBengio-et-al-arxiv2015}是通过随意选择生成值或真实的数据值作为输入以减小训练时和测试时看到的输入之间的差别。
这种方法利用了\gls{curriculum_learning}策略,逐步使用更多生成值作为输入。
\subsection{计算\glsentrytext{RNN}的\glsentrytext{gradient}}
\label{sec:computing_the_gradient_in_a_recurrent_neural_network}
计算\gls{RNN}的\gls{gradient}是容易的。
我们可以简单地将\secref{sec:general_back_propagation}中的推广\gls{backward_propagation}算法应用于展开的\gls{computational_graph},而不需要特殊化的算法。
由\gls{backward_propagation}计算得到的\gls{gradient},并结合任何通用的基于\gls{gradient}的技术就可以训练~\glssymbol{RNN}。
为了获得~\glssymbol{BPTT}~算法行为的一些直观理解,我们举例说明如何通过~\glssymbol{BPTT}~计算上述\glssymbol{RNN}公式(\eqnref{eq:108a}和\eqnref{eq:1012L})的\gls{gradient}。
\gls{computational_graph}的节点包括参数$\MU,\MV,\MW, \Vb$和$\Vc$,以及以$t$为索引的节点序列$\Vx^{(t)}, \Vh^{(t)},\Vo^{(t)}$和$L^{(t)}$。
对于每一个节点$\TSN$,我们需要基于$\TSN$后面的节点的\gls{gradient},递归地计算\gls{gradient}~$\nabla_{\TSN} L$。
我们从紧接着最终损失的节点开始递归:
\begin{align}
\frac{\partial L}{\partial L^{(t)}} = 1.
\end{align}
在这个导数中,我们假设输出$\Vo^{(t)}$作为~\gls{softmax}~的参数,我们可以从~\gls{softmax}可以获得关于输出概率的向量$\hat{\Vy}$。
我们也假设损失是迄今为止给定了输入后的真实目标$y^{(t)}$的负对数似然。
对于所有$i,t$,关于\gls{time_step}~$t$输出的\gls{gradient}~$\nabla_{\Vo^{(t)}} L$如下:
\begin{align}
(\nabla_{\Vo^{(t)}} L)_i = \frac{\partial L}{\partial o_i^{(t)}}
= \frac{\partial L}{\partial L^{(t)}} \frac{\partial L^{(t)}}{\partial o_i^{(t)}}
= \hat y_i^{(t)} - \mathbf{1}_{i,y^{(t)}}.
\end{align}
我们从序列的末尾开始,反向进行计算。
在最后的\gls{time_step}~$\tau$, $\Vh^{(\tau)}$只有$\Vo^{(\tau)}$作为后续节点,因此这个\gls{gradient}很简单:
\begin{align}
\nabla_{\Vh^{(\tau)}} L = \MV^\top \nabla_{\Vo^{(\tau)}} L.
\end{align}
然后,我们可以从时刻$t=\tau-1$到$t=1$反向迭代, 通过时间\gls{backward_propagation}\gls{gradient},注意$\Vh^{(t)}(t < \tau)$同时具有$\Vo^{(t)}$和$\Vh^{(t+1)}$两个后续节点。
因此,它的\gls{gradient}由下式计算
\begin{align}
\nabla_{\Vh^{(t)}} L = \Big( \frac{\partial \Vh^{(t+1)}}{ \partial \Vh^{(t)}} \Big)^\top(\nabla_{\Vh^{(t+1)}} L)
+ \Big( \frac{\partial \Vo^{(t)}}{ \partial \Vh^{(t)}} \Big)^\top (\nabla_{\Vo^{(t)}} L) \\
= \MW^\top (\nabla_{\Vh^{(t+1)}} L) \text{diag} \Big( 1 - (\Vh^{(t+1)})^2 \Big)
+ \MV^\top ( \nabla_{\Vo^{(t)}} L ),
\end{align}
其中$\text{diag} \Big( 1 - (\Vh^{(t+1)})^2 \Big) $ 表示包含元素$1 - (h_i^{(t+1)})^2$的对角矩阵。
这是关于时刻$t+1$与\gls{hidden_unit}~$i$关联的双曲正切的\gls{jacobian}。
% -- 374 --
一旦获得了\gls{computational_graph}内部节点的\gls{gradient},我们就可以得到关于参数节点的\gls{gradient}。
因为参数在许多\gls{time_step}共享,我们必须在表示这些变量的微积分操作时谨慎对待。
我们希望实现的等式使用\secref{sec:general_back_propagation}中的{\tt bprop}方法计算\gls{computational_graph}中单一边对\gls{gradient}的贡献。
然而微积分中的$\nabla_{\MW} f$算子,计算$\MW$对于$f$的贡献时将\gls{computational_graph}中的\emph{所有}边都考虑进去了。
为了消除这种歧义,我们定义只在$t$时刻使用的虚拟变量$\MW^{(t)}$作为$\MW$的副本。
然后,我们可以使用$\nabla_{\MW^{(t)}}$表示权重在\gls{time_step}~$t$对\gls{gradient}的贡献。
使用这个表示,关于剩下参数的\gls{gradient}可以由下式给出:
\begin{align}
\nabla_{\Vc} L &= \sum_t \Big( \frac{\partial \Vo^{(t)}}{\partial \Vc} \Big)^\top \nabla_{\Vo^{(t)}} L
= \sum_t \nabla_{\Vo^{(t)}} L ,\\
\nabla_{\Vb} L &= \sum_t \Big( \frac{\partial \Vh^{(t)}}{\partial \Vb^{(t)}} \Big)^\top \nabla_{\Vh^{(t)}} L
= \sum_t \text{diag} \Big( 1 - \big( \Vh^{(t)} \big)^2 \Big) \nabla_{\Vh^{(t)}} L ,\\
\nabla_{\MV} L &= \sum_t \sum_i \Big( \frac{\partial L} {\partial o_i^{(t)}}\Big) \nabla_{\MV} o_i^{(t)}
= \sum_t (\nabla_{\Vo^{(t)}} L) \Vh^{(t)^\top},\\
\nabla_{\MW} L &= \sum_t \sum_i \Big( \frac{\partial L} {\partial h_i^{(t)}}\Big)
\nabla_{\MW^{(t)}} h_i^{(t)} \\
&= \sum_t \text{diag} \Big( 1 - \big( \Vh^{(t)} \big)^2 \Big) ( \nabla_{\Vh^{(t)}} L) \Vh^{(t-1)^\top} ,\\
\nabla_{\MU} L &= \sum_t \sum_i \Big( \frac{\partial L} {\partial h_i^{(t)}}\Big)
\nabla_{\MU^{(t)}} h_i^{(t)} \\
&= \sum_t \text{diag} \Big( 1 - \big( \Vh^{(t)} \big)^2 \Big) ( \nabla_{\Vh^{(t)}} L) \Vx^{(t)^\top} ,
\end{align}
因为\gls{computational_graph}中定义的损失的任何参数都不是训练数据$\Vx^{(t)}$的父节点,所以我们不需要计算关于它的\gls{gradient}。
% -- 375 --
\subsection{作为\glsentrytext{directed_graphical_model}的\glsentrytext{recurrent_network}}
\label{sec:recurrent_networks_as_directed_graphical_models}
目前为止,我们接触的\gls{recurrent_network}例子中损失$L^{(t)}$是训练目标$\Vy^{(t)}$和输出$\Vo^{(t)}$之间的\gls{cross_entropy}。
与\gls{feedforward_network}类似,原则上\gls{recurrent_network}几乎可以使用任何损失。
但必须根据任务来选择损失。
如\gls{feedforward_network},我们通常希望将~\glssymbol{RNN}~的输出解释为一个概率分布,并且我们通常使用与分布相关联的\gls{cross_entropy}来定义损失。
均方误差是与单位高斯分布的输出相关联的\gls{cross_entropy}损失,例如\gls{feedforward_network}中所使用的。
当我们使用一个预测性对数似然的训练目标,如\eqnref{eq:1012L},我们将~\glssymbol{RNN}~训练为能够根据之前的输入估计下一个序列元素$\Vy^{(t)}$的条件分布。
这可能意味着,我们最大化对数似然
\begin{align}
\log p(\Vy^{(t)} \mid \Vx^{(1)},\dots, \Vx^{(t)}),
\end{align}
或者,如果模型包括来自一个\gls{time_step}的输出到下一个\gls{time_step}的连接,
\begin{align}
\log p(\Vy^{(t)} \mid \Vx^{(1)},\dots, \Vx^{(t)},\Vy^{(1)},\dots, \Vy^{(t-1)} ).
\end{align}
将整个序列$\Vy$的联合分布分解为一系列单步的概率预测是捕获关于整个序列完整联合分布的一种方法。
当我们不把过去的$\Vy$值反馈给下一步作为预测的条件时,那么\gls{directed_graphical_model}不包含任何从过去$\Vy^{(i)}$到当前$\Vy^{(t)}$的边。
在这种情况下,给定x序列后,输出的y值之间条件独立。%在这种情况下,输出$\Vy$与给定的$\Vx$序列是条件独立的。%
当我们反馈真实的$\Vy$值(不是它们的预测值,而是真正观测到或生成的值)给网络时,那么\gls{directed_graphical_model}包含所有从过去$\Vy^{(i)}$到当前$\Vy^{(t)}$的边。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/fully_connected_chain}}
\fi
\caption{序列$y^{(1)},y^{(2)},\dots,y^{(t)},\dots$的全连接\gls{graphical_model}。
给定先前的值,每个过去的观察值$y^{(i)}$可以影响一些$y^{(t)}$($t>i$)的条件分布。
当序列中每个元素的输入和参数的数目越来越多,根据此图直接参数化\gls{graphical_model}(如\eqnref{eq:106}中)可能是非常低效的。
\glssymbol{RNN}~可以通过高效的参数化获得相同的全连接,如\figref{fig:chap10_rnn_graphical_model_with_state}所示。
}
\label{fig:chap10_fully_connected_chain}
\end{figure}
% -- 376 --
举一个简单的例子,让我们考虑对标量随机变量序列$ \SetY = \{\RSy^{(1)},\dots,\RSy^{(\tau)}\}$建模的~\glssymbol{RNN},也没有额外的输入$\RSx$。
在\gls{time_step}~$t$的输入仅仅是\gls{time_step}~$t-1$的输出。
该~\glssymbol{RNN}~定义了关于$\RSy$变量的\gls{directed_graphical_model}。
我们使用链式法则(用于条件概率的\eqnref{eq:chap3_chain_rule})参数化这些观察值的联合分布:
\begin{align}
P(\SetY) = P(\RVy^{(1)},\dots,\RVy^{(\tau)}) = \prod_{t=1}^{\tau}P(\RVy^{(t)} \mid \RVy^{(t-1)},\RVy^{(t-2)},
\dots,\RVy^{(1)}),
\end{align}
其中当$t=1$时竖杠右侧显然为空。
因此,根据这样一个模型,一组值$\{y^{(1)},\dots,y^{(\tau)} \}$的负对数似然为
\begin{align}
L = \sum_{t} L^{(t)},
\end{align}
其中
\begin{align}
L^{(t)} = -\log P(\RSy^{(t)} = y^{(t)} \mid y^{(t-1)},y^{(t-2)}, \dots, y^{(1)}).
\end{align}
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/rnn_graphical_model_with_state}}
\fi
\caption{在~\glssymbol{RNN}~\gls{graphical_model}中引入状态变量,尽管它是输入的确定性函数,但它有助于我们根据\eqnref{eq:105h}获得非常高效的参数化。
序列中的每个阶段(对于$\Vh^{(t)}$和$\Vy^{(t)}$)使用相同的结构(每个节点具有相同数量的输入),并且可以与其他阶段共享相同的参数。
}
\label{fig:chap10_rnn_graphical_model_with_state}
\end{figure}
\gls{graphical_model}中的边表示哪些变量直接依赖于其他变量。
许多\gls{graphical_model}的目标是省略不存在强相互作用的边以实现统计和计算的效率。
例如,我们通常可以作\ENNAME{Markov}假设,即\gls{graphical_model}应该只包含从$\{ \RSy^{(t-k)}, \dots, \RSy^{(t-1)}\}$到$\RSy^{(t)}$的边,而不是包含整个过去历史的边。
然而,在一些情况下,我们认为整个过去的输入会对序列的下一个元素有一定影响。
当我们认为$\RSy^{(t)}$的分布可能取决于遥远过去(在某种程度)的$\RSy^{(i)}$的值,且无法通过$\RSy^{(t-1)}$捕获$\RSy^{(i)}$的影响时,\glssymbol{RNN}~将会很有用。
解释~\glssymbol{RNN}~作为\gls{graphical_model}的一种方法是将\glssymbol{RNN}视为定义一个结构为完全图的\gls{graphical_model},且能够表示任何一对$\RSy$值之间的直接联系。
\figref{fig:chap10_fully_connected_chain}是关于$\RSy$值且具有完全图结构的\gls{graphical_model}。
该~\glssymbol{RNN}~完全图的解释基于排除并忽略模型中的\gls{hidden_unit}~$\Vh^{(t)}$。
% -- 377 --
更有趣的是,将\gls{hidden_unit}~$\Vh^{(t)}$视为随机变量,从而产生~\glssymbol{RNN}~的\gls{graphical_model}结构\footnote{给定这些变量的父变量,其条件分布是确定性的。
尽管设计具有这样确定性的\gls{hidden_unit}的\gls{graphical_model}是很少见的,但这是完全合理的。}。
在\gls{graphical_model}中包括隐藏单元预示~\glssymbol{RNN}~能对观测的联合分布提供非常有效的参数化。
假设我们用表格表示法来表示离散值上任意的联合分布,即对每个值可能的赋值分配一个单独条目的数组,该条目表示发生该赋值的概率。
如果$y$可以取$k$个不同的值,表格表示法将有$\CalO(k^\tau)$个参数。
对比~\glssymbol{RNN},由于\gls{parameter_sharing},\glssymbol{RNN}~的参数数目为$\CalO(1)$且是序列长度的函数。 % ??
我们可以调节~\glssymbol{RNN}~的参数数量来控制模型容量,但不用被迫与序列长度成比例。
\eqnref{eq:105h}展示了所述~\glssymbol{RNN}~通过循环应用相同的函数$f$以及在每个\gls{time_step}的相同参数$\Vtheta$,有效地参数化的变量之间的长期联系。
\figref{fig:chap10_rnn_graphical_model_with_state}说明了这个\gls{graphical_model}的解释。
在\gls{graphical_model}中结合$\Vh^{(t)}$节点可以用作过去和未来之间的中间量,从而将它们解耦。
遥远过去的变量$y^{(i)}$可以通过其对$\Vh$的影响来影响变量$y^{(t)}$。
该图的结构表明可以在\gls{time_step}使用相同的条件概率分布有效地参数化模型,并且当观察到全部变量时,可以高效地评估联合分配给所有变量的概率。
% -- 378 --
即便使用高效参数化的\gls{graphical_model},某些操作在计算上仍然具有挑战性。
例如,难以预测序列中缺少的值。
\gls{recurrent_network}为减少的参数数目付出的代价是\emph{优化}参数可能变得困难。
在\gls{recurrent_network}中使用的\gls{parameter_sharing}的前提是相同参数可用于不同\gls{time_step}的假设。
也就是说,假设给定时刻$t$的变量后,时刻$t +1$变量的条件概率分布是\firstgls{stationary},这意味着之前的\gls{time_step}与下个\gls{time_step}之间的关系并不依赖于$t$。
原则上,可以使用$t$作为每个\gls{time_step}的额外输入,并让学习器在发现任何时间依赖性的同时,在不同\gls{time_step}之间尽可能多地共享。
相比在每个$t$使用不同的条件概率分布已经好很多了,但网络将必须在面对新$t$时进行推断。
为了完整描述将~\glssymbol{RNN}~作为\gls{graphical_model}的观点,我们必须描述如何从模型采样。
我们需要执行的主要操作是简单地从每一\gls{time_step}的条件分布采样。
然而,这会导致额外的复杂性。
\glssymbol{RNN}~必须有某种机制来确定序列的长度。
这可以通过多种方式实现。
在当输出是从词汇表获取的符号的情况下,我们可以添加一个对应于序列末端的特殊符号\citep{schmidhuber2012self}。
当产生该符号时,采样过程停止。
在训练集中,我们将该符号作为序列的一个额外成员,即紧跟每个训练样本$\Vx^{(\tau)}$之后。
% -- 379 --
另一种选择是在模型中引入一个额外的~\ENNAME{Bernoulli}~输出,表示在每个\gls{time_step}决定继续生成或停止生成。
相比向词汇表增加一个额外符号,这种方法更普遍,因为它适用于任何~\glssymbol{RNN},而不仅仅是输出符号序列的~\glssymbol{RNN}。
例如,它可以应用于一个产生实数序列的~\glssymbol{RNN}。
新的输出单元通常使用~\ENNAME{sigmoid}~单元,并通过\gls{cross_entropy}训练。
在这种方法中,\ENNAME{sigmoid}~被训练为最大化正确预测的对数似然,即在每个\gls{time_step}序列决定结束或继续。
确定序列长度$\tau$的另一种方法是将一个额外的输出添加到模型并预测整数$\tau$本身。
模型可以采出$\tau$的值,然后采$\tau$步有价值的数据。
这种方法需要在每个\gls{time_step}的循环更新中增加一个额外输入,使得循环更新知道它是否是靠近所产生序列的末尾。
这种额外的输入可以是$\tau$的值,也可以是$\tau - t$即剩下\gls{time_step}的数量。
如果没有这个额外的输入,\glssymbol{RNN}~可能会产生突然结束序列,如一个句子在最终完整前结束。
此方法基于分解
\begin{align}
P(\Vx^{(1)},\dots, \Vx^{(\tau)}) = P(\tau) P(\Vx^{(1)},\dots,\Vx^{(\tau)} \mid \tau) .
\end{align}
直接预测$\tau$的例子见\cite{Goodfellow+et+al-ICLR2014a}。
\subsection{基于上下文的~\glssymbol{RNN}~序列建模}
\label{sec:modeling_sequences_conditioned_on_context_with_rnns}
上一节描述了没有输入$\Vx$时,关于随机变量序列$y^{(t)}$的\glssymbol{RNN}如何对应于\gls{directed_graphical_model}。
当然,如\eqnref{eq:108a}所示的\glssymbol{RNN}包含一个输入序列$\Vx^{(1)},\Vx^{(2)},\dots,\Vx^{(\tau)}$。
一般情况下,\glssymbol{RNN}~允许将\gls{graphical_model}的观点扩展到不仅代表$y$变量的联合分布也能表示给定$\Vx$后$y$条件分布。
如在\secref{sec:learning_conditional_distributions_with_maximum_likelihood}的\gls{feedforward_network}情形中所讨论的,任何代表变量$P(\Vy;\Vtheta)$的模型都能被解释为代表条件分布$P(\Vy \mid \Vomega)$的模型,其中$\Vomega=\Vtheta$。
我们能像之前一样使用$P(\Vy \mid \Vomega)$代表分布$P(\Vy \mid \Vx)$来扩展这样的模型,但要令$\Vomega$是关于$\Vx$的函数。
在~\glssymbol{RNN}~的情况,这可以通过不同的方式来实现。
此处,我们回顾最常见和最明显的选择。
% -- 380 --
之前,我们已经讨论了将$t =1, \dots, \tau$的向量$\Vx^{(t)}$序列作为输入的~\glssymbol{RNN}。
另一种选择是只使用单个向量$\Vx$作为输入。
当$\Vx$是一个固定大小的向量时,我们可以简单地将其看作产生$\Vy$序列~\glssymbol{RNN}~的额外输入。
将额外输入提供到~\glssymbol{RNN}~的一些常见方法是:
\begin{enumerate}
\item 在每个时刻作为一个额外输入,或
\item 作为初始状态$\Vh^{(0)}$,或
\item 结合两种方式。
\end{enumerate}
第一个也是最常用的方法如\figref{fig:chap10_conditional_rnn}所示。
输入$\Vx$和每个隐藏单元向量$\Vh^{(t)}$之间的相互作用是通过新引入的权重矩阵$\MR$参数化的,这是只包含$y$序列的模型所没有的。
同样的乘积$\Vx^\top\MR$在每个\gls{time_step}作为\gls{hidden_unit}的一个额外输入。
我们可以认为$\Vx$的选择(确定$\Vx^\top\MR$值),是有效地用于每个\gls{hidden_unit}的一个新\gls{bias_aff}参数。
权重与输入保持独立。
我们可以认为这种模型采用了非条件模型的$\Vtheta$,并将$\Vomega$代入$\Vtheta$,其中$\Vomega$内的\gls{bias_aff}参数现在是输入的函数。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/conditional_rnn}}
\fi
\caption{将固定长度的向量$\Vx$映射到序列$\MY$上分布的~\glssymbol{RNN}。
这类~\glssymbol{RNN}~适用于很多任务如图注,其中单个图像作为模型的输入,然后产生描述图像的词序列。
观察到的输出序列的每个元素$\Vy^{(t)}$同时用作输入(对于当前\gls{time_step})和训练期间的目标(对于前一\gls{time_step})。
}
\label{fig:chap10_conditional_rnn}
\end{figure}
% -- 381 --
\glssymbol{RNN}~可以接收向量序列$\Vx^{(t)}$作为输入,而不是仅接收单个向量$\Vx$作为输入。
\eqnref{eq:108a}描述的~\glssymbol{RNN}~对应条件分布$P(\Vy^{(1)}, \dots, \Vy^{(\tau)} \mid \Vx^{(1)}, \dots, \Vx^{(\tau)})$,并在条件独立的假设下这个分布分解为
\begin{align}
\prod_t P(\Vy^{(t)} \mid \Vx^{(1)}, \dots, \Vx^{(t)}).
\end{align}
为去掉条件独立的假设,我们可以在时刻$t$的输出到时刻$t+1$的\gls{hidden_unit}添加连接,如\figref{fig:chap10_causal_rnn}所示。
该模型就可以代表关于$\Vy$序列的任意概率分布。
这种给定一个序列表示另一个序列分布的模型的还是有一个限制,就是这两个序列的长度必须是相同的。
我们将在\secref{sec:encoder_decoder_sequence_to_sequence_architectures}描述如何消除这种限制。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/causal_rnn}}
\fi
\caption{将可变长度的$\Vx$值序列映射到相同长度的$\Vy$值序列上分布的条件\gls{RNN}。
对比\figref{fig:chap10_hidden_recurrence_rnn},此~\glssymbol{RNN}~包含从前一个输出到当前状态的连接。
这些连接允许此\glssymbol{RNN}对给定$\Vx$的序列后相同长度的$\Vy$序列上的任意分布建模。
\figref{fig:chap10_hidden_recurrence_rnn}的~\glssymbol{RNN}~仅能表示在给定$\Vx$值的情况下,$\Vy$值彼此条件独立的分布。
}
\label{fig:chap10_causal_rnn}
\end{figure}
% -- 382 --
\section{双向~\glssymbol{RNN}}
\label{sec:bidirectional_rnns}
目前为止我们考虑的所有\gls{RNN}有一个``因果''结构,意味着在时刻$t$的状态只能从过去的序列$\Vx^{(1)},\dots,\Vx^{(t-1)}$以及当前的输入$\Vx^{(t)}$捕获信息。
我们还讨论了某些在$\Vy$可用时,允许过去的$\Vy$值信息影响当前状态的模型。
然而,在许多应用中,我们要输出的$\Vy^{(t)}$的预测可能依赖于整个输入序列。
例如,在语音识别中,由于协同发音,当前声音作为音素的正确解释可能取决于未来几个音素,甚至潜在的可能取决于未来的几个词,因为词与附近的词之间的存在语义依赖:如果当前的词有两种声学上合理的解释,我们可能要在更远的未来(和过去)寻找信息区分它们。
这在手写识别和许多其他序列到序列学习的任务中也是如此,将会在下一节中描述。
双向\gls{RNN}(或双向~\glssymbol{RNN})为满足这种需要而被发明\citep{Schuster+Paliwal-1997}。
他们在需要双向信息的应用中非常成功\citep{Graves-book2012},如手写识别\citep{Graves-et-al-NIPS2007,Graves+Schmidhuber-2009},语音识别\citep{Graves+Schmidhuber-2005,Graves-et-al-ICASSP2013}以及生物信息学\citep{Baldi-et-al-1999}。
顾名思义,双向~\glssymbol{RNN}~结合时间上从序列起点开始移动的~\glssymbol{RNN}~和另一个时间上从序列末尾开始移动的~\glssymbol{RNN}。
\figref{fig:chap10_bidirectional_rnn}展示了典型的双向~\glssymbol{RNN},其中$\Vh^{(t)}$代表通过时间向前移动的子~\glssymbol{RNN}~的状态,$\Vg^{(t)}$代表通过时间向后移动的子~\glssymbol{RNN}~的状态。
这允许输出单元$\Vo^{(t)}$能够计算同时依赖于过去和未来且对时刻$t$的输入值最敏感的表示,而不必指定$t$周围固定大小的窗口(这是\gls{feedforward_network}、\gls{convolutional_network}或具有固定大小的先行缓存器的常规~\glssymbol{RNN}~所必须要做的)。
% -- 383 --
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/bidirectional_rnn}}
\fi
\caption{典型的双向\gls{RNN}中的计算,意图学习将输入序列$\Vx$映射到目标序列$\Vy$(在每个步骤$t$具有损失$L^{(t)}$)。
循环性$\Vh$在时间上向前传播信息(向右),而循环性$\Vg$在时间上向后传播信息(向左)。
因此在每个点$t$,输出单元$\Vo^{(t)}$可以受益于输入$\Vh^{(t)}$中关于过去的相关概要以及输入$\Vg^{(t)}$中关于未来的相关概要。
}
\label{fig:chap10_bidirectional_rnn}
\end{figure}
这个想法可以自然地扩展到2维输入,如图像,由\emph{四个}~\glssymbol{RNN}~组成,每一个沿着四个方向中的一个计算:上、下、左、右。
如果~\glssymbol{RNN}~能够学习到承载长期信息,那在2维网格每个点$(i, j)$的输出$O_{i,j}$就能计算一个能捕捉到大多局部信息但仍依赖于长期输入的表示。
相比\gls{convolutional_network},应用于图像的~\glssymbol{RNN}~计算成本通常更高,但允许同一特征图的特征之间存在长期横向的相互作用\citep{Visin-et-al-arxiv2015-renet,kalchbrenner2015grid}。
实际上,对于这样的~\glssymbol{RNN},\gls{forward_propagation}公式可以写成表示使用卷积的形式,计算自底向上到每一层的输入(在整合横向相互作用的特征图的循环传播之前)。
% -- 384 --
\section{基于编码-解码的序列到序列架构}
\label{sec:encoder_decoder_sequence_to_sequence_architectures}
我们已经在\figref{fig:chap10_single_output_rnn}看到\glssymbol{RNN}如何将输入序列映射成固定大小的向量,在\figref{fig:chap10_conditional_rnn}中看到\glssymbol{RNN}如何将固定大小的向量映射成一个序列,在\figref{fig:chap10_hidden_recurrence_rnn}、\figref{fig:chap10_output_recurrence_rnn}、\figref{fig:chap10_causal_rnn}和\figref{fig:chap10_bidirectional_rnn}中看到\glssymbol{RNN}如何将一个输入序列映射到等长的输出序列。
本节我们讨论如何训练\glssymbol{RNN},使其将输入序列映射到不一定等长的输出序列。
这在许多场景中都有应用,如语音识别、机器翻译或问答,其中训练集的输入和输出序列的长度通常不相同(虽然它们的长度可能相关)。
我们经常将\glssymbol{RNN}的输入称为``上下文''。
我们希望产生此上下文的表示,$C$。
这个上下文$C$可能是一个概括输入序列$\MX=(\Vx^{(1)},\dots,\Vx^{(n_x)})$的向量或者向量序列。
用于映射可变长度序列到另一可变长度序列最简单的\glssymbol{RNN}架构最初由\cite{cho-al-emnlp14}提出,之后不久由\cite{Sutskever-et-al-NIPS2014}独立开发,并且第一个使用这种方法获得翻译的最好结果。
前一系统是对另一个机器翻译系统产生的建议进行评分,而后者使用独立的\gls{recurrent_network}生成翻译。
这些作者分别将该架构称为编码-解码或序列到序列架构,如\figref{fig:chap10_rnn_encdec}所示。
这个想法非常简单:(1)\firstgls{encoder}或\,\textbf{读取器}\,(reader)或\,\textbf{输入}(input)~\glssymbol{RNN}~处理输入序列。
\gls{encoder}输出上下文$C$(通常是最终隐藏状态的简单函数)。
(2)\firstgls{decoder}或\,\textbf{写入器}(writer)或\,\textbf{输出}(output)~\glssymbol{RNN}~则以固定长度的向量(如\figref{fig:chap10_conditional_rnn})为条件产生输出序列$\MY=(\Vy^{(1)}, \dots, \Vy^{(n_y)})$。
这种架构对比本章前几节提出的架构的创新之处在于长度$n_x$和$n_y$可以彼此不同,而之前的架构约束$n_x = n_y = \tau$。
在序列到序列的架构中,两个~\glssymbol{RNN}~共同训练以最大化$\log P( \Vy^{(1)}, \dots, \Vy^{(n_y)} \mid \Vx^{(1)},\dots,\Vx^{(n_x)} )$(关于训练集中所有$\Vx$和$\Vy$对的平均)。
\gls{encoder}~\glssymbol{RNN}~的最后一个状态$\Vh_{n_x}$通常被当作输入的表示$C$并作为\gls{decoder}~\glssymbol{RNN}~的输入。
% -- 385 --
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/rnn_encdec}}
\fi
\caption{在给定输入序列$(\RVx^{(1)},\RVx^{(2)},\dots,\RVx^{(n_x)})$的情况下学习生成输出序列$(\RVy^{(1)},\RVy^{(2)},\dots,\RVy^{(n_y)})$的\gls{encoder}-\gls{decoder}或序列到序列的~\glssymbol{RNN}~架构的示例。
它由读取输入序列的\gls{encoder}~\glssymbol{RNN}~以及生成输出序列(或计算给定输出序列的概率)的\gls{decoder}~\glssymbol{RNN}~组成。
\gls{encoder}~\glssymbol{RNN}~的最终隐藏状态用于计算一般为固定大小的上下文变量$C$,$C$表示输入序列的语义概要并且作为\gls{decoder}~\glssymbol{RNN}~的输入。
}
\label{fig:chap10_rnn_encdec}
\end{figure}
如果上下文$C$是一个向量,则\gls{decoder}~\glssymbol{RNN}~只是在\secref{sec:modeling_sequences_conditioned_on_context_with_rnns}描述的向量到序列~\glssymbol{RNN}。
正如我们所见,向量到序列~\glssymbol{RNN}~至少有两种接受输入的方法。
输入可以被提供为~\glssymbol{RNN}~的初始状态,或连接到每个\gls{time_step}中的\gls{hidden_unit}。
这两种方式也可以结合。
这里并不强制要求\gls{encoder}与\gls{decoder}的隐藏层具有相同的大小。
此架构的一个明显不足是,\gls{encoder}~\glssymbol{RNN}~输出的上下文$C$的维度太小而难以适当地概括一个长序列。
这种现象由\cite{Bahdanau-et-al-ICLR2015-small}在机器翻译中观察到。
他们提出让$C$成为可变长度的序列,而不是一个固定大小的向量。
此外,他们还引入了将序列$C$的元素和输出序列的元素相关联的\firstgls{attention_mechanism}。
读者可在\secref{sec:using_an_attention_mechanism_and_aligning_pieces_of_data}了解更多细节。
% -- 386 --
\section{深度\glsentrytext{recurrent_network}}
\label{sec:deep_recurrent_networks}
大多数~\glssymbol{RNN}~中的计算可以分解成三块参数及其相关的变换:
\begin{enumerate}
\item 从输入到隐藏状态,
\item 从前一隐藏状态到下一隐藏状态,以及
\item 从隐藏状态到输出。
\end{enumerate}
根据\figref{fig:chap10_hidden_recurrence_rnn}中的~\glssymbol{RNN}~架构,这三个块都与单个权重矩阵相关联。
换句话说,当网络被\gls{unfolding}时,每个块对应一个浅的变换。
能通过深度~\glssymbol{MLP}~内单个层来表示的变换称为浅变换。
通常,这是由学成的仿射变换和一个固定非线性表示组成的变换。
在这些操作中引入深度会有利的吗?
实验证据\citep{Graves-et-al-ICASSP2013,Pascanu-et-al-ICLR2014}强烈暗示理应如此。
实验证据与我们需要足够的深度以执行所需映射的想法一致。
读者可以参考~\cite{Schmidhuber92,ElHihi+Bengio-nips8}或~\cite{Jaeger2007}了解更早的关于深度~\glssymbol{RNN}~的研究。
\cite{Graves-et-al-ICASSP2013}第一个展示了将~\glssymbol{RNN}~的状态分为多层的显著好处,如\figref{fig:chap10_deep}~\emph{(左)}。
我们可以认为,在\figref{fig:chap10_deep}(a)所示层次结构中较低的层起到了将原始输入转化为对更高层的隐藏状态更合适表示的作用。
\cite{Pascanu-et-al-ICLR2014}更进一步提出在上述三个块中各使用一个单独的~\glssymbol{MLP}(可能是深度的),如\figref{fig:chap10_deep}(b)所示。
考虑表示容量,我们建议在这三个步中都分配足够的容量,但增加深度可能会因为优化困难而损害学习效果。
在一般情况下,更容易优化较浅的架构,加入\figref{fig:chap10_deep}(b)的额外深度导致从\gls{time_step}~$t$的变量到\gls{time_step}~$t+1$的最短路径变得更长。
例如,如果具有单个隐藏层的~\glssymbol{MLP}~被用于状态到状态的转换,那么与\figref{fig:chap10_hidden_recurrence_rnn}相比,我们就会加倍任何两个不同\gls{time_step}变量之间最短路径的长度。
然而\cite{Pascanu-et-al-ICLR2014}认为,在隐藏到隐藏的路径中引入\gls{skip_connection}可以缓和这个问题,如\figref{fig:chap10_deep}(c)所示。
% -- 387 --
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/deep}}
\fi
\caption{\gls{RNN}可以通过许多方式变得更深\citep{Pascanu-et-al-ICLR2014}。
(a)隐藏循环状态可以被分解为具有层次的组。
(b)可以向输入到隐藏,隐藏到隐藏以及隐藏到输出的部分引入更深的计算(如~\glssymbol{MLP})。
这可以延长链接不同\gls{time_step}的最短路径。
(c)可以引入\gls{skip_connection}来缓解路径延长的效应。
}
\label{fig:chap10_deep}
\end{figure}
\section{递归神经网络}
\label{sec:recursive_neural_networks}
递归神经网络\footnote{我们建议不要将``递归神经网络''缩写为``\glssymbol{RNN}'',以免与``\gls{RNN}''混淆。}代表\gls{recurrent_network}的另一个扩展,它被构造为深的树状结构而不是~\glssymbol{RNN}~的链状结构,因此是不同类型的\gls{computational_graph}。
递归网络的典型\gls{computational_graph}如\figref{fig:chap10_recursive_net}所示。
递归神经网络由~\cite{Pollack90}引入,而~\cite{tr-bottou-2011}描述了这类网络的潜在用途——学习推论。
递归网络已成功地应用于输入是\emph{数据结构}的\gls{NN}~\citep{Frasconi97,Frasconi-1998},如自然语言处理\citep{Socher+al-NIPS2011,Socher+al-EMNLP2011-small,Socher-et-al-EMNLP2013}和计算机视觉\citep{Socher-2011}。
% -- 388 --
递归网络的一个明显优势是,对于具有相同长度$\tau$的序列,深度(通过非线性操作的组合数量来衡量)可以急剧地从$\tau$减小为$\CalO(\log \tau)$,这可能有助于解决\gls{long_term_dependency}。
一个悬而未决的问题是如何以最佳的方式构造树。
一种选择是使用不依赖于数据的树结构,如平衡二叉树。
在某些应用领域,外部方法可以为选择适当的树结构提供借鉴。
例如,处理自然语言的句子时,用于递归网络的树结构可以被固定为句子语法分析树的结构(可以由自然语言语法分析程序提供)\citep{Socher+al-NIPS2011,Socher+al-EMNLP2011-small}。
理想的情况下,人们希望学习器自行发现和推断适合于任意给定输入的树结构,如\citep{tr-bottou-2011}所建议。
% -- 389 --
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/recursive_net}}
\fi
\caption{递归网络将循环网络的链状计算图推广到树状计算图。
可变大小的序列$\Vx^{(1)},\Vx^{(2)},\dots,\Vx^{(t)}$可以通过固定的参数集合(权重矩阵$\MU,\MV,\MW$)映射到固定大小的表示(输出$\Vo$)。
该图展示了\gls{supervised_learning}的情况,其中提供了一些与整个序列相关的目标$\Vy$。
}
\label{fig:chap10_recursive_net}
\end{figure}
递归网络想法的变种存在很多。
例如,\cite{Frasconi97}和~\cite{Frasconi-1998}将数据与树结构相关联,并将输入和目标与树的单独节点相关联。
由每个节点执行的计算无须是传统的人工神经计算(所有输入的仿射变换后跟一个单调非线性)。
例如,\cite{Socher-et-al-EMNLP2013}提出用张量运算和双线性形式,在这之前人们已经发现当概念是由连续向量(嵌入)表示时,这种方式有利于建模概念之间的联系\citep{Weston+Bengio+Usunier-2010,Bordes-et-al-AISTATS2012-small}。
\section{\glsentrytext{long_term_dependency}的挑战}
\label{sec:the_challenge_of_long_term_dependencies}
学习\gls{recurrent_network}\gls{long_term_dependency}的数学挑战在\secref{sec:long_term_dependencies}中引入。
根本问题是,经过许多阶段传播后的\gls{gradient}倾向于消失(大部分情况)或爆炸(很少,但对优化过程影响很大)。
即使我们假设\gls{recurrent_network}是参数稳定的(可存储记忆,且\gls{gradient}不爆炸),但\gls{long_term_dependency}的困难来自比短期相互作用指数小的权重(涉及许多~\gls{jacobian}~相乘)。
许多资料提供了更深层次的讨论\citep{Hochreiter91-small,Doya93,Bengio1994ITNN,Pascanu+al-ICML2013-small}。
在这一节中,我们会更详细地描述该问题。
其余几节介绍克服这个问题的方法。
% -- 390 --
\gls{recurrent_network}涉及相同函数的多次组合,每个\gls{time_step}一次。
这些组合可以导致极端非线性行为,如\figref{fig:chap10_composition_color}所示。
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/composition_color}}
\fi
\caption{重复组合函数。
当组合许多非线性函数(如这里所示的线性tanh层)时,结果是高度非线性的,通常大多数值与微小的导数相关联,也有一些具有大导数的值,以及在增加和减小之间的多次交替。% ??
此处,我们绘制从100维隐藏状态降到单个维度的线性投影,绘制于$y$轴上。
$x$轴是100维空间中沿着随机方向的初始状态的坐标。
因此,我们可以将该图视为高维函数的线性截面。
曲线显示每个\gls{time_step}之后的函数,或者等价地,转换函数被组合一定次数之后。
}
\label{fig:chap10_composition_color}
\end{figure}
特别地,\gls{RNN}所使用的函数组合有点像矩阵乘法。
我们可以认为,循环联系
\begin{align}
\Vh^{(t)} = \MW^\top \Vh^{(t-1)}
\end{align}
是一个非常简单的、缺少非线性激活函数和输入$\Vx$的\gls{RNN}。
如\secref{sec:long_term_dependencies}描述,这种递推关系本质上描述了幂法。
它可以被简化为
\begin{align}
\Vh^{(t)} = (\MW^t)^\top \Vh^{(0)},
\end{align}
而当$\MW$符合下列形式的特征分解
\begin{align}
\MW = \MQ \VLambda \MQ^\top,
\end{align}
其中$\MQ$正交,循环性可进一步简化为
\begin{align}
\Vh^{(t)} = \MQ^\top \VLambda^t \MQ \Vh^{(0)}.
\end{align}
特征值提升到$t$次后,导致幅值不到一的特征值衰减到零,而幅值大于一的就会激增。
任何不与最大特征向量对齐的$\Vh^{(0)}$的部分将最终被丢弃。
这个问题是针对\gls{recurrent_network}的。
在标量情况下,想象多次乘一个权重$w$。
该乘积$w^t$消失还是爆炸取决于$w$的幅值。
然而,如果每个时刻使用不同权重$w^{(t)}$的非\gls{recurrent_network},情况就不同了。
如果初始状态给定为$1$,那么时刻$t$的状态可以由$\prod_t w^{(t)}$给出。
假设$w^{(t)}$的值是随机生成的,各自独立,且有$0$均值$v$方差。
乘积的方差就为$\CalO(v^n)$。
为了获得某些期望的方差$v^*$,我们可以选择单个方差为$v=\sqrt[n]{v^*}$权重。
因此,非常深的\gls{feedforward_network}通过精心设计的比例可以避免\gls{gradient}消失和爆炸问题,如~\cite{Sussillo14}所主张的。
% -- 391 --
\glssymbol{RNN}~\gls{gradient}消失和爆炸问题是由不同研究人员独立发现\citep{Hochreiter91-small,Bengio_icnn93,Bengio1994ITNN}。
有人可能会希望通过简单地停留在\gls{gradient}不消失或爆炸的参数空间来避免这个问题。
不幸的是,为了储存记忆并对小扰动具有鲁棒性,\glssymbol{RNN}~必须进入参数空间中的\gls{gradient}消失区域\citep{Bengio_icnn93,Bengio1994ITNN}。
具体来说,每当模型能够表示\gls{long_term_dependency}时,长期相互作用的\gls{gradient}幅值就会变得指数小(相比短期相互作用的\gls{gradient}幅值)。
这并不意味着这是不可能学习的,由于\gls{long_term_dependency}关系的信号很容易被短期相关性产生的最小波动隐藏,因而学习\gls{long_term_dependency}可能需要很长的时间。
实践中,\cite{Bengio1994ITNN}的实验表明,当我们增加了需要捕获的依赖关系的跨度,基于\gls{gradient}的优化变得越来越困难,\glssymbol{SGD}~在长度仅为10或20的序列上成功训练传统~\glssymbol{RNN}~的概率迅速变为0。
将\gls{recurrent_network}作为动力系统更深入探讨的资料见~\cite{Doya93,Bengio1994ITNN,Siegelmann+Sontag-1995}及~
\cite{Pascanu-et-al-ICML2013}的回顾。
本章的其余部分将讨论目前已经提出的降低学习\gls{long_term_dependency}(在某些情况下,允许一个~\glssymbol{RNN}~学习横跨数百步的依赖)难度的不同方法,但学习\gls{long_term_dependency}的问题仍是\gls{DL}中的一个主要挑战。
\section{\glsentrytext{ESN}}
\label{sec:echo_state_networks}
从$\Vh^{(t-1)}$到$\Vh^{(t)}$的循环权重映射以及从$\Vx^{(t)}$到$\Vh^{(t)}$的输入权重映射是\gls{recurrent_network}中最难学习的参数。
研究者\citep{Jaeger-NIPS2002,Maass-et-al-2002,Jaeger+Haas-2004,Jaeger-2007}提出避免这种困难的方法是设定循环\gls{hidden_unit},使其能很好地捕捉过去输入历史,并且\emph{只学习输出权重}。
\firstgls{ESN}或~\glssymbol{ESN}~\citep{Jaeger+Haas-2004,Jaeger-2007},以及\firstgls{liquid_state_machines}\citep{Maass-et-al-2002}分别独立地提出了这种想法。
后者是类似的,只不过它使用脉冲神经元(二值输出)而不是~\glssymbol{ESN}~中的连续\gls{hidden_unit}。
\glssymbol{ESN}~和\gls{liquid_state_machines}都被称为\firstgls{reservoir_computing}\citep{Lukosevicius+Jaeger-2009},因为\gls{hidden_unit}形成了可能捕获输入历史不同方面的临时特征池。
% -- 392 --
\gls{reservoir_computing}\gls{recurrent_network}类似于\gls{kernel_machines},这是思考它们的一种方式:它们将任意长度的序列(到时刻$t$的输入历史)映射为一个长度固定的向量(循环状态$\Vh^{(t)}$),之后可以施加一个线性预测算子(通常是一个\gls{linear_regression})以解决感兴趣的问题。
训练\gls{criterion}就可以很容易地设计为输出权重的凸函数。
例如,如果输出是从\gls{hidden_unit}到输出目标的\gls{linear_regression},训练\gls{criterion}就是\gls{mean_squared_error},由于是凸的就可以用简单的学习算法可靠地解决\citep{Jaeger-NIPS2002}。
因此,重要的问题是:我们如何设置输入和循环权重才能让一组丰富的历史可以在\gls{RNN}的状态中表示?
\gls{reservoir_computing}研究给出的答案是将\gls{recurrent_network}视为动态系统,并设定让动态系统接近稳定边缘的输入和循环权重。
最初的想法是使状态到状态转换函数的~\gls{jacobian}~矩阵的特征值接近1。
如\secref{sec:long_term_dependencies}解释,\gls{recurrent_network}的一个重要特征就是~\gls{jacobian}~矩阵的特征值谱$\MJ^{(t)} = \frac{\partial s^{(t)}}{\partial s^{(t-1)}}$。
特别重要的是$\MJ^{(t)}$的\firstgls{spectral_radius},定义为特征值的最大绝对值。
为了解\gls{spectral_radius}的影响,可以考虑\gls{backward_propagation}中~\gls{jacobian}~矩阵$\MJ$不随$t$改变的简单情况。
例如当网络是纯线性时,会发生这种情况。
假设$\MJ$特征值$\lambda$对应的特征向量为$\Vv$。
考虑当我们通过时间向后传播\gls{gradient}向量时会发生什么。
如果刚开始的\gls{gradient}向量为$\Vg$,然后经过\gls{backward_propagation}的一个步骤后,我们将得到$\MJ \Vg$,$n$步之后我们会得到$\MJ^n \Vg$。
现在考虑如果我们向后传播扰动版本的$\Vg$会发生什么。
如果我们刚开始是$\Vg + \delta \Vv$,一步之后,我们会得到$\MJ(\Vg + \delta \Vv)$。
$n$步之后,我们将得到$\MJ^n(\Vg + \delta \Vv)$。
由此我们可以看出,由$\Vg$开始的\gls{backward_propagation}和由$\Vg+\delta \Vv$开始的\gls{backward_propagation},$n$步之后偏离$\delta \MJ^n \Vv$。
如果$\Vv$选择为$\MJ$特征值$\lambda$对应的一个单位特征向量,那么在每一步乘~\gls{jacobian}~矩阵只是简单地缩放。
\gls{backward_propagation}的两次执行分离的距离为$\delta | \lambda |^n$。
当$\Vv$对应于最大特征值$|\lambda|$,初始扰动为$\delta$时这个扰动达到可能的最宽分离。
当$ | \lambda | > 1$,偏差$\delta | \lambda |^n$就会指数增长。
当$ | \lambda | < 1$,偏差就会变得指数小。
% -- 393 --
当然,这个例子假定~\gls{jacobian}~矩阵在每个\gls{time_step}是相同的,即对应于没有非线性\gls{recurrent_network}。
当非线性存在时,非线性的导数将在许多\gls{time_step}后接近零,并有助于防止因过大的\gls{spectral_radius}而导致的爆炸。
事实上,关于\gls{ESN}的最近工作提倡使用远大于1的\gls{spectral_radius}~\citep{yildiz2012re,jaeger2012long}。
我们已经说过多次,通过反复矩阵乘法的\gls{backward_propagation}同样适用于没有非线性的正向传播的网络,其状态为$\Vh^{(t+1)} = \Vh^{(t)\top} \MW $。
如果线性映射$\MW^\top$在$L^2$范数的测度下总是缩小$\Vh$,那么我们说这个映射是\firstgls{contractive}的。
当\gls{spectral_radius}小于一,则从$\Vh^{(t)}$到$\Vh^{(t+1)}$的映射是\gls{contractive}的,因此小变化在每个\gls{time_step}后变得更小。
当我们使用有限精度(如32位整数)来存储状态向量时,必然会使得网络忘掉过去的信息。
\gls{jacobian}~矩阵告诉我们$\Vh^{(t)}$一个微小的变化如何向前一步传播,或等价的,$\Vh^{(t+1)}$的\gls{gradient}如何向后一步传播。
需要注意的是,$\MW$和$\MJ$都不需要是对称的(尽管它们是实方阵),因此它们可能有复的特征值和特征向量,其中虚数分量对应于潜在的振荡行为(如果迭代地应用同一~\gls{jacobian})。
即使$\Vh^{(t)}$或$\Vh^{(t)}$中有趣的小变化在\gls{backward_propagation}中是实值的,它们仍可以用这样的复数基表示。
重要的是,当向量乘以矩阵时,这些复数基的系数幅值(复数的绝对值)会发生什么变化。
幅值大于1的特征值对应于放大(如果反复应用则指数增长)或收缩(如果反复应用则指数减小)。
非线性映射情况时,\gls{jacobian}~会在每一步任意变化。
因此,动态量变得更加复杂。
然而,一个小的初始变化多步之后仍然会变成一个大的变化。
纯线性和非线性情况的一个不同之处在于使用压缩非线性(如$\tanh$)可以使循环动态量有界。
注意,即使\gls{forward_propagation}动态量有界,\gls{backward_propagation}的动态量仍然可能无界,例如,当$\tanh$序列都在它们状态中间的线性部分,并且由\gls{spectral_radius}大于1的权重矩阵连接。
然而,所有$\tanh$单元同时位于它们的线性激活点是非常罕见的。
% -- 394 --
\gls{ESN}的策略是简单地固定权重使其具有一定的\gls{spectral_radius}如3,其中信息通过时间前向传播,但会由于饱和非线性单元(如$\tanh$)的稳定作用而不会爆炸。
最近,已经有研究表明,用于设置~\glssymbol{ESN}~权重的技术可以用来\emph{初始化}完全可训练的\gls{recurrent_network}的权重(通过时间\gls{backward_propagation}来训练隐藏到隐藏的循环权重),帮助学习\gls{long_term_dependency}~\citep{Sutskever-thesis2012,sutskeverimportance}。
在这种设定下,结合\secref{sec:parameter_initialization_strategies}中稀疏初始化的方案,设置$1.2$的初始\gls{spectral_radius}表现不错。
\section{\glsentrytext{leaky_unit}和其他多时间尺度的策略}
\label{sec:leaky_units_and_other_strategiesfor_multiple_time_scales}
处理\gls{long_term_dependency}的一种方法是设计工作在多个时间尺度的模型,使模型的某些部分在细粒度时间尺度上操作并能处理小细节,而其他部分在粗时间尺度上操作并能把遥远过去的信息更有效地传递过来。
存在多种同时构建粗细时间尺度的策略。
这些策略包括在时间轴增加\gls{skip_connection},``\gls{leaky_unit}''使用不同时间常数整合信号,并去除一些用于建模细粒度时间尺度的连接。
\subsection{时间维度的\glsentrytext{skip_connection}}
\label{sec:adding_skip_connections_through_time}
增加从遥远过去的变量到目前变量的直接连接是得到粗时间尺度的一种方法。
使用这样\gls{skip_connection}的想法可以追溯到\cite{Lin-ieeetnn96},紧接是向\gls{feedforward_network}引入延迟的想法\citep{Lang+Hinton88}。
在普通的\gls{recurrent_network}中,循环从时刻$t$的单元连接到时刻$t+1$单元。
构造较长的延迟\gls{recurrent_network}是可能的\citep{Bengio91}。
正如我们在\secref{sec:long_term_dependencies}看到,\gls{gradient}可能\emph{关于时间步数}呈指数消失或爆炸。
\citep{Lin-ieeetnn96}引入了$d$延时的循环连接以减轻这个问题。
现在导数指数减小的速度与$\frac{\tau}{d}$相关而不是$\tau$。
既然同时存在延迟和单步连接,\gls{gradient}仍可能成$t$指数爆炸。
这允许学习算法捕获更长的依赖性,但不是所有的\gls{long_term_dependency}都能在这种方式下良好地表示。
% -- 395 --
\subsection{\glsentrytext{leaky_unit}和一系列不同时间尺度}
\label{sec:leaky_units_and_a_spectrum_of_different_time_scales}
获得导数乘积接近1的另一方式是设置\emph{线性}自连接单元,并且这些连接的权重接近1。
我们对某些$v$值应用更新$\mu^{(t)} \gets \alpha \mu^{(t-1)} + (1-\alpha) v^{(t)}$累积一个滑动平均值$\mu^{(t)}$,其中$\alpha$是一个从$ \mu^{(t-1)}$到$ \mu^{(t)}$线性自连接的例子。
当$\alpha$接近1时,滑动平均值能记住过去很长一段时间的信息,而当$\alpha$接近0,关于过去的信息被迅速丢弃。
线性自连接的\gls{hidden_unit}可以模拟滑动平均的行为。
这种\gls{hidden_unit}称为\firstgls{leaky_unit}。
$d$~\gls{time_step}的\gls{skip_connection}可以确保单元总能被$d$个\gls{time_step}前的那个值影响。
使用权重接近1的线性自连接是确保该单元可以访问过去值的不同方式。
线性自连接通过调节实值$\alpha$更平滑灵活地调整这种效果,而不是调整整数值的跳跃长度。
这个想法由~\cite{Mozer-nips92}和~\cite{ElHihi+Bengio-nips8}提出。
在\gls{ESN}中,\gls{leaky_unit}也被发现很有用\citep{JaegerLPS07}。
我们可以通过两种基本策略设置\gls{leaky_unit}使用的时间常数。
一种策略是手动将其固定为常数,例如在初始化时从某些分布采样它们的值。
另一种策略是使时间常数成为自由变量,并学习出来。
在不同时间尺度使用这样的\gls{leaky_unit}似乎能帮助学习\gls{long_term_dependency}~\citep{Mozer-nips92,Pascanu+al-ICML2013-small}。
\subsection{删除连接}
\label{sec:removing_connections}
处理\gls{long_term_dependency}另一种方法是在多个时间尺度组织~\glssymbol{RNN}~状态的想法\citep{ElHihi+Bengio-nips8},信息在较慢的时间尺度上更容易长距离流动。
这个想法与之前讨论的时间维度上的\gls{skip_connection}不同,因为它涉及主动\emph{删除}长度为一的连接并用更长的连接替换它们。
以这种方式修改的单元被迫在长时间尺度上运作。
而通过时间\gls{skip_connection}是\emph{添加}边。
收到这种新连接的单元,可以学习在长时间尺度上运作,但也可以选择专注于自己其他的短期连接。
% -- 396 --
强制一组循环单元在不同时间尺度上运作有不同的方式。
一种选择是使循环单元变成\gls{leaky_unit},但不同的单元组关联不同的固定时间尺度。
这由~\cite{Mozer-nips92}提出,并被成功应用于~\cite{Pascanu+al-ICML2013-small}。
另一种选择是使显式且离散的更新发生在不同的时间,不同的单元组有不同的频率。
这是~\cite{ElHihi+Bengio-nips8}和~\cite{Koutnik-et-al-ICML2014}的方法。
它在一些基准数据集上表现不错。
\section{\glsentrytext{LSTM}和其他\glsentrytext{gated_rnn}}
\label{sec:the_long_short_term_memory_and_other_gated_rnns}
本文撰写之时,实际应用中最有效的序列模型称为\firstgls{gated_rnn}。
包括基于\firstgls{LSTM}和基于\firstgls{gated_recurrent_unit}的网络。
像\gls{leaky_unit}一样,\gls{gated_rnn}~想法也是基于生成通过时间的路径,其中导数既不消失也不发生爆炸。
\gls{leaky_unit}通过手动选择常量的连接权重或参数化的连接权重来达到这一目的。
\gls{gated_rnn}~将其推广为在每个\gls{time_step}都可能改变的连接权重。
\gls{leaky_unit}允许网络在较长持续时间内\emph{积累}信息(诸如用于特定特征或类的线索)。
然而,一旦该信息被使用,让\gls{NN}\emph{遗忘}旧的状态可能是有用的。
例如,如果一个序列是由子序列组成,我们希望\gls{leaky_unit}能在各子序列内积累线索,我们需要将状态设置为0以忘记旧状态的机制。
我们希望\gls{NN}学会决定何时清除状态,而不是手动决定。
这就是\gls{gated_rnn}~要做的事。
\subsection{\glssymbol{LSTM}}
\label{sec:lstm}
引入自循环的巧妙构思,以产生\gls{gradient}长时间持续流动的路径是初始\firstall{LSTM}模型的核心贡献\citep{Hochreiter+Schmidhuber-1997}。
其中一个关键扩展是使自循环的权重视上下文而定,而不是固定的\citep{Gers-et-al-2000}。
\gls{gated}此自循环(由另一个\gls{hidden_unit}控制)的权重,累积的时间尺度可以动态地改变。
在这种情况下,即使是具有固定参数的~\glssymbol{LSTM},累积的时间尺度也可以因输入序列而改变,因为时间常数是模型本身的输出。
\glssymbol{LSTM}~已经在许多应用中取得重大成功,如无约束手写识别\citep{Graves-et-al-2009}、语音识别\citep{Graves-et-al-ICASSP2013,Graves+Jaitly-ICML2014}、手写生成\citep{Graves-arxiv2013}、机器翻译\citep{Sutskever-et-al-NIPS2014}、为图像生成标题\citep{Kiros-et-al-arxiv2014,Vinyals-et-al-arxiv2014,Xu-et-al-ICML2015}和解析\citep{Vinyals2014}。
% -- 397 --
\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter10/figures/lstm}}
\fi
\caption{\glssymbol{LSTM}~\gls{recurrent_network}``细胞''的框图。
细胞彼此循环连接,代替一般\gls{recurrent_network}中普通的\gls{hidden_unit}。
这里使用常规的人工神经元计算输入特征。
如果sigmoid输入门允许,它的值可以累加到状态。
状态单元具有线性自循环,其权重由\gls{forget_gate}控制。