///|
/// Online Poisson regression for count-valued event streams.
pub struct OnlinePoissonRegression {
weights : Array[Double]
learning_rate : Double
l2 : Double
mut steps : Int
}
///|
pub fn OnlinePoissonRegression::new(
dimension : Int,
learning_rate? : Double = 0.01,
l2? : Double = 0.0,
) -> OnlinePoissonRegression {
{
weights: Array::make(if dimension < 0 { 0 } else { dimension }, 0.0),
learning_rate,
l2,
steps: 0,
}
}
///|
pub fn OnlinePoissonRegression::rate(
self : OnlinePoissonRegression,
features : Array[Double],
) -> Double {
@math.exp(clamp(dot_product(self.weights, features), -30.0, 30.0))
}
///|
pub fn OnlinePoissonRegression::predict(
self : OnlinePoissonRegression,
features : Array[Double],
) -> Double {
self.rate(features)
}
///|
pub fn OnlinePoissonRegression::update(
self : OnlinePoissonRegression,
features : Array[Double],
count : Double,
) -> Unit {
let error = self.rate(features) - (if count < 0.0 { 0.0 } else { count })
let limit = if features.length() < self.weights.length() {
features.length()
} else {
self.weights.length()
}
for i in 0.. Double {
let safe_count = if count < 0.0 { 0.0 } else { count }
self.rate(features) -
safe_count * @math.ln(self.rate(features)) +
0.5 * self.l2 * squared_norm(self.weights)
}
///|
pub fn OnlinePoissonRegression::weights(
self : OnlinePoissonRegression,
) -> Array[Double] {
copy_vector(self.weights)
}
///|
pub fn OnlinePoissonRegression::steps(self : OnlinePoissonRegression) -> Int {
self.steps
}
///|
pub fn OnlinePoissonRegression::reset(self : OnlinePoissonRegression) -> Unit {
self.weights.fill(0.0)
self.steps = 0
}
///|
pub struct OnlineGammaRegression {
weights : Array[Double]
learning_rate : Double
l2 : Double
mut steps : Int
}
///|
pub fn OnlineGammaRegression::new(
dimension : Int,
learning_rate? : Double = 0.01,
l2? : Double = 0.0,
) -> OnlineGammaRegression {
{
weights: Array::make(if dimension < 0 { 0 } else { dimension }, 0.0),
learning_rate,
l2,
steps: 0,
}
}
///|
pub fn OnlineGammaRegression::predict(
self : OnlineGammaRegression,
features : Array[Double],
) -> Double {
@math.exp(clamp(dot_product(self.weights, features), -30.0, 30.0))
}
///|
pub fn OnlineGammaRegression::update(
self : OnlineGammaRegression,
features : Array[Double],
value : Double,
) -> Unit {
let target = if value <= 1.0e-9 { 1.0e-9 } else { value }
let prediction = self.predict(features)
let error = 1.0 - target / prediction
let limit = if features.length() < self.weights.length() {
features.length()
} else {
self.weights.length()
}
for i in 0.. Double {
let target = if value <= 1.0e-9 { 1.0e-9 } else { value }
let prediction = self.predict(features)
target / prediction + @math.ln(prediction)
}
///|
pub fn OnlineGammaRegression::weights(
self : OnlineGammaRegression,
) -> Array[Double] {
copy_vector(self.weights)
}
///|
pub fn OnlineGammaRegression::steps(self : OnlineGammaRegression) -> Int {
self.steps
}
///|
pub fn OnlineGammaRegression::reset(self : OnlineGammaRegression) -> Unit {
self.weights.fill(0.0)
self.steps = 0
}