chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..common_ops_import import Variable
|
||||
from ..framework import (
|
||||
LayerHelper,
|
||||
OpProtoHolder,
|
||||
convert_nptype_to_datatype_or_vartype,
|
||||
core,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from paddle import Tensor
|
||||
|
||||
__all__ = []
|
||||
|
||||
|
||||
def _convert_(name):
|
||||
"""
|
||||
Formatting.
|
||||
|
||||
Args:
|
||||
name: The name/alias
|
||||
|
||||
This function takes in a name and converts it to a standard format of
|
||||
group1_group2. Where as per the regular expression, group1 can have
|
||||
alphabets and numbers and group2 has capital alphabets.
|
||||
|
||||
"""
|
||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
||||
|
||||
|
||||
def generate_layer_fn(op_type: str):
|
||||
"""Register the Python layer for an Operator.
|
||||
|
||||
Args:
|
||||
op_type: The name of the operator to be created.
|
||||
|
||||
This function takes in the operator type (sigmoid, mean , average etc) and
|
||||
creates the operator functionality.
|
||||
|
||||
"""
|
||||
op_proto = OpProtoHolder.instance().get_op_proto(op_type)
|
||||
not_intermediate_outputs = [
|
||||
output for output in op_proto.outputs if not output.intermediate
|
||||
]
|
||||
intermediate_outputs = [
|
||||
output for output in op_proto.outputs if output.intermediate
|
||||
]
|
||||
|
||||
if len(not_intermediate_outputs) != 1:
|
||||
raise ValueError(
|
||||
"Only one non intermediate output operator can be"
|
||||
f"automatically generated. {op_type}"
|
||||
)
|
||||
|
||||
if not_intermediate_outputs[0].duplicable:
|
||||
raise ValueError(
|
||||
"Only non duplicable op can be automatically generated."
|
||||
)
|
||||
|
||||
for output in intermediate_outputs:
|
||||
if output.duplicable:
|
||||
raise ValueError(
|
||||
"The op can be automatically generated only when "
|
||||
"all intermediate ops are not duplicable."
|
||||
)
|
||||
|
||||
o_name = not_intermediate_outputs[0].name
|
||||
intermediate_output_names = [output.name for output in intermediate_outputs]
|
||||
|
||||
def infer_and_check_dtype(op_proto, *args, **kwargs):
|
||||
"""
|
||||
This function performs the sanity check for dtype and
|
||||
instance type.
|
||||
"""
|
||||
dtype = None
|
||||
for ipt in op_proto.inputs:
|
||||
name = _convert_(ipt.name)
|
||||
val = kwargs.pop(name, [])
|
||||
if not isinstance(val, list) and not isinstance(val, tuple):
|
||||
val = [val]
|
||||
if len(val) == 0:
|
||||
if len(args) == 0:
|
||||
continue
|
||||
val = [args[0]]
|
||||
args = args[1:]
|
||||
|
||||
for each in val:
|
||||
if not isinstance(each, Variable):
|
||||
raise ValueError(f"input of {op_type} must be variable")
|
||||
|
||||
if dtype is None:
|
||||
dtype = each.dtype
|
||||
elif dtype != each.dtype:
|
||||
raise ValueError(
|
||||
f"operator {op_type} must input same dtype. {dtype} vs {each.dtype}"
|
||||
)
|
||||
|
||||
if dtype is None:
|
||||
arg_dtype = kwargs.get("dtype")
|
||||
if arg_dtype:
|
||||
if not isinstance(arg_dtype, core.VarDesc.VarType):
|
||||
dtype = convert_nptype_to_datatype_or_vartype(arg_dtype)
|
||||
else:
|
||||
dtype = arg_dtype
|
||||
else:
|
||||
dtype = core.VarDesc.VarType.FP32
|
||||
return dtype
|
||||
|
||||
def func(*args, **kwargs) -> Tensor:
|
||||
helper = LayerHelper(op_type, **kwargs)
|
||||
|
||||
dtype = infer_and_check_dtype(op_proto, *args, **kwargs)
|
||||
|
||||
inputs = {}
|
||||
for ipt in op_proto.inputs:
|
||||
name = _convert_(ipt.name)
|
||||
val = kwargs.pop(name, [])
|
||||
if not isinstance(val, list) and not isinstance(val, tuple):
|
||||
val = [val]
|
||||
if len(val) == 0 and len(args) != 0:
|
||||
val = args[0]
|
||||
args = args[1:]
|
||||
inputs[ipt.name] = val
|
||||
|
||||
outputs = {}
|
||||
out = kwargs.pop(_convert_(o_name), [])
|
||||
if out:
|
||||
out_var = out[0] if isinstance(out, (list, tuple)) else out
|
||||
else:
|
||||
out_var = helper.create_variable_for_type_inference(dtype=dtype)
|
||||
outputs[o_name] = [out_var]
|
||||
for name in intermediate_output_names:
|
||||
outputs[name] = [
|
||||
helper.create_variable_for_type_inference(dtype=dtype)
|
||||
]
|
||||
helper.append_op(
|
||||
type=op_type, inputs=inputs, outputs=outputs, attrs=kwargs
|
||||
)
|
||||
return helper.append_activation(out_var)
|
||||
|
||||
func.__name__ = op_type
|
||||
return func
|
||||
Reference in New Issue
Block a user