-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
executable file
·3029 lines (2266 loc) · 230 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[雪地]]></title>
<link href="http://yinzo.github.io/atom.xml" rel="self"/>
<link href="http://yinzo.github.io/"/>
<updated>2017-06-11T02:07:25+08:00</updated>
<id>http://yinzo.github.io/</id>
<author>
<name><![CDATA[]]></name>
</author>
<generator uri="http://www.mweb.im/">MWeb</generator>
<entry>
<title type="html"><![CDATA[CS229 学习笔记 Part3]]></title>
<link href="http://yinzo.github.io/14968173531750.html"/>
<updated>2017-06-07T14:35:53+08:00</updated>
<id>http://yinzo.github.io/14968173531750.html</id>
<content type="html"><![CDATA[
<ul>
<li>
<a href="#toc_0">SVM</a>
<ul>
<li>
<a href="#toc_1">函数间隔和几何间隔 (Functional and geometric margin)</a>
</li>
<li>
<a href="#toc_2">最优间隔分类器 (Optimal margin classifier)</a>
</li>
<li>
<a href="#toc_3">拉格朗日对偶问题</a>
<ul>
<li>
<a href="#toc_4">原始问题</a>
</li>
<li>
<a href="#toc_5">对偶问题</a>
</li>
<li>
<a href="#toc_6">KKT 条件</a>
</li>
</ul>
</li>
<li>
<a href="#toc_7">回到最优间隔分类器问题</a>
</li>
<li>
<a href="#toc_8">核 (Kernels)</a>
</li>
<li>
<a href="#toc_9">正则化</a>
</li>
<li>
<a href="#toc_10">SMO 算法</a>
<ul>
<li>
<a href="#toc_11">坐标上升算法 (Coordinate ascent)</a>
</li>
<li>
<a href="#toc_12">SMO</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="toc_0">SVM</h2>
<p>CS229 对于 SVM 的理论解释是我学习到的最详细也是最好的一份资料了,对比对象有周志华《机器学习》、《机器学习实战》、Coursera 上的 Machine Learning 等。相当推荐学习 CS229。</p>
<p>分类间隔 (Margin) 和 SVM 的优化目标『最大化分类间隔』这里就不多说了,很好理解,主要还是记录 CS229 中学到的新内容。一个数据点离分类边界 (decision boundary) 越远,则确信度越高。我们的优化目标也相当于寻找一个远离所有数据点的分类边界,当然,前提是这个分类边界得到的分类都正确。</p>
<p>SVM 的一些特殊定义也提及一下,</p>
<ul>
<li>\(y\) 的取值不是 \(\{0,1\}\) 而是 \(\{-1,1\}\)。</li>
<li>假设函数 \(h_{w,b}(x) = g(w^Tx+b)\) 中,我们把截距项单独写出来,便与后续的计算。</li>
<li>我们的分类器输出结果会直接是 1 或 -1,不像 Logistic 回归那样先输出 \(y\) 是某一类的概率。</li>
</ul>
<span id="more"></span><!-- more -->
<h3 id="toc_1">函数间隔和几何间隔 (Functional and geometric margin)</h3>
<p>函数间隔 \(\hat{\gamma}\) 的定义如下<br/>
\[\hat{\gamma}^{(i)} = y^{(i)}(w^Tx+b)\]</p>
<p>\[\hat{\gamma} = \min_{i=1,\cdots,m} \hat{\gamma}^{(i)}\]</p>
<p>函数间隔,是所有数据点的函数输出中的最小值,函数间隔越大,说明这个点分类的自信越高。但是可以发现,我们等比例放大参数 \(w\) 和 \(b\) 的数值大小,可以使得函数间隔变大,并且分类间隔直线的位置并不会移动。于是我们又定义了几何间隔</p>
<p><img src="media/14968173531750/14968200759292.jpg" alt=""/></p>
<p>注意图中的点 A,我们需要求 A 到分类边界的距离 \(\gamma^{(i)}\),就是我们现在需要求的值。</p>
<p>因为 A 代表着 \(x^{(i)}\), 所以我们可以得到点 B 的公式为 \(x^{(i)} - \gamma^{(i)} \cdot w/\|w\|\),并且点 B 在分类边界上,我们有 \(w^Tx+b=0\),因此</p>
<p>\[w^T\left(x^{(i)}-\gamma^{(i)}\frac{w}{\|w\|}\right)+b=0\]</p>
<p>\[\gamma^{(i)} = \frac{w^Tx^{(i)}+b}{\|w\|} = \left(\frac{w}{\|w\|}\right)^Tx^{(i)}+\frac{b}{\|w\|}\]</p>
<p>再把函数的正负性考虑进去,最终我们得到</p>
<p>\[\gamma^{(i)} = y^{(i)}\left(\left(\frac{w}{\|w\|}\right)^Tx^{(i)}+\frac{b}{\|w\|}\right)\]</p>
<p>注意如果 \(\|w\| = 1\),则函数间隔等于几何间隔——这给了我们一个联系起这两种间隔的思路。并且,几何间隔并不受参数的等比缩放影响,这个特性在后面的推导中很有用。比如说我们在拟合 w 和 b 的时候,我们需要对他进行一个缩放以满足 \(\|w\| = 1\) 这个约束,那么我们并不需要担心几何间隔会因此改变。</p>
<p>最后,对于一组大小为 m 的训练集,我们同样定义</p>
<p>\[\gamma = \min_{i=1,\cdots,m}\gamma^{(i)}\]</p>
<h3 id="toc_2">最优间隔分类器 (Optimal margin classifier)</h3>
<p>当我们假设数据是线性可分的时候,也就是存在一个超平面能够将正类和负类分隔开,这时我们如何找到这个最大化集合间隔的分类器呢,有以下优化问题</p>
<p>\[\begin{eqnarray}<br/>
\max_{\gamma,w,b}&&\gamma \nonumber \\<br/>
s.t. & &y^{(i)}(w^Tx^{(i)}+b)\geq \gamma,i=1,\cdots,m \nonumber \\<br/>
&&\|w\|=1 \nonumber \\<br/>
\end{eqnarray}\]</p>
<p>我们限制了 \(\|w\|=1\),所以几何间隔和函数间隔此时是相等的。因此,解决这个优化问题,我们能够求出对于这个训练集最大的几何间隔。但是,"\(\|w\|=1\)“ 这个限制不怎么友好(non-convex),我们无法套用现成的优化求解算法来解决它,所以我们尝试把它变形一下</p>
<p>\[\begin{eqnarray}\max_{\hat{\gamma},w,b} &&\frac{\hat{\gamma}}{\|w\|} \nonumber \\<br/>
s.t. && y^{(i)}(w^Tx^{(i)}+b)\geq \hat{\gamma},\ \ i=1,\cdots,m \nonumber \\<br/>
\end{eqnarray}\]</p>
<p>现在我们尝试最大化 \(\hat{\gamma}/\|w\|\),这个优化问题和上面的那个是等价的,并且我们成功抛弃掉了那个不友好的限制条件。但是,现在变成我们的目标函数不怎么友好了 (non-convex)。</p>
<p>让我们继续尝试变形。回想起我们能够随意等比例缩放 \(w,b\),这非常关键。我们限制\(\hat{\gamma}=1\),则我们的优化目标可以变为最大化 \(\hat{\gamma}/\|w\| = 1/\|w\|\),也就相当于最小化 \(\|w\|^2\)</p>
<p>\[\begin{eqnarray}<br/>
\min_{\gamma,w,b} &&\frac{1}{2}\|w\|^2 \nonumber \\<br/>
s.t. && y^{(i)}(w^Tx^{(i)}+b)\geq 1,\ \ i=1,\cdots,m \nonumber \\<br/>
\end{eqnarray}\]</p>
<p>现在我们终于将问题转化为一个能够使用现成计算包解决的优化问题了。上面的优化问题是一个凸二次优化问题,并且只有一个线性约束。但是相比使用现成计算包直接解决这个优化问题,我们还有一个解决办法,并且解决过程中还引出了更加重要的 kernel 概念。</p>
<h3 id="toc_3">拉格朗日对偶问题</h3>
<h4 id="toc_4">原始问题</h4>
<p>有『等式约束条件』和『不等式约束条件』下的优化问题,能够通过拉格朗日方法,转换为无约束的拉格朗日函数优化问题。<br/>
比如说<br/>
\[\begin{eqnarray}<br/>
\min_w && f(w)\nonumber \\<br/>
s.t. &&g_i(w) \leq 0, \ \ i=1,\cdots,k\nonumber \\<br/>
&&h_i(w)=0, \ \ i=1,\cdots,l \nonumber \\<br/>
\end{eqnarray}\]<br/>
通过引入拉格朗日乘数 \(\alpha_i, \beta_i\) ,我们能够得到拉格朗日函数</p>
<p>\[\mathcal{L}(w,\alpha,\beta) = f(w) + \sum^k_{i=1}\alpha_ig_i(w)+\sum^l_{i=1}\beta_i h_i(w)\]</p>
<p>此时,若我们对拉格朗日函数求最大值的优化问题</p>
<p>\[\theta_{\mathcal{P}}(w) = \max_{\alpha,\beta:\alpha_i \geq 0} \mathcal{L}(w,\alpha,\beta)\]</p>
<p>我们发现,当 \(h_i(w)\) 等于零的时候,即 \(w\) 的取值符合原函数约束时,拉格朗日函数等于原函数;当\(w\) 的取值不符合原函数约束时,即 \(h_i(w)\) 不等于零的时候,总能通过使 \(\beta_i\) 等于正无穷或负无穷,使得 \(\theta_{\mathcal{P}}(w)\) 等于正无穷。</p>
<p>\[\theta_{\mathcal{P}}(w) = \left\{ <br/>
\begin{array}{ll}<br/>
f(w) &若 w 满足原问题约束 \\<br/>
\infty &其他 \\<br/>
\end{array}<br/>
\right.\]</p>
<p>利用这个性质,我们再对 \(\theta_{\mathcal{P}}(w)\) 函数化为最小值的优化问题,则得到</p>
<p>\[\min_w \theta_{\mathcal{P}}(w) = \min_w \max_{\alpha,\beta:\alpha_i \geq0} \mathcal{L}(w,\alpha,\beta)\]</p>
<p>求解这一个优化问题,我们就将得到在满足原问题约束条件下,对于原目标函数 \(f(w)\) 的最小值优化问题的解,因为不符合约束条件的参数会使得函数变为正无穷,从而被符合约束条件的参数筛选掉。</p>
<p>\[\min_w \max_{\alpha,\beta:\alpha_i \geq0} \mathcal{L}(w,\alpha,\beta)\]</p>
<p>这个优化问题,就称为拉格朗日函数的原始问题 (primal problem)。</p>
<h4 id="toc_5">对偶问题</h4>
<p>那么,对偶问题是什么呢。可以看到,原始问题中有两个最值优化步骤。将这两个最值优化步骤对调一下顺序,就成为了拉格朗日函数的对偶问题 (dual problem)</p>
<p>我们称,原始问题最终求得的最优解为 \(p^*\),对偶问题的最优解为 \(d^*\)。我们很容易想到</p>
<p>\[d^* = \max_{\alpha,\beta:\alpha_i \geq0} \min_w \mathcal{L}(w,\alpha,\beta) \leq \min_w \max_{\alpha,\beta:\alpha_i \geq0} \mathcal{L}(w,\alpha,\beta) = p^*\]</p>
<p>并且,在一定条件下,我们有</p>
<p>\[d^* = p^*\]</p>
<h4 id="toc_6">KKT 条件</h4>
<p>若满足以下假设,必定存在 \(w^*, \alpha^*, \beta^*\) 是原始问题的解。<br/>
1. 函数 \(f\) 和 \(g_i\) 都是凸函数<br/>
2. \(h_i\) 函数是仿射函数(\(h_i\) 满足 \(h_i(w) = a_i^Tw+b_i\) 形式,称 \(h_i\) 为仿射函数 (Affine))</p>
<p>并且,若 \(w^*, \alpha^*, \beta^*\) 同时满足 <strong>KKT 条件</strong>,则此解同时是对偶问题和原始问题的解。<br/>
\[\begin{eqnarray}<br/>
\frac{\partial}{\partial w_i}\mathcal{L}(w^*,\alpha^*,\beta^*) &=& 0,i=1,\cdots,n \\<br/>
\frac{\partial}{\partial \beta_i}\mathcal{L}(w^*,\alpha^*,\beta^*) &=& 0,i=1,\cdots,l \\<br/>
\alpha_i^*g_i(w^*) &=& 0, i=1,\cdots,k \\<br/>
g_i(w^*) &\leq& 0, i=1,\cdots,k \\<br/>
\alpha^* &\geq& 0, i=1,\cdots,k \\<br/>
\end{eqnarray}\]</p>
<h3 id="toc_7">回到最优间隔分类器问题</h3>
<p>现在,我们尝试使用拉格朗日方法来解决我们的最优间隔分类器优化问题</p>
<p>\[\min_{\gamma,w,b} \frac{1}{2} \|w\|^2\]<br/>
\[s.t.\ \ y^{(i)}(w^Tx^{(i)} +b)\geq 1,\ i=1,\cdots,m\]</p>
<p>我们将约束条件化为以下形式</p>
<p>\[g_i(w) = -y^{(i)}(w^Tx^{(i)}+b) + 1 \leq 0\]</p>
<p>则我们根据 KKT 条件中的公式(3)得知,只有当函数间隔恰好等于 1 时,\(g_i(w) = 0\),\(\alpha_i\) 才有可能大于0. 我们称 \(\alpha_i > 0\) 的数据点为支持向量 (support vectors),也就是支持向量机的名称由来。并且支持向量的数量一般远少于训练集样本数量,这是后续算法优化的一个很重要的特性。</p>
<p>我们求出原优化问题的拉格朗日函数</p>
<p>\[ \begin{equation} \mathcal{L}(w,b,\alpha) = \frac{1}{2}\|w\|^2-\sum^m_{i=1}\alpha_i[y^{(i)}(w^Tx^{(i)}+b)-1] \end{equation} \]</p>
<p>我们求解对偶问题,首先使用 \(w,b\) 为参数,求解拉格朗日函数的最小值。则我们求函数分别对于 \(w,b\) 的偏导数并使其等于零</p>
<p>\[\nabla_w\mathcal{L}(w,b,\alpha) = w-\sum^m_{i=1}\alpha_iy^{(i)}x^{(i)}= 0\]</p>
<p>\[ \begin{equation} w=\sum^m_{i=1}\alpha_iy^{(i)}x^{(i)} \end{equation} \]</p>
<p>\[ \begin{equation} \frac{\partial}{\partial b}\mathcal{L}(w,b,\alpha) = \sum^m_{i=1} \alpha_iy^{(i)}=0\end{equation} \]</p>
<p>然后我们将他们代入原拉格朗日函数中,进行下一步最值求解</p>
<p>\[\mathcal{L}(w,b,\alpha) = \sum^m_{i=1}\alpha_i - \frac{1}{2}\sum^m_{i,j=1}y^{(i)}y^{(j)}\alpha_i\alpha_j(x^{(i)})^Tx^{(j)}\]</p>
<p>需要注意的是,此时 KKT 条件中的公式(5),以及刚刚求出的公式(8) 成为了现在的最值优化问题的新约束。则我们得到<br/>
\[\begin{eqnarray}<br/>
\max_a &&W(\alpha) = \sum^m_{i=1}\alpha_i-\frac{1}{2}\sum^m_{i,j=1}y^{(i)}y^{(j)}\alpha_i\alpha_j\langle x^{(i)},x^{(j)}\rangle \nonumber \\ <br/>
s.t. && \alpha_i \geq 0,\ \ i=1,\cdots,m \nonumber \\<br/>
&&\sum^m_{i=1}\alpha_iy^{(i)} = 0 \nonumber \\<br/>
\end{eqnarray}\]<br/>
最终我们求出 \(\alpha_i\) 的最优值,代入到公式(7) 求得 \(w\) 的最优值,再将 \(w, \alpha_i\) 代入原拉格朗日函数公式(6) 中,求得</p>
<p>\[ \begin{equation} b^* = -\frac{\max_{i:y^{(i)}=-1}w^*Tx^{(i)} + \min_{i:y^{(i)}=1} w^{*T}x^{(i)}}{2} \end{equation} \]</p>
<p>则此时我们已经求得了我们原优化问题的最优解,可喜可贺。</p>
<h3 id="toc_8">核 (Kernels)</h3>
<p>还能有什么优化的地方?我们的分类器的可用性还存在一个前提,数据必须线性可分。如果线性不可分呢?我们引入了『核』的概念,用来对输入数据进行一个特征转换。我们定义特征函数</p>
<p>\[\phi(x) = \begin{bmatrix}<br/>
x\\<br/>
x^2\\<br/>
x^3<br/>
\end{bmatrix}\]</p>
<p>回头看我们的公式(7),如果将它代入到我们的假设函数 \(w^Tx+b\) 中,我们得到</p>
<p>\[\begin{eqnarray}<br/>
w^Tx+b &=& \left( \sum^m_{i=1}\alpha_iy^{(i)}x^{(i)} \right)^Tx+b \\<br/>
&=& \sum^m_{i=1}\alpha_iy^{(i)}\langle x^{(i)}, x\rangle +b \\<br/>
\end{eqnarray}\]<br/>
将假设函数转化成了输入数据和所有支持向量的点积的形式(\(\langle x^{(i)},x\rangle\) 指 \(x^{(i)}\) 和 \(x\) 的点积),于是我们就可以将这个点积替换成一个特征向量的点积了。<br/>
我们再定义一个关于 \(x^{(i)}\) 和 \(x\) 的函数 \(K(x,z)\)</p>
<p>\[K(x,z) = \phi(x)^T\phi(z)\]</p>
<p>这个函数,我们就称为<strong>核函数</strong>。我们现在只需要将公式(11)中的点积替换成核函数,我们的 SVM 就可以处理非线性可分的数据集了。<br/>
为什么我们使用核函数,而不是直接套用特征向量的点积呢?让我们看下面一个例子</p>
<p>\[K(x,z) = (x^Tz)^2\]</p>
<p>也可以写成下面这个形式<br/>
\[\begin{eqnarray}<br/>
K(x,z) &=& \left(\sum^n_{i=1}x_iz_i \right) \left(\sum^n_{j=1}x_jz_j \right) \nonumber \\<br/>
&=&\sum^n_{i=1} \sum^n_{j=1}x_ix_jz_iz_j \nonumber \\<br/>
&=&\sum^n_{i,j=1}(x_ix_j)(z_iz_j)\nonumber \\<br/>
\end{eqnarray}\]<br/>
化为特征向量点积的形式,我们可以得到这个核函数对应的特征向量是这个形式的</p>
<p>\[\phi(x) = \begin{bmatrix}<br/>
x_1x_1\\<br/>
x_1x_2\\<br/>
x_1x_3\\<br/>
x_2x_1\\<br/>
x_2x_2\\<br/>
x_2x_3\\<br/>
x_3x_1\\<br/>
x_3x_2\\<br/>
x_3 x_3<br/>
\end{bmatrix}\]</p>
<p>我们可以发现,直接使用特征向量点积,计算复杂度为 \(O(n^2)\),而核函数形式的计算复杂度仅为 \(O(n)\)。所以使用核函数,能够大幅优化计算复杂度。</p>
<p>那么,是否所有的函数都能作为核函数呢?当然不是。</p>
<p>假设 \(K\) 是一个合法核函数,并定义核函数矩阵 \(K_{ij} = K(x^{(i)},x^{(j)})\)。</p>
<p>则有 \(K_{ij} = K(x^{(i)},x^{(j)}) = \phi(x^{(i)})^T\phi(x^{(j)}) = \phi(x^{(j)})^T\phi(x^{(i)}) = K(x^{(j)},x^{(i)}) = K_{ji}\)</p>
<p>所以,<strong>核函数矩阵必须是对称的</strong></p>
<p>然后,我们使用一个任意向量 \(z\),有</p>
<p>\[\begin{eqnarray} z^TKz &=& \sum_i\sum_jz_iK_{ij}z_j \nonumber \\<br/>
&=&\sum_i\sum_jz_i \phi(x^{(i)})^T \phi(x^{(j)}) z_j \nonumber \\<br/>
&=&\sum_i\sum_jz_i \sum_k \phi_k(x^{(i)}) \phi_k(x^{(j)}) z_j \nonumber \\<br/>
&=&\sum_k\sum_i\sum_j z_i \phi_k(x^{(i)}) \phi_k(x^{(j)}) z_j \nonumber \\<br/>
&=&\sum_k\left(\sum_i z_i\phi_k(x^{(i)})\right)^2 \nonumber \\<br/>
&\geq& 0 \nonumber <br/>
\end{eqnarray}\]</p>
<p>所以,<strong>核函数矩阵</strong>是半正定的。</p>
<p>需要注意的是,核函数的概念并不是专门为 SVM 提出的,它的概念比 SVM 要广得多。实际上你可以将任何学习算法中的点积替换成核函数,就能使得这个学习算法支持高维度特征学习。</p>
<h3 id="toc_9">正则化</h3>
<p>我们的分类器一直以来都有一个限制条件,那就是分类边界必须能够正确的分类所有的样本。我们知道现实中的样本,绝大部分都存在着噪音数据。如果出现了噪音数据,就会导致 SVM 的分类边界很不合理,如下图所示<br/>
<img src="media/14968173531750/14969181791214.jpg" alt=""/></p>
<p>为了解决这个问题,我们加入了一个 \(l1\) 正则项:</p>
<p>\[\begin{eqnarray}<br/>
\min_{\gamma,w,b} &&\frac{1}{2}\|w\| ^2+C\sum^m_{i=1}\xi_i \nonumber \\<br/>
s.t. && y^{(i)}(w^Tx^{(i)}+b)\geq1-\xi_i,i=1,\cdots,m \nonumber \\<br/>
&& \xi_i\geq0,\ i=1,\cdots,m \nonumber \\<br/>
\end{eqnarray}\]</p>
<p>这使得样本的函数间隔能够小于1 (甚至为负数)。其中的参数 \(C\) 代表了两个目标权重的权衡:</p>
<ol>
<li>使所有样本的函数间隔大于1</li>
<li>最小化 \(\|w\|^2\)</li>
</ol>
<p>\(C\) 越大,则优化目标越偏向目标1,即最原始的,强迫所有样本必须分类正确的模型。</p>
<p>在新的优化目标下,我们的 KKT 条件有一点改变:</p>
<p>\[\begin{eqnarray}<br/>
\alpha_i = 0 &\Rightarrow& y^{(i)}(w^Tx^{(i)}+b)\geq1 \\<br/>
\alpha_i = C &\Rightarrow& y^{(i)}(w^Tx^{(i)}+b)\leq 1 \\<br/>
0<\alpha_i <C &\Rightarrow& y^{(i)}(w^Tx^{(i)}+b) = 1 \\<br/>
\end{eqnarray}\]</p>
<h3 id="toc_10">SMO 算法</h3>
<p>SMO 算法全称 Sequential minimal optimization,提供了一种有效的方法来解决 SVM 的对偶问题。在介绍 SMO 算法之前,我们先了解另一个算法。</p>
<h4 id="toc_11">坐标上升算法 (Coordinate ascent)</h4>
<p>假设你正在尝试解决一个无约束优化问题</p>
<p>\[\max_aW(\alpha_1,\alpha_2,\cdots,\alpha_m)\]</p>
<p>新算法逻辑如下:</p>
<p><img src="media/14968173531750/14970255117856.jpg" alt=""/><br/>
可以看到在循环的最里层,我们固定了除了 \(\alpha_i\) 以外的所有参数,然后仅通过 \(\alpha_i\) 来优化函数 \(W\)。以下是一个坐标上升算法实战中的情形<br/>
<img src="media/14968173531750/14970260504690.jpg" alt=""/></p>
<h4 id="toc_12">SMO</h4>
<p>这是我们准备解决的对偶优化问题:</p>
<p>\[\begin{eqnarray}<br/>
\max_\alpha &&W(\alpha) = \sum^m_{i=1}\alpha_i -\frac{1}{2}\sum^m_{i,j=1}y^{(i)}y^{(j)}\alpha_i\alpha_j\langle x^{(i)},x^{(j)}\rangle \\<br/>
s.t. &&0\leq \alpha_i \leq C,\ \ i=1,\cdots,m \\ <br/>
&&\sum^m_{i=1}\alpha_iy^{(i)}=0 \\<br/>
\end{eqnarray}\]<br/>
假设我们使 \(\alpha_i\) 都符合公式(16)、(17)的约束。现在,如果我们将 \(\alpha_2,\cdots,\alpha_m\) 都固定,并使用坐标上升算法来尝试优化目标函数,你觉得这能产生效果吗?并不能。因为我们有一个约束是这样的</p>
<p>\[ \alpha_1y^{(1)} = -\sum^m_{i=2}\alpha_iy^{(i)}\]</p>
<p>两边同乘以 \(y^{(1)}\)</p>
<p>\[\alpha_1 = -y^{(1)}\sum^m_{i=2}\alpha_iy^{(i)}\]<br/>
因此,如果你固定了 \(\alpha_2,\cdots,\alpha_m\),实际上你也固定了 \(\alpha_1\)。所以如果我们需要通过 \(\alpha_i\) 来优化目标函数,我们需要同时使用其中的两项来进行优化,也就是我们 SMO 算法的主要思想<br/>
<img src="media/14968173531750/14970275107451.jpg" alt=""/></p>
<p>我们使用 SMO 算法有一个重要的原因,那就是 \(\alpha_i, \alpha_j\) 的计算非常简单。</p>
<p>首先,我们通过计算剩余项的和,可以写出以下约束</p>
<p>\[\alpha_1y^{(1)}+\alpha_2y^{(2)}=-\sum^m_{i=3}\alpha_iy^{(i)}\]<br/>
使等号右边等于一个常数 \(\zeta\),则我们有</p>
<p>\[ \begin{equation}\alpha_1y^{(1)}+\alpha_2y^{(2)} = \zeta \end{equation} \]<br/>
并且,根据新的 KKT 条件公式(12-14) \(\alpha_i\) 的取值范围被固定在了 \([0,C]\),则我们可以画出以下图像<br/>
<img src="media/14968173531750/14970286141343.jpg" alt=""/></p>
<p>并且根据公式(18) ,我们发现能够将原优化目标写成以下形式的二次函数<br/>
\[a\alpha_2^2 + b\alpha_2+c\]</p>
<p>则我们先计算得出 \(\alpha_2\) 的最优值,再根据上图的值域限制进行一个修剪 (clip)<br/>
<img src="media/14968173531750/14970845058858.jpg" alt=""/><br/>
以此得到符合限制条件的新 \(\alpha_2\) 值。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[CS229 学习笔记 Part2]]></title>
<link href="http://yinzo.github.io/14965964854250.html"/>
<updated>2017-06-05T01:14:45+08:00</updated>
<id>http://yinzo.github.io/14965964854250.html</id>
<content type="html"><![CDATA[
<ul>
<li>
<a href="#toc_0">判别式和生成式</a>
<ul>
<li>
<a href="#toc_1">判别式</a>
</li>
<li>
<a href="#toc_2">生成式</a>
</li>
</ul>
</li>
<li>
<a href="#toc_3">Gaussian discriminant analysis</a>
</li>
<li>
<a href="#toc_4">讨论:GDA 和 Logistic 回归</a>
</li>
<li>
<a href="#toc_5">朴素贝叶斯</a>
<ul>
<li>
<a href="#toc_6">拉普拉斯平滑</a>
</li>
<li>
<a href="#toc_7">用于文本分类的事件模型</a>
</li>
</ul>
</li>
</ul>
<h2 id="toc_0">判别式和生成式</h2>
<p>对于一个分类任务,判别式和生成式分别代表了两种不同的思路:</p>
<h3 id="toc_1">判别式</h3>
<p>通过直接从输入数据中学习,得到一个『特定输入对应的实际类别』的概率模型,模型的参数为 \(\theta\) 。即学习建模 \(p(y\mid x)\)</p>
<h3 id="toc_2">生成式</h3>
<p>通过对每一个类进行建模,然后就可以通过条件概率算出输入的数据更可能由哪一类生成。即学习建模 \(p(x\mid y)\) 和 \(p(y)\) ,然后计算 \[\arg\max\limits_y\frac{p(x \mid y)p(y)}{p(x)}\]</p>
<p>并且实际计算中,分母 \(p(x)\) 并不会影响各个类别概率的排序,所以最终简化成 \[\arg\max\limits_y p(x \mid y)p(y)\]</p>
<span id="more"></span><!-- more -->
<h2 id="toc_3">Gaussian discriminant analysis</h2>
<p>作为生成式模型的第一个例子,它假设数据的分布 \(p(x\mid y)\) 是多元高斯分布 (multivariate normal distribution),分类结果为二分类,即 \(y \sim \mathrm{Bernoulli}(\phi)\)。</p>
<p>根据生成式模型的思路,它通过训练数据,计算出两个类的隐含分布——多元高斯分布的参数 \(\mu_0, \mu_1,\Sigma\) (需要注意的是,这里对于两个多元正态分布的 \(\Sigma\),我们使用的是一个公共的参数,也就是我们假设两个分布的『形状』是一样的),以及对于分类结果的伯努利分布参数 \(\phi\)</p>
<p>根据定义,我们可以得到以下模型</p>
<p>\[p(y) = \phi^y(1-\phi)^{1-y}\]</p>
<p>\[p(x\mid y=0) = \frac{1}{(2\pi)^{n/2}|\Sigma|^{1/ 2}} \exp\left(-\frac{1}{2}(x-\mu_0)^T\Sigma^{-1}(x-\mu_0)\right)\]</p>
<p>\[p(x\mid y=1) = \frac{1}{(2\pi)^{n/2}|\Sigma|^{1/ 2}} \exp\left(-\frac{1}{2}(x-\mu_1)^T\Sigma^{-1}(x-\mu_1)\right)\]</p>
<p>接下来开始估计各个参数的值。我们使用一个新的似然函数 <strong>Joint likelihood</strong></p>
<p>\[\ell(\phi, \mu_0, \mu_1, \Sigma) = log \prod^m_{i=1} p(x^{(i)}, y^{(i)}; \phi, \mu_0, \mu_1, \Sigma)\]</p>
<p>\[\phantom{ \ell(\phi, \mu_0, \mu_1, \Sigma)} = log \prod^m_{i=1} p(x^{(i)}\mid y^{(i)}; \mu_0, \mu_1, \Sigma)p(y^{(i)};\phi)\]</p>
<p>通过最大化此似然函数,我们能够得到以上几个参数的估计值</p>
<p>\[\phi = \frac{1}{m}\sum^m_{i=1}1\{y^{(i)}=1\}\]</p>
<p>\[\mu_0 = \frac{\sum^m_{i=1}1\{y^{(i)} = 0\}x^{(i)}}{\sum^m_{i=1}1\{y^{(i)} = 0\}}\]</p>
<p>\[\mu_1 = \frac{\sum^m_{i=1}1\{y^{(i)} = 1\}x^{(i)}}{\sum^m_{i=1}1\{y^{(i)} = 1\}}\]</p>
<p>\[\Sigma = \frac{1}{m}\sum^m_{i=1}(x^{(i)}-\mu_{y^{(i)}})(x^{(i)}-\mu_{y^{(i)}})^T\]</p>
<p>而 GDA 的判别公式则是作为作业的一部分自行完成。</p>
<h2 id="toc_4">讨论:GDA 和 Logistic 回归</h2>
<p>GDA 的判别公式能够化为以下形式<br/>
\[p(y=1\mid x;\phi, \Sigma, \mu_0, \mu_1) = \frac{1}{1+\exp(-\theta^Tx)}\]</p>
<p>也就是 Logistic 回归的形式。(这个公式转化的具体过程是课后习题的一部分)<br/>
其中 \(\theta\) 是关于 \(\phi,\Sigma,\mu_0,\mu_1\) 的函数。那么 GDA 和 Logistic 回归(下称 LR)的区别在哪里呢?</p>
<p>假设 \(p(x\mid y)\) 满足多元高斯分布,那么 \(p(y\mid x)\) 能够写成 logistic 函数的形式。但是,反之并不成立。\(p(y\mid x)\) 能够写成 logistic 函数的形式并不意味着 \(p(x\mid y)\) 符合多元高斯分布。这说明,GDA 做出了一个更强的假设 (<em>stronger</em> modeling assumption)。</p>
<p>并且,当这个假设符合现实( \(p(x\mid y)\) 符合多元高斯分布 ),并且在训练集足够大的情况下,没有其他算法优于 GDA<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>。而且通常来说,对于一个较小的训练集,我们通常会觉得 GDA 会表现的更好。</p>
<p>反过来说,对于使用了较弱假设的 LR,它拥有更强的鲁棒性,对于错误的模型假设也更不敏感。对 \(p(x\mid y)\) 分布的假设,有很多种情况能够使得 \(p(y\mid x)\) 可以化为 Logistic 函数的形式。比如说,\(x \mid y = 0\) 和 \(x \mid y = 1\) 分别符合两个独立的泊松分布时既是如此。</p>
<h2 id="toc_5">朴素贝叶斯</h2>
<p>对于一个文本分类问题,使用50000个词的简化词袋模型时,我们的目标是对 \(p(x_1,\cdots,x_{50000}\mid y)\) 构建出最准确的模型。</p>
<p>\[p(x_1,\cdots,x_{50000}\mid y)\]</p>
<p>\[ = p(x_1\mid y)p(x_2\mid y,x_1)p(x_3\mid y,x_1,x_2)\cdots p(x_{50000}\mid y,x_1,x_2,\cdots,x_{49999})\]</p>
<p>此时的式子称为贝叶斯分类器。而朴素贝叶斯和贝叶斯的区别在于哪里呢?关键就在于以下假设:</p>
<p><strong>朴素贝叶斯假设:假设 \(x_i\) 条件独立于 \(y_i\)</strong></p>
<p>则原概率公式<br/>
\[ = p(x_1\mid y)p(x_2\mid y)p(x_3\mid y)\cdots p(x_{50000}\mid y)\]</p>
<p>此时的式子就称为<strong>朴素</strong>贝叶斯分类器了。虽然朴素贝叶斯假设是一个很强的假设 (strong assumption),但是它出人意料的在很多问题上都表现的不错。</p>
<p>使用朴素贝叶斯概率公式,则词袋中的每个词,对于每种文本分类都属于一个独立参数的伯努利分布。即此例子中,词袋大小50000,2种文本分类,于是共有 100,000 个伯努利分布参数需要估计,以及一个对于类别 y 的伯努利分布参数 \(\phi_y\)。</p>
<p>我们使用 Joint likelihood 作为目标函数</p>
<p>\[ \mathcal{L}(\phi_y, \phi_{j\mid y=0}, \phi_{j\mid y=1}) = \prod^m_{i=1}p(x^{(i)}, y^{(i)})\]</p>
<p>最大化似然函数得到各个参数的估计</p>
<p>\[j \in \{1,2,\cdots,50000\}\]</p>
<p>\[ \phi_{j\mid y=1} = \frac{\sum^m_{i=1}\operatorname{1}\{x_j^{(i)} = 1 \wedge y^{(i)} = 1 \}}{\sum^m_{i=1}\operatorname{1}\{ y^{(i)} = 1 \}} \]</p>
<p>\[\phi_{j\mid y=0} = \frac{\sum^m_{i=1}\operatorname{1}\{x_j^{(i)} = 1 \wedge y^{(i)} = 0 \}}{\sum^m_{i=1}\operatorname{1}\{ y^{(i)} = 0 \}}\]</p>
<p>\[\phi_y = \frac{\sum^m_{i=1}\operatorname{1}\{ y^{(i)} = 1 \}}{m}\]</p>
<p>朴素贝叶斯的判别公式如下:</p>
<p>\[p(y=1\mid x) = \frac{p(x\mid y =1)p(y=1)}{p(x)}\]</p>
<p>\[ = \frac{(\prod^n_{i=1}p(x_i|y=1))p(y=1)}{(\prod^n_{i=1}p(x_i|y=1))p(y=1)+(\prod^n_{i=1}p(x_i|y=0))p(y=0)}\]</p>
<p>最后,我们能够很容易的想到,可以将 \(x_i\) 的取值从二值变为多值,就成为了这个算法的泛化。为了做到这一点,我们只需要将对 \(p(x_i\mid y)\) 假设的伯努利分布,替换成多项式分布即可。如果原始属性是连续值,我们也可以通过分段的办法,将他离散化。之后,就可以仿照我们上述的过程来使用朴素贝叶斯算法了。当原始的连续属性使用多元正态分布不能很好的建模时,将他离散化后使用朴素贝叶斯通常能取得更好的效果。</p>
<h3 id="toc_6">拉普拉斯平滑</h3>
<p>上述标准的朴素贝叶斯通常情况下效果都很好,但是在一些特殊情况下会出现奇怪的情况。比如说,当你的分类器遇到了一个从来没有见过的词(不存在于训练数据中)的时候,对于这个词两个类别的概率都会等于零,并且由于累乘的结果,会使得整个输出都变为零。这显然不合理,所以这就是拉普拉斯平滑要解决的事情。</p>
<p>原理很简单,我们对于一个多项式分布输入的类别概率计算公式如下</p>
<p>\[p(z=j) = \phi_j = \frac{\sum^m_{i=1} \operatorname{1}\{z^{(i)}=j\}}{m}\]</p>
<p>我们想要让这个式子不等于零,很直觉的办法是在分子上加上一个很小的数。所以我们在分子上加一个 1。但是这还不够,我们需要让多项式分布的各个类整体概率和仍然为 1,即 \(\sum^k_{j=1}\phi_j = 1\),\(k\) 是多项式分布可选的类的数量。所以我们分母也需要稍作改动,最终我们得到</p>
<p>\[p(z=j) = \phi_j = \frac{\sum^m_{i=1} \operatorname{1}\{z^{(i)}=j\}+1}{m+k}\]</p>
<p>读者可以自己验算 \(\sum^k_{j=1}\phi_j = 1\)</p>
<h3 id="toc_7">用于文本分类的事件模型</h3>
<p>之前的模型我们称为『多变量伯努利分布事件模型』<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>,而对于文本分类的任务,接下来这个模型通常能够取得更好的效果,称为『多项式分布事件模型』<sup id="fnref3"><a href="#fn3" rel="footnote">3</a></sup>。</p>
<p>在这个模型中,一个由 n 个词组成的文本段将化为一个 n 维向量,每一维符合都一个相同的多项式分布,多项式分布一个选项对应一个特定的词。比如一个电子邮件内容为『快来 购买……』,在多项式分布中,快来对应的类别编号为33,购买的类别编号为580,则形成的输入向量就是 [33, 580, …]</p>
<p>文本段中每一个词的分布都来自同一个多项式分布,需要注意的是,词在文中的位置并不影响他的取值分布。</p>
<p>则似然函数定义如下</p>
<p>\[\mathcal{L}(\phi, \phi_{k\mid y=0}, \phi_{k\mid y=1}) = \prod^m_{i=1}p(x^{(i)},y^{(i)})\]</p>
<p>\[= \prod^m_{i=1}\left( \prod^{n_i}_{j=1}p(x_j^{(i)}\mid y;\phi_{k\mid y=0},\phi_{k\mid y=1}) \right)p(y^{(i)};\phi_y)\]</p>
<p>最大化似然函数得到参数估计</p>
<p>\[\phi_{k\mid y=1} = \frac{\sum^m_{i=1}\sum^{n_i}_{j=1} \operatorname{1}\{x_j^{(i)} = k\wedge y^{(i)} = 1 \} }{\sum^m_{i=1} \operatorname{1}\{ y^{(i)} = 1\} n_i}\]</p>
<p>\[\phi_{k\mid y=0} = \frac{\sum^m_{i=1}\sum^{n_i}_{j=1} \operatorname{1}\{x_j^{(i)} = k\wedge y^{(i)} = 0 \} }{\sum^m_{i=1} \operatorname{1}\{ y^{(i)} = 0\} n_i}\]</p>
<p>\[\phi_y = \frac{\sum^m_{i=1}\operatorname{1}\{y^{(i)} = 1\}}{m}\]</p>
<p>多项式分布事件模型和之前的模型的不同点在于,新模型除了统计某一个词是否出现,还考虑了某一个词出现的次数。</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1">
<p>in the limit of vary large training sets (large m), there is no algorithm that is strictly better than GDA. <a href="#fnref1" rev="footnote">↩</a></p>
</li>
<li id="fn2">
<p>multi-variate Bernoulli event model <a href="#fnref2" rev="footnote">↩</a></p>
</li>
<li id="fn3">
<p>multinomial event model <a href="#fnref3" rev="footnote">↩</a></p>
</li>
</ol>
</div>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[CS229 学习笔记 Part 1]]></title>
<link href="http://yinzo.github.io/14946020792948.html"/>
<updated>2017-05-12T23:14:39+08:00</updated>
<id>http://yinzo.github.io/14946020792948.html</id>
<content type="html"><![CDATA[
<p>此笔记为我的 CS229 的学习笔记之一,由 Andrew Ng 的 CS229 Lecture notes 和 课堂录像整理而来。用于记录所学到的内容。记录顺序重新编排过,并非是课程原本的教学顺序,并且省略了课程中的一些推导过程,所以适合学习后整理备忘使用,不适合用于同步辅助学习。</p>
<ul>
<li>
<a href="#toc_0">广义线性模型 GLM (Generalized Linear Models)</a>
<ul>
<li>
<a href="#toc_1">具体步骤</a>
</li>
</ul>
</li>
<li>
<a href="#toc_2">优化方法</a>
<ul>
<li>
<a href="#toc_3">梯度下降法</a>
</li>
<li>
<a href="#toc_4">牛顿法</a>
</li>
</ul>
</li>
<li>
<a href="#toc_5">Linear Regression</a>
<ul>
<li>
<a href="#toc_6">Locally weighted linear regression</a>
</li>
</ul>
</li>
</ul>
<h2 id="toc_0">广义线性模型 GLM (Generalized Linear Models)</h2>
<p>广义线性模型是所学到的 Linear Regression 以及 Logistic Regression 的推广形式(更准确的说,这两种模型都属于 GLM 的特殊情况)。它有三个关键假设(Assumptions)构成:</p>
<ol>
<li>\(y \mid x;\theta\sim ExponentialFamily(\eta)\) :对于固定的参数 \(\theta\) 以及给定 \(x\), \(y\) 的分布服从某一指数分布族(如高斯分布、伯努利分布、Softmax分布)</li>
<li>对于给定的 \(x\) ,目标是预测 \(T(y)\) 的值。换一种说法就是,我们定义假设函数 \(h(x) = E[y\mid x]\)</li>
<li>natural parameter \(\eta\) 和 输入 \(x\) 是线性相关的, \(\eta = \theta^ \mathrm{ T } x\) (其中,当输入 \(x\) 和 \(\eta\) 是向量的时候, \(\eta_i = \theta_i^ \mathrm{T}x\))</li>
</ol>
<span id="more"></span><!-- more -->
<p>以上三个假设,一般只有第一个需要我们决定所使用的分布,其他两个假设都是直接定义。关键的地方来了,通过选择不同的<em>指数分布族</em>分布,我们能够得到不同的模型:</p>
<ul>
<li>高斯分布,则得到 Linear Regression</li>
<li>伯努利分布,则得到 Logistic Regression</li>
<li>Softmax 分布,得到 Softmax Regression</li>
</ul>
<p>其中,Lenear Regression 为回归模型 (regression), Logistic Regression 和 Softmax Regression 都是分类模型 (classification)。</p>
<p>则我猜测,是否根据所假设的分布是离散分布还是连续分布,分别能够得到分类模型和回归模型呢?有待后续的学习验证。</p>
<h3 id="toc_1">具体步骤</h3>
<ol>
<li>假设 \(y\) 服从的分布,并将所假设的分布化为标准的指数分布族标准形式:\[ p(y;\eta) = b(y)\exp(\eta^\mathrm{T}T(y)-a(\eta))\]</li>
<li>使用 \(\eta\) 表示出 \(E[y\mid x;\theta]\),则我们得到了使用 \(\eta\) 表示的假设函数 \(h_\theta(\eta)\)</li>
<li>根据假设3,\(\eta = \theta^ \mathrm{ T } x\),直接代入假设函数,得到 \(h_\theta(x)\)</li>
</ol>
<p>之后:</p>
<ol>
<li>通过得到的假设函数,我们能够定义出代价函数 (Cost function) 或 似然函数 (likelihood) </li>
<li>通过优化方法如梯度下降、牛顿法,以最小化代价函数或者最大化似然函数,得到最优的 \(\theta\) 值。</li>
</ol>
<h2 id="toc_2">优化方法</h2>
<h3 id="toc_3">梯度下降法</h3>
<p>包括以下三种子类:</p>
<ul>
<li>Batch Gradient Descent </li>
<li>Mini-batch Gradient Descent</li>
<li>Stochastic Gradient Descent</li>
</ul>
<p>三种方法的主要区别在于,每一步优化所使用的样本数量大小:</p>
<ul>
<li>Batch 使用<strong>全部</strong>样本计算平均梯度后才进行一步更新;</li>
<li>Mini-batch 使用<strong>一小部分</strong>样本计算平均梯度就进行一步更新;</li>
<li>Stochastic 使用<strong>一个</strong>样本,计算梯度,进行更新</li>
</ul>
<h3 id="toc_4">牛顿法</h3>
<p>牛顿法用于寻找函数零点位置的优化方法,使用函数的导数(梯度)来计算参数的变化量,从而更新参数</p>
<p>由于我们需要寻找函数的极大值(极小值),则我们可以通过牛顿法寻找原函数的一阶导数的零点,将优化问题转化为寻找零点问题,以此来寻找原函数的极大值(极小值)。</p>
<p>牛顿法在二维的参数更新公式为:</p>
<p>\[\theta := \theta - \Delta\]</p>
<p>\[\Delta = \frac{f^\prime(\theta)}{f^{\prime\prime}(\theta)}\]</p>
<p>多维时,参数更新公式变为: </p>
<p>\[\theta := \theta - H^{-1}\nabla_\theta \ell(\theta)\]</p>
<h2 id="toc_5">Linear Regression</h2>
<p>简单的模型介绍就不说了,只记录这门课程给我额外学习到的一些知识点。</p>
<p>首先是 Linear Regression 使用的是最小平方误差法 LMS 来进行函数优化并寻找最优 \(\theta\) 值的。在我第一次学习到这个方法的时候,仅仅是觉得这个误差函数很有道理,感觉能说得过去,并没有理解其背后的理论基础。</p>
<p>Andrew Ng 使用概率学上的解释,告诉了我,为什么使用最小平方误差法。</p>
<p>我们使用假设函数 \(h(x) = \theta^\mathrm{T}x^{(i)}\) 来作为给定输入 \(x\) 时,对 \(y\) 的预测,则我们可以得到这样一个等式</p>
<p>\[y^{(i)} = \theta^\mathrm{T}x^{(i)} + \epsilon^{(i)}\]</p>
<p>\(\epsilon^{(i)}\) 是误差项,包括了未被找到的特征或随机噪声。此时,我们假设:</p>
<ol>
<li>误差都是独立同分布的</li>
<li>误差项符合高斯分布</li>
</ol>
<p>则有\(\epsilon^{(i)}\sim \cal{N}(0,\sigma^2) \),即 \(y^{(i)} - \theta^\mathrm{T}x^{(i)}\sim \cal{N}(0,\sigma^2) \)</p>
<p>省略一部分推导,我们能够得到对数似然函数 </p>
<p>\[\ell (\theta) = m\log \frac{1}{\sqrt{2\pi}\sigma} - \frac{1}{\sigma^2}\cdot\frac{1}{2}\sum_{i=1}^{m} (y^{(i)} - \theta^\mathrm{T}x^{(i)})^2\]</p>
<p>则当我们最大化对数似然函数时,即最小化 </p>
<p>\[\frac{1}{2}\sum_{i=1}^{m}(y^{(i)} - \theta^\mathrm{T}x^{(i)})^2\] </p>
<p>即最小化平方误差。</p>
<p>最终我们得到结论:当我们对数据的分布进行以上假设时,最大化对数似然函数相当于最小化平方误差。</p>
<h3 id="toc_6">Locally weighted linear regression</h3>
<p>这是一种 Linear Regression 的特殊形式,它在误差函数中增加了一项权重,变为\(\sum_i w^{(i)}(y^{(i)} - \theta^\mathrm{T}x^{(i)})^2\)</p>
<p>其中 \(w^{(i)}\) 就是非负权重,对于需要重点拟合的区域 \(w^{(i)}\) 会比较大。\(w^{(i)}\) 并不需要满足和为1的约束,因为他不是概率分布,只是单纯的惩罚项。</p>
<p>通常来说,对于权重 \(w^{(i)}\) 的选择,我们使用以下函数</p>
<p>\[w^{(i)} = \exp(-\frac{(x^{(i)} - x)^2}{2\tau^2})\]</p>
<p>需要注意的是,这个函数和高斯分布没有关系,仅仅是常规的钟形函数而已。参数 \(\tau\) 影响了当远离所求点 \(x\) 时权值下降的速度。</p>
<p>则对于权重较大的区域,所求得的曲线拟合程度较高。这一方法在预测的时候,通常将待预测区域的权重提高,然后重新拟合曲线。所以每一次预测都需要重新拟合曲线,使得它在训练样本较大时效率比较低。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[原始模型优化笔记]]></title>
<link href="http://yinzo.github.io/14883590547961.html"/>
<updated>2017-03-01T17:04:14+08:00</updated>
<id>http://yinzo.github.io/14883590547961.html</id>
<content type="html"><![CDATA[
<p>对于原始弹幕分类CNN模型进行优化。</p>
<h2 id="toc_0">修改 word2vec model 的 vector size</h2>
<ul>
<li>400:
Nice at epoch 38, validation acc 96.56%</li>
<li>200:
Nice at epoch 37, validation acc 95.22%</li>
<li>100:
Nice at epoch 34, validation acc 94.78%
单轮训练时间与50维相近,测试样例测试耗时 0.92secs</li>
<li>50:
Nice at epoch 40, validation acc 94.39%
单轮训练时间在7秒左右,测试样例(av 8365806)测试耗时 0.7secs</li>
</ul>
<h2 id="toc_1">尝试加入dropout</h2>
<p>在两个 conv 层之间和两个 fc 层之间各加入了一个 \(p=0.5\) 的 dropout</p>
<p>40 epoch 时只有 89.1 acc, 和预想的一样,会导致 达到最佳效果的 epoch 数上升。</p>
<p>用了 dropout 后一个很明显的变化是,原本训练过程中通常是train acc 高于 validation acc,现在通常是 validation acc 高于 train acc,训练后期才基本持平或反超</p>
<p>vector在 epoch 90 左右 达到了96.50%上下的 acc,最终在epoch 300 以上能达到 97.10% 左右的 acc</p>
<p><img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-02-24%2022.15.27.png" alt="屏幕快照 2017-02-24 22.15.27"/></p>
<span id="more"></span><!-- more -->
<p>人工检查实际识别效果,仍有少量漏网。果然几个百分点的区别,人简单扫视还是很难看出区别的,而且还要排除安慰剂效应。</p>
<p>实验证明 dropout 确实有效防止了过拟合,并且提高了一定的分类准确度。</p>
<p>接着将几个 word2vec 长度的模型训练图都画出来对比:</p>
<p><img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-03-01%2016.57.28.png" alt="屏幕快照 2017-03-01 16.57.28"/></p>
<p>可以从左下角的 tooltip 看到,从上至下分别是词向量长度为 400、200、100、50、25 的模型,在相同迭代次数下的准确度排序。由于选取的是上述模型都仍有收敛空间的迭代数,所以这个排名一定程度上可以代表模型训练所需的迭代次数排序。</p>
<p>由此可以得出结论,词向量维数越多,模型收敛所需的迭代次数越少,但是最终收敛的效果没有变化,这可能是目前训练样本较少的原因。</p>
<p><img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-03-01%2017.01.36.png" alt="屏幕快照 2017-03-01 17.01.36"/></p>
<p>切换到训练时间为横轴的图来看,收敛速度实际上是100维最快,这倒是出乎意外,原本以为会是低维模型最快,结果发现,100维由于单次迭代提升更大,虽然迭代速度稍慢但是总体收敛最快。我还特地检查了100维的data graph,确定的确是在用100维的词向量来训练的。</p>
<h3 id="toc_2">关于卷积层是否应该加入 dropout 的问题</h3>
<p>这个问题我找到了 <a href="https://www.reddit.com/r/MachineLearning/comments/42nnpe/why_do_i_never_see_dropout_applied_in/">Reddit 的这个讨论串</a></p>
<h4 id="toc_3">里面提到了以下这些说法:</h4>
<ul>
<li>卷积层的参数数量没有全连接层那么多,所以不那么需要 regularizaion</li>
<li>卷积层 filter map 的梯度是对于整个样本进行平均化的<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>,这样会使得卷积核原本存在相关性的参数,在样本的不同位置使用了不同的 dropout mask,导致 dropout 无效。当然,你可以想办法使卷积核的 dropout mask 在同一层中固定,但是这又会导致 regularizaion 过强。</li>
<li>Srivastava/Hinton 在 dropout 的论文中也有提到:在卷积层加入 dropout 的效果等于没有 \((3.02\% \rightarrow 2.55\%)\),因为卷积层的参数太少了,不存在过拟合的问题,所以 dropout 几乎没有效果。但是 dropout 在较低的层仍是有用的,它的效果相当于产生一点噪声,使得后面层数较高的全连接层避免过拟合。</li>
<li><p>在卷积层使用 dropout 也不是绝对没有的,以下几篇论文中就有用到:</p>
<ul>
<li><a href="http://arxiv.org/pdf/1511.07289v3.pdf">http://arxiv.org/pdf/1511.07289v3.pdf</a></li>
<li><a href="http://torch.ch/blog/2015/07/30/cifar.html">http://torch.ch/blog/2015/07/30/cifar.html</a></li>
<li><a href="http://danielnouri.org/notes/2014/12/17/using-convolutional-neural-nets-to-detect-facial-keypoints-tutorial/">http://danielnouri.org/notes/2014/12/17/using-convolutional-neural-nets-to-detect-facial-keypoints-tutorial/</a></li>
</ul>
<p>但是他们都有卷积层的 dropout 『keep_prob 较大』的特点。</p></li>
</ul>
<h4 id="toc_4">以下是测试的结果:</h4>
<p>先测试了卷积层不使用 dropout 的效果<br/>
<img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-02-27%2013.11.43.png" alt="屏幕快照 2017-02-27 13.11.43"/></p>
<p>绿线是没有 卷积层dropout 的 acc, 紫线是卷积层 p=0.5 dropout 的 acc,两者都有一个 p=0.5 的全连接 dropout。由此可得卷积层的 dropout 还是有效果的,首先防止过拟合的程度要更高,其次对于准确度的提升也是有的 \((\uparrow2.3\%)\)</p>
<p><img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-03-01%2015.45.56.png" alt="屏幕快照 2017-03-01 15.45.56"/></p>
<p>卷积层 p=0.6 和 p=0.4 dropout 的测试,相比 p=0.5 的模型,收敛速度、收敛精度都没有明显的区别。</p>
<h2 id="toc_5">尝试加入 max_pooling</h2>
<p>先在卷积层和全连接层之间加入一个大小为2的 <code>max_pooling1d</code><br/>
<img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-02-26%2016.54.23.png" alt="屏幕快照 2017-02-26 16.54.23"/></p>
<p>可以看到,这个 max_pool 对于最终收敛精度没有影响,在前期略微加快了收敛,但是中期减慢了收敛。</p>
<p>尝试移动该 pooling 层到两个卷积层之间。</p>
<p><img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-02-28%2013.42.28.png" alt="屏幕快照 2017-02-28 13.42.28"/></p>
<p>上图为多次测试的结果。收敛速度和收敛准确率没有较为明显的提高或降低 \((96.623\% \rightarrow 96.694\%)\),只有训练速度有略微的提高。</p>
<p>值得一提的是,加入了 max-pool 的模型在高迭代次数的时候,标准差在逐渐增大。我认为这是因为 max-pool 一定程度上降低了训练样本的精度,相当于训练样本变少了,于是乎少量增加了整个模型在高迭代次数过拟合的风险。这里我选择使用84次迭代的模型,也就是图中横坐标约为 1k 的位置。相对来说过拟合的程度应该是非常小的。</p>
<p><img src="media/14879250453025/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-02-26%2018.49.29.png" alt="屏幕快照 2017-02-26 18.49.29"/></p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1">
<blockquote>
<p>the gradients are averaged over the spatial extent of the feature maps <a href="#fnref1" rev="footnote">↩</a></p>
</blockquote>
</li>
</ol>
</div>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[低素质弹幕分类器的CNN实现]]></title>
<link href="http://yinzo.github.io/14863637393852.html"/>
<updated>2017-02-06T14:48:59+08:00</updated>
<id>http://yinzo.github.io/14863637393852.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">整体架构</h2>
<p>对于一条弹幕,首先进行分词,然后通过 word2vec 转换为词向量,再填充至固定长度,作为卷积神经网络的输入。</p>
<p>卷积神经网络的结构如下:</p>
<pre><code class="language-python">model = Sequential()
model.add(Convolution1D(100, 4, border_mode='valid', input_shape=(100, word_model.vector_size)))
model.add(Activation('relu'))
model.add(Convolution1D(100, 4, border_mode='valid', input_shape=(100, word_model.vector_size)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(2, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy']
)
</code></pre>
<p>最终输出为2位的 categorical result,直接使用第一项,即骂人弹幕的概率作为输出。</p>
<p>然后通过代理,在弹幕服务器与播放器之间插入一层,实现弹幕的分类与屏蔽。最终实现了有效的骂人弹幕自动屏蔽,但是误伤的情况依然存在。</p>
<h2 id="toc_1">搭建过程</h2>
<span id="more"></span><!-- more -->
<p>使用游戏区的所有弹幕来训练 word2vec model。这里我是用的是 word2vec 的 Python 实现 gensim</p>
<p>训练脚本来自这篇文章 <a href="http://www.52nlp.cn/%E4%B8%AD%E8%8B%B1%E6%96%87%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91%E8%AF%AD%E6%96%99%E4%B8%8A%E7%9A%84word2vec%E5%AE%9E%E9%AA%8C">中英文维基百科语料上的Word2Vec实验</a></p>
<pre><code class="language-python"># -*- coding: utf-8 -*-
"""
build a word2vec model by text file, each sentence for a line.
usage: [input file] [gensim model filename] [word2vec model filename]
example: output.txt life_damku.model life_damku.vector
"""
import logging
import os.path
import sys
import multiprocessing
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# check and process input arguments
if len(sys.argv) < 4:
print(globals()['__doc__'] % locals())
sys.exit(1)
inp, outp1, outp2 = sys.argv[1:4]
model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5,
workers=multiprocessing.cpu_count())
# trim unneeded model memory = use(much) less RAM
# model.init_sims(replace=True)
model.save(outp1)
model.save_word2vec_format(outp2, binary=False)
</code></pre>
<p>然后,我从所有弹幕中随机抽取了5000条,进行人工标注分类,其中有63条骂人弹幕。由于骂人弹幕太少,我又通过关键词搜索加人工筛选的方式,增加了4000条骂人弹幕。</p>
<p>以这约9000条弹幕作为训练样本,80%的弹幕作为 train set, 其余的20%作为 validation set</p>
<p>对训练样本进行预处理:</p>
<ol>
<li>分词</li>
<li>转换为词向量</li>
<li>填充至100位长,其中填充的位的词向量全部置零。</li>
</ol>
<p>开始构建卷积神经网络,我选用的框架是使用 TensorFlow 后端的 keras。最终经过调试,得到这样一个结构</p>
<p><a href="https://yinzo.github.io/14863637259966.html">具体的训练过程可以看这里</a></p>
<pre><code class="language-python">model = Sequential()
model.add(Convolution1D(100, 4, border_mode='valid', input_shape=(100, word_model.vector_size)))
model.add(Activation('relu'))
model.add(Convolution1D(100, 4, border_mode='valid', input_shape=(100, word_model.vector_size)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(2, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy']
)
</code></pre>
<p>需要注意的是,<code>model.fit</code> 指定了 class weight</p>
<pre><code class="language-python">model.fit(X_train, Y_train, nb_epoch=1, batch_size=300, class_weight={
0: len(positive_sample)/len(negative_sample),
1: 1