我上了这个课:
case class IDADiscretizer(
nAttrs: Int,
nBins: Int = 5,
s: Int = 5) extends Serializable {
private[this] val log = LoggerFactory.getLogger(this.getClass)
private[this] val V = Vector.tabulate(nAttrs)(i => new IntervalHeapWrapper(nBins, i))
private[this] val randomReservoir = SamplingUtils.reservoirSample((1 to s).toList.iterator, 1)
def updateSamples(v: LabeledVector): Vector[IntervalHeapWrapper] = {
val attrs = v.vector.map(_._2)
val label = v.label
// TODO: Check for missing values
attrs
.zipWithIndex
.foreach {
case (attr, i) =>
if (V(i).getNbSamples < s) {
V(i) insertValue attr // insert
} else {
if (randomReservoir(0) <= s / (i + 1)) {
//val randVal = Random nextInt s
//V(i) replace (randVal, attr)
V(i) insertValue attr
}
}
}
V
}
/**
* Return the cutpoints for the discretization
*
*/
def cutPoints: Vector[Vector[Double]] = V map (_.getBoundaries.toVector)
def discretize(data: DataSet[LabeledVector]): (DataSet[Vector[IntervalHeapWrapper]], Vector[Vector[Double]]) = {
val r = data map (x => updateSamples(x))
val c = cutPoints
(r, c)
}
}
使用flink,我想在调用discretize
之后获得切点,但是似乎存储在V
中的信息会丢失。我是否必须像在this question中那样使用Broadcast
?有没有更好的方法来访问类状态?
我尝试用两种方式致电cutpoints
,一种方式是:
def discretize(data: DataSet[LabeledVector]) = data map (x => updateSamples(x))
然后,从外面打电话:
val a = IDADiscretizer(nAttrs = 4)
val r = a.discretize(dataSet)
r.print
val cuts = a.cutPoints
这里,cuts为空,因此我尝试计算离散化以及discretize
内的cutpoints:
def discretize(data: DataSet[LabeledVector]) = {
val r = data map (x => updateSamples(x))
val c = cutPoints
(r, c)
}
并像这样使用它:
val a = IDADiscretizer(nAttrs = 4)
val (d, c) = a.discretize(dataSet)
c foreach println
但是同样的事情发生。
最后,我还试图将V
完全公开:
val V = Vector.tabulate(nAttrs)(i => new IntervalHeapWrapper(nBins, i))
仍然为空
我在做什么错了?
相关问题:
多亏@TillRohrmann,我终于做到了:
private[this] def computeCutPoints(x: LabeledVector) = {
val attrs = x.vector.map(_._2)
val label = x.label
attrs
.zipWithIndex
.foldLeft(V) {
case (iv, (v, i)) =>
iv(i) insertValue v
iv
}
}
/**
* Return the cutpoints for the discretization
*
*/
def cutPoints(data: DataSet[LabeledVector]): Seq[Seq[Double]] =
data.map(computeCutPoints _)
.collect
.last.map(_.getBoundaries.toVector)
def discretize(data: DataSet[LabeledVector]): DataSet[LabeledVector] =
data.map(updateSamples _)
然后像这样使用它:
val a = IDADiscretizer(nAttrs = 4)
val d = a.discretize(dataSet)
val cuts = a.cutPoints(dataSet)
d.print
cuts foreach println
我不知道这是否是最好的方法,但至少现在可以正常工作。
答案 0 :(得分:1)
Flink的工作方式是用户定义运算符/用户定义的函数,这些函数对来自源函数的输入数据进行运算。为了执行程序,将用户代码发送到Flink集群,并在其中执行该代码。计算结果必须通过接收器功能输出到某些存储系统。
由于这个原因,在尝试解决方案时,不可能轻松地混合使用本地计算和分布式计算。 discretize
的作用是定义一个map
运算符,该运算符将转换输入DataSet
data
。例如,一旦您调用ExecutionEnvironment#execute
或DataSet#print
,就会执行此操作。现在,用户代码和IDADiscretizer
的定义被发送到实例化它们的集群。 Flink将更新IDADiscretizer
实例中的值,该实例与您在客户端上的实例不同。