-
Notifications
You must be signed in to change notification settings - Fork 0
/
MLY_cn.tex
2410 lines (1803 loc) · 151 KB
/
MLY_cn.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
\hypertarget{ux5f15ux8a00}{%
\part{引言}\label{ux5f15ux8a00}}
\hypertarget{ux673aux5668ux5b66ux4e60ux4e3aux4ec0ux4e48ux9700ux8981ux7b56ux7565}{%
\chapter{机器学习为什么需要策略}\label{ux673aux5668ux5b66ux4e60ux4e3aux4ec0ux4e48ux9700ux8981ux7b56ux7565}}
\textbf{机器学习(machine
learning)}已然成为无数重要应用的基石------如今,在网络搜索、垃圾邮件检测、语音识别以及产品推荐等领域,你都能够发现它的身影。如果你或你的团队正在研发一款机器学习相关应用,并期待取得较快进展,那么这本书将会是你的得力助手。
案例:建立猫咪图片初创公司
想象一下,你正在建立一家初创公司,这家公司的产品目标是为猫咪爱好者们提供数不尽的猫咪图片,你打算应用\textbf{神经网络(neural
network)}技术来构建一套计算机视觉系统,通过该系统来识别图片中的猫。
\includegraphics{./img/ch01_cats.jpg}
但悲剧的是,目前你的学习算法准确度还不够好。为了改进这个猫咪检测器,你正面临着巨大的压力。可你该怎么做呢?
你的团队给出了许多建议,例如:
\begin{itemize}
\tightlist
\item
获取更多的数据,即收集更多的猫咪图片
\item
收集更加多样化的训练数据集,图片中猫的位置可能不常见,也有可能颜色奇异,或者拍摄时使用不同的相机参数
\item
通过增加梯度下降的迭代次数,使算法训练得久一些
\item
尝试一个拥有更多层/更多隐藏元/更多参数的,规模更大的神经网络
\item
尝试一个更小的神经网络
\item
尝试加入正则化(例如 L2 正则化)
\item
改变神经网络的架构(激活函数,隐藏元数量等等)
\item
\ldots{}
\end{itemize}
在上面众多的方向中,如果你做出了正确的选择,就将建立起一个效果领先的猫咪图片识别平台,并带领你的公司取得成功。但如果你选择了一个糟糕的方向,则可能因此浪费掉几个月的时间。那么你该如何做出决定呢?
这本书将告诉你应该怎么做。众多的机器学习问题会留下一些线索,告诉你什么样的尝试有用,什么样的没用。而学会解读这些线索将会节省你几个月甚至几年的开发时间。
\hypertarget{ux5982ux4f55ux4f7fux7528ux6b64ux4e66ux6765ux5e2eux52a9ux4f60ux7684ux56e2ux961f}{%
\chapter{如何使用此书来帮助你的团队}\label{ux5982ux4f55ux4f7fux7528ux6b64ux4e66ux6765ux5e2eux52a9ux4f60ux7684ux56e2ux961f}}
完成本书的阅读后,你将进一步理解如何为一个机器学习项目设定技术方向,但团队成员可能不理解你为何要推荐某个特定的方向。有时你希望你的团队定义一个单值评估指标,但他们并不认可你的想法,此时你将如何说服他们?
这正是我决定缩短章节篇幅的原因------这样你就能够将它们打印出来,并且让你的成员仅阅读其中他们需要了解的那几页。
优先级的稍加改变会对团队的生产力产生巨大的影响,我希望你能帮助团队做出一些这样的改变,从而成为团队里的超级英雄!
\hypertarget{ux5148ux4feeux77e5ux8bc6ux4e0eux7b26ux53f7ux8bf4ux660e}{%
\chapter{先修知识与符号说明}\label{ux5148ux4feeux77e5ux8bc6ux4e0eux7b26ux53f7ux8bf4ux660e}}
如果你有学习过机器学习相关课程(例如我在 Coursera 开设的机器学习
MOOC),或者有过监督学习的应用经验,这本书的内容对你而言则不难理解。
本书假设你熟悉\textbf{监督学习(supervised
learning)}概念,即使用标注(labeled)的训练样本\((x,y)\)来学习一个从\(x\)映射到\(y\)的函数。监督学习算法主要包括线性回归(linear
regression)、对数几率回归(logistic
regression,又译作逻辑回归、逻辑斯蒂回归)和神经网络(neural
network)。虽然机器学习的形式有许多种,但当前具备实用价值的大部分机器学习算法都来自于监督学习。
我将经常提及神经网络(也被人们称为``深度学习''
),但你只需对这个概念有基础的了解便可以阅读本书后面的内容。
如果对上文提到的一些概念你还不是很熟悉,可以在 Coursera
观看《机器学习》前三周的课程内容。(课程地址:http://ml-class.org)
\hypertarget{ux89c4ux6a21ux9a71ux52a8ux673aux5668ux5b66ux4e60ux53d1ux5c55}{%
\chapter{规模驱动机器学习发展}\label{ux89c4ux6a21ux9a71ux52a8ux673aux5668ux5b66ux4e60ux53d1ux5c55}}
关于深度学习(神经网络)的一些想法在几十年前就有了,那为什么它们到现在才流行起来了呢?
推动其近期发展的主要因素有两个:
\begin{itemize}
\tightlist
\item
\textbf{数据可用性(data
availability)}:如今人们在数字设备(笔记本电脑、移动设备等)上花费的时间越来越多,对应的数字化行为与活动产生了海量的数据,而这些数据都可以提供给我们的学习算法用来训练。
\item
\textbf{计算规模(computational
scale)}:在近几年前,我们才开始有能力训练出规模足够大的神经网络来使用现有的海量数据集。
\end{itemize}
具体来说,即使你积累了更多的数据,但应用在类似于对数几率回归(logistic
regression)这样较传统的学习算法上,其性能表现(performance)也将趋于
``平稳'' 。这意味着算法的学习曲线将 ``变得平缓''
,就算提供更多的数据,算法的性能也将不再提升。
\includegraphics{./img/ch04_01.png}
传统学习算法似乎并不知道要如何来处理现今这般规模量级的数据。
在同样的监督学习任务下,选择训练一个小型的神经网络(neutral network,
NN),你可能会获得较好的性能表现:
\includegraphics{./img/ch04_02.png}
\begin{quote}
该图显示了在小数据集上应用神经网络的效果会更好,但这种效果与将神经网络应用在大数据集时不太一致。在小数据集情况下,传统算法是否会表现得更好,取决于人们如何进行特征选择工程。例如,假设你只有
20
个训练样本,那么使用对数几率回归还是神经网络可能无关紧要;此时人为的特征选择工程比起选择哪种算法将产生更大的影响。但如果你有
100 万个样本数据,我会赞成你使用神经网络。
\end{quote}
这里的 ``小型神经网络''
指的是只含有少量的隐藏元/层/参数的神经网络。但如果你训练的神经网络规模越来越大,最终很有可能会获得更好的表现:
\includegraphics{./img/ch04_03.png}
因此,为了获得最佳的性能表现,你可以这样做:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
训练大型的神经网络,效果如同上图的绿色曲线;
\item
拥有海量的数据。
\end{enumerate}
在算法训练时,许多其它的细节也同等重要,例如神经网络的架构。但目前来说,提升算法性能的更加可靠的方法仍然是训练更大的网络以及获取更多的数据。完成
1 和 2
的过程异常复杂,本书将对其中的细节作进一步的讨论。我们将从传统学习算法与神经网络中都起作用的通用策略入手,循序渐进地讲解至最前沿的构建深度学习系统的策略。
\hypertarget{ux8bbeux7f6eux5f00ux53d1ux96c6ux4e0eux6d4bux8bd5ux96c6}{%
\part{设置开发集与测试集}\label{ux8bbeux7f6eux5f00ux53d1ux96c6ux4e0eux6d4bux8bd5ux96c6}}
\hypertarget{ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux7684ux5b9aux4e49}{%
\chapter{开发集和测试集的定义}\label{ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux7684ux5b9aux4e49}}
继续分析我们之前提到的猫咪图片的案例:现在你负责运营一个移动端
app,用户会向这个 app 上传许多不同内容的图片。而你希望这个 app
能够从图片中自动地找到含有猫的图片。
你的团队已经在不同的网站下载了含有猫的图片(正样本,又译作正例),以及不含猫的图片(负样本,又译作反例),从而得到了一个巨型的数据集。他们将数据集按照
70\% / 30\% 的比例划分为训练集(training set)和测试集(test
set),并且使用这些数据构建出了一个在训练集和测试集上均表现良好的猫咪检测器。
可当你将这个分类器(classifier)部署到移动应用中时,却发现它的性能相当之差!
这究竟是什么原因导致的呢?
你会发现,从网站上下载下来作为训练集的图片与用户上传的图片有较大的区别------用户上传的图片大部分是使用手机拍摄的,此类图片往往分辨率较低,且模糊不清,采光也不够理想。但由于用来进行训练和测试的数据集图片均取自网站,这就导致了算法不能够很好地泛化(generalize)到我们所关心的手机图片的实际分布(actual
distribution)情况上。
在大数据时代来临前,机器学习中的普遍做法是使用 70\% / 30\%
的比例来随机划分出训练集和测试集。这种做法的确可行,但在越来越多的实际应用中,训练数据集的分布(例如上述案例中的网站图片)与人们最终所关心的分布情况(例如上述案例中的手机图片)往往不同,此时执意采取这样的划分其实是一个坏主意。
我们通常认为:
\begin{itemize}
\item
\textbf{训练集(training set)}用于运行你的学习算法。
\item
\textbf{开发集(development
set)}用于调整参数,选择特征,以及对学习算法作出其它决定。有时也称为\textbf{留出交叉验证集(hold-out
cross validation set)}。
\item
\textbf{测试集(test
set)}用于评估算法的性能,但不会据此改变学习算法或参数。
\end{itemize}
在定义了开发集(development set)和测试集(test
set)后,你的团队将可以尝试许多的想法,比如调整学习算法的参数来探索哪些参数的使用效果最好。开发集和测试集能够帮助你的团队快速检测算法性能。
换而言之,\textbf{开发集和测试集的使命就是引导你的团队对机器学习系统做出最重要的改变。}
所以你应当这样处理:
\begin{quote}
合理地选择开发集和测试集,使之能够代表将来实际数据的情况,并期望算法能够运行良好。
\end{quote}
也就是说你的测试集不应该仅是简单地将可用的数据划分出
30\%,尤其是将来获取的数据(移动端图片)在性质上可能会与训练集(网站图片)有所不同时。
如果你尚未推出移动端
app,那么可能还没有任何的用户,因此也无法获取一些准确的反馈数据来为后续的行动提供依据。但你仍然能够尝试去模拟出这种情况,例如邀请你的朋友用手机拍下照片并发送给你。当你的
app 上线后,就能够使用实际的用户数据对开发集和测试集进行更新。
如果你实在没有途径获取近似未来实际情况的数据,也可以尝试使用已有的网站图片。但你应该意识到这其中的风险,它将导致系统不能够很好地泛化(generalize)。
选择一个理想的开发集和测试集是需要一定投入的,投入多少由你来决定。但请不要武断地认为测试集分布和训练集分布是一致的。尽可能地选择你最终期望算法能够正确处理的样本作为测试集,而不是随便选择一个你恰好拥有的训练集样本。
\hypertarget{ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux5e94ux8be5ux670dux4eceux540cux4e00ux5206ux5e03}{%
\chapter{开发集和测试集应该服从同一分布}\label{ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux5e94ux8be5ux670dux4eceux540cux4e00ux5206ux5e03}}
根据公司的核心市场分布情况,你将猫咪 app 的图像数据划分为 ``美国'' 、
``中国'' 、 ``印度'' 和 ``其它地区''
四个区域。在设立开发集和测试集时,可以尝试将 ``美国'' 和 ``印度''
的数据归于开发集,而 ``中国'' 和 ``其它地区''
的数据归于测试集。也就是说我们可以随机地将其中两个区域的数据分配给开发集,另外两个区域的数据分配给测试集。\textbf{这样做对吗?}
当然不对!
一旦定义好了开发集和测试集,你的团队将专注于提升开发集的性能表现,这就要求开发集能够体现核心任务:使算法在四个地区都表现优异,而不仅仅是其中的两个。
开发集和测试集的分布不同还将导致第二个问题:你的团队所开发的系统可能在开发集上表现良好,却在测试集上表现不佳。我曾目睹过这样的事件,这令人十分沮丧并且还会浪费大量的时间,因此希望你不要重蹈他们的覆辙。
举个例子,假设你的团队开发了一套能在开发集上运行性能良好,却在测试集上效果不佳的系统。如果此时开发集和测试集的分布相同,那么你就能清楚地明白问题所在:算法在开发集上过拟合了(overfit)。解决方案显然就是去获取更多的开发集数据。
但是如果开发集和测试集服从不同的分布,解决方案就不那么明确了。此时可能存在以下一种或者多种情况:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
算法在开发集上过拟合了。
\item
测试集比开发集更难进行预测,尽管算法做得足够好了,却很难有进一步的提升空间。
\item
测试集不一定更难预测,但它与开发集性质并不相同(分布不同)。因此在开发集上表现良好的算法不一定在测试集上也能够取得出色表现。如果是这种情况,大量针对开发集性能的改进工作将会是徒劳的。
\end{enumerate}
构建机器学习应用已并非易事,而开发集和测试集分布的不匹配又会引入额外的不确定性------即提高算法在开发集上的性能表现,是否也能提升其在测试集的性能表现?在这种情况下很难去弄清楚哪些工作是有效的,哪些工作又是在浪费时间,从而会影响到工作的优先级安排。
在处理第三方基准测试(benchmark)问题时,样本提供方很可能已经指定了服从不同分布的开发集和测试集数据。与数据分布一致的情况相比,此时运气带来的性能影响将超过你使用的技术所带来的影响。因此,寻找能够在某个分布上进行训练,同时也能够很好地泛化到另一个分布上的学习算法,同样是一个重要的研究课题。但是如果你想要在特定的机器学习应用上取得进展,而不是搞研究,我建议你尽可能地选择服从相同分布的开发集和测试集数据,这会让你的团队更有效率。
\hypertarget{ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux5e94ux8be5ux6709ux591aux5927}{%
\chapter{开发集和测试集应该有多大?}\label{ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux5e94ux8be5ux6709ux591aux5927}}
开发集的规模应该尽可能的大,至少要能够区分出你所尝试的不同算法之间的性能差异。例如,如果分类器
A 的准确率为 90.0\% ,而分类器 B 的准确率为 90.1\% ,那么使用仅含有 100
个样本的开发集将无法检测出这 0.1\%
的差异。与我所遇到的机器学习问题相比,一个样本容量仅为 100
的开发集,规模太小了。通常来说,开发集的规模应该在 1,000 到 10,000
个样本数据之间,而当开发集样本容量为 10,000 时,你将很有可能检测到这
0.1\% 的性能提升。
\begin{quote}
从理论上来说,我们还可以检测算法的变化是否对开发集存在统计学意义上的显著差异。
然而在实践中,大多数团队并不会执着于此(除非他们正在发表学术研究论文),而且,通常在检测过程中,我并没有发现统计显著性检验能够起到多少作用。
\end{quote}
在类似广告服务、网络搜索和产品推荐等较为成熟且关键的应用领域,我曾见过一些团队非常积极地去改进算法性能,哪怕只有
0.01\%
的提升,因为这将直接影响到公司的利润。在这种情况下,开发集规模可能远超过
10,000 个样本,从而有利于检测到那些不易察觉的效果提升。
那么测试集的大小又该如何确定呢?它的规模应该大到使你能够对整体系统的性能进行一个高度可信的评估。一种常见的启发式策略是将整体
30\% 的数据用作测试集,这适用于总体数据量规模一般的情况(比如 100 至
10,000
个样本)。但是在大数据时代,有时我们所面临的机器学习问题的样本数量将超过
10
个亿,即使开发集和测试集中样本的绝对数量一直在增长,可总体上分配给开发集和测试集的数据比例正在不断降低。可以看出,我们并不需要将开发集和测试集的规模提升到远远超过评估算法性能所需的程度,也就是说,开发集和测试集的规模并不是越大越好。
\hypertarget{ux4f7fux7528ux5355ux503cux8bc4ux4f30ux6307ux6807ux8fdbux884cux4f18ux5316}{%
\chapter{使用单值评估指标进行优化}\label{ux4f7fux7528ux5355ux503cux8bc4ux4f30ux6307ux6807ux8fdbux884cux4f18ux5316}}
所谓的\textbf{单值评估指标(single-number evaluation
metric)}有很多,分类准确率就是其中的一种:待你在开发集(或测试集)上运行分类器之后,它将返回单个数值,代表着样本被正确分类的比例。根据这个指标,如果分类器
A 的准确率为 97%,而分类器 B 的准确率为 90\%,那么我们可以认为分类器 A
更优秀。
相比之下,\textbf{查准率}(Precision,又译作精度)和\textbf{查全率}(Recall,又译作召回率)的组合并不能作为单值评估指标,因为它给出了两个值来对你的分类器进行评估。多值评估指标提高了在算法之间进行优劣比较的难度,假设你的算法表现如下:
\begin{longtable}[]{@{}lll@{}}
\toprule
Classifier & Precision & Recall \\
\midrule
\endhead
A & 95\% & 90\% \\
B & 98\% & 85\% \\
\bottomrule
\end{longtable}
\begin{quote}
猫分类器的查准率指的是在开发集(或测试集)内,那些已经被预测为``猫''的图片之中,实际类别是``猫''的样本比例。而查全率指的是在开发集(或测试集)内,所有实际类别为``猫''的图片中,被正确预测为``猫''的样本比例。人们常常在查准率和查全率之间权衡取舍。
\end{quote}
若根据上方表格中的数值对两个分类器进行比较,显然二者都没有较为明显的优势,因此也无法指导你立即做出选择。
\begin{longtable}[]{@{}llll@{}}
\toprule
Classifier & Precision & Recall & F1 score \\
\midrule
\endhead
A & 95\% & 90\% & \textbf{92.4\%} \\
\bottomrule
\end{longtable}
当你的团队在进行开发时,往往会尝试多种多样的算法架构、模型参数、特征选择,或是一些其它的想法。你可以通过使用单值评估指标(如准确率),根据所有的模型在此指标上的表现,进行排序,从而能够快速确定哪一个模型的性能表现最好。
如果你认为查准率和查全率指标很关键,可以参照其他人的做法,将这两个值合并为一个值来表示。例如取二者的平均值,或者你可以计算
``F1分数(F1 score)''
,这是一种经过修正的平均值计算方法,比起直接取平均值的效果会好一些。
\begin{longtable}[]{@{}llll@{}}
\toprule
Classifier & Precision & Recall & F1 score \\
\midrule
\endhead
A & 95\% & 90\% & \textbf{92.4\%} \\
B & 98\% & 85\% & \textbf{91.0\%} \\
\bottomrule
\end{longtable}
\begin{quote}
如果你想了解更多关于 F1 分数的信息,可以参考
\url{https://en.wikipedia.org/wiki/F1_score}
它是查准率和查全率的调和平均数,计算公式为 2 / ( (1/Precision) +
(1/Recall) ).
\end{quote}
综上可知,当你需要在多个分类器之间进行选择时,使用单值评估指标将帮助你更快速地作出决定。它能给出一个清晰明了的分类器性能排名,从而帮助团队明确后续的改进方向。
最后补充一个例子,假设你在 ``美国'' 、 ``印度'' 、 ``中国'' 和
``其它地区''
这四个关键市场追踪你的猫分类器准确率,并且获得了四个指标。通过对这四个指标取平均值或进行加权平均,你将得到一个单值指标。\textbf{取平均值或者加权平均值是将多个指标合并为一个指标的最常用方法之一。}
\hypertarget{ux4f18ux5316ux6307ux6807ux548cux6ee1ux610fux5ea6ux6307ux6807}{%
\chapter{优化指标和满意度指标}\label{ux4f18ux5316ux6307ux6807ux548cux6ee1ux610fux5ea6ux6307ux6807}}
下面我们来了解一下组合多个评估指标的另一种方法。
假设你既关心学习算法的准确率(accuracy),又在意其运行时间(running
time),请从下面的三个分类器中做出选择:
\begin{longtable}[]{@{}lll@{}}
\toprule
Classifier & Accuracy & Running time \\
\midrule
\endhead
A & 90\% & 80ms \\
B & 92\% & 95ms \\
C & 95\% & 1,500ms \\
\bottomrule
\end{longtable}
将准确率和与运行时间放入单个公式计算后可以导出单个的指标,这似乎不太符合常理,例如:
\[
Accuracy - 0.5 * RunningTime
\]
有一种替代方案可供选择:首先定义一个 ``可接受的'' 运行时间,一般低于
100ms
。接着,在限定的运行时间范围内,尽可能地将分类器的准确率最大化。此时,运行时间代表着
``满意度指标'' ------ 你的分类器必须在这个指标上表现得 ``足够好''
,这里指的是运行时间约束上限为 100ms;而准确度则代表着 ``优化指标''。
如果要考虑\(N\)项不同的标准,比如模型的二进制文件大小(这对移动端 app
尤为重要,因为用户不想下载体积很大的
app)、运行时间和准确率,你或许需要设置\(N-1\)个 ``满意度''
指标,即先要求它们满足一定的值或范围,下一步才是定义一个 ``优化''
指标。例如分别为二进制文件的大小和运行时间设定可接受的阈值,并尝试根据这些限制来优化准确率指标。
最后再举一个例子,假设你正在设计一个硬件设备,该设备可以根据用户设置的特殊
``唤醒词'' 来唤醒系统,类似于 Amazon Echo 的监听词为
``Alexa'',苹果(Apple) Siri 的监听词为 ``Hey Siri'',安卓(Android)
的监听词为 ``Okay Google'',以及百度(Baidu)应用的监听词 ``Hello
Baidu.'' 我们关心的指标是假正例率(false positive
rate,又译作假阳率,误诊率)------
用户没有说出唤醒词,系统却被唤醒了,以及假反例率(false negative
rate,又译作假阴率,漏诊率)------用户说出了唤醒词,系统却没能正确被唤醒。这个系统的一个较为合理的优化对象是尝试去最小化假反例率(优化指标),减少用户说出唤醒词而系统却没能正确唤醒的发生率,同时设置约束为每
24 小时不超过一次误报(满意度指标)。
一旦你的团队在优化评估指标上保持一致,他们将能够取得更快的进展。
\hypertarget{ux901aux8fc7ux5f00ux53d1ux96c6ux548cux5ea6ux91cfux6307ux6807ux52a0ux901fux8fedux4ee3}{%
\chapter{通过开发集和度量指标加速迭代}\label{ux901aux8fc7ux5f00ux53d1ux96c6ux548cux5ea6ux91cfux6307ux6807ux52a0ux901fux8fedux4ee3}}
对于当前面临的新问题,我们很难提前知道使用哪种方法会是最合适的,即使是一个经验丰富的机器学习研究员,通常也需要在尝试多种多样的方法之后才能发现令人满意的方案。当我要建立一个机器学习系统时,往往会这么做:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
尝试一些关于系统构建的\textbf{想法(idea)}。
\item
使用\textbf{代码(code)}实现想法。
\item
根据\textbf{实验(experiment)}结果判断想法是否行得通。(第一个想到的点子一般都行不通!)在此基础上学习总结,从而产生新的想法,并保持这一迭代过程。迭代过程如下图所示:
\end{enumerate}
\includegraphics{./img/ch10_01.png}
迭代过程循环得越快,你也将进展得越快。此时,拥有开发集、测试集和度量指标的重要性便得以体现了:每当你有了一个新想法,在开发集上评估其性能就可以帮助你判断当前的方向是否正确。
假如你没有一个特定的开发集和度量指标,则需要在每次开发新的分类器时把它整合到
app
中,并通过几个小时的体验来了解分类器的性能是否有所改进------这会浪费大量的时间!另外,如果你的团队将分类器的准确率从
95.0% 提高到 95.1%,这 0.1\%
的提升可能很难被检测出来。但是积少成多,通过不断积累这 0.1%
的改进,你的系统将取得巨大的提升。拥有开发集和度量指标,可以使你更快地检测出哪些想法给系统带来了小(或大)的提升
,从而快速确定下一步要研究或者是要放弃的方向。
\hypertarget{ux4f55ux65f6ux4feeux6539ux5f00ux53d1ux96c6ux6d4bux8bd5ux96c6ux548cux6307ux6807}{%
\chapter{何时修改开发集、测试集和指标}\label{ux4f55ux65f6ux4feeux6539ux5f00ux53d1ux96c6ux6d4bux8bd5ux96c6ux548cux6307ux6807}}
每当开展一个新项目时,我会尽快选好开发集和测试集,因为这可以帮团队制定一个明确的目标。
我通常会要求我的团队在不到一周(一般不会更长)的时间内给出一个初始的开发集、测试集和指标,提出一个不太完美的方案并迅速执行
,这比起花过多的时间去思考要好很多。但是一周的时间要求并不适用于成熟的应用程序,譬如垃圾邮件过滤。我也见到过一些团队在已经成熟的系统上花费数月的时间来获得更好的开发集和测试集。
如果你渐渐发现初始的开发集、测试集和指标设置与期望目标有一定差距,那就尽快想办法去改进它们。例如你的开发集与指标在排序时将分类器
A 排在 B 的前面,然而你的团队认为分类器 B
在实际产品上的表现更加优异,这个时候就需要考虑修改开发集和测试集,或者是你的评估指标了。
在上述例子中,有三个主要原因可能导致开发集/评估指标错误地将分类器A排在B前面:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
\textbf{你需要处理的实际数据的分布和开发集/测试集数据的分布情况不同。}
假设你的初始开发集和测试集中主要是成年猫的图片,然而你在 app
上发现用户上传的更多是小猫的图片,这就导致了开发集和测试集的分布与你需要处理数据的实际分布情况不同。在这种情况下,需要更新你的开发集和测试集,使之更具代表性。
\item
\textbf{算法在开发集上过拟合了。}
在开发集上反复评估某个想法会导致算法在开发集上 ``过拟合''
。当你完成开发后,应该在测试集上评估你的系统。如果你发现算法在开发集上的性能比测试集好得多,则表明你很有可能在开发集上过拟合了。在这种情况下,你需要获取一个新的开发集。
如果需要跟踪团队的进度,你可以每周或者每月在测试集上对系统进行一次定期评估。但不要根据测试集指标对算法做出任何决策,包括是否将系统回滚到前一周的状态。坚持这样做会导致算法在测试集上开始过拟合,并且不要再指望通过测试集对你的系统性能进行完全无偏估计(这对发表研究论文以及需要做出商业决策的人来说影响很大)。
\item
\textbf{该指标不是项目应当优化的目标。}
假设你的猫咪 app 当前的指标为分类准确率,而该指标认为分类器 A
优于分类器 B。然而在尝试了两种算法后,你发现分类器 A
竟然允许出现一些色情图片,这实在是难以容忍。应该怎么办呢?
以上这种情况表明,此时的指标并不能辨别出算法 B
在实际产品中的表现是否比 A
更好,因此根据该指标来选择算法并不可靠,也说明此时应该改变现有的评估指标。你可以选择修改指标,使之对出现色情图片的情况执行严重惩罚。此外,强烈建议你选择一个新的指标并为你的团队制定一个新的研究目标,而不是在不可信的指标上耗费太多的时间,最终导致不得不回过头对分类器进行人工选择。
\end{enumerate}
在项目中改变开发集、测试集或者指标是很常见的。一个初始的开发集、测试集和指标能够帮助团队进行快速迭代,当你发现它们对团队的导向不正确时,不要担心,你只需要对其进行修改并确保团队能够了解接下来的新方向。
\hypertarget{ux5c0fux7ed3ux5efaux7acbux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6}{%
\chapter{小结:建立开发集和测试集}\label{ux5c0fux7ed3ux5efaux7acbux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6}}
\begin{itemize}
\tightlist
\item
被选择作为开发集和测试集的数据,应当与你未来计划获取并对其进行良好处理的数据有着相同的分布,而不一定和训练集的数据分布一致。
\item
开发集和测试集的分布应当尽可能一致。
\item
为你的团队选择一个单值评估指标进行优化。当需要考虑多项目标时,不妨将它们整合到一个表达式里(比如对多个误差指标取平均),或者设定满意度指标和优化指标。
\item
机器学习是一个高度迭代的过程:在出现最终令人满意的方案之前,你可能要尝试很多想法。
\item
拥有开发集、测试集和单值评估指标可以帮助你快速评估一个算法,从而加速迭代进程。
\item
当你要探索一个全新的应用时,尽可能在一周内建立你的开发集、测试集和评估指标;而在已经相对成熟的应用上,可以考虑花费更长的时间来执行这些工作。
\item
传统的 70\% / 30\%
训练集/测试集划分对于大规模数据并不适用,实际上,开发集和测试集的比例会远低于
30\%.
\item
开发集的规模应当大到能够检测出算法精度的细微改变,但也不需要太大;测试集的规模应该大到能够使你能对系统的最终性作出一个充分的估计。
\item
当开发集和评估指标对于团队已经不能提供一个正确的导向时,尽快修改它们:(i)
如果算法在开发集上过拟合,则需要获取更多的开发集数据。(ii)
如果开发集与测试集的数据分布和实际数据分布不同,则需要获取新的开发集和测试集。
(iii) 如果评估指标无法对最重要的任务目标进行度量,则需要修改评估指标。
\end{itemize}
\hypertarget{ux57faux7840ux8befux5deeux5206ux6790}{%
\part{基础误差分析}\label{ux57faux7840ux8befux5deeux5206ux6790}}
\hypertarget{ux5febux901fux6784ux5efaux5e76ux8fedux4ee3ux4f60ux7684ux7b2cux4e00ux4e2aux7cfbux7edf}{%
\chapter{快速构建并迭代你的第一个系统}\label{ux5febux901fux6784ux5efaux5e76ux8fedux4ee3ux4f60ux7684ux7b2cux4e00ux4e2aux7cfbux7edf}}
当你想要构建一个新的垃圾邮件过滤系统时,团队可能会有各式各样不同的想法:
\begin{itemize}
\tightlist
\item
收集海量的垃圾邮件作为训练集。例如,设置一个
``蜜罐(honeypot,计算机安全领域又称为诱饵)'',故意地向垃圾邮件系统发送一些虚假邮件地址,以便于能够自动收集到垃圾邮件系统发送到这些地址的垃圾邮件内容。
\item
开发用于理解邮件文本内容的功能。
\item
开发用于理解邮件信封或邮件头部特征的功能,据此了解邮件经由了哪些网络服务器进行中转。
\item
更多\ldots{}
\end{itemize}
虽然我在反垃圾邮件领域已经有了一定的经验,却依然难以保证每次都能顺利在上面的方向中进行抉择。如果你在此领域并不是一个专家,难度会变得更大。
如果在一开始就试图设计和构建出完美的系统会显得有些困难,不妨先花几天时间构建并训练一个最基础的系统。
\begin{quote}
这个建议旨在帮助那些想要构建 AI
应用的读者,而不是那些想要发表研究论文的人,我将会在之后的内容中提到与研究有关的话题。
\end{quote}
或许这个最基础的系统与我们所能构建的 ``最佳''
系统相去甚远,但研究其中的基础功能也是很有价值的:你能快速找到一些线索来帮助你决定在什么方向上投入时间。后面的一些章节会向你剖析该如何解读这些线索。
\hypertarget{ux8befux5deeux5206ux6790ux6839ux636eux5f00ux53d1ux96c6ux6837ux672cux8bc4ux4f30ux60f3ux6cd5}{%
\chapter{误差分析:根据开发集样本评估想法}\label{ux8befux5deeux5206ux6790ux6839ux636eux5f00ux53d1ux96c6ux6837ux672cux8bc4ux4f30ux60f3ux6cd5}}
在使用猫咪 app
时,你注意到它将一些狗的图片误分类为猫了,因为有些狗的样子的确很像猫。
团队中有人建议,加入第三方软件来帮助系统更好地处理狗的样本,但这需要一个月的时间去完成。面对团队成员高涨的热情,你会允许他们这样做吗?
在执行这项计划前,我建议你先预估一下该任务能提升多少系统精度。这样你就能够更加理性地判断是否值得花一个月的时间做这件事,还是将这段时间用于其它任务。
具体而言,你可以这样:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
收集 100 个开发集中被误分类的样本,即造成系统误差的样本。
\item
人为查看这些样本,并计算其中狗的比例。
\end{enumerate}
查看误分类样本的这一过程称为\textbf{误差分析}。在上面的例子中,如果只有
5\%
误分类的图像是狗,那么无论你在狗的问题上做多少的算法改进,最终都不会消除超过原有的
5\% 误差 . 也即是说 5\%
是该计划项目所能起到帮助的``上限''(最大可能值)。所以如果整个系统当前的精度为
90\%(对应误差为 10\%),那么这种改进最多能将精度提升到 90.5\%
(对应误差下降到 9.5\% , 改进了原有 10\% 误差其中的 5\%)。
相反,如果你发现 50\%
的误分类图像是狗,那就可以自信地说这个项目将效果明显,它可以将精度从
90\% 提升到 95\% (相对误差减少 50\%,整体误差由 10\% 下降到 5\%)。
这种简单的误差分析计算过程可以协助你快速评估,从而了解是否需要将处理狗样本的第三方软件进行整合。它为是否值得进行这项投入给出了一个量化的基准。
误差分析也可以帮助你在不同的想法中发现哪些想法将更有前景。我见过许多工程师不愿意进行误差分析,他们更倾向于直接提出一个并实现一个想法,而不考虑该想法是否值得花时间去投入。这是一个普遍的误解:后果可能是你的团队在耗费一个月的时间后却发现收益甚少。
人为检查 100
个样本并不会占用太多的时间。即使你每分钟只检查一张图片,也能够在两小时内完成,而这两个小时可能可以帮你节省一个月的工作量。
\textbf{误差分析}(Error Analysis)
指的是检查被算法误分类的开发集样本的过程,以便帮助你找到造成这些误差的原因。这将协助你确定各个项目的优先级(就像上面的例子所提到的那样)并且获得探索新方向的灵感,我们将会在之后再讨论这些内容。接下来的几章会给出一些误差分析的最佳实践。
\hypertarget{ux5728ux8befux5deeux5206ux6790ux65f6ux5e76ux884cux8bc4ux4f30ux591aux4e2aux60f3ux6cd5}{%
\chapter{在误差分析时并行评估多个想法}\label{ux5728ux8befux5deeux5206ux6790ux65f6ux5e76ux884cux8bc4ux4f30ux591aux4e2aux60f3ux6cd5}}
对于改进猫检测器,你的团队有一些想法:
\begin{itemize}
\tightlist
\item
修正算法将狗误分类为猫的问题。
\item
修正算法将大型猫科动物(比如狮子、黑豹等等,下面用大猫代指)误分类为家猫的问题。
\item
改善系统在模糊图像上的表现。
\item
\ldots{}
\end{itemize}
上述的想法都可以以并行的形式进行评估。通常我会创建一个电子表格,一边查看被误分类的
100
个开发集样本一边完善表格内容,同时我也会留下一些能够帮助我记住特定样本的备注。为了说明这一过程,如下所示是一个仅含四个样本的小型开发集的电子表格:
\begin{longtable}[]{@{}lllll@{}}
\toprule
图像 & 狗 & 大猫 & 模糊 & 备注 \\
\midrule
\endhead
1 & √ & & & 不常见的美国比特犬 \\
2 & & & √ & \\
3 & & √ & √ & 狮子;雨天在动物园拍摄的图片 \\
4 & & √ & & 树木后的美洲豹 \\
占全体比例 & 25\% & 50\% & 50\% & \\
\bottomrule
\end{longtable}
你会发现表格中图片 3
的''大猫''与``模糊''列都被勾选了,另外由于一个样本可能与多个类别都有关联,所以表格底部的百分比加起来可能不是
100 \%.
虽然你可能事先规定了一些类别(狗,大猫,模糊)并进行了手动的分类,但在浏览图像时你可能会受到启发并发现一些新的类别。比如你在浏览一些图片时发现,经过
Instagram
滤镜处理过的图片在识别时对结果造成了误差,你就可以在电子表格中加入一个新的
``Instagram''
列。手动查看误分类样本,并思考人类如何/是否能正确地分类这些样本,这将帮助你发现新的类别以及解决方案。
探寻方法去改进对应误差的类别是很有帮助的。举个例子,如果你能``撤销''
Instagram 的滤镜效果并恢复到原始图片,那么 Instagram
分类就能发挥作用。这不代表你只能局限于那些已有的改进途径的类别;这个过程主要是为了帮助你对一些潜在的,有改进效果的方向培养一定的敏感度。
假设你已检查了 100 个开发集的误分类样本,并得到了下面的表格:
\begin{longtable}[]{@{}lllll@{}}
\toprule
图像 & 狗 & 大猫 & 模糊 & 备注 \\
\midrule
\endhead
1 & √ & & & 不常见的美国比特犬 \\
2 & & & √ & \\
3 & & √ & √ & 狮子;雨天在动物园拍摄的图片 \\
4 & & √ & & 树木后的美洲豹 \\
\ldots{} & \ldots{} & \ldots{} & \ldots{} & \\
占全体比例 & 8\% & 43\% & 61\% & \\
\bottomrule
\end{longtable}
现在你应该可以判断出,对于解决狗的误分类问题项目最多可以改进 8\%
的误差,处理大猫和模糊类则可以改进更多。因此你将更有可能挑选后两者之一进行处理。如果你的团队有足够的人力并行处理多个方向,则可以要求一部分成员处理大猫类别,另一部分成员处理模糊类别。
误差分析并不会产生一个明确的数学公式来告诉你什么任务的优先级最高。你还需要考虑在不同类别上的预期进展以及解决每个类别所需的工作量。
\hypertarget{ux6e05ux6d17ux8befux6807ux6ce8ux7684ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux6837ux672c}{%
\chapter{清洗误标注的开发集和测试集样本}\label{ux6e05ux6d17ux8befux6807ux6ce8ux7684ux5f00ux53d1ux96c6ux548cux6d4bux8bd5ux96c6ux6837ux672c}}
在进行误差分析时,你可能会注意到一些开发集的样本被误标注(mislabeled
)了。此处的``误标注''指的是图像在使用算法处理前,已经被负责标注的人员进行了错误的标注,也就是说,某个样本
\((x,y)\) 的分类标签(label)\(y\)
的值并不正确。例如,一些不是猫的图片被误标注为猫,反之亦然。如果你不确定这些被误标注的图片是否起着关键作用,可以添加一个类别来跟踪记录误标注样本的比例:
\begin{longtable}[]{@{}llllll@{}}
\toprule
图像 & 狗 & 大猫 & 模糊 & 误标注 & 备注 \\
\midrule
\endhead
\ldots{} & & & & & \\
89 & & & & √ & 标注者忽略了背景中的猫 \\
99 & & √ & & & \\
100 & & & & √ & 猫的画像;非真猫 \\
占全体比例 & 8\% & 43\% & 61\% & 6\% & \\
\bottomrule
\end{longtable}
那么这个时候,需要修正开发集中的标签吗?回忆一下当初设立开发集的目标------帮助你快速评估算法性能,从而判断算法
A 和 B
哪一个更好。如果开发集中误标注的部分的确影响了你的判断,那么花时间去修正这些标签就是值得的。
举个例子,假设你的分类器表现如下:
\begin{itemize}
\tightlist
\item
开发集整体精度\ldots\ldots\ldots\ldots\ldots.. 90\% (10\% 整体误差)
\item
误标注样本造成的误差\ldots\ldots{} 0.6\% (6\% 开发集误差)
\item
其它原因造成的误差\ldots\ldots\ldots. 9.4\% (94\% 开发集误差)
\end{itemize}
相对于你正在改进的 9.4\% 误差,误标记的 0.6\%
误差看起来就不那么重要了。在开发集中手动修正误标注样本不会带来不好的影响,但这样的做法并不是必要的:当你不知道整个系统的误差是
10\% 还是 9.4\% 时,这样处理会看起来不错。
假设你不断地改进猫分类器,并达到了以下性能:
\begin{itemize}
\tightlist
\item
开发集整体精度\ldots\ldots\ldots\ldots\ldots.. 98.0\% (2.0\%
整体误差)
\item
误标注样本造成的误差\ldots\ldots{} 0.6\% (30\% 开发集误差)
\item
其它原因造成的误差\ldots\ldots\ldots. 1.4\% (70\% 开发集误差)
\end{itemize}
此时 30\%
的开发集误差是由误标注样本造成的,这对精度估计造成了显著的影响。此时就应该考虑改进开发集样本中的标签质量。处理这些误标注的样本将帮助你找出分类器的误差是接近
1.4\% 还是 2.0\% ,差异显著。
在项目初始阶段容许一些误标注的开发集/测试集样本并不罕见,你可以选择在系统改进到一定程度时再来考虑被误标注的样本,因为这些误差在整体误差中的占比会逐渐增大。
上一章中解释了如何通过算法改进类似于狗、大猫和模糊图片的误差类别,而在本章你学习了如何通过修正数据的标签来处理误标注的样本。
不论你使用什么方式修正开发集标签,请记住,要将同样的方式应用于你的测试集,这可以保持二者服从相同的分布。我们在第
6
章中已经讨论过了这样操作的意义,在那个问题中,团队成员花费了很多时间优化开发集,直到后来才意识到他们正在根据不同的测试集以不同的标准进行判断。
如果你决定改进标签质量,请仔细检查系统中被误分类和正确分类的样本的标签。对于某个样本,可能原始标注和算法预测的标签都是错误的。如果你仅修复系统误分类的样本标签,则有可能在评估中引入偏差。假设你有
1000 个开发集样本,同时分类准确率为 98\%,那么检查 20
个误分类的样本会比检查 980
个正确分类的样本要容易得多。由于在实际操作中,检查误分类样本较为容易,这就导致了开发集会衍生出一定的偏差。如果你只对开发产品和应用感兴趣,如此程度的偏差是可以接受的。但如果你计划在学术论文中引用此结果,可能就需要完全无偏地度量测试集的精度,此时这样做就会出现问题。
\hypertarget{ux5c06ux5927ux578bux5f00ux53d1ux96c6ux62c6ux5206ux4e3aux4e24ux4e2aux5b50ux96c6ux4e13ux6ce8ux5176ux4e00}{%
\chapter{将大型开发集拆分为两个子集,专注其一}\label{ux5c06ux5927ux578bux5f00ux53d1ux96c6ux62c6ux5206ux4e3aux4e24ux4e2aux5b50ux96c6ux4e13ux6ce8ux5176ux4e00}}
假设你有一个含有 5000 个样本的大型开发集,该开发集的误差为 20\%
,这意味着算法将误分类 1000 张开发集图片。人工手动检查这 1000
张图片会花费很长时间,所以我们在误差分析时没必要使用所有的图片。
在这种情况下,我会将开发集明确地分成两个子集,但只人工检查其中的一个。你将使得那些经人工查看的图片更快地过拟合,而另一部分没有被人工查看的图片可以在调参时使用。
继续上面的例子:在该例子中,算法将 5000 个开发集样本中 的1000
个样本误分类。假设我们想要对经人工检查的大约 100
个错误样本(整体的10\%)进行误差分析,你应该随机选择 10\%
的开发集,并将其放入 \textbf{Eyeball
开发集}中(译者注:直译为眼球不妥,保留原文),以提醒我们自己,我们正在用眼睛看着它。(对于语音识别项目,你可能需要听一些音频的剪辑,此时则将数据集称为
Ear 开发集)。因此 Eyeball 开发集将有 500
个样本,其中,预计被算法误分类样本约 100 个。
第二个子集叫做 \textbf{Blackbox
开发集}(直译为黑箱,保留原文),它由剩余的 4500 个样本组成。你可以使用
Blackbox
开发集,通过测量错误率来自动评估分类器,也可以使用它来选择算法或调整超参数。但是,你应该避免将目光局限于此。我们使用术语``
Blackbox ''是因为我们只使用该子集来获得分类器的`` Blackbox ''评价。
为什么我们要把开发集明确分为 Eyeball 开发集和 Blackbox
开发集呢?因为当你在 Eyeball
开发集中建立了对样本的直观认识之后,可使得Eyeball开发集更快地过拟合。如果你发现
Eyeball 开发集的性能比 Blackbox 开发集提升得更快,说明已经过拟合到
Eyeball 开发集了。此时可能需要丢弃它并寻找一个新的 Eyeball
开发集,比如可以将更多 Blackbox 开发集中的样本移到 Eyeball
开发集中,也可以考虑去获取新的标注数据。
将开发集明确地分为 Eyeball 和 Blackbox
开发两个子集将很有帮助,它使你了解在人为的误差分析过程中 Eyeball
开发集何时开始发生过拟合。
\hypertarget{eyeball-ux548c-blackbox-ux5f00ux53d1ux96c6ux8be5ux8bbeux7f6eux591aux5927}{%
\chapter{Eyeball 和 Blackbox
开发集该设置多大?}\label{eyeball-ux548c-blackbox-ux5f00ux53d1ux96c6ux8be5ux8bbeux7f6eux591aux5927}}
Eyeball
开发集应该大到能够让你对算法的主要错误类别有所察觉。如果你正在处理一项实际情况中人类表现良好的任务(例如识别图像中的猫),下面是一些粗略的指导方案:
\begin{itemize}
\tightlist
\item
如果分类器在 Eyeball 开发集上只出现 10
次误判,这个开发集就有点小了。若只有 10
个错误样本,很难准确估计不同错误类别的影响。但如果数据非常少且无法提供更多
Eyeball 开发集样本时,聊胜于无,这将有助于确立项目的优先级。
\item
如果分类器在 Eyeball 开发集样本上出现了约 20
次误判,你将可以开始大致了解主要的误差来源。
\item
如果有约 50 个错误样本,你将能够比较好地了解主要的误差来源。
\item
如果有约 100
个错误样本,你将会非常清楚主要的误差来源。我见过有人手动分析更多的错误样本------有时候多达500个。只要你有足够多的数据,这将是无害的。
\end{itemize}
假设你的分类器有 5\% 的错误率。为了确保在 Eyeball 开发集中有约 100
个误分类的样本,样本开发集应该有约 2000 个样本(因为 0.05 * 2000 =
100)。分类器的错误率越低,为了获得足够多的错误样本进行误差分析,需要的
Eyeball 开发集就越大。
如果你正在处理一项,实际情况中人类也无法很好完成的任务,那么检查 Eyeball
开发集将不会有大的帮助,因为很难找出算法不能正确分类一个样本的原因。此时你可能也不需要建立
Eyeball 开发集,我们会在后面的章节讨论诸如此类问题的指导方案。
Blackbox 开发集该有多大呢?我们先前提到,开发集有约 1000-10000
个样本是正常的 。完善一下该陈述,一个有 1000-10000 个样本的 Blackbox
开发集通常会为你提供足够的数据去调超参和选择模型,即使数据再多一些也无妨。而含有
100 个样本的 Blackbox 开发集虽然比较小,但仍然是有用的。
如果开发集较小,那么你可能没有足够的数据将其分成足够大的 Eyeball
开发集和 Blackbox 开发集来满足目的。相反,你的整个开发集可能需要用作
Eyeball 开发集------即,你将手动检查所有的开发集数据。
在 Eyeball 和 Blackbox 开发集之间,我认为 Eyeball
开发集更加重要(假设你正在研究一个人类能够很好解决的问题,检查这些样本能使得你更有洞悉力)。如果你只有一个
Eyeball
开发集,你可以在这个开发集上进行误差分析、模型选择和超参数调整,缺点是过拟合开发集的风险更大。
如果你有充足的数据,那么 Eyeball
开发集的大小将主要取决于你能够手动分析样本的时间。实际上,我很少看到有人手动分析超过
1000 个错误样本。
\hypertarget{ux5c0fux7ed3ux57faux7840ux8befux5deeux5206ux6790}{%
\chapter{小结:基础误差分析}\label{ux5c0fux7ed3ux57faux7840ux8befux5deeux5206ux6790}}
\begin{itemize}
\tightlist
\item
当你开始一个新项目,尤其是在一个你不擅长的领域开展项目时,很难正确预判出最有前景的方向。
\item
所以,不要在一开始就试图设计和构建一个完美的系统。相反,应尽可能快(例如在短短几天内)地构建和训练一个系统雏形。然后使用误差分析法去帮助你识别出最有前景的方向,并据此不断迭代改进你的算法。
\item
通过手动检查约 100
个被算法错误分类的开发集样本来执行误差分析,并计算主要的错误类别。使用这些信息来确定优先修正哪种类型的错误。
\item
考虑将开发集分为人为检查的 Eyeball 开发集和非人为检查的 Blackbox
开发集。如果在 Eyeball 开发集上的性能比在 Blackbox
开发集上好很多,说明你已过拟合 Eyeball
开发集,下一步应该考虑为其获取更多数据。
\item
Eyeball
开发集应该足够大,以便于算法有足够多的错误分类样本供你分析。对大多数应用来说,含有1000-10000个样本的
Blackbox 开发集已足够。
\item
如果你的开发集不够大,无法按照这种方式进行拆分,那么就使用 Eyeball
开发集来执行人工误差分析、模型选择和调超参。
\end{itemize}
\hypertarget{ux504fux5deeux4e0eux65b9ux5dee}{%
\part{偏差与方差}\label{ux504fux5deeux4e0eux65b9ux5dee}}
\hypertarget{ux504fux5deeux548cux65b9ux5deeux8befux5deeux7684ux4e24ux5927ux6765ux6e90}{%
\chapter{偏差和方差:误差的两大来源}\label{ux504fux5deeux548cux65b9ux5deeux8befux5deeux7684ux4e24ux5927ux6765ux6e90}}
假设你的训练集、开发集和测试集都来自相同的分布,那么每次你都应该试图去获取更多的训练数据,因为这样能单独提高性能,对吗?
拥有更多的数据是无害的,然而它并不总是如我们期望的那样有帮助。有时获取更多的数据可能是在浪费时间。那么,何时才应该添加数据呢?
机器学习中有两个主要的误差来源:偏差和方差。理解它们将协助你决定是否该添加数据,并依此合理安排时间去执行其它的策略来提升性能。
假设你希望构建一个误差为 5\% 的猫识别器。而目前的训练集错误率为
15\%,开发集错误率为
16\%。在这种情况下,添加数据对结果可能不会有太多帮助。你应该关注其他改进策略。实际上,在你的训练集上添加过多样本只会让你的算法难以在训练集上做的更好。(我们在后面章节中解释了原因)
如果你在训练集上的错误率是 15\%(即 85\% 的精度),但你的目标是 5\%
错误率(95\%
精度),那么首先要解决的问题是提高算法在训练集上的性能。算法在开发/测试集上的性能通常比在训练集上要差。所以,如果算法在已知样本上达到了
85\% 的精度,那么是不可能在未知样本上达到 95\% 精度的。
如上所述,假设你的算法在开发集上有 16\% 的错误率(84\% 精度),我们将这
16\% 的错误率分为两部分:
\begin{itemize}
\tightlist
\item
第一部分是算法在训练集上的错误率。在本例中,它是
15\%。我们非正式地将它作为算法的\textbf{偏差(bias)}。
\item
第二部分指的是算法在开发集(或测试集)上的表现比训练集上差多少。在本例中,开发集表现比训练集差
1\%。我们非正式地将它作为算法的\textbf{方差(variance)}。
\end{itemize}
\begin{quote}
在统计学领域有着更多关于偏差和方差的正式定义,但不必担心。粗略地说,偏差指的是算法在大型训练集上的错误率;方差指的是算法在测试集上的表现低于训练集的程度。当你使用均方误差(MSE)作为误差度量指标时,你可以写下偏差和方差对应的两个公式,并且证明\textbf{总误差=偏差+方差}。但在处理机器学习问题时,此处给出的偏差和方差的非正式定义已经足够。
\end{quote}
一些学习算法的优化能解决误差来源的第一个部分------偏差,并且提高算法在训练集上的性能;而另一些优化能解决第二个部分------方差,并帮助算法从训练集到开发/测试集上更好地泛化。为了选择最有成效的改变方向,了解二者哪一方更需解决是很有用的。
\begin{quote}
还有一些方法能够对系统架构做出较大改变,同时减少偏差和方差。但是这些方法往往难以鉴定和实现。
\end{quote}
建立对偏差和方差的良好直觉将帮助你为算法选择出有效的改进策略。
\hypertarget{ux504fux5deeux548cux65b9ux5deeux4e3eux4f8b}{%
\chapter{偏差和方差举例}\label{ux504fux5deeux548cux65b9ux5deeux4e3eux4f8b}}
思考一下,我们的``猫分类''任务目标:一个``理想的''分类器(比如人类)在这个任务中能够取得近乎完美的表现。
假设你的算法表现如下:
\begin{itemize}
\tightlist
\item
训练错误率 = 1\%
\item
开发错误率 = 11\%
\end{itemize}
这其中存在什么问题呢?根据前一章的定义,我们估计偏差为 1\%,方差为
10\%(=11\%-1\%)。因此,它有一个很高的方差(\textbf{high
variance})。虽然分类器的训练误差非常低,但是并没有成功泛化到开发集上。这也被叫做过拟合(\textbf{overfitting})。
接下来,考虑如下情况:
\begin{itemize}
\tightlist
\item
训练错误率 = 15\%
\item
开发错误率 = 16\%
\end{itemize}
我们估计偏差为 15\%,方差为 1\%。该分类器的错误率为
15\%,没有很好地拟合训练集,但它在开发集上的误差不比在训练集上的误差高多少。因此,该分类器具有较高的偏差(\textbf{high
bias}),而方差较低。我们称该算法是欠拟合(\textbf{underfitting})的。
下面,考虑如下情况:
\begin{itemize}
\tightlist
\item
训练错误率 = 15\%
\item
开发错误率 = 30\%
\end{itemize}
我们估计偏差为 15\%,方差为 15\%。该分类器有高偏差和高方差(\textbf{high
bias and high
variance}):它在训练集上表现得很差,因此有较高的偏差,而它在开发集上表现更差,因此方差同样较高。由于该分类器同时过拟合和欠拟合,过拟合/欠拟合术语很难准确应用于此。
最后,考虑如下情况:
\begin{itemize}
\tightlist
\item
训练错误率 = 0.5\%
\item
开发错误率 = 1\%
\end{itemize}
该分类器效果很好,它具有低偏差和低方差。恭喜获得这么好的表现!
\hypertarget{ux4e0eux6700ux4f18ux9519ux8befux7387ux6bd4ux8f83}{%
\chapter{与最优错误率比较}\label{ux4e0eux6700ux4f18ux9519ux8befux7387ux6bd4ux8f83}}
在我们的``猫咪识别''案例中,``理想''错误率------即一个``最优''分类器应该达到的值------接近
0\%。在几乎所有情况下,人类总是可以识别出图片中的猫。因此,我们希望机器也能够有这样优秀的表现。
若换作其他问题,难度则更大:假设你正在构建一个语音识别系统,并发现 14\%
的音频片段背景噪声太多,或者十分难以理解,导致即使是人类也无法识别出所说的内容。在这种情况下,即使是``最优''的语音识别系统也可能约有
14\% 的误差。
假设在这个语音识别问题上,你的算法达到:
\begin{itemize}
\tightlist
\item
训练错误率 = 15\%
\item
开发错误率 = 30\%
\end{itemize}
算法在训练集上的表现已经接近最优错误率
14\%,因此在偏差上或者说在训练集表现上没有太大的提升空间。然而,算法没有很好地泛化到开发集上,在方差造成的误差上还有很大的提升空间。
这个例子和前一章的第三个例子类似,都有 15\% 的训练错误率和 30\%
的开发错误率。如果最优错误率接近 0\%,那么 15\%
的训练错误率则留下了很大的提升空间,这表明降低偏差可能有益。但如果最优错误率是
14\%,那么 15\%
的训练错误率表现告诉我们,在分类器的偏差方面几乎没有改进的余地。
对于最佳错误率远超零的状况,有一个对算法误差更详细的分解。继续使用上述语音识别的例子,可以将
30\% 的总开发集误差分解如下(类似的分析可以应用于测试集误差):
\begin{itemize}
\tightlist
\item
\textbf{最优错误率(``不可避免偏差'')}:14\%。假设我们决定,即使是世界上最好的语音系统,仍会有
14\% 的误差。我们可以将其认为是学习算法的偏差``不可避免''的部分。
\item
\textbf{可避免偏差}:1\%。即训练错误率和最优误差率之间的差值。
\item
\textbf{方差}:15\%。即开发错误和训练错误之间的差值。
\end{itemize}
\begin{quote}
如果可避免偏差值是负的,即算法在训练集上的表现比最优错误率要好。这意味着你正在过拟合训练集,并且算法已经过度记忆(over-memorized)训练集。你应该专注于有效降低方差的方法,而不是选择进一步减少偏差的方法。
\end{quote}
为了将这与我们之前的定义联系起来,偏差和可避免偏差关系如下:
偏差 = 最佳误差率(``不可避免偏差'')+ 可避免的偏差
\begin{quote}
使用这些定义是为了更好地帮助读者理解如何改进学习算法。这些定义与统计学家定义的偏差和方差不同。从技术角度上说,这里定义的``偏差''应该叫做``我们认为是偏差的误差'';另外``可避免偏差''应该叫做``我们认为学习算法的偏差超过最优错误率的误差''。
\end{quote}
这个``可避免偏差''反映了算法在训练集上的表现比起``最优分类器''差多少。
方差的概念和之前保持一致。理论上来说,我们可以通过训练一个大规模训练集将方差减少到接近零。因此只要拥有足够大的数据集,所有的方差都是可以``避免的'',所以不存在所谓的``不可避免方差''。
再考虑一个例子,该例子中最优错误率是 14\%,我们有:
\begin{itemize}
\tightlist
\item
训练误差 = 15\%
\item
开发误差 = 16\%
\end{itemize}
我们在前一章称之为高偏差分类器,现在可避免的偏差误差是 1\%,方差误差约为
1\%。因此,算法已经做的很好了,几乎没有提升的空间。它只比最佳错误率低
2\%。
从这些例子中我们可以看出,了解最优错误率有利于指导我们的后续工作。在统计学上,最优错误率也被称为\textbf{贝叶斯错误率(Bayes
error rate)},或贝叶斯率。
如何才能知道最优错误率是多少呢?对于人类擅长的任务,例如图片识别或音频剪辑转录,你可以让普通人提供标签,然后测评这些人为标签相对于训练集标签的精度,这将给出最优错误率的估计。如果你正在解决一项人类也很难解决的问题(例如预测推荐什么电影,或向用户展示什么广告),这将很难去估计最优错误率。
在``与人类表现比较''(第33\textasciitilde35章)这一节中,我将更详细地讨论学习算法的表现和人类表现相比较的过程。
在前面几个章节中,你学习了如何通过查看训练集和开发集的错误率来估计可避免/不可避免的偏差和方差。下一章将讨论如何据此来判断该优先减少偏差还是方差。项目当前的问题是高偏差(可避免偏差)还是高方差,将导致你采用截然不同的方法。请继续阅读。
\hypertarget{ux5904ux7406ux504fux5deeux548cux65b9ux5dee}{%
\chapter{处理偏差和方差}\label{ux5904ux7406ux504fux5deeux548cux65b9ux5dee}}
下面是处理偏差和方差问题最简单的形式:
\begin{itemize}
\tightlist
\item
如果具有较高的可避免偏差,那么加大模型的规模(例如通过添加层/神经元数量来增加神经网络的大小)。
\item
如果具有较高的方差,那么增加训练集的数据量。
\end{itemize}
如果你可以加大神经网络的规模且无限制地增加训练集数据,那么许多机器学习问题都可以取得很好的效果。
实际上,不断加大网络的规模使你终将遇到算力问题,因为训练一个大型模型需要很多时间。另外,你也可能会耗尽获取更多训练数据的能力。(即使在网上,猫图片的数量也是有限的)
不同的模型架构(例如不同的神经网络架构)对于你的问题将有不同的偏差/方差值。近期,不少深度学习研究已经开发出很多新的模型架构。所以,如果你在使用神经网络,学术文献可能会是一个很好的灵感来源,在
Github
上也有许多不错的开源实现。但尝试新架构的结果要比简单地加大模型规模或添加数据的形式更难以预测。
加大模型的规模通常可以减少偏差,但也可能会增加方差和过拟合的风险。然而,这种过拟合风险通常只在你不使用正则化技术的时候出现。如果你的算法含有一个精心设计的正则化方法,通常可以安全地加大模型的规模,而不用担心增加过拟合风险。