在学习梯度下降的时候,尝试自己写代码表达思想,也尝试使用sklearn
等等工具协助我们进行学习,深入理解。
不过呢,轮子用的再多,用轮子的人没有完全理解轮子的本质也是白搭,最近就自己整理了开发笔记协助我深入理解,以此文加深记忆。
下图中的点是数据可视化后的结果,我们的目的是通过梯度下降画一条直线将这两种颜色的点分开
首先是读取数据,将数据集格式化为矩阵
Input = file2matrix("testSet.txt", "\t")
target = Input[:, -1] # 获取分类标签列表
[m, n] = shape(Input)
此时的Input
,target
的大小分别为
Input.shape(100, 3)
target.shape(100, 1)
注意到
也代表一条直线,不妨假设X有两个特征x1,x2,那么有
此时代码构造为
dataMat = buildMat(Input)
weights = ones((n, 1)) # 初始化权重向量为1
梯度下降计算
steps = 5000 # 迭代次数
alpha = 0.001234 # 步长
# 主程序
for k in xrange(steps):
# mat用来将weight的列表转换为矩阵
gradient = dataMat * mat(weights)
# sigmoid(wx)
output = logistic(gradient) # logistic function
errors = target - output # 计算误差
# .T是简单转置矩阵的意思
weights = weights + alpha * dataMat.T * errors
这里的步长由我们自己随机设置,业界调侃我等为调参师
便是这些充满玄学的随机设置。
代码的数学原理推导起来也是简单,我们不妨简化下我们的数据量为3*2的矩阵,即
得出参数b和w
y=w*x+b: b:weights[0]/weights[2]; w:weights[1]/weights[2]
即
Y = -(double(weights[0]) + X * (double(weights[1]))) / double(weights[2])
我们初始化权重向量的时候,为何默认为1?而不是0或者2?
weights = ones((n, 1)) # 初始化权重向量
当初始化为0,在计算梯度时,gradient
为0,后续的计算无意义
gradient = dataMat * mat(weights)
当初始化为-1,在计算梯度时,初始化失败,计算得到权值为[[-208.44200602][ -66.06053372][3143.37196469]]
主要到-1会令sigmod
函数溢出,此时的直线为
当初始化为2,此时的直线为
原因是在计算权重的时候,已然被约分
为何
上面的推断可得
b=\frac{b*(error_1+error_2)}{k_2*error_1+k_4*error_2} w=\frac{k_1*error_1+k3*error_2}{k_2*error_1+k_4*error_2}
显然等式不成立
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有