Learnify
A didactic Python library for machine learning and deep learning built with raw Python and NumPy.
Quick start
Build a tiny autodiff graph and render it as SVG.
Installation
Set up the project and development dependencies with uv.
Overview
See the small public API surface and how to read the signatures.
Reference
Core API
Autodiff values, graph rendering utilities, and optimization helpers.
Utilities
Metrics and the NumPy-backed random generator helpers.
Models
Linear models, trees, forests, SVMs, clustering, and MLPs.
Plotting
Matplotlib helpers for model diagnostics and visual explanations.
Notes
Compatibility limits and practical assumptions across the library.
Overview
The public surface is intentionally small and readable. Most models follow familiar
fit and predict patterns, while the autodiff system centers on
a single scalar Value type.
Top-level exports:
Value
GradientDescentOptimizer
gradient_descent_step
trace_graph
computation_graph_svg
save_computation_graph_svg
computation_graph_dot
mean_squared_error
accuracy_score
r2_score
rng
plotting
LinearRegressionGD
LogisticRegressionGD
DecisionTreeClassifier
RandomForestClassifier
LinearSVM
KMeans
AgglomerativeClustering
MLP
Reading the signatures:
Xmeans a feature array, usually shaped(n_samples, n_features).ymeans targets or class labels.fit(...)returns the fitted model instance unless noted otherwise.- Names ending in
_are learned or generated after fitting. ax=Nonemeans you may pass an existing Matplotlib axis, or let Learnify create one.
Quick Start
from learnify import Value, computation_graph_svg
x = Value(2.0, label="x")
y = Value(-3.0, label="y")
z = ((x * y) + 4.0).tanh()
z.label = "z"
z.backward()
svg = computation_graph_svg(z)
xandyare scalar autodiff nodes.zis a derived output node built from earlier operations.backward()computes gradients fromzthrough the graph.computation_graph_svg(z)returns an SVG string for the graph rooted atz.
Installation
uv sync --dev
uv sync --devinstalls the package and development dependencies for local work.
Core API
Value
A scalar node in a computation graph.
Value(data, _children=(), op="", label="")
data: the scalar value stored in the node._children: parent nodes used internally to trace the graph.op: a short operation label such as"+"or"tanh".label: optional display text for graph output and debugging.
exp() -> Value
tanh() -> Value
relu() -> Value
sigmoid() -> Value
topo() -> list[Value]
zero_grad() -> None
backward(grad=1.0) -> None
exp(),tanh(),relu(), andsigmoid()each return a new derivedValue.topo()returns the connected graph in topological order.zero_grad()clears gradients across the reachable graph.gradinbackward(grad=1.0)is the incoming output gradient and defaults to1.0.
Graph Utilities
trace_graph(root) -> (nodes, edges)
computation_graph_svg(root, *, node_width=200, node_height=94, horizontal_gap=64, vertical_gap=28, padding=24) -> str
save_computation_graph_svg(root, path, **kwargs) -> Path
computation_graph_dot(root) -> str
root: the outputValueto trace or render.path: destination file path when saving an SVG.node_widthandnode_height: dimensions of each rendered node box.horizontal_gapandvertical_gap: spacing between nodes and layers.padding: outer margin around the SVG drawing.kwargs: forwarded fromsave_computation_graph_svg()intocomputation_graph_svg().
Optimization
gradient_descent_step(parameters, gradients, learning_rate) -> None
GradientDescentOptimizer(learning_rate=0.01)
step_values(parameters) -> None
zero_grad(parameters) -> None
step_arrays(parameters, gradients) -> None
parameters: the arrays orValueobjects to update.gradients: gradient arrays aligned with the array parameters.learning_rate: the gradient descent step size.step_values()updates autodiff parameters in place.zero_grad()clears gradients on a sequence ofValueparameters.step_arrays()applies the same update rule to NumPy arrays.
Utilities
Metrics
mean_squared_error(y_true, y_pred) -> float
accuracy_score(y_true, y_pred) -> float
r2_score(y_true, y_pred) -> float
y_true: expected numeric values or labels.y_pred: predicted numeric values or labels to compare againsty_true.
RNG
learnify.rng.seed(value) -> None
learnify.rng.rand(*shape) -> np.ndarray
learnify.rng.normal(loc=0.0, scale=1.0, size=None) -> np.ndarray
learnify.rng.integers(low, high=None, size=None) -> np.ndarray
learnify.rng.choice(a, size=None, replace=True, p=None) -> np.ndarray
value: integer seed for Learnify's internal random generator.*shape: output dimensions for uniform random samples.locandscale: mean and standard deviation for normal samples.lowandhigh: lower and upper bounds for integer sampling, withhighexclusive.size: output shape fornormal(),integers(), orchoice().a: the source array, sequence, or integer range forchoice().replace: whetherchoice()samples with replacement.p: optional sampling probabilities forchoice().
Models
LinearRegressionGD
LinearRegressionGD(learning_rate=0.01, n_iterations=1000, fit_intercept=True)
fit(X, y) -> LinearRegressionGD
predict(X) -> np.ndarray
score(X, y) -> float
learning_rate: step size for full-batch gradient descent.n_iterations: number of optimization updates.fit_intercept: whether to learn a bias term.X: feature matrix for training or prediction.y: target values for fitting or scoring.score()returns the model'sR^2value.
- Fitted attributes include
weights_,bias_, andloss_history_.
LogisticRegressionGD
LogisticRegressionGD(learning_rate=0.1, n_iterations=1000, l2=0.0)
fit(X, y) -> LogisticRegressionGD
decision_function(X) -> np.ndarray
predict_proba(X) -> np.ndarray
predict(X, threshold=0.5) -> np.ndarray
learning_rate: optimization step size.n_iterations: number of training updates.l2: L2 regularization strength.X: feature matrix for training or inference.y: binary class labels for fitting.threshold: cutoff used bypredict()for the positive class.
- Fitted attributes include
classes_,weights_,bias_, andloss_history_. - This implementation supports binary classification only.
DecisionTreeClassifier
DecisionTreeClassifier(max_depth=None, min_samples_split=2, max_features=None, random_state=None)
fit(X, y) -> DecisionTreeClassifier
predict(X) -> np.ndarray
predict_proba(X) -> np.ndarray
max_depth: optional limit on tree depth.min_samples_split: minimum number of samples required to split a node.max_features: feature sampling rule per split.random_state: seed for internal randomness.X: numeric feature matrix.y: class labels for training.
- Fitted attributes include
classes_,root_,depth_,n_leaves_,feature_importances_, andn_features_in_.
RandomForestClassifier
RandomForestClassifier(n_estimators=10, max_depth=None, min_samples_split=2, max_features="sqrt", bootstrap=True, random_state=None)
fit(X, y) -> RandomForestClassifier
predict_proba(X) -> np.ndarray
predict(X) -> np.ndarray
n_estimators: number of trees in the forest.max_depth,min_samples_split, andmax_features: tree-building controls passed to each estimator.bootstrap: whether each tree uses bootstrap sampling.random_state: seed for forest construction.X: feature matrix.y: class labels.
- Fitted attributes include
trees_,estimators_,feature_importances_,classes_, andn_features_in_.
LinearSVM
LinearSVM(learning_rate=0.01, regularization=0.01, epochs=1000)
fit(X, y) -> LinearSVM
decision_function(X) -> np.ndarray
predict(X) -> np.ndarray
learning_rate: update size during optimization.regularization: weight penalty strength.epochs: number of passes through the optimization loop.X: feature matrix.y: binary class labels.
decision_function()returns signed margins before thresholding.- Fitted attributes include
weights_,bias_,classes_, andloss_history_. - This implementation supports binary classification only.
KMeans
KMeans(n_clusters=2, max_iter=100, tol=1e-4, random_state=None)
fit(X) -> KMeans
fit_predict(X) -> np.ndarray
predict(X) -> np.ndarray
n_clusters: target number of clusters.max_iter: maximum number of refinement steps.tol: convergence tolerance for center movement.random_state: seed for center initialization.X: numeric feature matrix to cluster.
- Fitted attributes include
cluster_centers_,labels_, andinertia_.
AgglomerativeClustering
AgglomerativeClustering(n_clusters=2, linkage="average")
fit(X) -> AgglomerativeClustering
fit_predict(X) -> np.ndarray
n_clusters: final number of clusters after merging.linkage: merge rule, one of"single","complete", or"average".X: numeric feature matrix to cluster.
- Fitted attributes include
labels_,clusters_,children_, anddistances_.
MLP
MLP(n_inputs, layer_sizes, seed=None)
parameters() -> list[Value]
fit(X, y, *, epochs=100, learning_rate=0.05) -> list[float]
predict(X) -> np.ndarray
n_inputs: input width expected by the network.layer_sizes: sizes of hidden layers followed by the output layer.seed: initialization seed for network weights.X: training or prediction inputs.y: training targets.epochsandlearning_rate: training loop length and step size forfit().
parameters()returns the model's learnableValueobjects.fit()returns the loss history across epochs.- Fitted attributes include
loss_history_,n_inputs_,layer_sizes_, andlayers.
Plotting
Import plotting helpers from learnify.plotting. Each function returns a Matplotlib Figure.
Training And Linear Models
plot_loss_curve(loss_history, *, ax=None, title="Training loss")
plot_linear_coefficients(model, *, ax=None, feature_names=None, title="Weights and bias")
plot_regression_fit(model, X, y, *, ax=None, feature_name="x", target_name="y", title="Linear regression fit")
plot_binary_decision_surface(model, X, y, *, ax=None, feature_names=None, response="decision", title="Decision surface")
plot_discriminant_function(model, X, y=None, *, ax=None, feature_names=None, title="Discriminant function")
loss_history: numeric training trace forplot_loss_curve().model: fitted linear or binary classification estimator.Xandy: data to visualize.ax: optional existing Matplotlib axis.feature_names,feature_name,target_name, andtitle: display labels.response: whether the decision-surface plot shows raw scores or probabilities.
Trees And Forests
plot_decision_tree(tree, *, ax=None, feature_names=None, class_names=None, title="Decision tree")
plot_tree_feature_importances(tree, *, ax=None, feature_names=None, title="Decision tree feature importance")
plot_random_forest_feature_importances(forest, *, ax=None, feature_names=None, title="Random forest feature importance")
plot_random_forest(forest, *, feature_names=None, class_names=None, max_trees=4, title="Random forest overview")
treeandforest: fitted estimators to draw.ax: optional existing axis for the single-plot helpers.feature_namesandclass_names: optional display labels.max_trees: number of trees to show in the forest overview.title: figure title.
Clustering
plot_kmeans_clusters(model, X, *, ax=None, feature_names=None, title="KMeans clustering")
plot_agglomerative_clusters(model, X, *, ax=None, feature_names=None, title="Agglomerative clustering")
plot_agglomerative_dendrogram(model, *, ax=None, leaf_labels=None, title="Agglomerative merge diagram")
model: fitted clustering model.X: data to plot for the cluster scatter views.ax: optional existing axis.feature_names: axis labels for feature dimensions.leaf_labels: custom sample labels for the dendrogram.title: figure title.
Neural Networks
plot_mlp_architecture(model, *, ax=None, title="MLP architecture")
plot_mlp_weight_matrices(model, *, title="MLP weight matrices")
plot_mlp_predictions(model, X, y, *, ax=None, feature_name="x", target_name="y", title="MLP regression fit")
model: fittedMLPinstance.Xandy: data for prediction visualizations.ax: optional existing axis where supported.feature_name,target_name, andtitle: display labels.
Notes
- Most model APIs accept NumPy arrays and reshape one-dimensional inputs into column vectors when needed.
LogisticRegressionGDandLinearSVMcurrently support binary classification only.- Several plotting helpers expect one or two input features, depending on the chart.
- Implementations favor readability over scikit-learn compatibility or production optimizations.