forked from nnadl-ja/nnadl_site_ja
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchap2.html
2417 lines (2377 loc) · 219 KB
/
chap2.html
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
<!DOCTYPE html>
<html lang="en">
<!-- Produced from a LaTeX source file. Note that the production is done -->
<!-- by a very rough-and-ready (and buggy) script, so the HTML and other -->
<!-- code is quite ugly! Later versions should be better. -->
<meta charset="utf-8">
<meta name="citation_title" content="ニューラルネットワークと深層学習">
<meta name="citation_author" content="Nielsen, Michael A.">
<meta name="citation_publication_date" content="2014">
<meta name="citation_fulltext_html_url" content="http://neuralnetworksanddeeplearning.com">
<meta name="citation_publisher" content="Determination Press">
<link rel="icon" href="nnadl_favicon.ICO" />
<title>ニューラルネットワークと深層学習</title>
<script src="assets/jquery.min.js"></script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$']]},
"HTML-CSS":
{scale: 92},
TeX: { equationNumbers: { autoNumber: "AMS" }}});
</script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<link href="assets/style.css" rel="stylesheet">
<link href="assets/pygments.css" rel="stylesheet">
<style>
/* Adapted from */
/* https://groups.google.com/d/msg/mathjax-users/jqQxrmeG48o/oAaivLgLN90J, */
/* by David Cervone */
@font-face {
font-family: 'MJX_Math';
src: url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Math-Italic.eot'); /* IE9 Compat Modes */
src: url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Math-Italic.eot?iefix') format('eot'),
url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff') format('woff'),
url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Math-Italic.otf') format('opentype'),
url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/svg/MathJax_Math-Italic.svg#MathJax_Math-Italic') format('svg');
}
@font-face {
font-family: 'MJX_Main';
src: url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Main-Regular.eot'); /* IE9 Compat Modes */
src: url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Main-Regular.eot?iefix') format('eot'),
url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff') format('woff'),
url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Main-Regular.otf') format('opentype'),
url('http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/svg/MathJax_Main-Regular.svg#MathJax_Main-Regular') format('svg');
}
</style>
</head>
<body><div class="header"><h1 class="chapter_number">
<a href="">CHAPTER 2</a></h1>
<h1 class="chapter_title"><a href="">
<!--逆伝播の仕組み-->
逆伝播の仕組み
</a></h1></div><div class="section"><div id="toc">
<p class="toc_title"><a href="index.html">ニューラルネットワークと深層学習</a></p><p class="toc_not_mainchapter"><a href="about.html">What this book is about</a></p><p class="toc_not_mainchapter"><a href="exercises_and_problems.html">On the exercises and problems</a></p><p class='toc_mainchapter'><a id="toc_using_neural_nets_to_recognize_handwritten_digits_reveal" class="toc_reveal" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';"><img id="toc_img_using_neural_nets_to_recognize_handwritten_digits" src="images/arrow.png" width="15px"></a><a href="chap1.html">ニューラルネットワークを用いた手書き文字認識</a><div id="toc_using_neural_nets_to_recognize_handwritten_digits" style="display: none;"><p class="toc_section"><ul><a href="chap1.html#perceptrons"><li>Perceptrons</li></a><a href="chap1.html#sigmoid_neurons"><li>Sigmoid neurons</li></a><a href="chap1.html#the_architecture_of_neural_networks"><li>The architecture of neural networks</li></a><a href="chap1.html#a_simple_network_to_classify_handwritten_digits"><li>A simple network to classify handwritten digits</li></a><a href="chap1.html#learning_with_gradient_descent"><li>Learning with gradient descent</li></a><a href="chap1.html#implementing_our_network_to_classify_digits"><li>Implementing our network to classify digits</li></a><a href="chap1.html#toward_deep_learning"><li>Toward deep learning</li></a></ul></p></div>
<script>
$('#toc_using_neural_nets_to_recognize_handwritten_digits_reveal').click(function() {
var src = $('#toc_img_using_neural_nets_to_recognize_handwritten_digits').attr('src');
if(src == 'images/arrow.png') {
$("#toc_img_using_neural_nets_to_recognize_handwritten_digits").attr('src', 'images/arrow_down.png');
} else {
$("#toc_img_using_neural_nets_to_recognize_handwritten_digits").attr('src', 'images/arrow.png');
};
$('#toc_using_neural_nets_to_recognize_handwritten_digits').toggle('fast', function() {});
});</script><p class='toc_mainchapter'><a id="toc_how_the_backpropagation_algorithm_works_reveal" class="toc_reveal" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';"><img id="toc_img_how_the_backpropagation_algorithm_works" src="images/arrow.png" width="15px"></a><a href="chap2.html">逆伝播の仕組み</a><div id="toc_how_the_backpropagation_algorithm_works" style="display: none;"><p class="toc_section"><ul><a href="chap2.html#warm_up_a_fast_matrix-based_approach_to_computing_the_output_from_a_neural_network"><li>Warm up: a fast matrix-based approach to computing the output from a neural network</li></a><a href="chap2.html#the_two_assumptions_we_need_about_the_cost_function"><li>The two assumptions we need about the cost function</li></a><a href="chap2.html#the_hadamard_product_$s_\odot_t$"><li>The Hadamard product, $s \odot t$</li></a><a href="chap2.html#the_four_fundamental_equations_behind_backpropagation"><li>The four fundamental equations behind backpropagation</li></a><a href="chap2.html#proof_of_the_four_fundamental_equations_(optional)"><li>Proof of the four fundamental equations (optional)</li></a><a href="chap2.html#the_backpropagation_algorithm"><li>The backpropagation algorithm</li></a><a href="chap2.html#the_code_for_backpropagation"><li>The code for backpropagation</li></a><a href="chap2.html#in_what_sense_is_backpropagation_a_fast_algorithm"><li>In what sense is backpropagation a fast algorithm?</li></a><a href="chap2.html#backpropagation_the_big_picture"><li>Backpropagation: the big picture</li></a></ul></p></div>
<script>
$('#toc_how_the_backpropagation_algorithm_works_reveal').click(function() {
var src = $('#toc_img_how_the_backpropagation_algorithm_works').attr('src');
if(src == 'images/arrow.png') {
$("#toc_img_how_the_backpropagation_algorithm_works").attr('src', 'images/arrow_down.png');
} else {
$("#toc_img_how_the_backpropagation_algorithm_works").attr('src', 'images/arrow.png');
};
$('#toc_how_the_backpropagation_algorithm_works').toggle('fast', function() {});
});</script><p class='toc_mainchapter'><a id="toc_improving_the_way_neural_networks_learn_reveal" class="toc_reveal" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';"><img id="toc_img_improving_the_way_neural_networks_learn" src="images/arrow.png" width="15px"></a><a href="chap3.html">ニューラルネットワークの学習の改善</a><div id="toc_improving_the_way_neural_networks_learn" style="display: none;"><p class="toc_section"><ul><a href="chap3.html#the_cross-entropy_cost_function"><li>The cross-entropy cost function</li></a><a href="chap3.html#overfitting_and_regularization"><li>Overfitting and regularization</li></a><a href="chap3.html#weight_initialization"><li>Weight initialization</li></a><a href="chap3.html#handwriting_recognition_revisited_the_code"><li>Handwriting recognition revisited: the code</li></a><a href="chap3.html#how_to_choose_a_neural_network's_hyper-parameters"><li>How to choose a neural network's hyper-parameters?</li></a><a href="chap3.html#other_techniques"><li>Other techniques</li></a></ul></p></div>
<script>
$('#toc_improving_the_way_neural_networks_learn_reveal').click(function() {
var src = $('#toc_img_improving_the_way_neural_networks_learn').attr('src');
if(src == 'images/arrow.png') {
$("#toc_img_improving_the_way_neural_networks_learn").attr('src', 'images/arrow_down.png');
} else {
$("#toc_img_improving_the_way_neural_networks_learn").attr('src', 'images/arrow.png');
};
$('#toc_improving_the_way_neural_networks_learn').toggle('fast', function() {});
});</script><p class='toc_mainchapter'><a id="toc_a_visual_proof_that_neural_nets_can_compute_any_function_reveal" class="toc_reveal" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';"><img id="toc_img_a_visual_proof_that_neural_nets_can_compute_any_function" src="images/arrow.png" width="15px"></a><a href="chap4.html">ニューラルネットワークが任意の関数を表現できることの視覚的証明</a><div id="toc_a_visual_proof_that_neural_nets_can_compute_any_function" style="display: none;"><p class="toc_section"><ul><a href="chap4.html#two_caveats"><li>Two caveats</li></a><a href="chap4.html#universality_with_one_input_and_one_output"><li>Universality with one input and one output</li></a><a href="chap4.html#many_input_variables"><li>Many input variables</li></a><a href="chap4.html#extension_beyond_sigmoid_neurons"><li>Extension beyond sigmoid neurons</li></a><a href="chap4.html#fixing_up_the_step_functions"><li>Fixing up the step functions</li></a><a href="chap4.html#conclusion"><li>Conclusion</li></a></ul></p></div>
<script>
$('#toc_a_visual_proof_that_neural_nets_can_compute_any_function_reveal').click(function() {
var src = $('#toc_img_a_visual_proof_that_neural_nets_can_compute_any_function').attr('src');
if(src == 'images/arrow.png') {
$("#toc_img_a_visual_proof_that_neural_nets_can_compute_any_function").attr('src', 'images/arrow_down.png');
} else {
$("#toc_img_a_visual_proof_that_neural_nets_can_compute_any_function").attr('src', 'images/arrow.png');
};
$('#toc_a_visual_proof_that_neural_nets_can_compute_any_function').toggle('fast', function() {});
});</script><p class='toc_mainchapter'><a id="toc_why_are_deep_neural_networks_hard_to_train_reveal" class="toc_reveal" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';"><img id="toc_img_why_are_deep_neural_networks_hard_to_train" src="images/arrow.png" width="15px"></a><a href="chap5.html">ニューラルネットワークを訓練するのはなぜ難しいのか</a><div id="toc_why_are_deep_neural_networks_hard_to_train" style="display: none;"><p class="toc_section"><ul><a href="chap5.html#the_vanishing_gradient_problem"><li>The vanishing gradient problem</li></a><a href="chap5.html#what's_causing_the_vanishing_gradient_problem_unstable_gradients_in_deep_neural_nets"><li>What's causing the vanishing gradient problem? Unstable gradients in deep neural nets</li></a><a href="chap5.html#unstable_gradients_in_more_complex_networks"><li>Unstable gradients in more complex networks</li></a><a href="chap5.html#other_obstacles_to_deep_learning"><li>Other obstacles to deep learning</li></a></ul></p></div>
<script>
$('#toc_why_are_deep_neural_networks_hard_to_train_reveal').click(function() {
var src = $('#toc_img_why_are_deep_neural_networks_hard_to_train').attr('src');
if(src == 'images/arrow.png') {
$("#toc_img_why_are_deep_neural_networks_hard_to_train").attr('src', 'images/arrow_down.png');
} else {
$("#toc_img_why_are_deep_neural_networks_hard_to_train").attr('src', 'images/arrow.png');
};
$('#toc_why_are_deep_neural_networks_hard_to_train').toggle('fast', function() {});
});</script><p class='toc_mainchapter'><a id="toc_deep_learning_reveal" class="toc_reveal" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';"><img id="toc_img_deep_learning" src="images/arrow.png" width="15px"></a>Deep learning<div id="toc_deep_learning" style="display: none;"><p class="toc_section"><ul><li>Convolutional neural networks</li><li>Pretraining</li><li>Recurrent neural networks, Boltzmann machines, and other models</li><li>Is there a universal thinking algorithm?</li><li>On the future of neural networks</li></ul></p></div>
<script>
$('#toc_deep_learning_reveal').click(function() {
var src = $('#toc_img_deep_learning').attr('src');
if(src == 'images/arrow.png') {
$("#toc_img_deep_learning").attr('src', 'images/arrow_down.png');
} else {
$("#toc_img_deep_learning").attr('src', 'images/arrow.png');
};
$('#toc_deep_learning').toggle('fast', function() {});
});</script><p class="toc_not_mainchapter"><a href="acknowledgements.html">Acknowledgements</a></p><p class="toc_not_mainchapter"><a href="faq.html">Frequently Asked Questions</a></p>
<hr>
<span class="sidebar_title">Sponsors</span>
<br/>
<a href='http://www.ersatz1.com/'><img src='assets/ersatz.png' width='140px' style="padding: 0px 0px 10px 8px; border-style: none;"></a>
<a href='http://gsquaredcapital.com/'><img src='assets/gsquared.png' width='150px' style="padding: 0px 0px 10px 10px; border-style: none;"></a>
<a href='http://www.tineye.com'><img src='assets/tineye.png' width='150px'
style="padding: 0px 0px 10px 8px; border-style: none;"></a>
<a href='http://www.visionsmarts.com'><img
src='assets/visionsmarts.png' width='160px' style="padding: 0px 0px
0px 0px; border-style: none;"></a> <br/>
<!--
<p class="sidebar">Thanks to all the <a
href="supporters.html">supporters</a> who made the book possible.
Thanks also to all the contributors to the <a
href="bugfinder.html">Bugfinder Hall of Fame</a>. </p>
<p class="sidebar">The book is currently a beta release, and is still
under active development. Please send error reports to
[email protected]. For other enquiries, please see the <a
href="faq.html">FAQ</a> first.</p>
-->
<p class="sidebar">著者と共にこの本を作り出してくださった<a
href="supporters.html">サポーター</a>の皆様に感謝いたします。
また、<a
href="bugfinder.html">バグ発見者の殿堂</a>に名を連ねる皆様にも感謝いたします。
また、日本語版の出版にあたっては、<a
href="translators.html">翻訳者</a>の皆様に深く感謝いたします。
</p>
<p class="sidebar">この本は目下のところベータ版で、開発続行中です。
エラーレポートは [email protected] まで、日本語版に関する質問は [email protected] までお送りください。
その他の質問については、まずは<a
href="faq.html">FAQ</a>をごらんください。</p>
<hr>
<span class="sidebar_title">Resources</span>
<p class="sidebar">
<a href="https://github.com/mnielsen/neural-networks-and-deep-learning">Code repository</a></p>
<p class="sidebar">
<a href="http://eepurl.com/BYr9L">Mailing list for book announcements</a>
</p>
<p class="sidebar">
<a href="http://eepurl.com/0Xxjb">Michael Nielsen's project announcement mailing list</a>
</p>
<hr>
<a href="http://michaelnielsen.org"><img src="assets/Michael_Nielsen_Web_Small.jpg" width="160px" style="border-style: none;"/></a>
<p class="sidebar">
著:<a href="http://michaelnielsen.org">Michael Nielsen</a> / 2014年9月-12月 <br > 訳:<a href="https://github.com/nnadl-ja/nnadl_site_ja">「ニューラルネットワークと深層学習」翻訳プロジェクト</a>
</p>
</div>
</p>
<p>
<!--In the <a href="chap1.html">last chapter</a> we saw how neural networks can
learn their weights and biases using the gradient descent algorithm.
There was, however, a gap in our explanation: we didn't discuss how to
compute the gradient of the cost function. That's quite a gap! In
this chapter I'll explain a fast algorithm for computing such
gradients, an algorithm known as <em>backpropagation</em>. -->
<a href="chap1.html">前章</a>では、勾配降下法を用いてニューラルネットワークが重みとバイアスをどのように学習するかを説明しました。
しかし、その説明にはギャップがありました。具体的には、コスト関数の勾配をどのように計算するかを議論していません。これはとても大きなギャップです!
本章では、<em>逆伝播</em>と呼ばれる、コスト関数の勾配を高速に計算するアルゴリズムを説明します。
</p>
<p>
<p>
<!--The backpropagation algorithm was originally introduced in the 1970s,
but its importance wasn't fully appreciated until a
<a href="http://www.nature.com/nature/journal/v323/n6088/pdf/323533a0.pdf">famous 1986 paper</a> by
<a href="http://en.wikipedia.org/wiki/David_Rumelhart">David Rumelhart</a>,
<a href="http://www.cs.toronto.edu/~hinton/">Geoffrey Hinton</a>, and
<a href="http://en.wikipedia.org/wiki/Ronald_J._Williams">Ronald Williams</a>.
That paper describes several
neural networks where backpropagation works far faster than earlier
approaches to learning, making it possible to use neural nets to solve
problems which had previously been insoluble. Today, the
backpropagation algorithm is the workhorse of learning in neural
networks.-->
逆伝播アルゴリズムはもともと1970年代に導入されました。
しかし逆伝播が評価されたのは、
<a href="http://en.wikipedia.org/wiki/David_Rumelhart">David Rumelhart</a>・
<a href="http://www.cs.toronto.edu/~hinton/">Geoffrey Hinton</a>・
<a href="http://en.wikipedia.org/wiki/Ronald_J._Williams">Ronald Williams</a>
による1986年の著名な論文が登場してからでした。
その論文では、逆伝播を用いると既存の学習方法よりもずっと早く学習できる事をいくつかのニューラルネットワークに対して示し、それまでニューラルネットワークでは解けなかった問題が解ける事を示しました。
今日では、逆伝播はニューラルネットワークを学習させる便利なアルゴリズムです。
<!--
2014/12/24 Kenta OONO
"workhorse" の訳語がもっとうまいものがあったら偏向したい
-->
</p>
<p>
<!--This chapter is more mathematically involved than the rest of the
book. If you're not crazy about mathematics you may be tempted to
skip the chapter, and to treat backpropagation as a black box whose
details you're willing to ignore. Why take the time to study those
details?-->
本章は他の章に比べて数学的に難解です。
よほど数学に対し熱心でなければ、本章を飛ばして、逆伝播を中身を無視できるブラックボックスとして扱いたくなるかもしれません。
では、なぜ時間をかけて逆伝播の詳細を勉強するのでしょうか?
</p>
<p>
<!--The reason, of course, is understanding. At the heart of
backpropagation is an expression for the partial derivative $\partial
C / \partial w$ of the cost function $C$ with respect to any weight
$w$ (or bias $b$) in the network. The expression tells us how quickly
the cost changes when we change the weights and biases. And while the
expression is somewhat complex, it also has a beauty to it, with each
element having a natural, intuitive interpretation. And so
backpropagation isn't just a fast algorithm for learning. It actually
gives us detailed insights into how changing the weights and biases
changes the overall behaviour of the network. That's well worth
studying in detail.-->
その理由はもちろん理解のためです。
逆伝播の本質はコスト関数$C$のネットワークの重み$w$(もしくはバイアス$b$)に関する偏微分$\partial C / \partial w$ ($\partial C / \partial b$)です。
<!--
2014/12/24 Kenta OONO
バイアスの場合の数式$\partial C / \partial b$を追加しました
-->
偏微分をみると、重みとバイアスを変化させた時のコスト関数の変化の度合いがわかります。
偏微分の式は若干複雑ですが、そこには美しい構造があり、式の各要素には自然で直感的な解釈を与える事ができます。
そうです、逆伝播は単なる高速な学習アルゴリズムではありません。
逆伝播をみることで、重みやバイアスを変化させた時のニューラルネットワーク全体の挙動の変化に関して深い洞察が得られます。
逆伝播を勉強する価値はそこにあるのです。
</p>
<p>
<!--With that said, if you want to skim the chapter, or jump straight to
the next chapter, that's fine. I've written the rest of the book to
be accessible even if you treat backpropagation as a black box. There
are, of course, points later in the book where I refer back to results
from this chapter. But at those points you should still be able to
understand the main conclusions, even if you don't follow all the
reasoning.-->
そうは言うものの、本章をざっと読んだり、読み飛ばして次の章に進んでも大丈夫です。
この本は逆伝播をブラックボックスとして扱っても他の章を理解できるように書いています。
もちろん次章以降で本章の結果を参照する部分はあります。
しかし、その参照部分の議論をすべて追わなくても、主な結論は理解できるはずです。
</p>
<p><h3><a name="warm_up_a_fast_matrix-based_approach_to_computing_the_output
_from_a_neural_network"></a><a href="#warm_up_a_fast_matrix-based_approach_to_computing_the_output
_from_a_neural_network">
<!--Warm up: a fast matrix-based approach to computing the output from a neural network-->
ウォーミングアップ:ニューラルネットワークの出力の行列を用いた高速な計算
</a></h3></p>
<p>
<!--Before discussing backpropagation, let's warm up with a fast
matrix-based algorithm to compute the output from a neural network.
We actually already briefly saw this algorithm
<a href="chap1.html#implementing_our_network_to_classify_digits">near
the end of the last chapter</a>, but I described it quickly, so it's
worth revisiting in detail. In particular, this is a good way of
getting comfortable with the notation used in backpropagation, in a
familiar context.-->
逆伝播を議論する前に、ニューラルネットワークの出力を高速に計算する行列を用いたアルゴリズムでウォーミングアップしましょう。
私達は
<a href="chap1.html#implementing_our_network_to_classify_digits">前章の最後のあたり</a>
で既にこのアルゴリズムを簡単に見ています。
しかしその時はざっと書いていたので、ここで立ち戻って詳しく説明しようと思います。
特にこれまで説明して慣れた文脈で逆伝播で使用する記号に慣れるのに、このウォーミングアップは良い方法です。
<!--
2014/12/24 Kenta OONO
"in a familiar context"が何を指しているのかがよくわかりませんでした
-->
</p>
<p>
<!--Let's begin with a notation which lets us refer to weights in the
network in an unambiguous way. We'll use $w^l_{jk}$ to denote the
weight for the connection from the $k^{\rm th}$ neuron in the
$(l-1)^{\rm th}$ layer to the $j^{\rm th}$ neuron in the $l^{\rm th}$
layer. So, for example, the diagram below shows the weight on a
connection from the fourth neuron in the second layer to the second
neuron in the third layer of a network:-->
ニューラルネットワーク中の重みを曖昧性なく指定する表記方法からまず始めましょう。
$w^l_{jk}$で$(l-1)$番目の層の$k$番目のニューロンから$l$番目の層の$j$番目のニューロンへの接続に対する重みを表します。
例えば、下図は2番目の層の4番目のニューロンから3番目の層の2番目のニューロンへの接続の重みを表します。
<!--
2014/12/24 Kenta OONO
- "connection"を愚直に「接続」と訳しているけれど、固いので解釈して「枝」としてもいいかも
- l-th layer は「l番目の層」と「l層目」のどちらが適切か?
-->
<center>
<img src="images/tikz16.png"/>
</center>
<!--This notation is cumbersome at first, and it does take some work to
master. But with a little effort you'll find the notation becomes
easy and natural. One quirk of the notation is the ordering of the
$j$ and $k$ indices. You might think that it makes more sense to use
$j$ to refer to the input neuron, and $k$ to the output neuron, not
vice versa, as is actually done. I'll explain the reason for this
quirk below.-->
この表記方法は最初は面倒で、使いこなすのにある程度の練習が必要かもしれません。
しかし、少し頑張ればこの表記方法は簡単で自然だと感じるようになるはずです。
この表記方法で若干曲者なのが、$j$と$k$の順番です。
$j$を入力ニューロン、$k$を出力ニューロンとする方が理にかなっていると思うかもしれませんが、
実際には逆にしています。
奇妙なこの記述方法の理由は後程説明します。
</p>
<p>
<!--
We use a similar notation for the network's biases and activations.
Explicitly, we use $b^l_j$ for the bias of the $j^{\rm th}$ neuron in
the $l^{\rm th}$ layer. And we use $a^l_j$ for the activation of the
$j^{\rm th}$ neuron in the $l^{\rm th}$ layer. The following diagram
shows examples of these notations in use:-->
ニューラルネットワークのバイアスと活性についても似た表記方法を導入します。
具体的には、$b^l_j$で$l$番目の層の$j$番目のニューロンのバイアスを表します。
また、$a^l_j$で$l$番目の層の$j$番目のニューロンの活性を表します。
下図はこれらの表記方法の利用例です。
<center>
<img src="images/tikz17.png"/>
</center>
<!--With these notations, the activation $a^{l}_j$ of the $j^{\rm th}$
neuron in the $l^{\rm th}$ layer is related to the activations in the
$(l-1)^{\rm th}$ layer by the equation (compare Equation
<span id="margin_295319563926_reveal" class="equation_link">(4)</span>
<span id="margin_295319563926" class="marginequation" style="display: none;">
<a href="chap1.html#eqtn4" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
\frac{1}{1+\exp(-\sum_j w_j x_j-b)} \nonumber
\end{eqnarray}
</a>
</span>
<script>$('#margin_295319563926_reveal').click(function() {$('#margin_295319563926').toggle('slow', function() {});});</script>
and surrounding discussion in the last chapter)
<a class="displaced_anchor" name="eqtn23"></a>\begin{eqnarray}
a^{l}_j = \sigma\left( \sum_k w^{l}_{jk} a^{l-1}_k + b^l_j \right),
\tag{23}\end{eqnarray}
where the sum is over all neurons $k$ in the $(l-1)^{\rm th}$ layer. -->
これらの表記を用いると、$l$番目の層の$j$番目のニューロンの活性$a^l_j$は、$(l-1)$番目の層の活性と以下の式で関係付けられます(式
<span id="margin_295319563926_reveal" class="equation_link">(4)</span>
<span id="margin_295319563926" class="marginequation" style="display: none;">
<a href="chap1.html#eqtn4" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
\frac{1}{1+\exp(-\sum_j w_j x_j-b)} \nonumber
\end{eqnarray}
</a>
</span>
<script>$('#margin_295319563926_reveal').click(function() {$('#margin_295319563926').toggle('slow', function() {});});</script>
と前章の周辺の議論を比較してください)
<a class="displaced_anchor" name="eqtn23"></a>\begin{eqnarray}
a^{l}_j = \sigma\left( \sum_k w^{l}_{jk} a^{l-1}_k + b^l_j \right).
\tag{23}\end{eqnarray}
ここで、和は$(l-1)$番目の層の全てのニューロン$k$について足しています。
<!-- To rewrite this expression in a matrix form we define a <em>weight
matrix</em> $w^l$ for each layer, $l$. The entries of the weight matrix
$w^l$ are just the weights connecting to the $l^{\rm th}$ layer of neurons,
that is, the entry in the $j^{\rm th}$ row and $k^{\rm th}$ column is $w^l_{jk}$.
Similarly, for each layer $l$ we define a <em>bias vector</em>, $b^l$.
You can probably guess how this works - the components of the bias
vector are just the values $b^l_j$, one component for each neuron in
the $l^{\rm th}$ layer. And finally, we define an activation vector $a^l$
whose components are the activations $a^l_j$.-->
この式を行列で書き直すため、各層$l$に対し<em>重み行列</em>$w^l$を定義します。
重み行列$w^l$の各要素は$l$番目の層のニューロンを終点とする接続の重みです。
<!--
2014/12/24 Kenta OONO
「終点」は"connecting to the l-th layer"のtoの訳にあたります
-->
すなわち、$j$行目$k$列目の要素を$w^l_{jk}$とします。
同様に、各層$l$に対し、<em>バイアスベクトル</em>$b^l$を定義します。
おそらく想像できると思いますが、バイアスベクトルの要素は$b^l_j$達で、
$l$番目の層の各ニューロンに対し1つの行列要素が伴います。
最後に、活性ベクトル$a^l$を活性$a^l_j$達で定義します。
</p>
<p>
<!--The last ingredient we need to rewrite
<span id="margin_910880967978_reveal" class="equation_link">(23)</span>
<span id="margin_910880967978" class="marginequation" style="display: none;">
<a href="chap2.html#eqtn23" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
a^{l}_j = \sigma\left( \sum_k w^{l}_{jk} a^{l-1}_k + b^l_j \right) \nonumber
\end{eqnarray}
</a>
</span>
<script>$('#margin_910880967978_reveal').click(function() {$('#margin_910880967978').toggle('slow', function() {});});</script>
in a matrix form is the idea of vectorizing a function such as $\sigma$.
-->
<span id="margin_910880967978_reveal" class="equation_link">(23)</span>
<span id="margin_910880967978" class="marginequation" style="display: none;">
<a href="chap2.html#eqtn23" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
a^{l}_j = \sigma\left( \sum_k w^{l}_{jk} a^{l-1}_k + b^l_j \right) \nonumber
\end{eqnarray}
</a>
</span>
<script>$('#margin_910880967978_reveal').click(function() {$('#margin_910880967978').toggle('slow', function() {});});</script>
を行列形式に書き直すのに必要な最後の要素は、$\sigma$などの関数のベクトル化です。
<!--
We met vectorization briefly in the last chapter, but to recap, the
idea is that we want to apply a function such as $\sigma$ to every
element in a vector $v$. We use the obvious notation $\sigma(v)$ to
denote this kind of elementwise application of a function. That is,
the components of $\sigma(v)$ are just $\sigma(v)_j = \sigma(v_j)$.
As an example, if we have the function $f(x) = x^2$ then the
vectorized form of $f$ has the effect
<a class="displaced_anchor" name="eqtn24"></a>\begin{eqnarray}
f\left(\left[ \begin{array}{c} 2 \\ 3 \end{array} \right] \right)
= \left[ \begin{array}{c} f(2) \\ f(3) \end{array} \right]
= \left[ \begin{array}{c} 4 \\ 9 \end{array} \right],
\tag{24}\end{eqnarray}
that is, the vectorized $f$ just squares every element of the vector.-->
ベクトル化は既に前章で簡単に見ました。
要点をまとめると、$\sigma$のような関数をベクトル$v$の各要素に適用したいというのがアイデアです。
このような各要素への関数適用には$\sigma(v)$という自然な表記を用います。
つまり、$\sigma(v)$の各要素は$\sigma(v)_j = \sigma(v_j)$です。
例えば$f(x) = x^2$とすると、次のようになります。
<a class="displaced_anchor" name="eqtn24"></a>\begin{eqnarray}
f\left(\left[ \begin{array}{c} 2 \\ 3 \end{array} \right] \right)
= \left[ \begin{array}{c} f(2) \\ f(3) \end{array} \right]
= \left[ \begin{array}{c} 4 \\ 9 \end{array} \right].
\tag{24}\end{eqnarray}
すなわち、ベクトル化した$f$はベクトルの各要素を2乗します。
</p>
<p>
<!--With these notations in mind, Equation
<span id="margin_948905994145_reveal" class="equation_link">(23)</span>
<span id="margin_948905994145" class="marginequation" style="display: none;">
<a href="chap2.html#eqtn23" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
a^{l}_j = \sigma\left( \sum_k w^{l}_{jk} a^{l-1}_k + b^l_j \right) \nonumber
\end{eqnarray}</a>
</span>
<script>$('#margin_948905994145_reveal').click(function() {$('#margin_948905994145').toggle('slow', function() {});});</script>
can be rewritten in the beautiful and compact vectorized form
<a class="displaced_anchor" name="eqtn25"></a>
\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l). \tag{25}
\end{eqnarray}
-->
この表記方法を用いると、式
<span id="margin_948905994145_reveal" class="equation_link">(23)</span>
<span id="margin_948905994145" class="marginequation" style="display: none;">
<a href="chap2.html#eqtn23" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
a^{l}_j = \sigma\left( \sum_k w^{l}_{jk} a^{l-1}_k + b^l_j \right) \nonumber
\end{eqnarray}</a>
</span>
<script>$('#margin_948905994145_reveal').click(function() {$('#margin_948905994145').toggle('slow', function() {});});</script>
は次のような美しくコンパクトなベクトル形式で書けます。
<a class="displaced_anchor" name="eqtn25"></a>
\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l). \tag{25}
\end{eqnarray}
<!--
This expression gives us a much more global way of thinking about how
the activations in one layer relate to activations in the previous
layer: we just apply the weight matrix to the activations, then add
the bias vector, and finally apply the $\sigma$ function*
-->
この表現を用いると、ある層の活性とその前の層の活性との関係を俯瞰できます。
我々が行っているのは活性に対し重み行列を掛け、バイアスベクトルを足し、最後に$\sigma$関数を適用するだけです。
<!--
<span class="marginnote">
*By the way, it's this expression that motivates the quirk in the
$w^l_{jk}$ notation mentioned earlier. If we used $j$ to index the
input neuron, and $k$ to index the output neuron, then we'd need to
replace the weight matrix in Equation
<span id="margin_305931363478_reveal" class="equation_link">(25)</span>
<span id="margin_305931363478" class="marginequation" style="display: none;">
<a href="chap2.html#eqtn25" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l) \nonumber
\end{eqnarray}</a></span>
<script>$('#margin_305931363478_reveal').click(function() {$('#margin_305931363478').toggle('slow', function() {});});</script>
by the transpose of the weight matrix. That's a small change, but
annoying, and we'd lose the easy simplicity of saying (and thinking)
"apply the weight matrix to the activations".</span>.-->
<span class="marginnote">*ところで、先ほどの$w^l_{jk}$という奇妙な表記を用いる動機はこの式に由来します。
もし、$j$を入力ニューロンに用い、$k$を出力ニューロンに用いたとすると、式
<span id="margin_305931363478_reveal" class="equation_link">(25)</span>
<span id="margin_305931363478" class="marginequation" style="display: none;">
<a href="chap2.html#eqtn25" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">
\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l) \nonumber
\end{eqnarray}</a></span>
<script>$('#margin_305931363478_reveal').click(function() {$('#margin_305931363478').toggle('slow', function() {});});</script>
は重み行列をそれの転置行列に置き換えなければなりません。
些細な変更ですが、煩わしい上に「重み行列を掛ける」と簡単に言ったり(もしくは考えたり)できなくなってしまいます。
</span>
<!--
That global view
is often easier and more succinct (and involves fewer indices!) than
the neuron-by-neuron view we've taken to now. Think of it as a way of
escaping index hell, while remaining precise about what's going on.
The expression is also useful in practice, because most matrix
libraries provide fast ways of implementing matrix multiplication,
vector addition, and vectorization. Indeed, the
<a href="chap1.html#implementing_our_network_to_classify_digits">code</a>
in the last chapter made implicit use of this expression to compute
the behaviour of the network.-->
この見方はこれまでのニューロン単位での見方よりも簡潔で、添字も少なくて済みます。
議論の正確性を失う事なく添字地獄から抜け出せる方法と考えると良いでしょう。
さらに、この表現方法は実用上も有用です。
というのも、多くの行列ライブラリでは高速な行列掛算・ベクトル足し算・関数のベクトル化の実装が提供されているからです。
実際、前章の<a href="chap1.html#implementing_our_network_to_classify_digits">コード</a>
では、ネットワークの挙動の計算にこの表式を暗に利用していました。
</p>
<p>
<!--When using Equation
<span id="margin_924913160001_reveal" class="equation_link">(25)</span><span id="margin_924913160001" class="marginequation" style="display: none;"><a href="chap2.html#eqtn25" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l) \nonumber\end{eqnarray}</a></span><script>$('#margin_924913160001_reveal').click(function() {$('#margin_924913160001').toggle('slow', function() {});});</script>
to compute $a^l$, we compute the intermediate quantity $z^l \equiv w^l a^{l-1}+b^l$
along the way.-->
$a^l$の計算のために式
<span id="margin_924913160001_reveal" class="equation_link">(25)</span><span id="margin_924913160001" class="marginequation" style="display: none;"><a href="chap2.html#eqtn25" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l) \nonumber\end{eqnarray}</a></span><script>$('#margin_924913160001_reveal').click(function() {$('#margin_924913160001').toggle('slow', function() {});});</script>
を利用する時には、途中で$z^l \equiv w^l a^{l-1}+b^l$を計算しています。
<!--This quantity turns out to be useful enough to be
worth naming: we call $z^l$ the <em>weighted input</em> to the neurons
in layer $l$. We'll make considerable use of the weighted input $z^l$
later in the chapter. -->
この値は後の議論で有用なので名前をつけておく価値があります。
$z^l$を$l$番目の層に対する<em>重みつき入力</em>と呼ぶことにします。
本章の以降の議論では重みつき入力$z^l$を頻繁に利用します。
<!--Equation
<span id="margin_957787478923_reveal" class="equation_link">(25)</span><span id="margin_957787478923" class="marginequation" style="display: none;"><a href="chap2.html#eqtn25" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l) \nonumber\end{eqnarray}</a></span><script>$('#margin_957787478923_reveal').click(function() {$('#margin_957787478923').toggle('slow', function() {});});</script>
is sometimes written in terms of the weighted input, as $a^l = \sigma(z^l)$. -->
式
<span id="margin_957787478923_reveal" class="equation_link">(25)</span><span id="margin_957787478923" class="marginequation" style="display: none;"><a href="chap2.html#eqtn25" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
a^{l} = \sigma(w^l a^{l-1}+b^l) \nonumber\end{eqnarray}</a></span><script>$('#margin_957787478923_reveal').click(function() {$('#margin_957787478923').toggle('slow', function() {});});</script>
をしばしば重み付き入力を用いて$a^l = \sigma(z^l)$とも書きます。
<!-- It's also worth noting that $z^l$ has components $z^l_j
= \sum_k w^l_{jk} a^{l-1}_k+b^l_j$, that is, $z^l_j$ is just the
weighted input to the activation function for neuron $j$ in layer $l$.-->
$z^l$の要素は$z^l_j = \sum_k w^l_{jk} a^{l-1}_k+b^l_j$と書ける事にも注意してください。
つまり、$z^l_j$は$l$番目の層の$j$番目のニューロンが持つ活性関数へ与える重みつき入力です。
</p>
<p><h3><a name="the_two_assumptions_we_need_about_the_cost_function"></a>
<a href="#the_two_assumptions_we_need_about_the_cost_function">
<!--The two assumptions we need about the cost function-->
コスト関数に必要な2つの仮定
</a></h3></p>
<p>
<!--The goal of backpropagation is to compute the partial derivatives
$\partial C / \partial w$ and $\partial C / \partial b$ of the cost
function $C$ with respect to any weight $w$ or bias $b$ in the
network. For backpropagation to work we need to make two main
assumptions about the form of the cost function. Before stating those
assumptions, though, it's useful to have an example cost function in
mind. -->
逆伝播の目標はニューラルネットワーク中の任意の重み$w$またはバイアス$b$に関するコスト関数$C$の偏微分、すなわち$\partial C / \partial w$と$\partial C / \partial b$の計算です。
逆伝播が機能するには、コスト関数の形について2つの仮定を置く必要があります。
それらの仮定を述べる前に、コスト関数の例を念頭に置くのが良いでしょう。
<!--We'll use the quadratic cost function from last chapter
(c.f. Equation <span id="margin_342696826100_reveal" class="equation_link">(6)</span><span id="margin_342696826100" class="marginequation" style="display: none;"><a href="chap1.html#eqtn6" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray} C(w,b) \equiv \frac{1}{2n} \sum_x \| y(x) - a\|^2 \nonumber\end{eqnarray}</a></span><script>$('#margin_342696826100_reveal').click(function() {$('#margin_342696826100').toggle('slow', function() {});});</script>).-->
前章でも出てきた2乗コスト関数(参考:式<span id="margin_342696826100_reveal" class="equation_link">(6)</span><span id="margin_342696826100" class="marginequation" style="display: none;"><a href="chap1.html#eqtn6" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray} C(w,b) \equiv) \frac{1}{2n} \sum_x \| y(x) - a\|^2 \nonumber\end{eqnarray}</a></span><script>$('#margin_342696826100_reveal').click(function() {$('#margin_342696826100').toggle('slow', function() {});});</script>)をここでも考えます。
<!--In the notation of the last section, the quadratic cost has the form
<a class="displaced_anchor" name="eqtn26"></a>\begin{eqnarray}
C = \frac{1}{2n} \sum_x \|y(x)-a^L(x)\|^2,
\tag{26}\end{eqnarray}
where: $n$ is the total number of training examples; the sum is over
individual training examples, $x$; $y = y(x)$ is the corresponding
desired output; $L$ denotes the number of layers in the network; and
$a^L = a^L(x)$ is the vector of activations output from the network
when $x$ is input.-->
前章の記法では、2乗コスト関数は以下の様な形をしていました
<a class="displaced_anchor" name="eqtn26"></a>\begin{eqnarray}
C = \frac{1}{2n} \sum_x \|y(x)-a^L(x)\|^2.
\tag{26}\end{eqnarray}
ここで、$n$は訓練例の総数、和は個々の訓練例$x$について足しあわせたもの、$y = y(x)$は対応する目標の出力、$L$はニューラルネットワークの層数、$a^L = a^L(x)$は$x$を入力した時のニューラルネットワークの出力のベクトルです。
</p>
<p>
<!--Okay, so what assumptions do we need to make about our cost function,
$C$, in order that backpropagation can be applied? The first
assumption we need is that the cost function can be written as an
average $C = \frac{1}{n} \sum_x C_x$ over cost functions $C_x$ for
individual training examples, $x$. This is the case for the quadratic
cost function, where the cost for a single training example is $C_x =
\frac{1}{2} \|y-a^L \|^2$. This assumption will also hold true for
all the other cost functions we'll meet in this book.-->
では、逆伝播を適用するために、コスト関数$C$に置く仮定はどのようなものでしょうか。
1つ目の仮定はコスト関数は個々の訓練例$x$に対するコスト関数$C_x$の平均 $C = \frac{1}{n} \sum_x C_x$で書かれているという事です。
2乗コスト関数ではこの仮定が成立しています。
それには1つの訓練例に対するコスト関数を$C_x = \frac{1}{2} \|y-a^L \|^2$とすれば良いです。
この仮定はこの本で登場する他のコスト関数でも成立しています。
</p>
<p>
<!--The reason we need this assumption is because what backpropagation
actually lets us do is compute the partial derivatives $\partial C_x
/ \partial w$ and $\partial C_x / \partial b$ for a single training
example. We then recover $\partial C / \partial w$ and $\partial C
/ \partial b$ by averaging over training examples. In fact, with this
assumption in mind, we'll suppose the training example $x$ has been
fixed, and drop the $x$ subscript, writing the cost $C_x$ as $C$.
We'll eventually put the $x$ back in, but for now it's a notational
nuisance that is better left implicit.-->
この仮定が必要となる理由は、逆伝播によって計算できるのは個々の訓練例に対する偏微分$\partial C_x / \partial w$、$\partial C_x / \partial b$だからです。
コスト関数の偏微分$\partial C / \partial w$、$\partial C / \partial b$は全訓練例についての平均を取ることで得られます。
この仮定を念頭に置き、私達は訓練例$x$を1つ固定していると仮定し、コスト$C_x$を添字$x$を除いて$C$と書くことにします。最終的に除いた$x$は元に戻しますが、当面は記法が煩わしいので暗に$x$が書かれていると考えます。
</p>
<p>
<!--The second assumption we make about the cost is that it can be written
as a function of the outputs from the neural network:
<center>
<img src="images/tikz18.png"/>
</center>-->
コスト関数に課す2つ目の仮定は、コスト関数はニューラルネットワークの出力の関数で書かれているという仮定です。
<center>
<img src="images/tikz18.png"/>
</center>
<!--For example, the quadratic cost function satisfies this requirement,
since the quadatic cost for a single training example $x$ may be
written as
<a class="displaced_anchor" name="eqtn27"></a>\begin{eqnarray}
C = \frac{1}{2} \|y-a^L\|^2 = \frac{1}{2} \sum_j (y_j-a^L_j)^2,
\tag{27}\end{eqnarray}
and thus is a function of the output activations. -->
例えば、2乗誤差関数はこの要求を満たしています、それは1つの訓練例$x$に対する誤差は以下のように書かれるためです
<a class="displaced_anchor" name="eqtn27"></a>\begin{eqnarray}
C = \frac{1}{2} \|y-a^L\|^2 = \frac{1}{2} \sum_j (y_j-a^L_j)^2.
\tag{27}\end{eqnarray}
<!--Of course, this
cost function also depends on the desired output $y$, and you may
wonder why we're not regarding the cost also as a function of $y$.
Remember, though, that the input training example $x$ is fixed, and so
the output $y$ is also a fixed parameter. In particular, it's not
something we can modify by changing the weights and biases in any way,
i.e., it's not something which the neural network learns. And so it
makes sense to regard $C$ as a function of the output activations
$a^L$ alone, with $y$ merely a parameter that helps define that
function.-->
もちろんこのコスト関数は目標とする出力$y$にも依存しています。
コスト関数を$y$の関数とみなさない事を不思議に思うかもしれません。
しかし、訓練例$x$を固定する事で、出力$y$も固定している事に注意してください。
つまり、出力$y$は重みやバイアスをどのように変化させた所で変化させられる量ではなく、ニューラルネットが学習するものではありません。
ですので、$C$を出力の活性$a^L$単独の関数とみなし、$y$は関数を定義するための単なるパラメータとみなすのは意味のある問題設定です。
</p>
<p></p>
<p></p>
<p></p>
<p><h3><a name="the_hadamard_product_$s_\odot_t$"></a><a href="#the_hadamard_product_$s_\odot_t$"><!--The Hadamard product, $s \odot t$-->
アダマール積 $s \odot t$
</a></h3></p>
<p>
<!--The backpropagation algorithm is based on common linear algebraic
operations - things like vector addition, multiplying a vector by a
matrix, and so on. But one of the operations is a little less
commonly used. In particular, suppose $s$ and $t$ are two vectors of
the same dimension. Then we use $s \odot t$ to denote the
<em>elementwise</em> product of the two vectors. Thus the components of
$s \odot t$ are just $(s \odot t)_j = s_j t_j$. -->
逆伝播アルゴリズムは、ベクトルの足し算やベクトルと行列の掛け算など、一般的な代数操作に基づいています。
しかし、その中で1つあまり一般的ではない操作があります。
$s$と$t$が同じ次元のベクトルとした時、$s \odot t$を2つのベクトルの<em>要素ごと</em>の積とします。つまり、$s \odot t$の要素は$(s \odot t)_j = s_j t_j$です。
<!-- As an example,
<a class="displaced_anchor" name="eqtn28"></a>\begin{eqnarray}
\left[\begin{array}{c} 1 \\ 2 \end{array}\right]
\odot \left[\begin{array}{c} 3 \\ 4\end{array} \right]
= \left[ \begin{array}{c} 1 * 3 \\ 2 * 4 \end{array} \right]
= \left[ \begin{array}{c} 3 \\ 8 \end{array} \right].
\tag{28}\end{eqnarray}
This kind of elementwise multiplication is sometimes called the
<em>Hadamard product</em> or <em>Schur product</em>. We'll refer to it as
the Hadamard product. Good matrix libraries usually provide fast
implementations of the Hadamard product, and that comes in handy when
implementing backpropagation.-->
例えば、
<a class="displaced_anchor" name="eqtn28"></a>\begin{eqnarray}
\left[\begin{array}{c} 1 \\ 2 \end{array}\right]
\odot \left[\begin{array}{c} 3 \\ 4\end{array} \right]
= \left[ \begin{array}{c} 1 * 3 \\ 2 * 4 \end{array} \right]
= \left[ \begin{array}{c} 3 \\ 8 \end{array} \right]
\tag{28}\end{eqnarray}
です。
この種の要素ごとの積はしばしば<em>アダマール積</em>、もしくは<em>シューア積</em>と呼ばれます。
私達はアダマール積と呼ぶことにします。
よく出来た行列ライブラリにはアダマール積の高速な実装が用意されており、逆伝播を実装する際に手軽に利用できます。
</p>
<p><h3><a name="the_four_fundamental_equations_behind_backpropagation"></a><a href="#the_four_fundamental_equations_behind_backpropagation">
<!--The four fundamental equations behind backpropagation-->
逆伝播の基礎となる4つの式
</a></h3></p>
<p>
<!--Backpropagation is about understanding how changing the weights and
biases in a network changes the cost function. Ultimately, this means
computing the partial derivatives $\partial C / \partial w^l_{jk}$ and
$\partial C / \partial b^l_j$. But to compute those, we first
introduce an intermediate quantity, $\delta^l_j$, which we call the
<em>error</em> in the $j^{\rm th}$ neuron in the $l^{\rm th}$ layer.
Backpropagation will give us a procedure to compute the error
$\delta^l_j$, and then will relate $\delta^l_j$ to $\partial C
/ \partial w^l_{jk}$ and $\partial C / \partial b^l_j$.-->
逆伝播は重みとバイアスの値を変えた時にコスト関数がどのように変化するかを把握する方法です。
これは究極的には$\partial C / \partial w^l_{jk}$と$\partial C / \partial b^l_j$とを計算する事を意味します。
これらの偏微分を計算する為にまずは中間的な値$\delta^l_j$を導入します。
この値は$l$番目の層の$j$番目のニューロンの<em>誤差</em>と呼びます。
逆伝播の仕組みを見ると$\delta^l_j$を計算手順と$\delta^l_j$を$\partial C/ \partial w^l_{jk}$や$\partial C / \partial b^l_j$と関連づける方法が得られます。
</p>
<p>
<!--To understand how the error is defined, imagine there is a demon in
our neural network:
<center>
<img src="images/tikz19.png"/>
</center>
The demon sits at the $j^{\rm th}$ neuron in layer $l$. As the input to the
neuron comes in, the demon messes with the neuron's operation. It
adds a little change $\Delta z^l_j$ to the neuron's weighted input, so
that instead of outputting $\sigma(z^l_j)$, the neuron instead outputs
$\sigma(z^l_j+\Delta z^l_j)$. This change propagates through later
layers in the network, finally causing the overall cost to change by
an amount $\frac{\partial C}{\partial z^l_j} \Delta z^l_j$.-->
誤差の定義方法を理解する為にニューラルネットワークの中にいる悪魔を想像してみましょう。
<center>
<img src="images/tikz19.png"/>
</center>
悪魔は$l$番目の層の$j$番目のニューロンに座っているとします。
ニューロンに入力が入ってきた時、悪魔はニューロンをいじって、重みつき入力に小さな変更$\Delta z^l_j$を加えます。
従って、ニューロンは$\sigma(z^l_j)$の代わりに、$\sigma(z^l_j+\Delta z^l_j)$を出力します。
この変化はニューラルネット中の後段の層に伝播し、最終的に全体のコスト関数の値は$\frac{\partial C}{\partial z^l_j} \Delta z^l_j$だけ変化します。
</p>
<p>
<!--Now, this demon is a good demon, and is trying to help you improve the cost, i.e., they're trying to find a $\Delta z^l_j$ which makes the
cost smaller.
Suppose $\frac{\partial C}{\partial z^l_j}$ has a large value (either positive or negative).
Then the demon can lower the cost quite a bit by choosing $\Delta z^l_j$ to have the opposite sign to $\frac{\partial C}{\partial z^l_j}$. By contrast, if $\frac{\partial C}{\partial z^l_j}$ is close to zero, then the demon can't improve the cost much at all by perturbing the weighted input
$z^l_j$.-->
ここで、この悪魔は善良な悪魔で、コスト関数を改善する、つまりコストを小さくするような$\Delta z^l_j$を探そうとするとします。
$\frac{\partial C}{\partial z^l_j}$が大きな値(正でも負も良いです)であるとします。
すると、$\frac{\partial C}{\partial z^l_j}$と逆の符号の$\Delta z^l_j$を選ぶことで、この悪魔はコストをかなり改善させられます。
逆に、もし$\frac{\partial C}{\partial z^l_j}$が$0$に近いと悪魔は重みつき入力$z^l_j$を摂動させてもコストをそれほどは改善できません。
<!--So far as the demon can tell, the neuron is already pretty near optimal*<span class="marginnote">
*This is only the case for small changes $\Delta
z^l_j$, of course. We'll assume that the demon is constrained to
make such small changes.</span>. And so there's a heuristic sense in
which $\frac{\partial C}{\partial z^l_j}$ is a measure of the error in
the neuron.-->
悪魔が判断できる範囲においてはニューロンは既に最適に近い状態だと言えます*<span class="marginnote">
*もちろんこれが正しいのは$\Delta z^l_j$が小さい場合に限ってです。悪魔は微小な変化しか起こせないと仮定しています</span>。
つまり、ヒューリスティックには、$\frac{\partial C}{\partial z^l_j}$はニューラルネットワークの誤差を測定しているという意味を与える事ができます。
</p>
<p>
<!--Motivated by this story, we define the error $\delta^l_j$ of neuron
$j$ in layer $l$ by
<a class="displaced_anchor" name="eqtn29"></a>\begin{eqnarray}
\delta^l_j \equiv \frac{\partial C}{\partial z^l_j}.
\tag{29}\end{eqnarray}
As per our usual conventions, we use $\delta^l$ to denote the vector
of errors associated with layer $l$. Backpropagation will give us a
way of computing $\delta^l$ for every layer, and then relating those
errors to the quantities of real interest, $\partial C / \partial
w^l_{jk}$ and $\partial C / \partial b^l_j$.-->
この話を動機として、$l$番目の層の$j$番目のニューロンの誤差$\delta^l_j$を以下のように定義します
<a class="displaced_anchor" name="eqtn29"></a>\begin{eqnarray}
\delta^l_j \equiv \frac{\partial C}{\partial z^l_j}.
\tag{29}\end{eqnarray}.
慣習に沿って、$\delta^l$で$l$番目の層の誤差からなるベクトルを表します。
逆伝播により、各層での$\delta^l$を計算し、これらを真に興味のある$\partial C / \partial w^l_{jk}$や$\partial C / \partial b^l_j$と関連付けることができます。
</p>
<p>
<!--You might wonder why the demon is changing the weighted input $z^l_j$.
Surely it'd be more natural to imagine the demon changing the output
activation $a^l_j$, with the result that we'd be using $\frac{\partial
C}{\partial a^l_j}$ as our measure of error. In fact, if you do
this things work out quite similarly to the discussion below. But it
turns out to make the presentation of backpropagation a little more
algebraically complicated. -->
悪魔はなぜ重みつき入力$z^l_j$を変えようとするのかを疑問に思うかもしれません。
確かに、出力活性$a^l_j$を変化させ、その結果の$\frac{\partial C}{\partial a^l_j}$を誤差の指標として用いる方が自然かもしれません。
実際そのようにしても、以下の議論は同じように進められます。
しかし、やってみるとわかるのですが、誤差逆伝播の表示が数学的に若干複雑になってしまいます。
<!--So we'll stick with $\delta^l_j =
\frac{\partial C}{\partial z^l_j}$ as our measure of error*<span class="marginnote">
*In
classification problems like MNIST the term "error" is sometimes
used to mean the classification failure rate. E.g., if the neural
net correctly classifies 96.0 percent of the digits, then the error
is 4.0 percent. Obviously, this has quite a different meaning from
our $\delta$ vectors. In practice, you shouldn't have trouble
telling which meaning is intended in any given useage.</span>.-->
ですので、我々は誤差の指標として$\delta^l_j = \frac{\partial C}{\partial z^l_j}$を用いることにします*<span class="marginnote">
*MNISTのような分類問題では、誤差(error)という言葉はしばしば誤分類の割合を意味します。
例えばニューラルネットが96.0%の数字を正しく分類できたとしたら、"error"は4.0%です。
もちろん、これは$\delta$ベクトルとは全く異なる意味です。
実際の文脈ではどちらの意味かで迷うことはないでしょう。
</span>。
</p>
<p>
<!--<strong>Plan of attack:</strong> Backpropagation is based around four
fundamental equations.
Together, those equations give us a way of computing both the error $\delta^l$ and the gradient of the cost function.
I state the four equations below.
Be warned, though: you shouldn't expect to instantaneously assimilate the equations.
Such an expectation will lead to disappointment.
In fact, the backpropagation equations are so rich that understanding them well requires considerable time and patience as you gradually delve deeper into the equations.
The good news is that such patience is repaid many times over.
And so the discussion in this section is merely a beginning, helping you on the way to a thorough understanding of the equations.-->
<strong>攻略計画</strong>
逆伝播は4つの基本的な式を基礎とします。
これらを組み合わせると、誤差$\delta^l$とコスト関数の勾配を計算ができます。
以下でその4つの式を挙げていきますが、1点注意があります:これらの式の意味をすぐに消化できると期待しない方が良いでしょう。
そのように期待するとがっかりするかもしれません。
逆伝播は内容が豊富であり、これらの式は相当の時間と忍耐がかけて徐々に理解できていくものです。
幸いなことに、ここで辛抱しておくと後々何度も報われることになります。
この節の議論はスタート地点に過ぎませんが、逆伝播の式を深く理解する過程の中で役に立つもののはずです。
</p>
<p>
<!--Here's a preview of the ways we'll delve more deeply into the
equations later in the chapter: I'll
<a href="chap2.html#proof_of_the_four_fundamental_equations_(optional)">give a short proof of the equations</a>
, which helps explain why they are true; we'll
<a href="chap2.html#the_backpropagation_algorithm">restate the equations</a>
in algorithmic form as pseudocode, and
<a href="chap2.html#the_code_for_backpropagation">see how</a>
the pseudocode can be implemented as real, running Python code; and, in
<a href="chap2.html#backpropagation_the_big_picture">the final section of the chapter</a>
, we'll develop an intuitive picture of what the backpropagation equations mean, and how someone might discover them from scratch.
Along the way we'll return repeatedly to the four
fundamental equations, and as you deepen your understanding those
equations will come to seem comfortable and, perhaps, even beautiful
and natural.-->
誤差逆伝播の式をより深く理解する方法の概略は以下の通りです。
まず、
<a href="chap2.html#proof_of_the_four_fundamental_equations_(optional)">これらの式の手短な証明</a>を示します。
この証明を見ればなぜこれらの式が正しいのかを理解しやすくなります。
その後、これらの式を<a href="chap2.html#the_backpropagation_algorithm">擬似コードで書き直し</a>、
その擬似コードを<a href="chap2.html#the_code_for_backpropagation">どのように実装できるか</a>を実際のPythonのコードで示します。
<a href="chap2.html#backpropagation_the_big_picture">本章の最後の節</a>では、誤差逆伝播の式の意味を直感的な図で示し、ゼロからスタートしてどのように誤差逆伝播を発見するかを見ていきます。
その道中で、我々は何度も4つの基本的な式に立ち戻ります。
理解が深まるにつれ、これらの式が快適で、美しく自然なものとさえ思えるようになるはずです。
</p>
<p><strong>
<!--An equation for the error in the output layer, $\delta^L$:-->
出力層での誤差$\delta^L$に関する式:
</strong>
<!--The components of $\delta^L$ are given by
<a class="displaced_anchor" name="eqtnBP1"></a>\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j).
\tag{BP1}\end{eqnarray}-->
$\delta^L$の各要素は
<a class="displaced_anchor" name="eqtnBP1"></a>\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j).
\tag{BP1}\end{eqnarray}
です。
<!--This is a very natural expression. The first term on the right,
$\partial C / \partial a^L_j$, just measures how fast the cost is
changing as a function of the $j^{\rm th}$ output activation. If, for
example, $C$ doesn't depend much on a particular output neuron, $j$,
then $\delta^L_j$ will be small, which is what we'd expect. The
second term on the right, $\sigma'(z^L_j)$, measures how fast the
activation function $\sigma$ is changing at $z^L_j$.-->
これはとても自然な表式です。右辺の第1項の$\partial C / \partial a^L_j$はコストが$j$番目の出力活性の関数としてどの程度敏感に変化するかの度合いを測っています。
例えば、$C$が出力層の特定のニューロン(例えば$j$番目とします)にそれほど依存していなければ、我々の期待通り$\delta^L_j$は小さくなります。
一方、右辺の第2項の$\sigma'(z^L_j)$は活性関数$\sigma$が$z^L_j$の変化にどの程度敏感に反応するかの度合いを表しています。
</p>
<p>
<!--Notice that everything in
<span id="margin_147792633206_reveal" class="equation_link">(BP1)</span><span id="margin_147792633206" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_147792633206_reveal').click(function() {$('#margin_147792633206').toggle('slow', function() {});});</script>
is easily computed.-->
ここで注目すべきなのは
<span id="margin_147792633206_reveal" class="equation_link">(BP1)</span><span id="margin_147792633206" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_147792633206_reveal').click(function() {$('#margin_147792633206').toggle('slow', function() {});});</script>
中の全ての項が簡単に計算できる事です。
<!--In particular, we compute $z^L_j$ while computing the behaviour of the network, and it's only a small additional overhead to compute
$\sigma'(z^L_j)$. The exact form of $\partial C / \partial a^L_j$
will, of course, depend on the form of the cost function. However,
provided the cost function is known there should be little trouble
computing $\partial C / \partial a^L_j$. For example, if we're using
the quadratic cost function then $C = \frac{1}{2} \sum_j (y_j-a_j)^2$,
and so $\partial C / \partial a^L_j = (a_j-y_j)$, which obviously is
easily computable.-->
ニューラルネットワークの挙動を計算する間に$z^L_j$を計算でき、さらに若干のオーバーヘッドを加えれば$\sigma'(z^L_j)$も計算できます。従って、第2項は計算できます。
<!--
2014/12/28 Kenta OONO
最後の1文を補足説明として追加しました。
-->
第1項に関してですが、$\partial C / \partial a^L_j$の具体的な表式はもちろんコスト関数の形に依存します。しかし、コスト関数が既知ならば$\partial C / \partial a^L_j$を計算するのは難しくありません。
例えば、2乗誤差コスト関数を用いた場合、$C = \frac{1}{2} \sum_j (y_j-a_j)^2$なので、$\partial C / \partial a^L_j = (a_j-y_j)$という簡単に計算できる式が得られます。
</p>
<p>
<!--Equation
<span id="margin_352512149181_reveal" class="equation_link">(BP1)</span><span id="margin_352512149181" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_352512149181_reveal').click(function() {$('#margin_352512149181').toggle('slow', function() {});});</script>
is a componentwise expression for $\delta^L$.-->
式<span id="margin_352512149181_reveal" class="equation_link">(BP1)</span><span id="margin_352512149181" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_352512149181_reveal').click(function() {$('#margin_352512149181').toggle('slow', function() {});});</script>
は$\delta^L$の各要素に対する表式です。
<!--It's a perfectly good expression, but not the matrix-based form we
want for backpropagation. However, it's easy to rewrite the equation
in a matrix-based form, as
<a class="displaced_anchor" name="eqtnBP1a"></a>\begin{eqnarray}
\delta^L = \nabla_a C \odot \sigma'(z^L).
\tag{BP1a}\end{eqnarray}
Here, $\nabla_a C$ is defined to be a vector whose components are the
partial derivatives $\partial C / \partial a^L_j$.
You can think of $\nabla_a C$ as expressing the rate of change of $C$ with respect to the output activations. -->
この表式自体は悪くはないのですが、逆伝播で欲しい行列を用いた表式ではありません。
この式を行列として書き直すのは容易で、以下の様に書けます
<a class="displaced_anchor" name="eqtnBP1a"></a>\begin{eqnarray}
\delta^L = \nabla_a C \odot \sigma'(z^L).
\tag{BP1a}\end{eqnarray}
ここで、$\nabla_a C$は偏微分$\partial C / \partial a^L_j$を並べたベクトルです。
$\nabla_a C$は出力活性に対する$C$の変化率とみなせます。
<!--It's easy to see that Equations
<span id="margin_744045597073_reveal" class="equation_link">(BP1a)</span><span id="margin_744045597073" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1a" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L = \nabla_a C \odot \sigma'(z^L) \nonumber\end{eqnarray}</a></span><script>$('#margin_744045597073_reveal').click(function() {$('#margin_744045597073').toggle('slow', function() {});});</script>
and
<span id="margin_713595193686_reveal" class="equation_link">(BP1)</span><span id="margin_713595193686" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_713595193686_reveal').click(function() {$('#margin_713595193686').toggle('slow', function() {});});</script>
are equivalent, and for that reason from now on we'll use
<span id="margin_645562843841_reveal" class="equation_link">(BP1)</span><span id="margin_645562843841" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_645562843841_reveal').click(function() {$('#margin_645562843841').toggle('slow', function() {});});</script>
interchangeably to refer to both equations.-->
<span id="margin_744045597073_reveal" class="equation_link">(BP1a)</span><span id="margin_744045597073" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1a" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L = \nabla_a C \odot \sigma'(z^L) \nonumber\end{eqnarray}</a></span><script>$('#margin_744045597073_reveal').click(function() {$('#margin_744045597073').toggle('slow', function() {});});</script>
と
<span id="margin_713595193686_reveal" class="equation_link">(BP1)</span><span id="margin_713595193686" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_713595193686_reveal').click(function() {$('#margin_713595193686').toggle('slow', function() {});});</script>
は同値である事はすぐにわかります。ですので、以下では両者の式を参照するのに
<span id="margin_645562843841_reveal" class="equation_link">(BP1)</span><span id="margin_645562843841" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_645562843841_reveal').click(function() {$('#margin_645562843841').toggle('slow', function() {});});</script>
を用いる事にします。
<!--As an example, in the case of the quadratic cost we have $\nabla_a C = (a^L-y)$, and so the fully matrix-based form of
<span id="margin_864112170226_reveal" class="equation_link">(BP1)</span><span id="margin_864112170226" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_864112170226_reveal').click(function() {$('#margin_864112170226').toggle('slow', function() {});});</script>
becomes
<a class="displaced_anchor" name="eqtn30"></a>\begin{eqnarray}
\delta^L = (a^L-y) \odot \sigma'(z^L).
\tag{30}\end{eqnarray}
As you can see, everything in this expression has a nice vector form,
and is easily computed using a library such as Numpy.-->
例として、2乗誤差コスト関数の例では$\nabla_a C = (a^L-y)$です。
従って行列形式の
<span id="margin_864112170226_reveal" class="equation_link">(BP1)</span><span id="margin_864112170226" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_864112170226_reveal').click(function() {$('#margin_864112170226').toggle('slow', function() {});});</script>
は以下のようになります。
<a class="displaced_anchor" name="eqtn30"></a>\begin{eqnarray}
\delta^L = (a^L-y) \odot \sigma'(z^L).
\tag{30}\end{eqnarray}
見ての通り、この表式内の全ての項がベクトル形式の表式となっており、Numpyなどのライブラリで簡単に計算できます。
</p>
<p><strong><!--An equation for the error $\delta^l$ in terms of the error in the next layer, $\delta^{l+1}$:-->
誤差$\delta^{l}$の次層での誤差$\delta^{l+1}$に関する表式:
</strong>
<!--In particular
<a class="displaced_anchor" name="eqtnBP2"></a>\begin{eqnarray}
\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma'(z^l),
\tag{BP2}\end{eqnarray}
where $(w^{l+1})^T$ is the tranpose of the weight matrix $w^{l+1}$ for
the $(l+1)^{\rm th}$ layer.-->
これは以下の通りです
<a class="displaced_anchor" name="eqtnBP2"></a>\begin{eqnarray}
\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma'(z^l).
\tag{BP2}\end{eqnarray}
ここで、$(w^{l+1})^T$は$(l+1)$番目の層の重み行列$w^{l+1}$の転置です。
<!-- This equation appears complicated, but each element has a nice interpretation.
Suppose we know the error $\delta^{l+1}$ at the $l+1^{\rm th}$ layer.
When we apply the transpose weight matrix, $(w^{l+1})^T$, we can think intuitively of this as moving the error <em>backward</em> through the network, giving us some sort of measure of the error at the output of the $l^{\rm th}$ layer.
We then take the Hadamard product $\odot \sigma'(z^l)$. This
moves the error backward through the activation function in layer $l$,
giving us the error $\delta^l$ in the weighted input to layer $l$.-->
この式は一見複雑ですが、各要素はきちんとした解釈を持ちます。
$(l+1)$番目の層の誤差$\delta^{l+1}$番目が既知だとします。
重み行列の転置$(w^{l+1})^T$を掛ける操作は、直感的には誤差をネットワークとは<em>逆方向</em>に伝播させていると考える事ができます。
従って、この値は$l$番目の層の出力の誤差を測る指標の一種とみなすことができます。
転置行列を掛けた後、$\sigma'(z^l)$とのアダマール積を取っています。
これにより$l$番目の層の活性関数を通してエラーを更に逆方向に伝播しています。
その結果、$l$番目の層の重みつき入力についての誤差$\delta^l$が得られます。
</p>
<p>
<!--By combining
<span id="margin_333455157300_reveal" class="equation_link">(BP2)</span><span id="margin_333455157300" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP2" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma'(z^l) \nonumber\end{eqnarray}</a></span><script>$('#margin_333455157300_reveal').click(function() {$('#margin_333455157300').toggle('slow', function() {});});</script>
with
<span id="margin_168271461280_reveal" class="equation_link">(BP1)</span><span id="margin_168271461280" class="marginequation" style="display: none;"><a href="chap2.html#eqtnBP1" style="padding-bottom: 5px;" onMouseOver="this.style.borderBottom='1px solid #2A6EA6';" onMouseOut="this.style.borderBottom='0px';">\begin{eqnarray}
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j) \nonumber\end{eqnarray}</a></span><script>$('#margin_168271461280_reveal').click(function() {$('#margin_168271461280').toggle('slow', function() {});});</script>
we can compute the error $\delta^l$ for any layer in the network.-->