MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / RoundWeights

Function RoundWeights

tensorflow/tools/graph_transforms/round_weights.cc:32–110  ·  view source on GitHub ↗

Rounds any large float constants to the specified number of levels.

Source from the content-addressed store, hash-verified

30
31// Rounds any large float constants to the specified number of levels.
32Status RoundWeights(const GraphDef& input_graph_def,
33 const TransformFuncContext& context,
34 GraphDef* output_graph_def) {
35 int32 num_steps;
36 TF_RETURN_IF_ERROR(
37 context.GetOneInt32Parameter("num_steps", 256, &num_steps));
38 TF_RETURN_IF_ERROR(ReplaceMatchingOpTypes(
39 input_graph_def, {"Const"},
40 [num_steps](const NodeMatch& match, const std::set<string>& input_nodes,
41 const std::set<string>& output_nodes,
42 std::vector<NodeDef>* new_nodes) {
43 const NodeDef& old_const_node = match.node;
44 if (!old_const_node.attr().count("dtype")) {
45 return errors::InvalidArgument("No 'dtype' attribute for Const node ",
46 old_const_node.name());
47 }
48 if (!old_const_node.attr().count("value")) {
49 return errors::InvalidArgument("No 'value' attribute for Const node ",
50 old_const_node.name());
51 }
52 const DataType old_dtype = old_const_node.attr().at("dtype").type();
53 Tensor old_tensor;
54 if (!old_tensor.FromProto(old_const_node.attr().at("value").tensor())) {
55 return errors::InvalidArgument("Decoding Tensor failed for node",
56 old_const_node.name());
57 }
58 const size_t num_elements = old_tensor.NumElements();
59 // If this isn't a float constant, or it's too small, then reuse the
60 // same node with no changes. The size is important because small
61 // constants tend to be used for more accuracy-sensitive calculations,
62 // and the benefit of shrinking them is very marginal.
63 if ((old_dtype != DT_FLOAT) || (num_elements < 16)) {
64 new_nodes->push_back(old_const_node);
65 return Status::OK();
66 }
67 const float* old_values = old_tensor.flat<float>().data();
68 float min = std::numeric_limits<float>::max();
69 float max = std::numeric_limits<float>::min();
70 for (int i = 0; i < num_elements; ++i) {
71 const float value = old_values[i];
72 min = std::min(min, value);
73 max = std::max(max, value);
74 }
75 // min_value == max_value is a tricky case. It can occur for general
76 // tensors, and of course for scalars. The quantized ops cannot deal
77 // with this case, so we set max_value to something else.
78 // It's a tricky question what is the numerically best solution to
79 // deal with this degeneracy.
80 // TODO(petewarden): Better use a tolerance than a hard comparison?
81 if (min == max) {
82 if (std::abs(min) < 0.000001f) {
83 max = min + 1.0f;
84 } else if (min > 0) {
85 max = 2.0f * min;
86 } else {
87 min = 2.0f * max;
88 }
89 }

Callers 1

TestRoundWeightsMethod · 0.85

Calls 15

ReplaceMatchingOpTypesFunction · 0.85
InvalidArgumentFunction · 0.85
floorClass · 0.85
GetOneInt32ParameterMethod · 0.80
attrMethod · 0.80
set_opMethod · 0.80
SetNodeAttrFunction · 0.70
nameMethod · 0.65
typeMethod · 0.65
maxFunction · 0.50
minFunction · 0.50
absFunction · 0.50

Tested by 1

TestRoundWeightsMethod · 0.68