apple / apple/coremltools

TensorFlow function divide_no_nan does not perform safe divide after conversion to CoreML

Open
#1,481 0 comments 0 reactions 0 assignees View on GitHub
bug tf2.x / tf.keras triaged
Dominant language
Python
Stars
5.4k
Forks
850
Avg merge
4d 5h
Merged PRs (30d)
10

Description

## 🐞Describe the bug

The TensorFlow function divide_no_nan (https://www.tensorflow.org/api_docs/python/tf/math/divide_no_nan) performs a safe division where the result is 0 if the denominator is 0.

The TF op DivNoNan is listed as supported in coremltools as of version 5.2, and converting a TF model that contains the function divide_no_nan to a .mlmodel within coremltools produces no compatibility errors.

However the resulting model does not behave the same as the TF model, and the converted divide_no_nan does not perform safe division. Divisions by 0 instead return Inf.

## Stack Trace
N/A

## To Reproduce

Here is a simple TF / Keras layer that computes the reciprocal of the input to demonstrate the issue:

```
import numpy as np
import tensorflow as tf
from tensorflow import keras
import coremltools as ct

class Reciprocal(keras.layers.Layer):
def __init__(self, **kwargs):
super(Reciprocal, self).__init__(**kwargs)

def call(self, inputs):
return tf.math.divide_no_nan(tf.constant(1.0), inputs)

model = keras.Sequential([keras.Input(shape=3, name='input'), Reciprocal(name='reciprocal')])

# convert model to CoreML
core_ml_model = ct.convert(model)

# compare output for both TF and CoreML versions of model
input_data = np.array([[0, 1, 2]]).astype('float32')

tf_output = model.predict(input_data)
core_ml_output = core_ml_model.predict({'input': input_data})

print(f'Input Data: {input_data}')
print(f'TensorFlow Output: {tf_output}')
print(f'CoreML Output: {core_ml_output["Identity"]}')

```

This example computed the reciprocal of 0, 1, and 2, and produces the following output. As can be seen, 1.0 / 0.0 produces 0 with divide_no_nan within TF (as intended), but produces Inf after the mlmodel conversion.

```
Input Data: [[0. 1. 2.]]
TensorFlow Output: [[0. 1. 0.5]]
CoreML Output: [[inf 1. 0.5]]

```
## System environment (please complete the following information):
- coremltools version: 5.2.0
- Python version: 3.9.1
- TensorFlow version: 2.6.2
- OS (e.g. MacOS version or Linux type): MacOS, I have replicated the same behavior on both OS 10.15.7 and 12.2.1.

## Additional context
N/A

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with the supplied TensorFlow/Keras Reciprocal example and inspect the TensorFlow conversion path for the DivNoNan operation. Compare the converted Core ML output with TensorFlow for a zero denominator; done means divide_no_nan returns 0 rather than Inf after conversion.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, tensorflow
Domain
machine-learning, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.