From 7c29da191ef28d9c44b648629d8e635d78f0f83d Mon Sep 17 00:00:00 2001 From: chentong319 Date: Tue, 12 May 2020 18:43:44 -0400 Subject: [PATCH] import onnx ml operations as a separate dialect (#97) * generate MLONNX dialect * Add MLONNX to Builder * add MLONNX dialect operation document * fix the format issues Co-authored-by: Gheorghe-Teodor Bercea --- CMakeLists.txt | 11 +- docs/Dialects/mlonnx.md | 597 +++++++++++++++++++++ src/Builder/CMakeLists.txt | 8 + src/Builder/FrontendDialectHelper.hpp | 6 +- src/Builder/FrontendDialectTransformer.cpp | 4 + src/Builder/MLOpBuildTable.inc | 42 ++ src/CMakeLists.txt | 5 + src/Dialect/CMakeLists.txt | 5 +- src/Dialect/MLONNX/CMakeLists.txt | 22 + src/Dialect/MLONNX/MLONNXOps.cpp | 48 ++ src/Dialect/MLONNX/MLONNXOps.hpp | 43 ++ src/Dialect/MLONNX/MLONNXOps.td | 67 +++ src/Dialect/MLONNX/MLONNXOps.td.inc | 373 +++++++++++++ utils/CMakeLists.txt | 25 + utils/gen_doc.py | 36 +- 15 files changed, 1276 insertions(+), 16 deletions(-) create mode 100644 docs/Dialects/mlonnx.md create mode 100644 src/Builder/MLOpBuildTable.inc create mode 100644 src/Dialect/MLONNX/CMakeLists.txt create mode 100644 src/Dialect/MLONNX/MLONNXOps.cpp create mode 100644 src/Dialect/MLONNX/MLONNXOps.hpp create mode 100644 src/Dialect/MLONNX/MLONNXOps.td create mode 100644 src/Dialect/MLONNX/MLONNXOps.td.inc diff --git a/CMakeLists.txt b/CMakeLists.txt index e3b474d..9084b78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,16 @@ add_subdirectory(third_party/pybind11) add_subdirectory(third_party/variant) set(CMAKE_CXX_STANDARD 14) + +if ($ENV{EXCLUDE_ONNX_ML}) + set(INCLUDE_ONNX_ML FALSE) +else() + set(INCLUDE_ONNX_ML TRUE) +endif() + +message(STATUS "INCLUDE_ONNX_ML Dialect " ${INCLUDE_ONNX_ML}) + add_subdirectory(utils) add_subdirectory(src) add_subdirectory(docs) -add_subdirectory(test) \ No newline at end of file +add_subdirectory(test) diff --git a/docs/Dialects/mlonnx.md b/docs/Dialects/mlonnx.md new file mode 100644 index 0000000..d7ab1e0 --- /dev/null +++ b/docs/Dialects/mlonnx.md @@ -0,0 +1,597 @@ + +### `mlonnx.ArrayFeatureExtractor` (MLONNXArrayFeatureExtractorOp) + +ONNX ArrayFeatureExtractor operation + +"Select elements of the input tensor based on the indices passed.
" +" The indices are applied to the last axes of the tensor." + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values +`Y` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Z` | memref of any type values or tensor of any type values + +### `mlonnx.Binarizer` (MLONNXBinarizerOp) + +ONNX Binarizer operation + +"Maps the values of the input tensor to either 0 or 1, element-wise, based on the outcome of a comparison against a threshold value." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`threshold` | FloatAttr | 32-bit float attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.CastMap` (MLONNXCastMapOp) + +ONNX CastMap operation + +"Converts a map to a tensor.
The map key must be an int64 and the values will be ordered" +" in ascending order based on this key.
The operator supports dense packing or sparse packing." +" If using sparse packing, the key cannot exceed the max_map-1 value." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`cast_to` | StringAttr | string attribute +`map_form` | StringAttr | string attribute +`max_map` | IntegerAttr | 64-bit signless integer attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.CategoryMapper` (MLONNXCategoryMapperOp) + +ONNX CategoryMapper operation + +"Converts strings to integers and vice versa.
" +" Two sequences of equal length are used to map between integers and strings," +" with strings and integers at the same index detailing the mapping.
" +" Each operator converts either integers to strings or strings to integers, depending " +" on which default value attribute is provided. Only one default value attribute" +" should be defined.
" +" If the string default value is set, it will convert integers to strings." +" If the int default value is set, it will convert strings to integers." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`cats_int64s` | ArrayAttr | 64-bit integer array attribute +`cats_strings` | ArrayAttr | string array attribute +`default_int64` | IntegerAttr | 64-bit signless integer attribute +`default_string` | StringAttr | string attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.DictVectorizer` (MLONNXDictVectorizerOp) + +ONNX DictVectorizer operation + +"Uses an index mapping to convert a dictionary to an array.
" +" Given a dictionary, each key is looked up in the vocabulary attribute corresponding to" +" the key type. The index into the vocabulary array at which the key is found is then" +" used to index the output 1-D tensor 'Y' and insert into it the value found in the dictionary 'X'.
" +" The key type of the input map must correspond to the element type of the defined vocabulary attribute." +" Therefore, the output array will be equal in length to the index mapping vector parameter." +" All keys in the input dictionary must be present in the index mapping vector." +" For each item in the input dictionary, insert its value in the output array." +" Any keys not present in the input dictionary, will be zero in the output array.
" +" For example: if the ``string_vocabulary`` parameter is set to ``[\"a\", \"c\", \"b\", \"z\"]``," +" then an input of ``{\"a\": 4, \"c\": 8}`` will produce an output of ``[4, 8, 0, 0]``." +" " + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`int64_vocabulary` | ArrayAttr | 64-bit integer array attribute +`string_vocabulary` | ArrayAttr | string array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.FeatureVectorizer` (MLONNXFeatureVectorizerOp) + +ONNX FeatureVectorizer operation + +"Concatenates input tensors into one continuous output.
" +" All input shapes are 2-D and are concatenated along the second dimention. 1-D tensors are treated as [1,C]." +" Inputs are copied to the output maintaining the order of the input arguments.
" +" All inputs must be integers or floats, while the output will be all floating point values." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`inputdimensions` | ArrayAttr | 64-bit integer array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.Imputer` (MLONNXImputerOp) + +ONNX Imputer operation + +"Replaces inputs that equal one value with another, leaving all other elements alone.
" +" This operator is typically used to replace missing values in situations where they have a canonical" +" representation, such as -1, 0, NaN, or some extreme value.
" +" One and only one of imputed_value_floats or imputed_value_int64s should be defined -- floats if the input tensor" +" holds floats, integers if the input tensor holds integers. The imputed values must all fit within the" +" width of the tensor element type. One and only one of the replaced_value_float or replaced_value_int64 should be defined," +" which one depends on whether floats or integers are being processed.
" +" The imputed_value attribute length can be 1 element, or it can have one element per input feature.
In other words, if the input tensor has the shape [*,F], then the length of the attribute array may be 1 or F. If it is 1, then it is broadcast along the last dimension and applied to each feature." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`imputed_value_floats` | ArrayAttr | 32-bit float array attribute +`imputed_value_int64s` | ArrayAttr | 64-bit integer array attribute +`replaced_value_float` | FloatAttr | 32-bit float attribute +`replaced_value_int64` | IntegerAttr | 64-bit signless integer attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.LabelEncoder` (MLONNXLabelEncoderOp) + +ONNX LabelEncoder operation + +"Maps each element in the input tensor to another value.
" +" The mapping is determined by the two parallel attributes, 'keys_*' and" +" 'values_*' attribute. The i-th value in the specified 'keys_*' attribute" +" would be mapped to the i-th value in the specified 'values_*' attribute. It" +" implies that input's element type and the element type of the specified" +" 'keys_*' should be identical while the output type is identical to the" +" specified 'values_*' attribute. If an input element can not be found in the" +" specified 'keys_*' attribute, the 'default_*' that matches the specified" +" 'values_*' attribute may be used as its output value.
" +" Let's consider an example which maps a string tensor to an integer tensor." +" Assume and 'keys_strings' is [\"Amy\", \"Sally\"], 'values_int64s' is [5, 6]," +" and 'default_int64' is '-1'. The input [\"Dori\", \"Amy\", \"Amy\", \"Sally\"," +" \"Sally\"] would be mapped to [-1, 5, 5, 6, 6].
" +" Since this operator is an one-to-one mapping, its input and output shapes" +" are the same. Notice that only one of 'keys_*'/'values_*' can be set.
" +" For key look-up, bit-wise comparison is used so even a float NaN can be" +" mapped to a value in 'values_*' attribute.
" + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`default_float` | FloatAttr | 32-bit float attribute +`default_int64` | IntegerAttr | 64-bit signless integer attribute +`default_string` | StringAttr | string attribute +`keys_floats` | ArrayAttr | 32-bit float array attribute +`keys_int64s` | ArrayAttr | 64-bit integer array attribute +`keys_strings` | ArrayAttr | string array attribute +`values_floats` | ArrayAttr | 32-bit float array attribute +`values_int64s` | ArrayAttr | 64-bit integer array attribute +`values_strings` | ArrayAttr | string array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.LinearClassifier` (MLONNXLinearClassifierOp) + +ONNX LinearClassifier operation + +"Linear classifier" + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`classlabels_ints` | ArrayAttr | 64-bit integer array attribute +`classlabels_strings` | ArrayAttr | string array attribute +`coefficients` | ArrayAttr | 32-bit float array attribute +`intercepts` | ArrayAttr | 32-bit float array attribute +`multi_class` | IntegerAttr | 64-bit signless integer attribute +`post_transform` | StringAttr | string attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values +`Z` | memref of any type values or tensor of any type values + +### `mlonnx.LinearRegressor` (MLONNXLinearRegressorOp) + +ONNX LinearRegressor operation + +"Generalized linear regression evaluation.
" +" If targets is set to 1 (default) then univariate regression is performed.
" +" If targets is set to M then M sets of coefficients must be passed in as a sequence" +" and M results will be output for each input n in N.
" +" The coefficients array is of length n, and the coefficients for each target are contiguous." +" Intercepts are optional but if provided must match the number of targets." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`coefficients` | ArrayAttr | 32-bit float array attribute +`intercepts` | ArrayAttr | 32-bit float array attribute +`post_transform` | StringAttr | string attribute +`targets` | IntegerAttr | 64-bit signless integer attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.Normalizer` (MLONNXNormalizerOp) + +ONNX Normalizer operation + +"Normalize the input. There are three normalization modes, which have the corresponding formulas," +" defined using element-wise infix operators '/' and '^' and tensor-wide functions 'max' and 'sum':
" +"
" +" Max: Y = X / max(X)
" +" L1: Y = X / sum(X)
" +" L2: Y = sqrt(X^2 / sum(X^2)}
" +" In all modes, if the divisor is zero, Y == X." +"
" +" For batches, that is, [N,C] tensors, normalization is done along the C axis. In other words, each row" +" of the batch is normalized independently." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`norm` | StringAttr | string attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.OneHotEncoder` (MLONNXOneHotEncoderOp) + +ONNX OneHotEncoder operation + +"Replace each input element with an array of ones and zeros, where a single" +" one is placed at the index of the category that was passed in. The total category count " +" will determine the size of the extra dimension of the output array Y.
" +" For example, if we pass a tensor with a single value of 4, and a category count of 8, " +" the output will be a tensor with ``[0,0,0,0,1,0,0,0]``.
" +" This operator assumes every input feature is from the same set of categories.
" +" If the input is a tensor of float, int32, or double, the data will be cast" +" to integers and the cats_int64s category list will be used for the lookups." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`cats_int64s` | ArrayAttr | 64-bit integer array attribute +`cats_strings` | ArrayAttr | string array attribute +`zeros` | IntegerAttr | 64-bit signless integer attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.SVMClassifier` (MLONNXSVMClassifierOp) + +ONNX SVMClassifier operation + +"Support Vector Machine classifier" + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`classlabels_ints` | ArrayAttr | 64-bit integer array attribute +`classlabels_strings` | ArrayAttr | string array attribute +`coefficients` | ArrayAttr | 32-bit float array attribute +`kernel_params` | ArrayAttr | 32-bit float array attribute +`kernel_type` | StringAttr | string attribute +`post_transform` | StringAttr | string attribute +`prob_a` | ArrayAttr | 32-bit float array attribute +`prob_b` | ArrayAttr | 32-bit float array attribute +`rho` | ArrayAttr | 32-bit float array attribute +`support_vectors` | ArrayAttr | 32-bit float array attribute +`vectors_per_class` | ArrayAttr | 64-bit integer array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values +`Z` | memref of any type values or tensor of any type values + +### `mlonnx.SVMRegressor` (MLONNXSVMRegressorOp) + +ONNX SVMRegressor operation + +"Support Vector Machine regression prediction and one-class SVM anomaly detection." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`coefficients` | ArrayAttr | 32-bit float array attribute +`kernel_params` | ArrayAttr | 32-bit float array attribute +`kernel_type` | StringAttr | string attribute +`n_supports` | IntegerAttr | 64-bit signless integer attribute +`one_class` | IntegerAttr | 64-bit signless integer attribute +`post_transform` | StringAttr | string attribute +`rho` | ArrayAttr | 32-bit float array attribute +`support_vectors` | ArrayAttr | 32-bit float array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.Scaler` (MLONNXScalerOp) + +ONNX Scaler operation + +"Rescale input data, for example to standardize features by removing the mean and scaling to unit variance." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`offset` | ArrayAttr | 32-bit float array attribute +`scale` | ArrayAttr | 32-bit float array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.TreeEnsembleClassifier` (MLONNXTreeEnsembleClassifierOp) + +ONNX TreeEnsembleClassifier operation + +"Tree Ensemble classifier. Returns the top class for each of N inputs.
" +" The attributes named 'nodes_X' form a sequence of tuples, associated by " +" index into the sequences, which must all be of equal length. These tuples" +" define the nodes.
" +" Similarly, all fields prefixed with 'class_' are tuples of votes at the leaves." +" A leaf may have multiple votes, where each vote is weighted by" +" the associated class_weights index.
" +" One and only one of classlabels_strings or classlabels_int64s" +" will be defined. The class_ids are indices into this list." + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`base_values` | ArrayAttr | 32-bit float array attribute +`class_ids` | ArrayAttr | 64-bit integer array attribute +`class_nodeids` | ArrayAttr | 64-bit integer array attribute +`class_treeids` | ArrayAttr | 64-bit integer array attribute +`class_weights` | ArrayAttr | 32-bit float array attribute +`classlabels_int64s` | ArrayAttr | 64-bit integer array attribute +`classlabels_strings` | ArrayAttr | string array attribute +`nodes_falsenodeids` | ArrayAttr | 64-bit integer array attribute +`nodes_featureids` | ArrayAttr | 64-bit integer array attribute +`nodes_hitrates` | ArrayAttr | 32-bit float array attribute +`nodes_missing_value_tracks_true` | ArrayAttr | 64-bit integer array attribute +`nodes_modes` | ArrayAttr | string array attribute +`nodes_nodeids` | ArrayAttr | 64-bit integer array attribute +`nodes_treeids` | ArrayAttr | 64-bit integer array attribute +`nodes_truenodeids` | ArrayAttr | 64-bit integer array attribute +`nodes_values` | ArrayAttr | 32-bit float array attribute +`post_transform` | StringAttr | string attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values +`Z` | memref of any type values or tensor of any type values + +### `mlonnx.TreeEnsembleRegressor` (MLONNXTreeEnsembleRegressorOp) + +ONNX TreeEnsembleRegressor operation + +"Tree Ensemble regressor. Returns the regressed values for each input in N.
" +" All args with nodes_ are fields of a tuple of tree nodes, and" +" it is assumed they are the same length, and an index i will decode the" +" tuple across these inputs. Each node id can appear only once" +" for each tree id.
" +" All fields prefixed with target_ are tuples of votes at the leaves.
" +" A leaf may have multiple votes, where each vote is weighted by" +" the associated target_weights index.
" +" All trees must have their node ids start at 0 and increment by 1.
" +" Mode enum is BRANCH_LEQ, BRANCH_LT, BRANCH_GTE, BRANCH_GT, BRANCH_EQ, BRANCH_NEQ, LEAF" + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`aggregate_function` | StringAttr | string attribute +`base_values` | ArrayAttr | 32-bit float array attribute +`n_targets` | IntegerAttr | 64-bit signless integer attribute +`nodes_falsenodeids` | ArrayAttr | 64-bit integer array attribute +`nodes_featureids` | ArrayAttr | 64-bit integer array attribute +`nodes_hitrates` | ArrayAttr | 32-bit float array attribute +`nodes_missing_value_tracks_true` | ArrayAttr | 64-bit integer array attribute +`nodes_modes` | ArrayAttr | string array attribute +`nodes_nodeids` | ArrayAttr | 64-bit integer array attribute +`nodes_treeids` | ArrayAttr | 64-bit integer array attribute +`nodes_truenodeids` | ArrayAttr | 64-bit integer array attribute +`nodes_values` | ArrayAttr | 32-bit float array attribute +`post_transform` | StringAttr | string attribute +`target_ids` | ArrayAttr | 64-bit integer array attribute +`target_nodeids` | ArrayAttr | 64-bit integer array attribute +`target_treeids` | ArrayAttr | 64-bit integer array attribute +`target_weights` | ArrayAttr | 32-bit float array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Y` | memref of any type values or tensor of any type values + +### `mlonnx.ZipMap` (MLONNXZipMapOp) + +ONNX ZipMap operation + +"Creates a map from the input and the attributes.
" +" The values are provided by the input tensor, while the keys are specified by the attributes." +" Must provide keys in either classlabels_strings or classlabels_int64s (but not both).
" +" The columns of the tensor correspond one-by-one to the keys specified by the attributes. There must be as many columns as keys.
" + +#### Attributes: + +| Attribute | MLIR Type | Description | +| :-------: | :-------: | ----------- | +`classlabels_int64s` | ArrayAttr | 64-bit integer array attribute +`classlabels_strings` | ArrayAttr | string array attribute + +#### Operands: + +| Operand | Description | +| :-----: | ----------- | +`X` | memref of any type values or tensor of any type values + +#### Results: + +| Result | Description | +| :----: | ----------- | +`Z` | memref of any type values or tensor of any type values + diff --git a/src/Builder/CMakeLists.txt b/src/Builder/CMakeLists.txt index 3e331a1..1e87f7e 100644 --- a/src/Builder/CMakeLists.txt +++ b/src/Builder/CMakeLists.txt @@ -8,6 +8,10 @@ target_include_directories(OMBuilder PRIVATE ${ONNX_MLIR_SRC_ROOT}) target_include_directories(OMBuilder PRIVATE ${CMAKE_BINARY_DIR}) target_include_directories(OMBuilder PRIVATE ${ONNX_MLIR_BIN_ROOT}) +if (INCLUDE_ONNX_ML) + add_definitions(-DINCLUDE_ONNX__ML=1) +endif() + # This will cause onnx to be built. More importantly, some variable definitions # when building onnx such as -DONNX_ML=1 -DONNX_NAMESPACE=onnx will be carried over # when compiling FrontendDialectHelper.cpp, etc. @@ -24,3 +28,7 @@ target_include_directories(OMBuilder # will NOT be carried over when compiling FrontendDialectHelper.cpp, etc. so # the compilation will fail. add_dependencies(OMBuilder OMONNXOps) + +if (INCLUDE_ONNX_ML) + add_dependencies(OMBuilder OMMLONNXOps) +endif() diff --git a/src/Builder/FrontendDialectHelper.hpp b/src/Builder/FrontendDialectHelper.hpp index e920cd6..82d0c21 100644 --- a/src/Builder/FrontendDialectHelper.hpp +++ b/src/Builder/FrontendDialectHelper.hpp @@ -32,6 +32,10 @@ #include "llvm/Support/raw_ostream.h" #include "src/Dialect/ONNX/ONNXOps.hpp" +#if INCLUDE_ONNX_ML == 1 +#include "src/Dialect/MLONNX/MLONNXOps.hpp" +#endif + #include "onnx/onnx_pb.h" namespace onnx_mlir { @@ -98,4 +102,4 @@ private: std::map nameToInitializedTensor; }; -} // namespace onnx_mlir \ No newline at end of file +} // namespace onnx_mlir diff --git a/src/Builder/FrontendDialectTransformer.cpp b/src/Builder/FrontendDialectTransformer.cpp index f094761..22a8b57 100644 --- a/src/Builder/FrontendDialectTransformer.cpp +++ b/src/Builder/FrontendDialectTransformer.cpp @@ -369,6 +369,10 @@ private: // one known reeason is the optional input #include "src/Builder/OpBuildTable.inc" +#if INCLUDE_ONNX_ML == 1 +#include "src/Builder/MLOpBuildTable.inc" +#endif + } /*! diff --git a/src/Builder/MLOpBuildTable.inc b/src/Builder/MLOpBuildTable.inc new file mode 100644 index 0000000..582497b --- /dev/null +++ b/src/Builder/MLOpBuildTable.inc @@ -0,0 +1,42 @@ +//******************************************************** +// Do not modify this file directly. +// This file is automatically generated via script. +// Details can be found in docs/readonnxdefs.md . +//******************************************************** + +if (opName == "ArrayFeatureExtractor") + return buildOperation(node, /* expected_num_operands = */ 2, /* expected_num_results = */ 1); +if (opName == "Binarizer") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "CastMap") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "CategoryMapper") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "DictVectorizer") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "FeatureVectorizer") + return buildOperation(node, /* expected_num_operands = */ -1, /* expected_num_results = */ 1); +if (opName == "Imputer") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "LabelEncoder") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "LinearClassifier") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 2); +if (opName == "LinearRegressor") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "Normalizer") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "OneHotEncoder") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "SVMClassifier") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 2); +if (opName == "SVMRegressor") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "Scaler") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "TreeEnsembleClassifier") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 2); +if (opName == "TreeEnsembleRegressor") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); +if (opName == "ZipMap") + return buildOperation(node, /* expected_num_operands = */ 1, /* expected_num_results = */ 1); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f67912..aa0a02f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,6 +43,11 @@ target_link_libraries(onnx-mlir ${MLIRLibs} ${CMAKE_DL_LIBS}) +if (INCLUDE_ONNX_ML) + target_link_libraries(onnx-mlir OMMLONNXOps) +endif() + + target_include_directories(onnx-mlir PRIVATE ${ONNX_MLIR_SRC_ROOT}) target_include_directories(onnx-mlir PRIVATE ${CMAKE_BINARY_DIR}) target_include_directories(onnx-mlir PRIVATE ${ONNX_MLIR_BIN_ROOT}) diff --git a/src/Dialect/CMakeLists.txt b/src/Dialect/CMakeLists.txt index 52599c3..9454959 100644 --- a/src/Dialect/CMakeLists.txt +++ b/src/Dialect/CMakeLists.txt @@ -1,2 +1,5 @@ add_subdirectory(Krnl) -add_subdirectory(ONNX) \ No newline at end of file +add_subdirectory(ONNX) +if (INCLUDE_ONNX_ML) + add_subdirectory(MLONNX) +endif() diff --git a/src/Dialect/MLONNX/CMakeLists.txt b/src/Dialect/MLONNX/CMakeLists.txt new file mode 100644 index 0000000..da4e977 --- /dev/null +++ b/src/Dialect/MLONNX/CMakeLists.txt @@ -0,0 +1,22 @@ +set(LLVM_TARGET_DEFINITIONS MLONNXOps.td) +onnx_mlir_tablegen(MLONNXOps.hpp.inc -gen-op-decls "-I${ONNX_MLIR_SRC_ROOT}/compiler/pass") +onnx_mlir_tablegen(MLONNXOps.cpp.inc -gen-op-defs "-I${ONNX_MLIR_SRC_ROOT}/compiler/pass") + +set(GEN_DOC_FILE ${CMAKE_BINARY_DIR}/docs/Dialects/mlonnx.md) +add_public_tablegen_target(OMMLONNXOpsIncGen) + +add_library(OMMLONNXOps + MLONNXOps.cpp + MLONNXOps.hpp) +target_include_directories(OMMLONNXOps + PRIVATE + ${ONNX_MLIR_SRC_ROOT} + ${ONNX_MLIR_BIN_ROOT} + ${ONNX_MLIR_SRC_ROOT}) +add_dependencies(OMMLONNXOps OMMLONNXOpsIncGen) +# Linking dependencies: +add_dependencies(OMMLONNXOps + OMPromotableConstOperandsOpInterface + OMShapeInferenceOpInterface) + +add_onnx_mlir_dialect_doc(mlonnx MLONNXOps.td) diff --git a/src/Dialect/MLONNX/MLONNXOps.cpp b/src/Dialect/MLONNX/MLONNXOps.cpp new file mode 100644 index 0000000..02d5ef1 --- /dev/null +++ b/src/Dialect/MLONNX/MLONNXOps.cpp @@ -0,0 +1,48 @@ +//===------------------ MLONNXOps.cpp - ONNX ML Operations ----------------===// +// +// Copyright 2019-2020 The IBM Research Authors. +// +// ============================================================================= +// +// This file provides definition of ONNX ML dialect operations. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Traits.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/Function.h" +#include "mlir/IR/IntegerSet.h" +#include "mlir/IR/Matchers.h" +#include "mlir/IR/Module.h" +#include "mlir/IR/OpImplementation.h" +#include "mlir/IR/PatternMatch.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallBitVector.h" + +#include "MLONNXOps.hpp" + +using namespace mlir; +using namespace mlir::OpTrait::util; + +//===----------------------------------------------------------------------===// +// MLONNXOpsDialect +//===----------------------------------------------------------------------===// + +/// Dialect creation, the instance will be owned by the context. This is the +/// point of registration of custom types and operations for the dialect. +MLONNXOpsDialect::MLONNXOpsDialect(mlir::MLIRContext *ctx) + : mlir::Dialect(getDialectNamespace(), ctx) { + addOperations< +#define GET_OP_LIST +#include "src/Dialect/MLONNX/MLONNXOps.cpp.inc" + >(); +} + + +//===----------------------------------------------------------------------===// +// TableGen'd op method definitions +//===----------------------------------------------------------------------===// + +#define GET_OP_CLASSES +#include "src/Dialect/MLONNX/MLONNXOps.cpp.inc" diff --git a/src/Dialect/MLONNX/MLONNXOps.hpp b/src/Dialect/MLONNX/MLONNXOps.hpp new file mode 100644 index 0000000..380a86a --- /dev/null +++ b/src/Dialect/MLONNX/MLONNXOps.hpp @@ -0,0 +1,43 @@ +//===----------------- MLONNXOps.hpp - ONNX ML Operations ----_------------===// +// +// Copyright 2019 The IBM Research Authors. +// +// ============================================================================= +// +// This file defines ONNX ML operations in the MLIR operation set. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/Dialect.h" +#include "mlir/IR/OpDefinition.h" +#include "mlir/IR/StandardTypes.h" + +#include "src/Interface/ShapeInferenceInterface.hpp" +#include "src/Interface/PromotableConstOperandsOpInterface.hpp" + +namespace mlir { + +class MLONNXOpsDialect : public Dialect { + public: + MLONNXOpsDialect(MLIRContext* context); + + /// Provide a utility accessor to the dialect namespace. This is used by + /// several utilities for casting between dialects. + static StringRef getDialectNamespace() { return "onnx"; } +}; + +/// Include the auto-generated header file containing the declarations of the +/// ONNX operations. +#define GET_OP_CLASSES +#include "src/Dialect/MLONNX/MLONNXOps.hpp.inc" + +} // end namespace mlir + +namespace onnx_mlir {} diff --git a/src/Dialect/MLONNX/MLONNXOps.td b/src/Dialect/MLONNX/MLONNXOps.td new file mode 100644 index 0000000..f71fdd1 --- /dev/null +++ b/src/Dialect/MLONNX/MLONNXOps.td @@ -0,0 +1,67 @@ +//===-- MLONNXOps.td -- ONNX ML Dialect Operation Definitions -*- tablegen -==// +// +// Copyright 2019-2020 The IBM Research Authors +// +// ============================================================================= +// +// Defines ONNX ML Dialect operations. +// +//===----------------------------------------------------------------------===// + +#ifdef MLONNX_OPS +#else +#define MLONNX_OPS + +#ifdef OP_BASE +#else +include "mlir/IR/OpBase.td" +#endif // OP_BASE + +#ifdef SHAPE_INFERENCE_INTERFACE +#else +include "src/Interface/ShapeInferenceInterface.td" +#endif // SHAPE_INFERENCE_INTERFACE + +#ifdef PROMOTABLE_CONST_OPERANDS_OP_INTERFACE +#else +include "src/Interface/PromotableConstOperandsOpInterface.td" +#endif // PROMOTABLE_CONST_OPERANDS_OP_INTERFACE + +def MLONNX_Dialect : Dialect { + let name = "mlonnx"; + let cppNamespace = ""; +} + +// Base class for ONNX dialect operations. This operation inherits from the base +// `Op` class in OpBase.td, and provides: +// * The parent dialect of the operation. +// * The mnemonic for the operation, or the name without the dialect prefix. +// * A list of traits for the operation. +class MLONNX_Op traits = []> : + Op; + +//===----------------------------------------------------------------------===// +// MLONNX Operations +//===----------------------------------------------------------------------===// + +//the tablegen code onnxop.in is generated with gen_doc.py +//clone and install onnx +// git clone --recursive https://github.com/onnx/onnx.git +// set up env for anaconda3 and for ONNX MLIR (BOOSTROOT, cmake, gcc ...) +// cd onnx +//install onnx +// CC=gcc CXX=g++ pip install -e . +//run the script +// python onnx/defs/gen_doc.py +//result is in docs/onnx_ops.td.inc +//current limitations: +// 1. Attributes are not processed +// 2. output type inference not implemented except Add +// 3. Type Attribute: 'optional' and 'Variadic hetergeneous' are ignored +// 4. type of string, complex64 and complex128 for input/output are ignored +// 5. unsigned int are treated as signed one + +include "mlir/Interfaces/SideEffects.td" +include "src/Dialect/MLONNX/MLONNXOps.td.inc" + +#endif // MLONNX_OPS diff --git a/src/Dialect/MLONNX/MLONNXOps.td.inc b/src/Dialect/MLONNX/MLONNXOps.td.inc new file mode 100644 index 0000000..88adf54 --- /dev/null +++ b/src/Dialect/MLONNX/MLONNXOps.td.inc @@ -0,0 +1,373 @@ +//******************************************************** +// Do not modify this file directly. +// This file is automatically generated via script. +// Details can be found in docs/readonnxdefs.md . +//******************************************************** + +def MLONNXArrayFeatureExtractorOp:MLONNX_Op<"ArrayFeatureExtractor", + [NoSideEffect]> { + let summary = "ONNX ArrayFeatureExtractor operation"; + let description = [{ + "Select elements of the input tensor based on the indices passed.
" + " The indices are applied to the last axes of the tensor." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Z); +} + +def MLONNXBinarizerOp:MLONNX_Op<"Binarizer", + [NoSideEffect]> { + let summary = "ONNX Binarizer operation"; + let description = [{ + "Maps the values of the input tensor to either 0 or 1, element-wise, based on the outcome of a comparison against a threshold value." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + DefaultValuedAttr:$threshold); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXCastMapOp:MLONNX_Op<"CastMap", + [NoSideEffect]> { + let summary = "ONNX CastMap operation"; + let description = [{ + "Converts a map to a tensor.
The map key must be an int64 and the values will be ordered" + " in ascending order based on this key.
The operator supports dense packing or sparse packing." + " If using sparse packing, the key cannot exceed the max_map-1 value." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + DefaultValuedAttr:$cast_to, + DefaultValuedAttr:$map_form, + DefaultValuedAttr:$max_map); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXCategoryMapperOp:MLONNX_Op<"CategoryMapper", + [NoSideEffect]> { + let summary = "ONNX CategoryMapper operation"; + let description = [{ + "Converts strings to integers and vice versa.
" + " Two sequences of equal length are used to map between integers and strings," + " with strings and integers at the same index detailing the mapping.
" + " Each operator converts either integers to strings or strings to integers, depending " + " on which default value attribute is provided. Only one default value attribute" + " should be defined.
" + " If the string default value is set, it will convert integers to strings." + " If the int default value is set, it will convert strings to integers." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$cats_int64s, + OptionalAttr:$cats_strings, + DefaultValuedAttr:$default_int64, + DefaultValuedAttr:$default_string); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXDictVectorizerOp:MLONNX_Op<"DictVectorizer", + [NoSideEffect]> { + let summary = "ONNX DictVectorizer operation"; + let description = [{ + "Uses an index mapping to convert a dictionary to an array.
" + " Given a dictionary, each key is looked up in the vocabulary attribute corresponding to" + " the key type. The index into the vocabulary array at which the key is found is then" + " used to index the output 1-D tensor 'Y' and insert into it the value found in the dictionary 'X'.
" + " The key type of the input map must correspond to the element type of the defined vocabulary attribute." + " Therefore, the output array will be equal in length to the index mapping vector parameter." + " All keys in the input dictionary must be present in the index mapping vector." + " For each item in the input dictionary, insert its value in the output array." + " Any keys not present in the input dictionary, will be zero in the output array.
" + " For example: if the ``string_vocabulary`` parameter is set to ``[\"a\", \"c\", \"b\", \"z\"]``," + " then an input of ``{\"a\": 4, \"c\": 8}`` will produce an output of ``[4, 8, 0, 0]``." + " " + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$int64_vocabulary, + OptionalAttr:$string_vocabulary); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXFeatureVectorizerOp:MLONNX_Op<"FeatureVectorizer", + [NoSideEffect]> { + let summary = "ONNX FeatureVectorizer operation"; + let description = [{ + "Concatenates input tensors into one continuous output.
" + " All input shapes are 2-D and are concatenated along the second dimention. 1-D tensors are treated as [1,C]." + " Inputs are copied to the output maintaining the order of the input arguments.
" + " All inputs must be integers or floats, while the output will be all floating point values." + }]; + let arguments = (ins Variadic>:$X, + OptionalAttr:$inputdimensions); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXImputerOp:MLONNX_Op<"Imputer", + [NoSideEffect]> { + let summary = "ONNX Imputer operation"; + let description = [{ + "Replaces inputs that equal one value with another, leaving all other elements alone.
" + " This operator is typically used to replace missing values in situations where they have a canonical" + " representation, such as -1, 0, NaN, or some extreme value.
" + " One and only one of imputed_value_floats or imputed_value_int64s should be defined -- floats if the input tensor" + " holds floats, integers if the input tensor holds integers. The imputed values must all fit within the" + " width of the tensor element type. One and only one of the replaced_value_float or replaced_value_int64 should be defined," + " which one depends on whether floats or integers are being processed.
" + " The imputed_value attribute length can be 1 element, or it can have one element per input feature.
In other words, if the input tensor has the shape [*,F], then the length of the attribute array may be 1 or F. If it is 1, then it is broadcast along the last dimension and applied to each feature." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$imputed_value_floats, + OptionalAttr:$imputed_value_int64s, + DefaultValuedAttr:$replaced_value_float, + DefaultValuedAttr:$replaced_value_int64); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXLabelEncoderOp:MLONNX_Op<"LabelEncoder", + [NoSideEffect]> { + let summary = "ONNX LabelEncoder operation"; + let description = [{ + "Maps each element in the input tensor to another value.
" + " The mapping is determined by the two parallel attributes, 'keys_*' and" + " 'values_*' attribute. The i-th value in the specified 'keys_*' attribute" + " would be mapped to the i-th value in the specified 'values_*' attribute. It" + " implies that input's element type and the element type of the specified" + " 'keys_*' should be identical while the output type is identical to the" + " specified 'values_*' attribute. If an input element can not be found in the" + " specified 'keys_*' attribute, the 'default_*' that matches the specified" + " 'values_*' attribute may be used as its output value.
" + " Let's consider an example which maps a string tensor to an integer tensor." + " Assume and 'keys_strings' is [\"Amy\", \"Sally\"], 'values_int64s' is [5, 6]," + " and 'default_int64' is '-1'. The input [\"Dori\", \"Amy\", \"Amy\", \"Sally\"," + " \"Sally\"] would be mapped to [-1, 5, 5, 6, 6].
" + " Since this operator is an one-to-one mapping, its input and output shapes" + " are the same. Notice that only one of 'keys_*'/'values_*' can be set.
" + " For key look-up, bit-wise comparison is used so even a float NaN can be" + " mapped to a value in 'values_*' attribute.
" + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + DefaultValuedAttr:$default_float, + DefaultValuedAttr:$default_int64, + DefaultValuedAttr:$default_string, + OptionalAttr:$keys_floats, + OptionalAttr:$keys_int64s, + OptionalAttr:$keys_strings, + OptionalAttr:$values_floats, + OptionalAttr:$values_int64s, + OptionalAttr:$values_strings); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXLinearClassifierOp:MLONNX_Op<"LinearClassifier", + [NoSideEffect]> { + let summary = "ONNX LinearClassifier operation"; + let description = [{ + "Linear classifier" + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$classlabels_ints, + OptionalAttr:$classlabels_strings, + F32ArrayAttr:$coefficients, + OptionalAttr:$intercepts, + DefaultValuedAttr:$multi_class, + DefaultValuedAttr:$post_transform); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y, + AnyTypeOf<[AnyMemRef, AnyTensor]>:$Z); +} + +def MLONNXLinearRegressorOp:MLONNX_Op<"LinearRegressor", + [NoSideEffect]> { + let summary = "ONNX LinearRegressor operation"; + let description = [{ + "Generalized linear regression evaluation.
" + " If targets is set to 1 (default) then univariate regression is performed.
" + " If targets is set to M then M sets of coefficients must be passed in as a sequence" + " and M results will be output for each input n in N.
" + " The coefficients array is of length n, and the coefficients for each target are contiguous." + " Intercepts are optional but if provided must match the number of targets." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$coefficients, + OptionalAttr:$intercepts, + DefaultValuedAttr:$post_transform, + DefaultValuedAttr:$targets); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXNormalizerOp:MLONNX_Op<"Normalizer", + [NoSideEffect]> { + let summary = "ONNX Normalizer operation"; + let description = [{ + "Normalize the input. There are three normalization modes, which have the corresponding formulas," + " defined using element-wise infix operators '/' and '^' and tensor-wide functions 'max' and 'sum':
" + "
" + " Max: Y = X / max(X)
" + " L1: Y = X / sum(X)
" + " L2: Y = sqrt(X^2 / sum(X^2)}
" + " In all modes, if the divisor is zero, Y == X." + "
" + " For batches, that is, [N,C] tensors, normalization is done along the C axis. In other words, each row" + " of the batch is normalized independently." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + DefaultValuedAttr:$norm); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXOneHotEncoderOp:MLONNX_Op<"OneHotEncoder", + [NoSideEffect]> { + let summary = "ONNX OneHotEncoder operation"; + let description = [{ + "Replace each input element with an array of ones and zeros, where a single" + " one is placed at the index of the category that was passed in. The total category count " + " will determine the size of the extra dimension of the output array Y.
" + " For example, if we pass a tensor with a single value of 4, and a category count of 8, " + " the output will be a tensor with ``[0,0,0,0,1,0,0,0]``.
" + " This operator assumes every input feature is from the same set of categories.
" + " If the input is a tensor of float, int32, or double, the data will be cast" + " to integers and the cats_int64s category list will be used for the lookups." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$cats_int64s, + OptionalAttr:$cats_strings, + DefaultValuedAttr:$zeros); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXSVMClassifierOp:MLONNX_Op<"SVMClassifier", + [NoSideEffect]> { + let summary = "ONNX SVMClassifier operation"; + let description = [{ + "Support Vector Machine classifier" + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$classlabels_ints, + OptionalAttr:$classlabels_strings, + OptionalAttr:$coefficients, + OptionalAttr:$kernel_params, + DefaultValuedAttr:$kernel_type, + DefaultValuedAttr:$post_transform, + OptionalAttr:$prob_a, + OptionalAttr:$prob_b, + OptionalAttr:$rho, + OptionalAttr:$support_vectors, + OptionalAttr:$vectors_per_class); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y, + AnyTypeOf<[AnyMemRef, AnyTensor]>:$Z); +} + +def MLONNXSVMRegressorOp:MLONNX_Op<"SVMRegressor", + [NoSideEffect]> { + let summary = "ONNX SVMRegressor operation"; + let description = [{ + "Support Vector Machine regression prediction and one-class SVM anomaly detection." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$coefficients, + OptionalAttr:$kernel_params, + DefaultValuedAttr:$kernel_type, + DefaultValuedAttr:$n_supports, + DefaultValuedAttr:$one_class, + DefaultValuedAttr:$post_transform, + OptionalAttr:$rho, + OptionalAttr:$support_vectors); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXScalerOp:MLONNX_Op<"Scaler", + [NoSideEffect]> { + let summary = "ONNX Scaler operation"; + let description = [{ + "Rescale input data, for example to standardize features by removing the mean and scaling to unit variance." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$offset, + OptionalAttr:$scale); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXTreeEnsembleClassifierOp:MLONNX_Op<"TreeEnsembleClassifier", + [NoSideEffect]> { + let summary = "ONNX TreeEnsembleClassifier operation"; + let description = [{ + "Tree Ensemble classifier. Returns the top class for each of N inputs.
" + " The attributes named 'nodes_X' form a sequence of tuples, associated by " + " index into the sequences, which must all be of equal length. These tuples" + " define the nodes.
" + " Similarly, all fields prefixed with 'class_' are tuples of votes at the leaves." + " A leaf may have multiple votes, where each vote is weighted by" + " the associated class_weights index.
" + " One and only one of classlabels_strings or classlabels_int64s" + " will be defined. The class_ids are indices into this list." + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$base_values, + OptionalAttr:$class_ids, + OptionalAttr:$class_nodeids, + OptionalAttr:$class_treeids, + OptionalAttr:$class_weights, + OptionalAttr:$classlabels_int64s, + OptionalAttr:$classlabels_strings, + OptionalAttr:$nodes_falsenodeids, + OptionalAttr:$nodes_featureids, + OptionalAttr:$nodes_hitrates, + OptionalAttr:$nodes_missing_value_tracks_true, + OptionalAttr:$nodes_modes, + OptionalAttr:$nodes_nodeids, + OptionalAttr:$nodes_treeids, + OptionalAttr:$nodes_truenodeids, + OptionalAttr:$nodes_values, + DefaultValuedAttr:$post_transform); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y, + AnyTypeOf<[AnyMemRef, AnyTensor]>:$Z); +} + +def MLONNXTreeEnsembleRegressorOp:MLONNX_Op<"TreeEnsembleRegressor", + [NoSideEffect]> { + let summary = "ONNX TreeEnsembleRegressor operation"; + let description = [{ + "Tree Ensemble regressor. Returns the regressed values for each input in N.
" + " All args with nodes_ are fields of a tuple of tree nodes, and" + " it is assumed they are the same length, and an index i will decode the" + " tuple across these inputs. Each node id can appear only once" + " for each tree id.
" + " All fields prefixed with target_ are tuples of votes at the leaves.
" + " A leaf may have multiple votes, where each vote is weighted by" + " the associated target_weights index.
" + " All trees must have their node ids start at 0 and increment by 1.
" + " Mode enum is BRANCH_LEQ, BRANCH_LT, BRANCH_GTE, BRANCH_GT, BRANCH_EQ, BRANCH_NEQ, LEAF" + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + DefaultValuedAttr:$aggregate_function, + OptionalAttr:$base_values, + OptionalAttr:$n_targets, + OptionalAttr:$nodes_falsenodeids, + OptionalAttr:$nodes_featureids, + OptionalAttr:$nodes_hitrates, + OptionalAttr:$nodes_missing_value_tracks_true, + OptionalAttr:$nodes_modes, + OptionalAttr:$nodes_nodeids, + OptionalAttr:$nodes_treeids, + OptionalAttr:$nodes_truenodeids, + OptionalAttr:$nodes_values, + DefaultValuedAttr:$post_transform, + OptionalAttr:$target_ids, + OptionalAttr:$target_nodeids, + OptionalAttr:$target_treeids, + OptionalAttr:$target_weights); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Y); +} + +def MLONNXZipMapOp:MLONNX_Op<"ZipMap", + [NoSideEffect]> { + let summary = "ONNX ZipMap operation"; + let description = [{ + "Creates a map from the input and the attributes.
" + " The values are provided by the input tensor, while the keys are specified by the attributes." + " Must provide keys in either classlabels_strings or classlabels_int64s (but not both).
" + " The columns of the tensor correspond one-by-one to the keys specified by the attributes. There must be as many columns as keys.
" + }]; + let arguments = (ins AnyTypeOf<[AnyMemRef, AnyTensor]>:$X, + OptionalAttr:$classlabels_int64s, + OptionalAttr:$classlabels_strings); + let results = (outs AnyTypeOf<[AnyMemRef, AnyTensor]>:$Z); +} + diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 3171cca..07c0ecb 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -22,3 +22,28 @@ add_custom_target(OMONNXOpsBuildTableIncGen add_custom_target(OMONNXOpsIncTranslation DEPENDS OMONNXOpsTableGenIncGen OMONNXOpsBuildTableIncGen) + +# Invoke gen_doc.py to obtain ONNXOps.td.inc, OpBuildTable.inc. +add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/MLONNXOps.td.inc + ${CMAKE_CURRENT_SOURCE_DIR}/MLOpBuildTable.inc + COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/gen_doc.py --domain="ONNX_ML" + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gen_doc.py) + +# Copy the generated files to respective destinations: +# ONNXOps.td.inc -> src/Dialect/ONNX/ONNXOps.td.inc +add_custom_target(OMMLONNXOpsTableGenIncGen + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/MLONNXOps.td.inc + ${ONNX_MLIR_SRC_ROOT}/src/Dialect/MLONNX/MLONNXOps.td.inc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MLONNXOps.td.inc) + +# OpBuildTable.inc -> src/Builder/OpBuildTable.inc +add_custom_target(OMMLONNXOpsBuildTableIncGen + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/MLOpBuildTable.inc + ${ONNX_MLIR_SRC_ROOT}/src/Builder/MLOpBuildTable.inc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MLOpBuildTable.inc) + +add_custom_target(OMMLONNXOpsIncTranslation + DEPENDS OMMLONNXOpsTableGenIncGen + OMMLONNXOpsBuildTableIncGen) diff --git a/utils/gen_doc.py b/utils/gen_doc.py index f7f44ff..3af41eb 100644 --- a/utils/gen_doc.py +++ b/utils/gen_doc.py @@ -29,6 +29,10 @@ parser.add_argument("--dry-run-op-build-table", help="Output OpBuildTable.inc content to stdout.", action="store_true", default=False) +parser.add_argument("--domain", + help="specify domain, ONNX or ONNX_ML", + default = "ONNX") + args = parser.parse_args() # Manual specification of attribute defaults. @@ -86,17 +90,10 @@ custom_builder_ops_list = ['Abs', 'Mul', 'Exp', 'ReduceSum', 'ReduceSumSquare'] SNIPPETS = collect_snippets() SAMPLE_IMPLEMENTATIONS = collect_sample_implementations() -ONNX_ML = not bool(os.getenv('ONNX_ML') == '0') +ONNX_ML = bool(args.domain == "ONNX_ML") -ONNX_ML = False sys.stderr.write("ONNX_ML {}\n".format(ONNX_ML)) -if ONNX_ML: - ext = '-ml.md' -else: - ext = '.md' - - def should_render_domain(domain): # type: (Text) -> bool if domain == ONNX_ML_DOMAIN and not ONNX_ML: return False @@ -360,7 +357,10 @@ def get_promotable_const_operands_func(s, indent, const_operands_name_to_idx): def gen_op_def(schema): indent = inc_indent() - s = 'def ONNX{0}Op:ONNX_Op<"{0}",\n'.format(schema.name) + if (ONNX_ML) : + s = 'def MLONNX{0}Op:MLONNX_Op<"{0}",\n'.format(schema.name) + else : + s = 'def ONNX{0}Op:ONNX_Op<"{0}",\n'.format(schema.name) # Generate decl for op traits. traits = ["NoSideEffect"] @@ -476,8 +476,12 @@ def gen_op_importer(schema, file): if OpSchema.FormalParameterOption.Variadic == output.option: expected_num_results = -1 - handler_func = special_op_handler.get( - schema.name, "buildOperation".format(schema.name)) + if ONNX_ML: + handler_func = special_op_handler.get( + schema.name, "buildOperation".format(schema.name)) + else: + handler_func = special_op_handler.get( + schema.name, "buildOperation".format(schema.name)) # Special handlers currently require expected num operands/results to be specified. # TODO: remove special handlers. @@ -557,13 +561,19 @@ if __name__ == '__main__': if args.dry_run_onnx_ops: op_def = StringIO() else: - op_def_file_path = os.path.join(curr_dir, 'ONNXOps.td.inc') + if args.domain == 'ONNX_ML': + op_def_file_path = os.path.join(curr_dir, 'MLONNXOps.td.inc') + else: + op_def_file_path = os.path.join(curr_dir, 'ONNXOps.td.inc') op_def = io.open(op_def_file_path, 'w', newline='') if args.dry_run_op_build_table: op_importer = StringIO() else: - op_importer_file_path = os.path.join(curr_dir, 'OpBuildTable.inc') + if args.domain == 'ONNX_ML': + op_importer_file_path = os.path.join(curr_dir, 'MLOpBuildTable.inc') + else : + op_importer_file_path = os.path.join(curr_dir, 'OpBuildTable.inc') op_importer = io.open(op_importer_file_path, 'w', newline='') main(Args)