forked from Wei-1/Scala-Machine-Learning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPerceptron.scala
68 lines (59 loc) · 2.21 KB
/
Perceptron.scala
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
// Wei Chen - Perceptron - linear version no kernel
// 2015-11-26
package com.scalaml.algorithm
import com.scalaml.general.MatrixFunc._
class Perceptron() extends Classification {
val algoname: String = "Perceptron"
val version: String = "0.1"
var projector = Array[Double]()
var lr: Double = 0.5
var limit: Int = 1000
override def clear(): Boolean = {
projector = Array[Double]()
lr = 0.5
limit = 1000
true
}
override def config(paras: Map[String, Any]): Boolean = try {
lr = paras.getOrElse("LEARNING_RATE", paras.getOrElse("learning_rate", paras.getOrElse("lr", 0.5))).asInstanceOf[Double]
limit = paras.getOrElse("LIMIT", paras.getOrElse("limit", 1000.0)).asInstanceOf[Double].toInt
true
} catch { case e: Exception =>
Console.err.println(e)
false
}
private def dot(x:Array[Double], y:Array[Double]): Double =
arraymultiply(x, y).sum
// train(Array((1,Array(1,2)),(1,Array(2,3)),(-1,Array(2,1)),(-1,Array(3,2))), 0.5, 100)
override def train(data: Array[(Int, Array[Double])]): Boolean = {
val traindatasize = data.size
val featuresize = data.head._2.size
var w = new Array[Double](featuresize + 1)
var c = 1.0
var iter = 0
var saturated = false
while (iter < limit && !saturated) {
iter += 1
for (j <- 0 until traindatasize) {
val (yi, xt) = data(j)
val xi = xt :+ 1.0
if (yi * dot(xi, w) < 1) w = arraysum(w, xi.map(_ * yi * lr))
}
val lostcost = data.map(l => 1 - l._1 * dot(l._2 :+ 1.0, w)).map(Math.max(_, 0)).sum
val weightcost = w.map(Math.pow(_, 2)).sum
val tmpcost = weightcost + lostcost
// println(iter + " " + tmpcost + " " + w.mkString(",") + " " + weightcost + " " + lostcost)
if (c != tmpcost) c = tmpcost
else saturated = true
}
projector = w
true
}
override def predict(data: Array[Array[Double]]): Array[Int] = {
return data.map { xt =>
val xi = xt :+ 1.0
if (dot(xi, projector) < 0) -1
else 1
}
}
}