【问题标题】:Trouble implementing Perceptron in Scala在 Scala 中实现感知器的问题
【发布时间】:2015-12-05 00:09:23
【问题描述】:

我正在参加 CalTech 在线课程 从数据中学习,但我很难在 Scala 中创建 Perceptron。我选择 Scala 是因为我正在学习它并想挑战自己。我了解理论,也了解其他人在 Python 和 Ruby 中的解决方案。但我不明白为什么我自己的 Scala 代码不起作用。

Perceptron 代码中的背景:Learning_algorithm

我在 OSX 10.10 上运行 Scala 2.11。

根据算法,我从权重 (0.0, 0.0, 0.0) 开始,其中权重 [2] 是学习的偏差分量。我已经在 X-Y 平面上的空间 [-1, 1],[-1,1] 中生成了一个测试集。我这样做是通过 a) 选择两个随机点并在它们之间画一条线,然后 b) 生成一些其他随机点并计算它们是在线的一侧还是另一侧。据我通过在 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 教授在此处展示的算法(或至少应该遵循):Library

问题是算法永远不会收敛。我的权重——其中的第三个组成部分是偏差——越来越消极或越来越积极。每次调整后我的权重向量如下所示:

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 的运作方式?我的体重更新是错误的吗?

感谢您在这方面给我的任何帮助!

【问题讨论】:

  • 根据维基百科判断,我认为你的更新公式是错误的。我认为它应该类似于newWt(0) = weight(0) + alpha * (y - h(weight, p)) * p.x,其中0 < alpha <= 1 是学习率。

标签: algorithm scala perceptron


【解决方案1】:

谢谢直到。我发现我的代码存在两个问题,我将分享它们,但为了解决您的问题:其他人在班级论坛上询问了这个问题,看起来 Wiki 公式所做的只是改变学习率。 Alpha 可以随机选择,y-h(weight, p) 会给你像

这样的权重
-1-1 = 2

在y=-1且h()=1的情况下,或者

1-(-1) = 2

在 y=1 且 h()=-1 的情况下

My/the class 公式采用1*p.x 而不是alpha*2,这似乎是学习率不同的问题。希望这是有道理的。

我的两个问题如下:

  1. 传入重新计算公式newHy 值需要是y 的目标值,即在生成测试点时发现的“正确的y”。我传入了通过 h() 生成的 y,这是被猜测的函数。这显然是有道理的,因为我们希望通过使用目标 y 来校正权重,而不是不正确的 y。
  2. 我在 Scala 中比较了目标 yh()=y,但比较的是通过 .get() 从映射中获得的元素。我的 Scala 映射看起来像 Map[Point,Double],其中 Double 值是指在测试集创建期间生成的 y 值。但是做.get() 给你Option[Double] 而不是Double 值。这在Scala Map#get and the return of Some() 中有解释,现在很有意义。我现在做了map.get(<some Point>).get(),因为我专注于调试而不是代码完善,然后我能够准确地比较两个Double 值。

【讨论】:

    猜你喜欢
    • 2019-01-20
    • 1970-01-01
    • 2018-04-23
    • 2017-12-28
    • 2011-06-07
    • 1970-01-01
    • 2019-04-13
    • 2017-01-06
    • 2019-02-22
    相关资源
    最近更新 更多