Skip to content

Commit b303a8f

Browse files
authored
Merge pull request #33 from alan-turing-institute/dev
For a 0.1.3 release
2 parents 7c7d643 + 490db4d commit b303a8f

File tree

3 files changed

+43
-43
lines changed

3 files changed

+43
-43
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "NearestNeighborModels"
22
uuid = "636a865e-7cf4-491e-846c-de09b730eb36"
33
authors = ["Anthony D. Blaom <anthony.blaom@gmail.com>", "Sebastian Vollmer <s.vollmer.4@warwick.ac.uk>", "Thibaut Lienart <thibaut.lienart@gmail.com>", "Okon Samuel <okonsamuel50@gmail.com>"]
4-
version = "0.1.2"
4+
version = "0.1.3"
55

66
[deps]
77
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"

src/models.jl

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function dict_preds(::Val{:columnaccess}, func, target_table, idxsvec, weights)
2929
dict_table = Dict(
3030
nm => func(weights, Tables.getcolumn(cols, nm), idxsvec) for nm in colnames
3131
)
32-
return dict_table
32+
return dict_table
3333
end
3434

3535
function dict_preds(::Val{:noncolumnaccess}, func, target_table, idxsvec, weights)
@@ -62,7 +62,7 @@ end
6262
function ntuple_preds(::Val{:noncolumnaccess}, func, target_table, idxsvec, weights)
6363
cols = Tables.columntable(target_table)
6464
colnames = Tables.columnnames(cols)
65-
column_table = NamedTuple{colnames}(
65+
column_table = NamedTuple{colnames}(
6666
func(weights, Tables.getcolumn(col, nm), idxsvec) for nm in colnames
6767
)
6868
return column_table
@@ -152,37 +152,37 @@ end
152152
function _predict_knnclassifier(weights, y, idxsvec)
153153
# `classes` and `classes_seen` has an ordering consistent with the pool of y
154154
classes = @inbounds MMI.classes(y[1])
155-
classes_seen = filter(in(unique(y)), classes)
155+
classes_seen = filter(in(unique(y)), classes)
156156
nclasses = length(classes)
157157
nc = length(classes_seen) # Number of classes seen in `y`.
158-
159-
# `labels` and `integers_seen` assigns ranks {1, 2, ..., nclasses}, to the
158+
159+
# `labels` and `integers_seen` assigns ranks {1, 2, ..., nclasses}, to the
160160
# `CategoricalValue`'s in `y` according the ordering given by the pool of `y`.
161-
# In the case of `integers_seen` the ranks happen to sorted with the lower ranks
161+
# In the case of `integers_seen` the ranks happen to sorted with the lower ranks
162162
# comming first and the higher rank coming last.
163163
# In both cases some ranks may be absent because some categorical values in `classes`
164-
# may be absent from `y` (in the case of `labels`) and `classes_seen`
164+
# may be absent from `y` (in the case of `labels`) and `classes_seen`
165165
# (in the case of `integers_seen`).
166166
labels = MMI.int(y)
167167
integers_seen = MMI.int(classes_seen)
168-
168+
169169
# Recode `integers_seen` to be in {1,..., nc}
170170
# same as nc == nclasses || replace!(labels, (integers_seen .=> 1:nc)...)
171171
nc == nclasses || _replace!(labels, integers_seen, 1:nc)
172172
nsamples = length(idxsvec)
173173
probs = zeros(eltype(weights), nsamples, nc)
174-
174+
175175
@inbounds for i in eachindex(idxsvec)
176176
idxs = idxsvec[i]
177177
idxs_labels = @view(labels[idxs])
178178
@simd for j in eachindex(idxs_labels)
179-
@inbounds probs[i, idxs_labels[j]] += weights[i, j]
179+
@inbounds probs[i, idxs_labels[j]] += weights[i, j]
180180
end
181-
end
181+
end
182182
return MMI.UnivariateFinite(classes_seen, scale(probs, dims=2))
183183
end
184-
185-
function MMI.predict(m::KNNClassifier, fitresult, X)
184+
185+
function MMI.predict(m::KNNClassifier, fitresult, X)
186186
err_if_given_invalid_K(m.K)
187187
Xmatrix = transpose(MMI.matrix(X))
188188
check_onebased_indexing("prediction input", Xmatrix)
@@ -233,12 +233,12 @@ function _predict_knnreg(weights, y, idxs_matrix)
233233
return preds
234234
end
235235
function MMI.predict(m::KNNRegressor, fitresult, X)
236-
err_if_given_invalid_K(m.K)
236+
err_if_given_invalid_K(m.K)
237237
#Xmatrix = MMI.matrix(X, transpose=true) # NOTE: copies the data
238238
Xmatrix = transpose(MMI.matrix(X))
239239
check_onebased_indexing("prediction input", Xmatrix)
240240
predict_args = setup_predict_args(m, Xmatrix, fitresult)
241-
preds = _predict_knnreg(predict_args...)
241+
preds = _predict_knnreg(predict_args...) |> vec
242242
return preds
243243
end
244244

@@ -301,25 +301,25 @@ function _predict_multiknnreg(weights, Ymatrix, idxs_matrix)
301301
);
302302
dims = 3
303303
)
304-
# Normalizing the weighted labels gives us our final preds
304+
# Normalizing the weighted labels gives us our final preds
305305
preds = @inbounds(@view(weighted_labels[:, :, 1])) ./ _sum(weights, dims=2)
306306
return preds
307307
end
308308

309309
function MMI.predict(m::MultitargetKNNRegressor, fitresult, X)
310-
err_if_given_invalid_K(m.K)
310+
err_if_given_invalid_K(m.K)
311311
#Xmatrix = MMI.matrix(X, transpose=true) # NOTE: copies the data
312312
Xmatrix = transpose(MMI.matrix(X))
313313
check_onebased_indexing("prediction input", Xmatrix)
314314
names, args = setup_predict_args(m, Xmatrix, fitresult)
315315
preds = _predict_multiknnreg(args...)
316-
# A matrix table was intentionally outputed.
316+
# A matrix table was intentionally outputed.
317317
# Users can coerce to their desired Table type.
318318
return MMI.table(preds, names = names)
319319
end
320320

321321
##################
322-
### FIT MODELS
322+
### FIT MODELS
323323
##################
324324

325325
struct MultiKNNRegressorTarget{S, M<:AbstractMatrix}
@@ -339,7 +339,7 @@ end
339339

340340
function get_target(::KNNRegressor, y)
341341
check_onebased_indexing("input_target", y)
342-
return y
342+
return y
343343
end
344344

345345
# `CategoricalArrays` and `Table(Finite)` are one-based indexed arrays and tables.
@@ -348,14 +348,14 @@ get_target(::Union{KNNClassifier, MultitargetKNNClassifier}, y) = y
348348
struct KNNResult{T, U, W}
349349
tree::T
350350
target::U
351-
sample_weights::W
351+
sample_weights::W
352352
end
353353

354354
const KNN = Union{
355355
KNNClassifier, KNNRegressor, MultitargetKNNRegressor, MultitargetKNNClassifier
356356
}
357357

358-
function MMI.fit(m::KNN, verbosity::Int, X, y, w::Union{Nothing, Vec{<:Real}}=nothing)
358+
function MMI.fit(m::KNN, verbosity::Int, X, y, w::Union{Nothing, Vec{<:Real}}=nothing)
359359
Xmatrix = transpose(MMI.matrix(X))
360360
target = get_target(m, y)
361361
if w !== nothing

test/models.jl

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
1-
2-
@testset "KNNClassifier" begin
1+
@testset "KNNClassifier" begin
32
# create something rather silly: 3 massive clusters very separated
43
rng = StableRNG(10)
54
n, p = 50, 3
65
x, w = make_x_and_w(n, p, rng=rng)
76
w1 = rand(rng, n-5)
8-
7+
98
y1 = fill("A", n)
109
y2 = fill("B", n)
1110
y3 = fill("C", n)
1211
y = categorical(vcat(y1, y2, y3))
13-
12+
1413
# generate test data
1514
ntest = 5
1615
xtest = make_xtest(ntest, p, rng=rng)
1716
ytest1 = fill("A", ntest)
1817
ytest2 = fill("B", ntest)
1918
ytest3 = fill("C", ntest)
2019
ytest = categorical(vcat(ytest1, ytest2, ytest3))
21-
20+
2221
# Test model fit
2322
knnc = KNNClassifier(weights=Inverse())
2423
f, _, _ = fit(knnc, 1, x, y)
@@ -27,7 +26,7 @@
2726
@test f2 isa KNNResult
2827
@test f2.sample_weights == w
2928
@test fitted_params(knnc, f) == (tree=f.tree,)
30-
29+
3130
# Check predictions gotten from the model
3231
p = predict(knnc, f, xtest)
3332
p2 = predict(knnc, f2, xtest)
@@ -39,7 +38,7 @@
3938
@test accuracy(p2, ytest) == 1.0
4039
end
4140

42-
@testset "MultitargetKNNClassifier" begin
41+
@testset "MultitargetKNNClassifier" begin
4342
# create something rather silly: 3 massive clusters very separated
4443
rng = StableRNG(10)
4544
n, p = 50, 3
@@ -53,7 +52,7 @@ end
5352
y1 = categorical(vcat(y11, y21, y31))
5453
y2 = categorical(vcat(y12, y22, y32), ordered=true)
5554
y = (a=y1, b=y2)
56-
55+
5756
# generate test data
5857
ntest = 5
5958
xtest = make_xtest(ntest, p, rng=rng)
@@ -66,14 +65,14 @@ end
6665
ytest1 = categorical(vcat(ytest11, ytest21, ytest31))
6766
ytest2 = categorical(vcat(ytest12, ytest22, ytest32), ordered=true)
6867
ytest = (a=ytest1, b=ytest2)
69-
70-
# Create two models, the first has an `output_type` of `DictTable` while the second
68+
69+
# Create two models, the first has an `output_type` of `DictTable` while the second
7170
# has an `output_type` of `ColumnTable`
7271
multi_knnc = MultitargetKNNClassifier(weights=Inverse())
7372
multi_knnc2 = MultitargetKNNClassifier(
7473
weights=Inverse(), output_type=ColumnTable
7574
)
76-
75+
7776
# Test model fit
7877
f, _, _ = fit(multi_knnc, 1, x, y)
7978
f2, _ , _ = fit(multi_knnc, 1, x, y, w)
@@ -83,7 +82,7 @@ end
8382
@test f2.sample_weights == w
8483
@test f4.sample_weights == w
8584
@test fitted_params(multi_knnc, f) == (tree=f.tree,)
86-
85+
8786
# Check predictions gotten from the model
8887
p = predict(multi_knnc, f, xtest)
8988
p2 = predict(multi_knnc, f2, xtest)
@@ -92,13 +91,13 @@ end
9291
p5 = predict_mode(multi_knnc, f, xtest)
9392
p6 = predict_mode(multi_knnc, f2, xtest)
9493
p7 = predict_mode(multi_knnc2, f3, xtest)
95-
p8 = predict_mode(multi_knnc2, f4, xtest)
94+
p8 = predict_mode(multi_knnc2, f4, xtest)
9695
for col in [:a, :b]
9796
@test p[col][1] isa UnivariateFinite
9897
@test p2[col][1] isa UnivariateFinite
9998
@test p3[col][1] isa UnivariateFinite
10099
@test p4[col][1] isa UnivariateFinite
101-
100+
102101
@test accuracy(p5[col], ytest[col]) == 1.0
103102
@test accuracy(p6[col], ytest[col]) == 1.0
104103
@test accuracy(p7[col], ytest[col]) == 1.0
@@ -145,20 +144,21 @@ end
145144
y2 = fill( 2.0, n)
146145
y3 = fill(-2.0, n)
147146
y = vcat(y1, y2, y3)
148-
147+
149148
# Test model fit
150149
knnr = KNNRegressor(weights=Inverse())
151150
f, _, _ = fit(knnr, 1, x, y)
152151
f2, _, _ = fit(knnr, 1, x, y, w)
153152
@test f2 isa KNNResult
154153
@test fitted_params(knnr, f) == (tree=f.tree,)
155-
154+
156155
# Create test data
157156
ntest = 5
158157
xtest = make_xtest(ntest, p, rng=rng)
159-
158+
160159
# Check predictions gotten from the model
161160
p = predict(knnr, f, xtest)
161+
@test p isa AbstractVector
162162
p2 = predict(knnr, f2, xtest)
163163
@test all(p[1:ntest] .≈ 0.0)
164164
@test all(p[ntest+1:2*ntest] .≈ 2.0)
@@ -172,19 +172,19 @@ end
172172
x, w = make_x_and_w(n, p, rng=rng)
173173
ymat = vcat(fill( 0.0, n, 2), fill(2.0, n, 2), fill(-2.0, n, 2))
174174
Y = table(ymat; names = [:a, :b])
175-
175+
176176
# Test model fit
177177
multi_knnr = MultitargetKNNRegressor(weights=Inverse())
178178
f, _ , _ = fit(multi_knnr, 1, x, Y)
179179
f2, _, _ = fit(multi_knnr, 1, x, Y, w)
180180
@test fitted_params(multi_knnr, f) == (tree=f.tree,)
181181
@test f2 isa KNNResult
182182
@test f2.sample_weights == w
183-
183+
184184
# Create test data
185185
ntest = 5
186186
xtest = make_xtest(ntest, p, rng=rng)
187-
187+
188188
# Check predictions gotten from the model
189189
pr = predict(multi_knnr, f, xtest)
190190
for col in [:a, :b]

0 commit comments

Comments
 (0)