Skip to content
pievos101Public

About

Unsupervised Random Forest-based Clustering

Resources

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

18 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

uRF

Installation

The uRF R-package can be installed using devtools.

install.packages("devtools")
library(devtools)
devtools::install_github("pievos101/uRF")
library(uRF)

Usage

Clustering

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])

Assigning new subjects to existing clusters

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 species

This 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_cluster

These 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.

Feature Importance per Cluster

# Now, that we have the clusters computed, 
# feature importance per cluster and feature can be determined
fimp = uRF::fimp(d, clusters=res$clusters)
fimp

Federated Computation


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])

Citation

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}
}

Acknowledgement

The uRF package is based on the ranger package (https://github.com/imbs-hl/ranger).

About

Unsupervised Random Forest-based Clustering

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages