or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backend-integration.mdindex.mdmodel-composition.mdmodel-construction.mdmodel-hub.mdmodel-io.mdmodel-validation.mdnumpy-integration.mdoperator-definitions.mdreference-implementation.mdshape-inference.mdtext-processing.mdversion-conversion.md

numpy-integration.mddocs/

0

# NumPy Integration

1

2

Bidirectional conversion between ONNX tensors and NumPy arrays, supporting all ONNX data types including specialized formats like bfloat16 and float8 variants. This module enables seamless integration between ONNX models and NumPy-based data processing workflows.

3

4

## Capabilities

5

6

### Array Conversion

7

8

Convert between ONNX TensorProto and NumPy arrays with full type support.

9

10

```python { .api }

11

def to_array(tensor: TensorProto, base_dir: str = "") -> np.ndarray:

12

"""

13

Converts a tensor def object to a numpy array.

14

15

Parameters:

16

- tensor: a TensorProto object.

17

- base_dir: if external tensor exists, base_dir can help to find the path to it

18

19

Returns:

20

numpy.ndarray: NumPy array with appropriate dtype and shape

21

22

Raises:

23

ValueError: If tensor data is invalid or unsupported

24

"""

25

26

def from_array(arr: np.ndarray, name: Optional[str] = None) -> TensorProto:

27

"""

28

Converts a numpy array to a tensor def.

29

30

Parameters:

31

- arr: a numpy array.

32

- name: (optional) the name of the tensor.

33

34

Returns:

35

TensorProto: ONNX tensor representation

36

37

Raises:

38

ValueError: If array dtype is not supported by ONNX

39

"""

40

```

41

42

### Container Conversion

43

44

Convert between ONNX container types and Python collections.

45

46

```python { .api }

47

def to_list(sequence):

48

"""

49

Convert ONNX SequenceProto to Python list.

50

51

Parameters:

52

- sequence: SequenceProto to convert

53

54

Returns:

55

list: Python list containing sequence elements

56

57

Raises:

58

ValueError: If sequence contains unsupported element types

59

"""

60

61

def from_list(lst, dtype=None, name=None):

62

"""

63

Convert Python list to ONNX SequenceProto.

64

65

Parameters:

66

- lst: Python list to convert

67

- dtype: Optional element data type specification

68

- name: Optional name for the sequence

69

70

Returns:

71

SequenceProto: ONNX sequence representation

72

73

Raises:

74

ValueError: If list elements cannot be converted to ONNX types

75

"""

76

77

def to_dict(map_proto):

78

"""

79

Convert ONNX MapProto to Python dictionary.

80

81

Parameters:

82

- map_proto: MapProto to convert

83

84

Returns:

85

dict: Python dictionary with converted key-value pairs

86

87

Raises:

88

ValueError: If map contains unsupported key or value types

89

"""

90

91

def from_dict(dict_, name=None):

92

"""

93

Convert Python dictionary to ONNX MapProto.

94

95

Parameters:

96

- dict_: Python dictionary to convert

97

- name: Optional name for the map

98

99

Returns:

100

MapProto: ONNX map representation

101

102

Raises:

103

ValueError: If dictionary keys or values cannot be converted

104

"""

105

106

def to_optional(optional):

107

"""

108

Convert ONNX OptionalProto to Python optional value.

109

110

Parameters:

111

- optional: OptionalProto to convert

112

113

Returns:

114

Any or None: Converted value or None if optional is empty

115

116

Raises:

117

ValueError: If optional contains unsupported element type

118

"""

119

120

def from_optional(value, name=None):

121

"""

122

Convert Python value to ONNX OptionalProto.

123

124

Parameters:

125

- value: Python value to convert (None for empty optional)

126

- name: Optional name for the optional

127

128

Returns:

129

OptionalProto: ONNX optional representation

130

131

Raises:

132

ValueError: If value cannot be converted to ONNX type

133

"""

134

```

135

136

### Specialized Float Type Conversion

137

138

Convert between specialized floating point formats and standard types.

139

140

```python { .api }

141

def bfloat16_to_float32(bfloat16_data, dims=None):

142

"""

143

Convert bfloat16 data to float32.

144

145

Parameters:

146

- bfloat16_data: NumPy array of bfloat16 data (as uint16)

147

- dims: Optional target dimensions for reshaping

148

149

Returns:

150

numpy.ndarray: Float32 array with converted values

151

"""

152

153

def float8e4m3_to_float32(float8_data, fn=True, uz=False):

154

"""

155

Convert float8 E4M3 data to float32.

156

157

Parameters:

158

- float8_data: NumPy array of float8 E4M3 data (as uint8)

159

- fn: Whether finite values only (True) or include infinities

160

- uz: Whether to use unsigned zero representation

161

162

Returns:

163

numpy.ndarray: Float32 array with converted values

164

"""

165

166

def float8e5m2_to_float32(float8_data, fn=True, uz=False):

167

"""

168

Convert float8 E5M2 data to float32.

169

170

Parameters:

171

- float8_data: NumPy array of float8 E5M2 data (as uint8)

172

- fn: Whether finite values only (True) or include infinities

173

- uz: Whether to use unsigned zero representation

174

175

Returns:

176

numpy.ndarray: Float32 array with converted values

177

"""

178

179

def combine_pairs_to_complex(fa):

180

"""

181

Combine pairs of float values to complex numbers.

182

183

Parameters:

184

- fa: Sequence of float values (length must be even)

185

186

Returns:

187

list: List of complex numbers

188

"""

189

```

190

191

### Utility Functions

192

193

Additional utilities for tensor data manipulation and conversion.

194

195

```python { .api }

196

def convert_endian(tensor):

197

"""

198

Convert tensor data endianness in place for cross-platform compatibility.

199

200

Parameters:

201

- tensor: TensorProto to modify

202

203

Returns:

204

None: Modifies tensor in place

205

"""

206

207

def create_random_int(shape, low=0, high=100, output_type=TensorProto.INT32, seed=None):

208

"""

209

Create a tensor with random integer values.

210

211

Parameters:

212

- shape: Tensor shape (list of integers)

213

- low: Minimum value (inclusive)

214

- high: Maximum value (exclusive)

215

- output_type: ONNX data type for output

216

- seed: Random seed for reproducibility

217

218

Returns:

219

TensorProto: Tensor with random integer data

220

"""

221

```

222

223

## Usage Examples

224

225

### Basic Array Conversion

226

227

```python

228

import onnx

229

from onnx import numpy_helper, TensorProto

230

import numpy as np

231

232

# Convert NumPy array to ONNX tensor

233

np_array = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)

234

onnx_tensor = numpy_helper.from_array(np_array, name="my_tensor")

235

236

print(f"ONNX tensor shape: {onnx_tensor.dims}")

237

print(f"ONNX tensor type: {onnx_tensor.data_type}")

238

239

# Convert ONNX tensor back to NumPy array

240

converted_array = numpy_helper.to_array(onnx_tensor)

241

print(f"Converted array shape: {converted_array.shape}")

242

print(f"Converted array dtype: {converted_array.dtype}")

243

print(f"Data preserved: {np.array_equal(np_array, converted_array)}")

244

```

245

246

### Working with Different Data Types

247

248

```python

249

import onnx

250

from onnx import numpy_helper, TensorProto

251

import numpy as np

252

253

# Create arrays with different dtypes

254

int_array = np.array([1, 2, 3, 4, 5], dtype=np.int64)

255

float_array = np.array([1.5, 2.5, 3.5], dtype=np.float64)

256

bool_array = np.array([True, False, True], dtype=bool)

257

258

# Convert to ONNX tensors

259

int_tensor = numpy_helper.from_array(int_array, "integers")

260

float_tensor = numpy_helper.from_array(float_array, "floats")

261

bool_tensor = numpy_helper.from_array(bool_array, "booleans")

262

263

print(f"Int tensor type: {int_tensor.data_type} (should be {TensorProto.INT64})")

264

print(f"Float tensor type: {float_tensor.data_type} (should be {TensorProto.DOUBLE})")

265

print(f"Bool tensor type: {bool_tensor.data_type} (should be {TensorProto.BOOL})")

266

267

# Convert back and verify

268

print(f"Int conversion: {np.array_equal(int_array, numpy_helper.to_array(int_tensor))}")

269

print(f"Float conversion: {np.array_equal(float_array, numpy_helper.to_array(float_tensor))}")

270

print(f"Bool conversion: {np.array_equal(bool_array, numpy_helper.to_array(bool_tensor))}")

271

```

272

273

### Container Type Conversion

274

275

```python

276

import onnx

277

from onnx import numpy_helper

278

import numpy as np

279

280

# Work with sequences

281

python_list = [

282

np.array([1, 2, 3], dtype=np.float32),

283

np.array([4, 5, 6], dtype=np.float32),

284

np.array([7, 8, 9], dtype=np.float32)

285

]

286

287

# Convert to ONNX sequence

288

onnx_sequence = numpy_helper.from_list(python_list, name="tensor_sequence")

289

print(f"Sequence has {len(onnx_sequence.tensor_values)} tensors")

290

291

# Convert back to Python list

292

converted_list = numpy_helper.to_list(onnx_sequence)

293

print(f"Converted list has {len(converted_list)} arrays")

294

295

# Work with dictionaries

296

python_dict = {

297

"feature_1": np.array([0.1, 0.2, 0.3], dtype=np.float32),

298

"feature_2": np.array([0.4, 0.5, 0.6], dtype=np.float32)

299

}

300

301

# Convert to ONNX map

302

onnx_map = numpy_helper.from_dict(python_dict, name="feature_map")

303

print(f"Map has {len(onnx_map.string_keys)} keys")

304

305

# Convert back to Python dict

306

converted_dict = numpy_helper.to_dict(onnx_map)

307

print(f"Converted dict keys: {list(converted_dict.keys())}")

308

309

# Work with optional values

310

optional_value = np.array([1, 2, 3], dtype=np.int32)

311

onnx_optional = numpy_helper.from_optional(optional_value, name="maybe_tensor")

312

313

# Convert back

314

converted_optional = numpy_helper.to_optional(onnx_optional)

315

print(f"Optional value shape: {converted_optional.shape}")

316

317

# Empty optional

318

empty_optional = numpy_helper.from_optional(None, name="empty_optional")

319

converted_empty = numpy_helper.to_optional(empty_optional)

320

print(f"Empty optional: {converted_empty}") # Should be None

321

```

322

323

### Specialized Float Type Handling

324

325

```python

326

import onnx

327

from onnx import numpy_helper

328

import numpy as np

329

330

# Simulate bfloat16 data (normally this would come from a model)

331

# bfloat16 is stored as uint16 with the lower 16 bits truncated

332

float32_data = np.array([1.0, 2.5, 3.14159, -1.5], dtype=np.float32)

333

334

# Convert to bfloat16 representation (this is conceptual)

335

# In practice, you'd get this from an ONNX tensor

336

bfloat16_as_uint16 = (float32_data.view(np.uint32) >> 16).astype(np.uint16)

337

338

# Convert bfloat16 back to float32

339

recovered_float32 = numpy_helper.bfloat16_to_float32(bfloat16_as_uint16)

340

print(f"Original: {float32_data}")

341

print(f"Recovered: {recovered_float32}")

342

343

# Work with complex numbers

344

complex_data = [1.0, 2.0, 3.0, 4.0] # Represents (1+2j) and (3+4j)

345

complex_numbers = numpy_helper.combine_pairs_to_complex(complex_data)

346

print(f"Complex numbers: {complex_numbers}")

347

```

348

349

### Integration with Model Processing

350

351

```python

352

import onnx

353

from onnx import numpy_helper

354

import numpy as np

355

356

def process_model_tensors(model_path, output_path):

357

"""Process all tensors in a model using NumPy operations."""

358

359

# Load model

360

model = onnx.load_model(model_path)

361

362

# Process initializer tensors

363

for i, tensor in enumerate(model.graph.initializer):

364

print(f"Processing tensor: {tensor.name}")

365

366

# Convert to NumPy array

367

np_array = numpy_helper.to_array(tensor)

368

print(f" Original shape: {np_array.shape}, dtype: {np_array.dtype}")

369

370

# Perform NumPy operations (example: normalize weights)

371

if np_array.dtype in [np.float32, np.float64]:

372

# Normalize to zero mean, unit variance

373

normalized = (np_array - np_array.mean()) / (np_array.std() + 1e-8)

374

375

# Convert back to ONNX tensor

376

new_tensor = numpy_helper.from_array(normalized, tensor.name)

377

378

# Replace in model

379

model.graph.initializer[i].CopyFrom(new_tensor)

380

print(f" Normalized tensor: mean={normalized.mean():.6f}, std={normalized.std():.6f}")

381

382

# Save processed model

383

onnx.save_model(model, output_path)

384

print(f"Processed model saved to: {output_path}")

385

386

# Example usage (commented out)

387

# process_model_tensors("input_model.onnx", "normalized_model.onnx")

388

```

389

390

### Error Handling and Data Validation

391

392

```python

393

import onnx

394

from onnx import numpy_helper, TensorProto

395

import numpy as np

396

397

def safe_tensor_conversion(np_array, tensor_name):

398

"""Safely convert NumPy array to ONNX tensor with error handling."""

399

400

try:

401

# Check for supported dtypes

402

if np_array.dtype not in [np.float32, np.float64, np.int32, np.int64,

403

np.uint32, np.uint64, np.bool_, np.float16]:

404

print(f"Warning: dtype {np_array.dtype} may not be fully supported")

405

406

# Check for NaN or infinite values in float arrays

407

if np.issubdtype(np_array.dtype, np.floating):

408

if np.any(np.isnan(np_array)):

409

print("Warning: Array contains NaN values")

410

if np.any(np.isinf(np_array)):

411

print("Warning: Array contains infinite values")

412

413

# Convert to ONNX tensor

414

onnx_tensor = numpy_helper.from_array(np_array, tensor_name)

415

416

# Verify round-trip conversion

417

recovered_array = numpy_helper.to_array(onnx_tensor)

418

419

if not np.allclose(np_array, recovered_array, equal_nan=True):

420

print("Warning: Round-trip conversion changed values")

421

return None

422

423

print(f"Successfully converted tensor '{tensor_name}'")

424

return onnx_tensor

425

426

except Exception as e:

427

print(f"Error converting tensor '{tensor_name}': {e}")

428

return None

429

430

# Test with various arrays

431

test_arrays = [

432

(np.array([1, 2, 3], dtype=np.int32), "integers"),

433

(np.array([1.0, 2.0, np.nan], dtype=np.float32), "with_nan"),

434

(np.array([1.0, 2.0, np.inf], dtype=np.float32), "with_inf"),

435

(np.array([True, False, True], dtype=bool), "booleans"),

436

]

437

438

for arr, name in test_arrays:

439

tensor = safe_tensor_conversion(arr, name)

440

```