-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.xml
More file actions
executable file
·248 lines (237 loc) · 18.6 KB
/
Copy pathindex.xml
File metadata and controls
executable file
·248 lines (237 loc) · 18.6 KB
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
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>My Home</title>
<link>http://mayf3.github.io/</link>
<description>Recent content on My Home</description>
<generator>Hugo -- gohugo.io</generator>
<language>zh-cn</language>
<lastBuildDate>Sat, 02 Jan 2021 19:46:00 +0800</lastBuildDate>
<atom:link href="http://mayf3.github.io/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>简介感知机算法</title>
<link>http://mayf3.github.io/post/perceptron/</link>
<pubDate>Sat, 02 Jan 2021 19:46:00 +0800</pubDate>
<guid>http://mayf3.github.io/post/perceptron/</guid>
<description><p>先放一张感知机的思维导图,下面的内容都是围绕着这张图介绍的。
<img src="http://mayf3.github.io/perceptron/B140FD45-6D28-491D-A781-3446CF0E351C.png" alt="8f7e79ba13c997cc8fd9eb2de6ecce6c"></p>
<h2 id="什么是感知机模型">什么是感知机模型</h2>
<p>感知机是Rosenblatt在1958年的<a href="http://homepages.math.uic.edu/~lreyzin/papers/rosenblatt58.pdf">论文</a>里提出的模型,该模型是支持向量机和神经网络的基础。</p>
<p>该模型主要的思想很简单,就是要找出一条直线(N维情况下就是N-1维超平面)把正样本和负样本完全分开,如下图:
<img src="http://mayf3.github.io/perceptron/451850DE-7A91-4D36-9782-FFD19AB4BB8C.png" alt="592a6df086d6369342f3d7d8a5be1172"></p>
<h2 id="模型">模型</h2>
<p>感知机模型的形式如下,其中w和b为参数:
$$
f(x) = sign(w \cdot x + b)
$$
sign函数定义如下,在感知机中的正样本类别为+1,负样本类别为-1:</p>
<p>$$
sign(x) = \begin{cases} +1, &amp; \text{} x &gt;= 0 \\\ -1, &amp; \text{} x &lt; 0 \end{cases}
$$</p>
<p>比较形象的理解,就是找出一条直线能完全区分开正负样本,比如二维情况下就是w1 * x1 + w2 * x2 + b = 0的直线,高维情况下就是用一个超平面来区分正负样本。</p>
<p>感知机模型的特征如下:</p>
<ol>
<li>该模型只能应用于<strong>二分类问题</strong>,毕竟只用一根直线来划分输入空间。</li>
<li>该模型属于<strong>线性模型</strong>,只能处理线性可分的数据,其假设空间是所有线性函数w·x+b。</li>
<li>该模型属于<strong>判别模型</strong>,直接得到决策函数(即上面的f(x))。</li>
</ol>
<h2 id="学习策略">学习策略</h2>
<p>我们希望得到一条区分正负样本的直线,一个显而易见的目标,就是最小化误分类点的数量,但这个目标使用了0-1损失函数,但该函数不可导,不方便优化,所以我们选择最小化误分类的点到直线的距离,即:
$$
\frac{1}{\lVert w \rVert}\lvert w \cdot x + b\rvert
$$
对于误分类的点(xi,yi),存在yi*(w*xi+b)&lt;0,则上述式子可以写成:
$$
-\frac{1}{\lVert w \rVert}y_i * (w \cdot x_i + b)
$$
不考虑前面w范数的倒数,可得到感知机模型的损失函数,该损失函数其实是经验风险函数,其中M是误分类点的集合:
$$
L(w, b) = - \sum_{x \in M}{y_i * (w \cdot x_i + b)}
$$
这样就得到感知机的学习策略,在假设空间中选取参数w, b使得损失函数最小。</p>
<h2 id="学习算法">学习算法</h2>
<p>感知机模型采用的学习算法是梯度下降法,不过我们不需要一次性优化整个集合M的梯度,而是可以随机选取集合M的一个点(xi, yi),进行梯度下降:
$$
w \leftarrow w + \eta * y_i * x_i
$$
$$
b \leftarrow b + \eta * y_i
$$
其中η是学习率,其取值范围为区间(0,1]。<br>
通过不断迭代上述的过程,最终可以得到完全区分正负样本的超平面。</p>
<h2 id="算法收敛性">算法收敛性</h2>
<p>略(详见李航《统计学习方法》,过段时间再证明)</p>
<h2 id="算法的对偶形式">算法的对偶形式</h2>
<p>可以通过拉格朗日法,将感知机问题转变为其对偶形式:
$$
f(x) = sign(\sum_{j=1}^M a_j * y_j * x_j * x + b)
$$
对偶问题的优化方法和原始形式相似,也是随机选取误分类集合M中的一个点(xi, yi),进行优化:
$$
a_i \leftarrow a_i + \eta
$$
$$
b \leftarrow b + \eta * y_i
$$
该算法一样收敛,其迭代过程和原始形式可以一一对应。</p>
<h2 id="感知机的尝试">感知机的尝试</h2>
<p>我在<a href="https://github.com/mayf3/machine_learning/tree/master/algorithm/perceptron">gihtub仓库</a>里实现了如下内容:</p>
<ol>
<li>perceptron.cc,原始感知机算法,每次迭代选择第一个误分类的点进行梯度下降。</li>
<li>perceptron_all.cc,原始感知机算法,但是迭代的时候,使用所有误分类的点进行梯度下降。</li>
<li>perceptron_dual.cc,感知机对偶形式的算法,类似原始感知机算法,但由于要计算内积矩阵,效率会比较低。</li>
<li>utils.cc,包含一些通用工具函数和一个数据生成函数。</li>
</ol>
<p>由于感知机算法要求数据是完全线性可分的,网上的数据集都不满足要求,所以我在utils里面实现了一个数据生成函数,其思路是在随机生成的数据里,选取两个点,以这两个点的中垂超平面来将点划分为正负样本,具体过程如下:</p>
<ol>
<li>随机生成size个dim维度的点集p。</li>
<li>计算点p[0]和p[1]的中点center和方向向量diff。</li>
<li>对于点集p的任意点x,计算(x - center)和diff的內积,大于等于0则标记其为正样本,否则标记其为负样本。</li>
</ol>
<h2 id="提问">提问</h2>
<p>下面是我在学习感知机的过程中,能想到的一些有助于检验学习结果的问题,有一些答案还需要进一步完善。</p>
<p><strong>问:感知机是判别模型还是生成模型?</strong><br>
答:判别模型</p>
<p><strong>问:感知机是二分类模型、多分类模型还是回归模型?</strong><br>
答:二分类</p>
<p><strong>问:感知机模型的假设空间是由哪些函数构成的?</strong><br>
答:所有线性函数w*x+b</p>
<p><strong>问:感知机的损失函数是经验风险函数还是结构风险函数?</strong><br>
答:经验风险函数</p>
<p><strong>问:为什么不能使用误分类的点数作为损失函数?</strong><br>
答:因为误分类点的个数,其实就是0-1损失函数的和,该函数不可导,不方便求解。</p>
<p><strong>问:从感知机模型的原始形式推导出对偶形式?</strong><br>
答:见#算法的对偶形式</p>
<p><strong>问:感知机的学习率可以小于0或则大于1吗?</strong><br>
答:学习率不可以小于等于0,但可以大于1,具体证明略</p>
<p><strong>问:证明感知机算法的收敛性。</strong><br>
答:见#算法收敛性</p>
<p><strong>问:证明感知机对偶算法的收敛性。</strong><br>
答:证明略</p>
<p><strong>问:证明线性可分的充分必要条件是正样本组成的凸壳和负样本组成的凸壳互不相交。</strong><br>
答:<br>
先证充分性:</p>
<ul>
<li>线性可分,则正负样本被直线L完全分开,则其对应的凸壳也完全被该直线L分开,互不相交。</li>
</ul>
<p>再证必要性:</p>
<ul>
<li>若凸壳互不相交,则可在正样本的凸壳和负样本的凸壳上,找出最近点对正样本凸壳上的点X和负样本凸壳上的点Y,构建直线L为X和Y的垂直平分线,直线L可以区分正负样本,证明略。</li>
</ul>
<p><strong>问:为什么不是一次性使所有错误分类的梯度下降,而是每次随机选择一个错误分类?</strong><br>
答:实际测试上,对所有错误分类进行梯度下降和每次随机选择一个错误分类进行梯度下降,在迭代次数上没有显著差异。</p>
<p><strong>问:为什么不需要感知机的损失函数,不需要考虑前面的系数,即不需要乘上w的范数的倒数?</strong><br>
答:等整理了支持向量机再回来回答曾问题。w其实不影响结果,毕竟线性函数w*x+b=0里面,等式两边除以w的范数,也还是表示同一条直线。<br>
推测可能的原因是,加上w的范数后,计算梯度会麻烦一点。</p>
<h2 id="参考资料">参考资料</h2>
<p>李航《统计学习方法》第二章</p>
</description>
</item>
<item>
<title>简介knn算法</title>
<link>http://mayf3.github.io/post/knn/</link>
<pubDate>Fri, 25 Dec 2020 09:28:00 +0800</pubDate>
<guid>http://mayf3.github.io/post/knn/</guid>
<description><h2 id="什么是knn">什么是knn</h2>
<p>knn是Cover和Hart在1968年的<a href="https://pdfs.semanticscholar.org/a3c7/50febe8e72a1e377fbae1a723768b233e9e9.pdf?_ga=2.260660749.1635069309.1608960216-652721388.1605965658">论文</a>里提出的分类算法,全名叫K Nearest Neighbor,中文翻译是k近邻算法。<br>
knn的思想很简单,核心假设是同类别的样本在特征空间上的距离较近,但由于数据存在噪声,只找最近的样本会有问题,所以我们综合考虑最近的k个样本。<br>
基于这个思想,knn对每一个样本,会在训练集中找出与该样本距离最接近的k个样本,取这k个样本中出现次数最多的类别作为该样本的分类结果。</p>
<p>用下面的例子来简单介绍一下knn,假设有10个训练数据,如下图,蓝三角形和绿圆形分别表示不同的类别:
<img src="http://mayf3.github.io/knn/DEBCF616-2EB5-42C7-9CA2-0B7C2F1BC9F5.png" alt="c44f2e1029eaa562953dbbd709b5846b">
若我们想得到下图红点的类别,假定k为3,则我们在训练样本中找最近的3个样本,即红色圆圈内有的两个蓝三角形和一个绿圆形,于是我们将红点分类红色圆圈内出现次数最多的类别,即蓝三角。
<img src="http://mayf3.github.io/knn/B4D9B651-D5A7-4A37-87A6-0AF9614DED62.png" alt="c9d5a145e64e0655c315dff4cc5661a4"></p>
<h2 id="knn有哪些参数">knn有哪些参数</h2>
<p>knn的模型主要由下面三个要素决定:</p>
<ol>
<li>k值的选择(例子中的k=3)</li>
<li>距离度量(例子中使用了欧式距离,所示的红色圆圈)</li>
<li>分类决策规则(例子中以多数类别作为分类结果)</li>
</ol>
<h3 id="k值的选择">k值的选择</h3>
<p>k值的选择需要结合具体的应用数据,通常会选用较小的一个值,然后通过交叉验证法来选取最优的k值。</p>
<p>可以从方差和偏差来考虑k值对模型的影响:<strong>随着k值的增大,模型的方差会逐渐变小,偏差逐渐变大。</strong></p>
<blockquote>
<p>假定k值为1,算法就退化成最近邻,此时模型对数据非常敏感,一旦数据噪声较多,则模型的准确率会很低。<br>
随着k值的增大,模型逐渐降低了数据噪声的干扰,但分类的结果会逐渐倾向于整体数据。<br>
当k值为N时,则将永远返回数据中占比最多的分类,此时方差为0。</p>
</blockquote>
<p>这里有一篇<a href="http://scott.fortmann-roe.com/docs/BiasVariance.html">文章</a>,以knn为例讲解了偏差和方差的区别,可以看看。</p>
<h3 id="距离度量">距离度量</h3>
<p>在数学上有对于距离度量的严谨定义,这里就不详细说了。<br>
常见的距离度量,主要是曼哈顿距离、欧式距离(knn最常用的距离)和切比雪夫距离。<br>
对于维度为N的x和y向量,各个距离的公式如下:</p>
<p>曼哈顿距离
$$
L_1 = \sum_{i=1}^N|X_i - Y_i|
$$</p>
<p>欧式距离
$$
L_2 = \Bigg(\sum_{i=1}^N{(X_i - Y_i)^{2}}\Biggr)^{\tfrac{1}{2}}
$$</p>
<p>切比雪夫距离
$$
L_\infty = \max_i|X_i - Y_i|
$$</p>
<h3 id="分类决策规则">分类决策规则</h3>
<p>knn的分类决策规则往往是多数表决,由距离最近的k个样本的多数类决定测试样本的类别。多数表决规则其实等价于经验风险最小化。<br>
其实还有其他方案,比如将这k个样本按照距离进行平均或则加权平均(该规则也能在回归任务上)等等。</p>
<h2 id="knn有哪些实现">knn有哪些实现</h2>
<p>knn算法的难点是如何快速在训练集里找到距离前k小的样本,最简单的实现是线性扫描,对于测试样本,计算该样本到所有训练样本的距离,排序取前k个。</p>
<p>另外一种常见的实现方法是采用kd树,这里就不展开介绍了,可以参考这个<a href="https://www.cnblogs.com/maxlpy/p/4297254.html">文章</a>。
在数据随机且维度不大的情况下,kd树的复杂度会优于线性扫描,但如果维度接近于样本数量,则kd树约等于线性扫描。</p>
<h2 id="knn的优缺点">knn的优缺点</h2>
<p>k近邻算法的优点如下:</p>
<ol>
<li>实现简单</li>
<li>没有显式的训练过程</li>
<li>精度高(根据knn的论文,knn的泛化错误率不超过贝叶斯最优分类器的错误率的两倍)</li>
<li>具有可解释性</li>
<li>对异常值不敏感</li>
<li>无数据输入假定</li>
</ol>
<p>k近邻算法的缺点如下:</p>
<ol>
<li>计算复杂度高</li>
<li>空间复杂度高</li>
</ol>
<h2 id="归一化">归一化</h2>
<p>knn使用的是欧式距离,欧式距离对数据的尺度很敏感,比如下面的例子:</p>
<blockquote>
<p>假定身高的单位为米,体重的单位为克,很明显这两者在尺度上就有巨大的差异。<br>
此时一个1.7m,60kg的样本和1.0m,60kg的样本的距离为0.7,而1.7m,60kg的样本和1.7m,59kg的样本的距离却高达1000。<br>
若我们是在做大人或小孩的分类,则这样的距离计算会很影响knn的性能。</p>
</blockquote>
<p>在大多数情况下,我们都不希望由于特征的尺度不同,而导致其对距离的贡献不一,比如上面例子中,身高的特征即使差异很大,也几乎不影响距离的计算。
为了解决这种问题,我们在使用knn的时候(或则其他和距离尺度相关的算法),我们常常会使用下面的归一化方法来处理数据。</p>
<p>min-max归一化,需要对每一个特征计算min和max。
$$
m = \frac{(x - x_{min})}{(x_{max} - x_{min})}
$$</p>
<p>z-score归一化,需要对每一个特征计算均值和标准差。
$$
z = (x - \mu) / \sigma
$$</p>
<p>当我在尝试knn算法的时候,也很好奇这两种归一化算法的优劣,然后就搜到了这篇<a href="http://j.mecs-press.net/ijcnis/ijcnis-v9-n11/IJCNIS-V9-N11-4.pdf">论文</a>。<br>
从论文里给出的对比效果来看,似乎min-max的要比z-score略好一点:
<img src="http://mayf3.github.io/knn/B4491EA5-817E-4F13-8994-50BE70C206D2.png" alt="427ee4485988d610a448fa4f96101bfd"></p>
<h2 id="knn的尝试">knn的尝试</h2>
<p>我在<a href="https://github.com/mayf3/machine_learning/tree/master/algorithm/knn">gihtub仓库</a>里实现了knn的线性扫描版本和kd树版本,拿mnist和鸢尾花卉数据集来评估knn的性能。<br>
结果发现knn的算法虽然简单,但效果确实还挺好,mnist的准确率有94%以上,鸢尾花卉的准确率也有93%(正确分类42个/总数45个)。<br>
此外我也在鸢尾花卉数据集上尝试对特征进行归一化,用min-max归一化算法后准确率达到95%(43/45),用z-score归一化后准确率达到98%(44/45)。</p>
<p>但knn有一个显著的问题,就是运行效率低,特别是在mnist数据集上,1w的测试数据,6w的训练数据,特征数量有28 * 28=784个。<br>
如果用线性扫描法,则总的运算量达到1w * 6w * 784,假设计算机每秒运算量为10的8次方,也需要4707秒,超过一个小时。<br>
尝试用kd树来优化knn,结果其性能反而比线性扫描还差。</p>
<p>如果想针对knn的效率问题进行优化,之后可以尝试一下非精确的knn算法,或则是对数据进行降维。</p>
<h2 id="参考资料">参考资料</h2>
<p>机器学习实战 第二章 k-近邻算法<br>
机器学习 第十章 降维与度量学习<br>
统计学习方法 第三章 k近邻法<br>
特征工程入门与实践 第三章 特征增强:清洗数据 - 3.3 标准化和归一化<br>
<a href="https://pdfs.semanticscholar.org/a3c7/50febe8e72a1e377fbae1a723768b233e9e9.pdf?_ga=2.260660749.1635069309.1608960216-652721388.1605965658">Nearest Neighbor Pattern Classification</a><br>
<a href="http://scott.fortmann-roe.com/docs/BiasVariance.html">Understanding the Bias-Variance Tradeoff</a><br>
<a href="http://j.mecs-press.net/ijcnis/ijcnis-v9-n11/IJCNIS-V9-N11-4.pdf">Comparative Analysis of KNN Algorithm using Various Normalization Techniques</a><br>
<a href="https://www.cnblogs.com/maxlpy/p/4297254.html">k-d tree算法详解</a>。</p>
</description>
</item>
</channel>
</rss>