forked from raven-ml/raven
raven doc coming-from-python.md
5.4 kB · 171 lines
Markdown

Coming from Python #

This page maps Python scientific computing concepts to their Raven equivalents. It assumes you already know OCaml basics.

Library Mapping #

Python Raven Notes
NumPy Nx N-dimensional arrays, broadcasting, linear algebra, FFT
JAX Rune Functional transformations: grad, jvp, vmap
PyTorch / Flax Kaun Layers, optimizers, training loops
HuggingFace Tokenizers Brot BPE, WordPiece, Unigram; HF-compatible
pandas / Polars Talon Typed tables and queries; CSV and Parquet
Matplotlib Hugin Figures from tensors, rendered to PNG, SVG and PDF
Jupyter + IPython Quill Interactive REPL and markdown notebooks

Key Differences #

Explicit Types #

NumPy casts types silently. Nx does not.

# Python: silently upcasts int + float -> float
a = np.array([1, 2, 3])
b = a + 1.5  # works
(* OCaml: types must match *)
let a = Nx.create Nx.Int32 [|3|] [|1l; 2l; 3l|]
(* Nx.add a (Nx.scalar Nx.Float32 1.5)  -- type error *)

(* Cast explicitly *)
let a_f = Nx.cast Nx.Float32 a
let b = Nx.add a_f (Nx.scalar Nx.Float32 1.5)

Array Literals #

NumPy uses Python lists. Nx uses OCaml arrays with [| |] syntax.

x = np.array([[1, 2], [3, 4]])
let x = Nx.create Nx.Float32 [|2; 2|] [|1.; 2.; 3.; 4.|]

Slicing #

NumPy uses [] with :. Nx uses the slice function with index constructors.

x[0:2, :]           # first two rows
x[:, 1]             # second column
x[::2]              # every other element
Nx.slice [R (0, 2); A] x      (* first two rows *)
Nx.slice [A; I 1] x            (* second column *)
Nx.slice [S (0, -1, 2)] x     (* every other element *)

No Separate Tensor Type #

In PyTorch, torch.Tensor is different from numpy.ndarray. In Raven, Rune operates directly on Nx.t values. There is no wrapper type.

# PyTorch: convert between types
x_np = np.array([1.0, 2.0])
x_torch = torch.from_numpy(x_np)
x_torch.requires_grad_(True)
(* Raven: just use Nx tensors directly *)
let x = Nx.create Nx.Float32 [|2|] [|1.0; 2.0|]
let gradient = Rune.grad' (fun x -> Nx.sum (Nx.mul x x)) x

Functional Transformations #

JAX users will find Rune familiar. PyTorch users: think of grad as a function transformer, not a method on tensors.

# JAX style
grad_fn = jax.grad(loss_fn)
grads = grad_fn(params)

# PyTorch style
loss = loss_fn(params)
loss.backward()
grads = params.grad
(* Rune: JAX-style functional transforms over your own typed record *)
let params_ptree = Nx.Ptree.instantiate (module Params)
let grads = Rune.grad params_ptree loss_fn params

(* Or compute value and gradient together *)
let loss, grads = Rune.value_and_grad params_ptree loss_fn params

Where JAX registers pytrees, Rune takes a structure: Params implements Nx.Ptree.S with one function, walk, over your record's fields, Nx.Ptree.instantiate makes it a value, and gradients come back with the same type as the parameters.

Module-Based Layers #

Kaun layers are plain records with init and apply functions, not classes with forward — and a model is a record you define, not a container object.

# PyTorch
class Model(nn.Module):
    def __init__(self):
        self.linear = nn.Linear(784, 10)
    def forward(self, x):
        return self.linear(x)
model = Model()
(* Kaun: a model is a typed record of layer records *)
type 'a model = { linear : 'a Kaun.Linear.t }

let apply p x = Kaun.Linear.apply p.linear x
let params = { linear = Kaun.Linear.init ~inputs:784 ~outputs:10 }

Parameters are plain data (records of Nx tensors), not hidden inside objects.

DataFrames #

pandas computes each operation as it is called, and finds a wrong column name when the line that uses it runs. Talon builds a query from typed column handles, checks every verb against its input's columns before reading any data, and computes the query when it runs.

# pandas
df["bmi"] = df["weight"] / df["height"] ** 2
(* Talon: a typed expression in a query *)
let weight = Talon.Col.float "weight" and height = Talon.Col.float "height"

let with_bmi df =
  Talon.Query.(df |> derive Talon.Expr.[ "bmi" := weight /. (height *. height) ])

Detailed Comparisons #

Each library has a dedicated comparison page with side-by-side code examples: