///|
pub struct Fold {
training_indices : Array[Int]
validation_indices : Array[Int]
}
///|
pub fn make_folds(sample_size : Int, folds : Int, seed : UInt64) -> Array[Fold] {
let actual_folds = if folds < 2 {
1
} else if folds > sample_size {
sample_size
} else {
folds
}
if sample_size <= 0 {
return []
}
let order = Array::new(capacity=sample_size)
for i in 0.. Double {
let n = if predictions.length() < actual.length() {
predictions.length()
} else {
actual.length()
}
if n == 0 {
return 0.0
}
let mut correct = 0
for i in 0.. Double {
let partitions = make_folds(covariates.length(), folds, seed)
let scores = Array::new()
let labels = Array::new()
for partition in partitions {
let train_x : Array[Array[Double]] = Array::new()
let train_t : Array[Bool] = Array::new()
for index in partition.training_indices {
train_x.push(covariates[index])
train_t.push(treatment[index])
}
let model = fit_logistic_regression(train_x, train_t, max_iterations=200)
for index in partition.validation_indices {
scores.push(model_predict(model, covariates[index]))
labels.push(treatment[index])
}
}
let predicted = Array::new(capacity=scores.length())
for score in scores {
predicted.push(score >= 0.0)
}
accuracy_from_labels(predicted, labels)
}
///|
pub fn cross_validate_outcome_rmse(
covariates : Array[Array[Double]],
outcomes : Array[Double],
folds : Int,
seed : UInt64,
) -> Double {
let partitions = make_folds(covariates.length(), folds, seed)
let errors = Array::new()
for partition in partitions {
let train_x : Array[Array[Double]] = Array::new()
let train_y : Array[Double] = Array::new()
for index in partition.training_indices {
train_x.push(covariates[index])
train_y.push(outcomes[index])
}
let model = fit_linear_outcome_model(train_x, train_y)
for index in partition.validation_indices {
let prediction = model_predict(model, covariates[index])
let difference = prediction - outcomes[index]
errors.push(difference * difference)
}
}
if errors.length() == 0 {
0.0
} else {
mean(errors).sqrt()
}
}
///|
pub fn auc_score(
probabilities : Array[Double],
treatment : Array[Bool],
) -> Double {
let positive = Array::new()
let negative = Array::new()
let n = if probabilities.length() < treatment.length() {
probabilities.length()
} else {
treatment.length()
}
for i in 0.. n {
wins += 1.0
} else if p == n {
wins += 0.5
}
}
}
wins / (positive.length() * negative.length()).to_double()
}