我正在参加CalTech在线课程“从数据中学习”( Learning ),我很难在Scala中创建一个Perceptron。我选择Scala是因为我正在学习Scala,我想挑战自己。我理解这个理论,我也理解其他人在Python和Ruby中的解决方案。但是我不明白为什么我自己的Scala代码不能工作。
获取Perceptron代码中的背景:算法
我在OSX10.10上运行Scala2.11。
根据该算法,我从权重(0.0、0.0、0.0)开始,其中weight2是一个学习偏差组件。我已经在X-Y平面上生成了一个空间- 1,1,1的测试集。我是这样做的:( a)选择两个随机点并画一条线穿过它们,然后生成一些其他随机点,并计算它们是否在这条线的一边。据我所知,通过用Python绘制它,这将生成线性可分离的数据。
我的下一步是采取我的初始化权值,并检查每一个点,以找到错误的分类点,即不产生正确的+1或-1的结果。下面是简单计算权重的点积和向量x的代码:
def h(weight:List[Double], p:Point ): Double = if ( (weight(0)*p.x + weight(1)*p.y + weight(2)) > 0) 1 else -1这是最初的重量,所以它们都是误分类的。然后我更新权重,如下所示:
def newH(weight:List[Double], p:Point, y:Double): List[Double] = {
val newWt = scala.collection.mutable.ArrayBuffer[Double](0.0, 0.0, 0.0)
newWt(0) = weight(0) + p.x*y
newWt(1) = weight(1) + p.y*y
newWt(2) = weight(2) + 1*y
return newWt.toList
}然后,通过检查测试集和上面h()输出的值,再次确定错误分类点,并继续迭代。
这遵循了Yaser教授在这里展示的算法(至少应该是这样的):图书馆
问题是算法永远不会收敛。我的体重--它的第三个部分是偏见--保持更多的负值或正数。每一次调整后,我的权重向量都类似于这样:
Weights: List(16.43341624736786, 11627.122008800507, -34130.0)
Weights: List(15.533397436141968, 11626.464265227318, -34131.0)
Weights: List(14.726969361305237, 11626.837346673012, -34132.0)
Weights: List(14.224745154380798, 11627.646470665932, -34133.0)
Weights: List(14.075232982635498, 11628.026384592056, -34134.0)我是一个Scala新手,所以我的代码可能很糟糕。但是,我是不是在Scala中遗漏了一些东西,比如重新分配,这可能会导致我的体重被搞砸了?还是我完全误解了Perceptron的运作方式?我的体重更新是错的吗?
谢谢你在这件事上给我的帮助!
发布于 2015-09-10 01:23:07
谢谢,直到。我已经发现了我的代码中的两个问题,我将分享它们,但是为了解决您的问题:其他人在课堂论坛上询问了这一点,看起来Wiki公式所做的仅仅是改变学习速度。阿尔法可以随机选择,而y-h(重量,p)给你的权重如下
-1-1 = 2如果y=-1和h()=1,或
1-(-1) = 2在y=1和h()=-1的情况下
我/该课程的公式采用1*p.x而不是alpha*2,这似乎是一个不同的学习速度问题。希望这是合理的。
我的两个问题如下:
y值newH需要是y的目标值,即生成测试点时发现的“正确的y”。我传入通过h()生成的y,这是猜测的-at函数。这显然是有意义的,因为我们使用的是目标y,而不是不正确的y。y和h()=y进行了比较,但比较是通过.get()从映射中获得的一个元素。我的Scala映射看起来像Map[Point,Double],其中Double值引用在测试集创建期间生成的y值。但是,执行.get()会为您提供Option[Double],而不是Double值。这在Scala Map#get和一些()的返回中得到了解释,现在有了很大的意义。现在我做了map.get(<some Point>).get(),因为我关注的是调试而不是代码的完善,然后我能够准确地比较两个Double值。https://stackoverflow.com/questions/32472501
复制相似问题