Unified Training Interface
smile.model.Model provides one entry point for tabular classification and regression. Choose an algorithm name, a Formula, data, and a Properties bag of hyperparameters; the result is a ClassificationModel or RegressionModel record containing the predictor, metrics, schema, formula, and metadata.
Use the focused classification and regression guides for algorithm theory and complete Options references.
Quick Start
This Random Forest example trains on Iris with a small Properties configuration. Passing null for the test frame still returns the rich model record.
import java.util.Properties;
import smile.datasets.Iris;
import smile.model.Model;
var iris = new Iris();
var params = new Properties();
params.setProperty("smile.random_forest.trees", "200");
var model = Model.classification(
"random-forest", iris.formula(), iris.data(), null, params);
System.out.println(model.algorithm());
System.out.println(model.train().accuracy());
random-forest
(training accuracy)
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = new Iris()
val params = new Properties()
params.setProperty("smile.random_forest.trees", "200")
val model = Model.classification(
"random-forest", iris.formula, iris.data, null, params)
println(model.algorithm)
println(model.train.accuracy)
random-forest
(training accuracy)
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = Iris()
val params = Properties()
params.setProperty("smile.random_forest.trees", "200")
val model = Model.classification(
"random-forest", iris.formula(), iris.data(), null, params)
println(model.algorithm())
println(model.train().accuracy())
random-forest
(training accuracy)
Core Concepts
Formula.lhs("y") selects y as the response and uses all remaining columns as predictors. The supplied Properties is cloned when the record is created: later changes to the original do not change model.tags().
import java.util.Properties;
import smile.datasets.Iris;
import smile.model.Model;
var iris = new Iris();
var params = new Properties();
var model = Model.classification(
"cart", iris.formula(), iris.data(), null, params);
params.setProperty("after.training", "not copied");
System.out.println(model.formula());
System.out.println(model.schema());
System.out.println(model.tags().containsKey("after.training"));
(formula)
(predictor schema)
false
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = new Iris()
val params = new Properties()
val model = Model.classification("cart", iris.formula, iris.data, null, params)
params.setProperty("after.training", "not copied")
println(model.formula)
println(model.schema)
println(model.tags.containsKey("after.training"))
(formula)
(predictor schema)
false
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = Iris()
val params = Properties()
val model = Model.classification("cart", iris.formula(), iris.data(), null, params)
params.setProperty("after.training", "not copied")
println(model.formula())
println(model.schema())
println(model.tags().containsKey("after.training"))
(formula)
(predictor schema)
false
Training Classification Models
The five-argument overload accepts an optional held-out test frame. The full overload additionally controls repeated cross-validation and whether fold predictors become the final ensemble.
import java.util.Properties;
import smile.datasets.ImageSegmentation;
import smile.model.Model;
var data = new ImageSegmentation();
var plain = Model.classification(
"random-forest", data.formula(), data.train(), null, new Properties());
var tested = Model.classification(
"random-forest", data.formula(), data.train(), data.test(), new Properties());
var validated = Model.classification(
"random-forest", data.formula(), data.train(), data.test(),
new Properties(), 5, 1, false);
System.out.println(tested.test().accuracy());
System.out.println(validated.validation().accuracy());
(held-out accuracy)
(average CV accuracy)
import java.util.Properties
import smile.datasets.ImageSegmentation
import smile.model.Model
val data = new ImageSegmentation()
val plain = Model.classification(
"random-forest", data.formula, data.train, null, new Properties())
val tested = Model.classification(
"random-forest", data.formula, data.train, data.test, new Properties())
val validated = Model.classification(
"random-forest", data.formula, data.train, data.test,
new Properties(), 5, 1, false)
println(tested.test.accuracy)
println(validated.validation.accuracy)
(held-out accuracy)
(average CV accuracy)
import java.util.Properties
import smile.datasets.ImageSegmentation
import smile.model.Model
val data = ImageSegmentation()
val plain = Model.classification(
"random-forest", data.formula(), data.train(), null, Properties())
val tested = Model.classification(
"random-forest", data.formula(), data.train(), data.test(), Properties())
val validated = Model.classification(
"random-forest", data.formula(), data.train(), data.test(),
Properties(), 5, 1, false)
println(tested.test().accuracy())
println(validated.validation().accuracy())
(held-out accuracy)
(average CV accuracy)
Training Regression Models
Regression has the same three overload shapes. The four-argument form returns DataFrameRegression; the forms with a test argument return RegressionModel.
import java.util.Properties;
import smile.datasets.Abalone;
import smile.model.Model;
var abalone = new Abalone();
var model = Model.regression(
"ols", abalone.formula(), abalone.train(), abalone.test(),
new Properties());
System.out.println(model.test().rmse());
var cv = Model.regression(
"ols", abalone.formula(), abalone.train(), abalone.test(),
new Properties(), 5, 1, false);
System.out.println(cv.validation().r2());
(held-out RMSE)
(average CV R²)
import java.util.Properties
import smile.datasets.Abalone
import smile.model.Model
val abalone = new Abalone()
val model = Model.regression(
"ols", abalone.formula, abalone.train, abalone.test, new Properties())
println(model.test.rmse)
val cv = Model.regression(
"ols", abalone.formula, abalone.train, abalone.test,
new Properties(), 5, 1, false)
println(cv.validation.r2)
(held-out RMSE)
(average CV R²)
import java.util.Properties
import smile.datasets.Abalone
import smile.model.Model
val abalone = Abalone()
val model = Model.regression(
"ols", abalone.formula(), abalone.train(), abalone.test(), Properties())
println(model.test().rmse())
val cv = Model.regression(
"ols", abalone.formula(), abalone.train(), abalone.test(),
Properties(), 5, 1, false)
println(cv.validation().r2())
(held-out RMSE)
(average CV R²)
Cross-Validation and Ensembles
Set kfold >= 2 to run round × kfold folds. Classification uses stratified folds; regression uses regression folds. validation() stores the average metrics. With ensemble=false, SMILE retrains on all training rows; with ensemble=true, the fold models are combined. When kfold < 2, validation is null and the flag is ignored.
For choosing folds and comparing candidates, see Model Validation. For searching property configurations, see Hyperparameter Optimization.
Evaluating Models
The records expose train(), validation(), and test(). Training metrics are always populated; validation and test metrics are nullable because their data is optional. Classification metrics include accuracy, errors, precision, recall, F1, and binary AUC where applicable. Regression metrics include RMSE, MAE, and R².
import java.util.Properties;
import smile.datasets.ImageSegmentation;
import smile.model.Model;
var data = new ImageSegmentation();
var model = Model.classification(
"cart", data.formula(), data.train(), data.test(),
new Properties(), 5, 1, false);
System.out.printf("train %.3f%n", model.train().accuracy());
System.out.printf("cv %.3f%n", model.validation().accuracy());
System.out.printf("test %.3f%n", model.test().accuracy());
train (accuracy)
cv (accuracy)
test (accuracy)
import java.util.Properties
import smile.datasets.ImageSegmentation
import smile.model.Model
val data = new ImageSegmentation()
val model = Model.classification(
"cart", data.formula, data.train, data.test,
new Properties(), 5, 1, false)
println(model.train.accuracy)
println(model.validation.accuracy)
println(model.test.accuracy)
train (accuracy)
cv (accuracy)
test (accuracy)
import java.util.Properties
import smile.datasets.ImageSegmentation
import smile.model.Model
val data = ImageSegmentation()
val model = Model.classification(
"cart", data.formula(), data.train(), data.test(),
Properties(), 5, 1, false)
println(model.train().accuracy())
println(model.validation().accuracy())
println(model.test().accuracy())
train (accuracy)
cv (accuracy)
test (accuracy)
Making Predictions
Both records implement single-row predict(Tuple). Classification also accepts a posterior-probability array and exposes numClasses(). For batches, call classifier() or regression() and predict a DataFrame.
import java.util.Properties;
import smile.datasets.Iris;
import smile.model.Model;
var iris = new Iris();
var model = Model.classification(
"random-forest", iris.formula(), iris.data(), null, new Properties());
int one = model.predict(iris.data().get(0));
double[] posterior = new double[model.numClasses()];
model.predict(iris.data().get(0), posterior);
int[] batch = model.classifier().predict(iris.data());
System.out.println(one + " / " + batch.length);
(predicted class) / 150
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = new Iris()
val model = Model.classification(
"random-forest", iris.formula, iris.data, null, new Properties())
val one = model.predict(iris.data(0))
val posterior = new Array[Double](model.numClasses)
model.predict(iris.data(0), posterior)
val batch = model.classifier.predict(iris.data)
println(s"$one / ${batch.length}")
(predicted class) / 150
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = Iris()
val model = Model.classification(
"random-forest", iris.formula(), iris.data(), null, Properties())
val one = model.predict(iris.data().get(0))
val posterior = DoubleArray(model.numClasses())
model.predict(iris.data().get(0), posterior)
val batch = model.classifier().predict(iris.data())
println("$one / ${batch.size}")
(predicted class) / 150
Metadata Tags
Tags are strings stored in the record's Properties. Model.ID and Model.VERSION are conventional keys; custom provenance keys are welcome. Read them with getTag(key) or getTag(key, defaultValue).
import java.util.Properties;
import smile.datasets.Iris;
import smile.model.Model;
var iris = new Iris();
var model = Model.classification(
"cart", iris.formula(), iris.data(), null, new Properties());
model.setTag(Model.ID, "iris-cart");
model.setTag(Model.VERSION, "1.0");
model.setTag("dataset", "iris");
System.out.println(model.getTag(Model.ID));
System.out.println(model.getTag("environment", "development"));
iris-cart
development
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = new Iris()
val model = Model.classification("cart", iris.formula, iris.data, null, new Properties())
model.setTag(Model.ID, "iris-cart")
model.setTag(Model.VERSION, "1.0")
model.setTag("dataset", "iris")
println(model.getTag(Model.ID))
println(model.getTag("environment", "development"))
iris-cart
development
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = Iris()
val model = Model.classification("cart", iris.formula(), iris.data(), null, Properties())
model.setTag(Model.ID, "iris-cart")
model.setTag(Model.VERSION, "1.0")
model.setTag("dataset", "iris")
println(model.getTag(Model.ID))
println(model.getTag("environment", "development"))
iris-cart
development
Algorithm Reference
Names below are the exact strings accepted by the Model switch cases. Prefixes identify the most useful property families, not every available key.
Classification
| Name | Algorithm | Key property prefix |
|---|---|---|
random-forest | Random Forest | smile.random_forest.* |
gradient-boost | Gradient Boosted Trees | smile.gradient_boost.* |
ada-boost | AdaBoost | smile.adaboost.* |
cart | Decision Tree | smile.cart.* |
logistic | Logistic Regression | smile.logistic.* |
fisher, lda, qda | Discriminant analysis | none |
rda | Regularized Discriminant Analysis | smile.rda.* |
mlp | Multilayer Perceptron | smile.mlp.* |
svm | Support Vector Machine | smile.svm.* |
rbf | RBF Network | algorithm defaults |
Regression
| Name | Algorithm | Key property prefix |
|---|---|---|
random-forest | Random Forest | smile.random_forest.* |
gradient-boost | Gradient Boosted Trees | smile.gradient_boost.* |
cart | Regression Tree | smile.cart.* |
ols | Ordinary Least Squares | smile.ols.* |
lasso | LASSO | smile.lasso.* |
elastic-net | Elastic Net | smile.elastic_net.* |
ridge | Ridge Regression | smile.ridge.* |
gaussian-process | Gaussian Process | smile.gaussian_process.* |
mlp | Multilayer Perceptron | smile.mlp.* |
svm | Support Vector Regression | smile.svm.* |
rbf | RBF Network | algorithm defaults |
Common examples include smile.random_forest.trees, smile.gradient_boost.shrinkage, smile.cart.max_depth, smile.svm.C, and smile.ols.method. Use Hyperparameter Optimization to generate candidate Properties configurations.
Kernel Specification Strings
SVM and Gaussian Process properties parse compact kernel strings. Supported forms include linear, Gaussian(sigma), Laplacian(sigma), Polynomial(degree,scale,offset), ThinPlateSpline(sigma), Pearson(omega,nu), Hyperbolic(scale,offset), Hellinger, SparsLinear, and BinarySparseLinear.
import java.util.Properties;
import smile.datasets.Iris;
import smile.model.Model;
var iris = new Iris();
var params = new Properties();
params.setProperty("smile.svm.kernel", "Gaussian(1.0)");
params.setProperty("smile.svm.C", "10");
params.setProperty("smile.svm.type", "ovo");
var svm = Model.classification(
"svm", iris.formula(), iris.data(), null, params);
System.out.println(svm.train().accuracy());
(training accuracy)
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = new Iris()
val params = new Properties()
params.setProperty("smile.svm.kernel", "Gaussian(1.0)")
params.setProperty("smile.svm.C", "10")
params.setProperty("smile.svm.type", "ovo")
val svm = Model.classification("svm", iris.formula, iris.data, null, params)
println(svm.train.accuracy)
(training accuracy)
import java.util.Properties
import smile.datasets.Iris
import smile.model.Model
val iris = Iris()
val params = Properties()
params.setProperty("smile.svm.kernel", "Gaussian(1.0)")
params.setProperty("smile.svm.C", "10")
params.setProperty("smile.svm.type", "ovo")
val svm = Model.classification("svm", iris.formula(), iris.data(), null, params)
println(svm.train().accuracy())
(training accuracy)
Serialization
Both model records implement Serializable. smile.io.Write.object writes a record and smile.io.Read.object restores it. Keep serialized models with their compatible SMILE version; Java serialization is not a language-neutral interchange format.
import java.nio.file.Path;
import java.util.Properties;
import smile.datasets.Iris;
import smile.io.Read;
import smile.io.Write;
import smile.model.ClassificationModel;
import smile.model.Model;
var iris = new Iris();
var model = Model.classification(
"cart", iris.formula(), iris.data(), null, new Properties());
Path path = Write.object(model);
var restored = (ClassificationModel) Read.object(path);
System.out.println(restored.predict(iris.data().get(0)));
(predicted class from restored model)
import java.util.Properties
import smile.datasets.Iris
import smile.io.{Read, Write}
import smile.model.{ClassificationModel, Model}
val iris = new Iris()
val model = Model.classification("cart", iris.formula, iris.data, null, new Properties())
val path = Write.object(model)
val restored = Read.object(path).asInstanceOf[ClassificationModel]
println(restored.predict(iris.data(0)))
(predicted class from restored model)
import java.util.Properties
import smile.datasets.Iris
import smile.io.Read
import smile.io.Write
import smile.model.ClassificationModel
import smile.model.Model
val iris = Iris()
val model = Model.classification("cart", iris.formula(), iris.data(), null, Properties())
val path = Write.object(model)
val restored = Read.object(path) as ClassificationModel
println(restored.predict(iris.data().get(0)))
(predicted class from restored model)
Complete End-to-End Example
This held-out Image Segmentation run trains, evaluates, tags, and uses one Random Forest model. The test frame is never used for fitting.
import java.util.Properties;
import smile.datasets.ImageSegmentation;
import smile.model.Model;
var data = new ImageSegmentation();
var params = new Properties();
params.setProperty("smile.random_forest.trees", "200");
params.setProperty("smile.random_forest.max_nodes", "100");
var model = Model.classification(
"random-forest", data.formula(), data.train(), data.test(), params);
model.setTag(Model.ID, "segmentation-rf");
model.setTag(Model.VERSION, "1.0");
System.out.printf("train accuracy = %.3f%n", model.train().accuracy());
System.out.printf("test accuracy = %.3f%n", model.test().accuracy());
int prediction = model.predict(data.test().get(0));
System.out.println("first prediction = " + prediction);
train accuracy = (value)
test accuracy = (value)
first prediction = (class)
import java.util.Properties
import smile.datasets.ImageSegmentation
import smile.model.Model
val data = new ImageSegmentation()
val params = new Properties()
params.setProperty("smile.random_forest.trees", "200")
params.setProperty("smile.random_forest.max_nodes", "100")
val model = Model.classification(
"random-forest", data.formula, data.train, data.test, params)
model.setTag(Model.ID, "segmentation-rf")
model.setTag(Model.VERSION, "1.0")
println(s"train accuracy = ${model.train.accuracy}")
println(s"test accuracy = ${model.test.accuracy}")
println(s"first prediction = ${model.predict(data.test(0))}")
train accuracy = (value)
test accuracy = (value)
first prediction = (class)
import java.util.Properties
import smile.datasets.ImageSegmentation
import smile.model.Model
val data = ImageSegmentation()
val params = Properties()
params.setProperty("smile.random_forest.trees", "200")
params.setProperty("smile.random_forest.max_nodes", "100")
val model = Model.classification(
"random-forest", data.formula(), data.train(), data.test(), params)
model.setTag(Model.ID, "segmentation-rf")
model.setTag(Model.VERSION, "1.0")
println("train accuracy = ${model.train().accuracy()}")
println("test accuracy = ${model.test().accuracy()}")
println("first prediction = ${model.predict(data.test().get(0))}")
train accuracy = (value)
test accuracy = (value)
first prediction = (class)