The uRF R-package can be installed using devtools.
install.packages("devtools")
library(devtools)
devtools::install_github("pievos101/uRF")
library(uRF)
library(uRF)
data(iris)
d = iris[,1:4]
# RF-based clustering
# Here, we just use one view, whereas it can be a list of views
res = uRF::uRF(list(d), k=3)
res$affinity
res$clusters
# Performance of the clustering
library(aricode)
ARI(res$clusters, iris[,5])
NMI(res$clusters, iris[,5])
Continuing the iris example above, use d and res$clusters to label the saved
forest's terminal nodes. Keep the predictor rows in the same order as the cluster
labels. Then use ordinary predict() to assign a new iris subject to one of
those clusters:
assignment_model = uRF::assign_clusters(res$model, d, res$clusters)
# Measurements for a new iris subject; use the same predictor column names
new_subject = data.frame(
Sepal.Length = 5.1,
Sepal.Width = 3.4,
Petal.Length = 1.5,
Petal.Width = 0.2
)
pred = predict(assignment_model, new_subject, seed = 42)
pred$predictions # Predicted cluster label (1, 2 or 3), not an iris speciesThis returns a copy of the forest with each terminal node labeled by its majority
cluster. Standard ranger prediction votes across trees; no trees are retrained
and no clustering is rerun. The original res$model is preserved. Assignments
approximate the original clustering, so check agreement on reference subjects:
mean(predict(assignment_model, d, seed = 42)$predictions == res$clusters)To get cluster probabilities as well as a predicted label, retain the cluster
proportions within each leaf with probability = TRUE:
probability_model = uRF::assign_clusters(
res$model, d, res$clusters, probability = TRUE
)
probabilities = predict(probability_model, new_subject)$predictions
probabilities # One row per subject, one column per cluster; each row sums to 1
# Select the cluster with the largest probability (first column wins a tie)
predicted_cluster = colnames(probabilities)[
max.col(probabilities, ties.method = "first")
]
predicted_clusterThese probabilities average the reference cluster proportions in the reached leaves across trees, as in ranger probability forests. They are not simply majority-vote fractions and are not calibrated probabilities. The maximum-probability label can differ from the default majority-vote label.
Every terminal node must contain at least one reference subject. For multiple
views, res$model currently contains only the last view's forest; pass that
view's predictor data. The assignment model then predicts from that view alone.
# Now, that we have the clusters computed,
# feature importance per cluster and feature can be determined
fimp = uRF::fimp(d, clusters=res$clusters)
fimp
library(uRF)
data(iris)
d = iris[,1:4]
# Distribute data over three clients
n.clients = 3
samp = as.numeric(rownames(d))
df = sample(samp, length(samp))
spl = split(df, rep(1:n.clients, length.out = length(df), each = ceiling(length(df)/3)))
d1 = d[spl[[1]],]
d2 = d[spl[[2]],]
d3 = d[spl[[3]],]
res_1 = uRF::uRF(list(d1), k=3)
res_2 = uRF::uRF(list(d2), k=3)
res_3 = uRF::uRF(list(d3), k=3)
res_1_global = uRF::feduRF(list(d1),
models=list(res_1$model,res_2$model,res_3$model), k=3)
res_2_global = uRF::feduRF(list(d2),
models=list(res_1$model,res_2$model,res_3$model), k=3)
res_3_global = uRF::feduRF(list(d3),
models=list(res_1$model,res_2$model,res_3$model), k=3)
library(aricode)
print("Local performance (non-federated model)")
ARI(res_1$clusters, iris[spl[[1]],5])
ARI(res_2$clusters, iris[spl[[2]],5])
ARI(res_3$clusters, iris[spl[[3]],5])
print("Local performance (federated model)")
ARI(res_1_global$clusters, iris[spl[[1]],5])
ARI(res_2_global$clusters, iris[spl[[2]],5])
ARI(res_3_global$clusters, iris[spl[[3]],5])
If you find the uRF package useful please cite
@article{pfeifer2024federated,
title={Federated unsupervised random forest for privacy-preserving patient stratification},
author={Pfeifer, Bastian and Sirocchi, Christel and Bloice, Marcus D and Kreuzthaler, Markus and Urschler, Martin},
journal={Bioinformatics},
volume={40},
number={Supplement\_2},
pages={ii198--ii207},
year={2024},
publisher={Oxford University Press}
}
The uRF package is based on the ranger package (https://github.com/imbs-hl/ranger).
