-
Notifications
You must be signed in to change notification settings - Fork 12
/
inductive_regression.jl
72 lines (59 loc) · 2.62 KB
/
inductive_regression.jl
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
68
69
70
71
72
"The `SimpleInductiveRegressor` is the simplest approach to Inductive Conformal Regression. Contrary to the [`NaiveRegressor`](@ref) it computes nonconformity scores using a designated calibration dataset."
mutable struct SimpleInductiveRegressor{Model<:Supervised} <: ConformalInterval
model::Model
coverage::AbstractFloat
scores::Union{Nothing,AbstractArray}
heuristic::Function
train_ratio::AbstractFloat
end
function SimpleInductiveRegressor(
model::Supervised;
coverage::AbstractFloat=0.95,
heuristic::Function=absolute_error,
train_ratio::AbstractFloat=0.5,
)
return SimpleInductiveRegressor(model, coverage, nothing, heuristic, train_ratio)
end
@doc raw"""
MMI.fit(conf_model::SimpleInductiveRegressor, verbosity, X, y)
For the [`SimpleInductiveRegressor`](@ref) nonconformity scores are computed as follows:
``
S_i^{\text{CAL}} = s(X_i, Y_i) = h(\hat\mu(X_i), Y_i), \ i \in \mathcal{D}_{\text{calibration}}
``
A typical choice for the heuristic function is ``h(\hat\mu(X_i),Y_i)=|Y_i-\hat\mu(X_i)|`` where ``\hat\mu`` denotes the model fitted on training data ``\mathcal{D}_{\text{train}}``.
"""
function MMI.fit(conf_model::SimpleInductiveRegressor, verbosity, X, y)
# Data Splitting:
train, calibration = partition(eachindex(y), conf_model.train_ratio)
Xtrain = selectrows(X, train)
ytrain = y[train]
Xtrain, ytrain = MMI.reformat(conf_model.model, Xtrain, ytrain)
Xcal = selectrows(X, calibration)
ycal = y[calibration]
Xcal, ycal = MMI.reformat(conf_model.model, Xcal, ycal)
# Training:
fitresult, cache, report = MMI.fit(conf_model.model, verbosity, Xtrain, ytrain)
# Nonconformity Scores:
ŷ = reformat_mlj_prediction(MMI.predict(conf_model.model, fitresult, Xcal))
conf_model.scores = @.(conf_model.heuristic(ycal, ŷ))
return (fitresult, cache, report)
end
# Prediction
@doc raw"""
MMI.predict(conf_model::SimpleInductiveRegressor, fitresult, Xnew)
For the [`SimpleInductiveRegressor`](@ref) prediction intervals are computed as follows,
``
\hat{C}_{n,\alpha}(X_{n+1}) = \hat\mu(X_{n+1}) \pm \hat{q}_{n, \alpha}^{+} \{S_i^{\text{CAL}} \}, \ i \in \mathcal{D}_{\text{calibration}}
``
where ``\mathcal{D}_{\text{calibration}}`` denotes the designated calibration data.
"""
function MMI.predict(conf_model::SimpleInductiveRegressor, fitresult, Xnew)
ŷ = reformat_mlj_prediction(
MMI.predict(conf_model.model, fitresult, MMI.reformat(conf_model.model, Xnew)...)
)
v = conf_model.scores
q̂ = qplus(v, conf_model.coverage)
ŷ = map(x -> (x .- q̂, x .+ q̂), eachrow(ŷ))
ŷ = reformat_interval(ŷ)
return ŷ
end