Inference
Validate feature-column order before NumPy inference
A correct matrix shape cannot detect swapped feature meanings. Pack named records using a fixed schema and reject mismatched fields before scoring.
Evidence and testing
Review record: Tensor Almanac automated evidence gate (no independent human review). Example versions, recorded outputs and limitations appear below.
Shape does not establish feature meaning
A two-column inference input can have the expected shape while its features occupy the wrong positions. Python dictionaries preserve insertion order, including iteration through values. Dictionary equality, however, compares key-value pairs without requiring the same order. Two equal records can therefore yield differently ordered value lists. [1]
Our fixture stores tokens=2 and requests=5 twice, inserting the keys in opposite orders. A toy linear score expects tokens first and requests second, with weights one and ten. Converting each record with list(row.values()) produces scores 52 and 25 even though the named inputs are equal. Both the incorrect and corrected matrices have shape (2, 2). These are executed fixture results, not measured model quality.
References: [1]
Read each value through the model schema
Keep the ordered feature names alongside the scoring artifact, then use that same order during input assembly. The example fixes the column tuple as tokens followed by requests. It looks up each value by its column name and passes the resulting nested sequence to np.array with an explicit float64 dtype. NumPy documents nested sequences as array input and dtype as the requested element type. [2]
Before converting any row, pack_rows requires its key set to match the schema exactly. It rejects a missing field, an extra field and a wrong field name even when the number of supplied fields is correct. It also rejects duplicate column names and an empty schema. Silently discarding unexpected keys or substituting zero for absent values would hide a different input contract.
Run python examples/feature_column_contract.py. Assertions verify the differing insertion-order scores, identical corrected scores, a single-row batch and five rejected field/schema fixtures. The empty batch retains shape (0, 2), so downstream code can handle that case explicitly.
Executed with Python 3.12.14 and NumPy 2.3.5 on CPU. Exact stdout and source-byte SHA-256 are preserved in private evidence.
"""Keep named input records aligned with an explicit model feature order."""
import numpy as np
def pack_rows(rows, columns):
columns = tuple(columns)
if not columns or len(set(columns)) != len(columns):
raise ValueError("feature columns must be nonempty and unique")
expected = set(columns)
packed = []
for row in rows:
if set(row) != expected:
raise ValueError("record fields must exactly match feature columns")
packed.append([row[name] for name in columns])
return np.array(packed, dtype=np.float64).reshape(-1, len(columns))
columns = ("tokens", "requests")
rows = [{"tokens": 2, "requests": 5}, {"requests": 5, "tokens": 2}]
assert rows[0] == rows[1]
weights = np.array([1.0, 10.0])
naive = np.array([list(row.values()) for row in rows], dtype=np.float64)
aligned = pack_rows(rows, columns)
assert naive.shape == aligned.shape == (2, 2)
assert (naive @ weights).tolist() == [52.0, 25.0]
assert (aligned @ weights).tolist() == [52.0, 52.0]
assert np.array_equal(aligned, np.array([[2.0, 5.0], [2.0, 5.0]]))
assert pack_rows(rows[:1], columns).shape == (1, 2)
rejected = 0
for bad_rows, bad_columns in (
([{"tokens": 2}], columns),
([{"tokens": 2, "requests": 5, "extra": 9}], columns),
([{"tokens": 2, "wrong_name": 5}], columns),
(rows, ("tokens", "tokens")),
(rows, ()),
):
try:
pack_rows(bad_rows, bad_columns)
except ValueError:
rejected += 1
assert rejected == 5
empty = pack_rows([], columns)
assert empty.shape == (0, 2) and empty.dtype == np.float64
print("equal input records:", rows[0] == rows[1])
print("naive and aligned shapes:", naive.shape, aligned.shape)
print("insertion-order scores:", (naive @ weights).tolist())
print("schema-order scores:", (aligned @ weights).tolist())
print("invalid field/schema fixtures rejected:", rejected)
print("empty batch shape:", empty.shape)
Recorded output
equal input records: True naive and aligned shapes: (2, 2) (2, 2) insertion-order scores: [52.0, 25.0] schema-order scores: [52.0, 52.0] invalid field/schema fixtures rejected: 5 empty batch shape: (0, 2)
Preserve semantics beyond the column names
Use the training feature order as the contract; sorting incoming keys independently can still disagree with it. Apply the same assembly helper in training and serving where possible, and check a known named record against its expected vector. An all-equal feature fixture would not expose this swap.
This helper handles small batches of dictionaries containing scalar numeric values. It does not validate units, value ranges, missing-value conventions, preprocessing versions or concurrent mutation. It materializes the batch in memory and does not train or load a model. A valid key set and a correct order establish only this part of the inference boundary.