Поскольку Apocalisp уже упомянул материал, на котором я собирался процитировать его, я буду обсуждать код. Вы говорите, что это просто умножение, но я не вижу этого - оно ссылается как минимум на три важных метода, определенных снаружи: order
, states
и M.log
. Я могу сделать вывод, что order
является Int
, и что states
возвращает функцию, которая принимает List[T]
и T
и возвращает Double
.
Там также происходят некоторые странные вещи ...
def logLikelihood(seq: Iterator[T]): Double = {
val sequence = seq.toList
sequence
никогда не используется, кроме как для определения seqPos
, так зачем это делать?
val stateSequence = (0 to order).toList.padTo(sequence.length,order)
val seqPos = sequence.zipWithIndex
def probOfSymbAtPos(symb: T, pos: Int) : Double = {
val state = states(stateSequence(pos))
M.log(state( seqPos.map( _._1 ).slice(0, pos).takeRight(order), symb))
На самом деле, вы могли бы использовать sequence
здесь вместо seqPos.map( _._1 )
, поскольку все, что нужно, это отменить zipWithIndex
. Кроме того, slice(0, pos)
это просто take(pos)
.
}
val probs = seqPos.map( i => probOfSymbAtPos(i._1,i._2) )
probs.sum
}
Теперь, учитывая отсутствующие методы, трудно утверждать, как это действительно должно быть написано в функциональном стиле. Хранение таинственных методов даст:
def logLikelihood(seq: Iterator[T]): Double = {
import scala.collection.immutable.Queue
case class State(index: Int, order: Int, slice: Queue[T], result: Double)
seq.foldLeft(State(0, 0, Queue.empty, 0.0)) {
case (State(index, ord, slice, result), symb) =>
val state = states(order)
val partial = M.log(state(slice, symb))
val newSlice = slice enqueue symb
State(index + 1,
if (ord == order) ord else ord + 1,
if (queue.size > order) newSlice.dequeue._2 else newSlice,
result + partial)
}.result
}
Только я подозреваю, что материал state
/ M.log
может быть также частью State
. Я замечаю другие оптимизации сейчас, когда я написал это так. Раздвижное окно, которое вы используете, напоминает мне, конечно, sliding
:
seq.sliding(order).zipWithIndex.map {
case (slice, index) => M.log(states(index + order)(slice.init, slice.last))
}.sum
Это начнется только с элемента orderth, так что некоторая адаптация будет в порядке. Не слишком сложно, хотя. Итак, давайте перепишем это снова:
def logLikelihood(seq: Iterator[T]): Double = {
val sequence = seq.toList
val slices = (1 until order).map(sequence take) ::: sequence.sliding(order)
slices.zipWithIndex.map {
case (slice, index) => M.log(states(index)(slice.init, slice.last))
}.sum
}
Хотел бы я видеть M.log
и states
... Держу пари, я мог бы превратить это map
в foldLeft
и покончить с этими двумя методами. И я подозреваю, что метод, возвращаемый states
, может принять весь срез вместо двух параметров.
Все же ... неплохо, не правда ли?