-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create rule S6929: The axis argument should be specified when using T…
…ensorFlow's reduction operations (#3644) * Create rule S6929 * Create rule S6929: The axis argument should be specified when using TensorFlow's reduction operations * Fix after review --------- Co-authored-by: joke1196 <[email protected]> Co-authored-by: David Kunzmann <[email protected]>
- Loading branch information
1 parent
c6d7ba2
commit 2b30d4d
Showing
3 changed files
with
130 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"title": "The axis argument should be specified when using TensorFlow's reduction operations", | ||
"type": "CODE_SMELL", | ||
"status": "ready", | ||
"remediation": { | ||
"func": "Constant\/Issue", | ||
"constantCost": "5min" | ||
}, | ||
"tags": [ | ||
], | ||
"defaultSeverity": "Major", | ||
"ruleSpecification": "RSPEC-6929", | ||
"sqKey": "S6929", | ||
"scope": "All", | ||
"defaultQualityProfiles": ["Sonar way"], | ||
"quickfix": "unknown", | ||
"code": { | ||
"impacts": { | ||
"MAINTAINABILITY": "MEDIUM", | ||
"RELIABILITY": "HIGH" | ||
}, | ||
"attribute": "CLEAR" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
This rule raises an issue when the axis argument is not provided to TensorFlow's reduction operations. | ||
|
||
== Why is this an issue? | ||
|
||
The result of TensorFlow's reduction operations (i.e. ``tf.math.reduce_sum``, ``tf.math.reduce_std``), | ||
highly depends on the shape of the Tensor provided. | ||
|
||
[source,python] | ||
---- | ||
import tensorflow as tf | ||
x = tf.constant([[1, 1, 1], [1, 1, 1]]) | ||
tf.math.reduce_sum(x) | ||
---- | ||
|
||
In the example above the reduction of the 2 dimensional array will return the value `6` as all the elements are added together. | ||
By default TensorFlow's reduction operations are applied across all axis. When specifying an axis the result will be completely different. | ||
|
||
[source,python] | ||
---- | ||
import tensorflow as tf | ||
x = tf.constant([[1, 1, 1], [1, 1, 1]]) | ||
tf.math.reduce_sum(x, axis=0) | ||
---- | ||
|
||
Here the result will be `[2,2,2]` as the reduction is applied only on the axis 0. | ||
|
||
TensorFlow's default behavior can be confusing, especially when the reducing array of different shapes. | ||
|
||
Considering the following example: | ||
|
||
[source,python] | ||
---- | ||
import tensorflow as tf | ||
x = tf.constant([[1], [2]]) | ||
y = tf.constant([1, 2]) | ||
tf.math.reduce_sum(x + y) | ||
---- | ||
|
||
Here the result will be `12` instead of the `6` that could be expected. This is because the implicit broadcasting reshapes the | ||
first array to `[[1,1], [2,2]]` which is then added to the `y` array `[1,2]` resulting in ``[[2,3], [3,4]]``. As the | ||
reduction happen across all dimensions the result is then ``2 + 3 + 3 + 4 = 12``. It is not clear by looking at the example | ||
if this was intentional or if the user made a mistake. | ||
|
||
This is why a good practice is to always specify the axis on which to perform the reduction. | ||
|
||
For example: | ||
|
||
[source,python] | ||
---- | ||
import tensorflow as tf | ||
x = tf.constant([[1], [2]]) | ||
y = tf.constant([1, 2]) | ||
tf.math.reduce_sum(x + y, axis=0) | ||
---- | ||
|
||
In the example above, specifying the axis clarifies the intent, as the result now is ``[5, 7]``. If the intent was to effectively | ||
reduce across all dimensions the user should provide the list of axis `axis=[0,1]` | ||
or clearly state the default behavior should be applied with ``axis=None``. | ||
|
||
== How to fix it | ||
|
||
To fix this issue provide the axis argument when using a TensorFlow reduction operation such as ``tf.math.reduce_sum``, ``tf.math.reduce_prod``, ``tf.math.reduce_mean``, etc... | ||
|
||
=== Code examples | ||
|
||
==== Noncompliant code example | ||
|
||
[source,python,diff-id=1,diff-type=noncompliant] | ||
---- | ||
import tensorflow as tf | ||
x = tf.constant([[1, 1, 1], [1, 1, 1]]) | ||
tf.math.reduce_sum(x) # Noncompliant: the axis arguments defaults to None | ||
---- | ||
|
||
==== Compliant solution | ||
|
||
[source,python,diff-id=1,diff-type=compliant] | ||
---- | ||
import tensorflow as tf | ||
x = tf.constant([[1, 1, 1], [1, 1, 1]]) | ||
tf.math.reduce_sum(x, axis=0) # Compliant: the reduction will happen only on the axis 0, resulting in `[2,2,2]` | ||
---- | ||
|
||
|
||
== Resources | ||
=== Documentation | ||
|
||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_max[tf.math.reduce_max reference] | ||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_mean[tf.math.reduce_mean reference] | ||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_min[tf.math.reduce_min reference] | ||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_prod[tf.math.reduce_prod reference] | ||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_std[tf.math.reduce_std reference] | ||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_sum[tf.math.reduce_sum reference] | ||
* TensorFlow Documentation - https://www.tensorflow.org/api_docs/python/tf/math/reduce_variance[tf.math.reduce_variance reference] | ||
|
||
=== Articles & blog posts | ||
|
||
* Vahidk Developers Guide - https://github.com/vahidk/EffectiveTensorflow?tab=readme-ov-file#broadcasting-the-good-and-the-ugly[Broadcasting the good and the ugly] |