NumPy is a powerful scientific computing library for Python via which developers can make short work of matrix operations, random number generation, and many other complex mathematical functions. It rocks — but sometimes one runs into an error that isn’t readily understood.
In this quick breakdown, we’ll look at such a case where NumPy might produce a runtime warning indicating that an invalid value was encountered while using the true_divide function. As the error suggests, this error arises from — wait for it — using an invalid value during a division process. Most commonly, this happens when a 0 or NaN appears as the denominator.
TL;DR
If you try to use the true_divide
function in NumPy when there are two 0
‘s present Python will generate a RuntimeWarning
. Consider the following:
# Two np.array objects b_1 = np.array([5, 6, 7, 8, 0]) b_2 = np.array([1, 2, 3, 4, 0]) # Divided using true_divide print(np.true_divide(b_1, b_2)) # Doesn't crash the program [5. 3. 2.33333333 2. nan] # But throws the following warning RuntimeWarning: divide by zero encountered in true_divide print(np.true_divide(b_1, b_2))
The solution is to address the issue of the 0
‘s shown as the last element in both the b_1
and b_2
array — with the 0
in b_2
being prioritized as it would still cause a RuntimeWarning
for dividing by zero even if the 0
in b_1
were replaced.
Quick Intro: The true_divide Function
NumPy’s true_divide
function is designed to make dividing collections of values such as arrays. It can be used to divide an array (a.k.a. matrix) via another array or by a single value. In either case, the operation happens element-wise.
Note: The true_divide
function requires that two arrays be the same shape.
Below is a quick example of the true_divide
method being used to divide an array into another:
import numpy as np # Define some arrays a_1 = [6, 7, 8, 9, 10] a_2 = [1, 2, 3, 4, 5] # Use true_divide explicitly print(np.true_divide(a_1, a_2)) # Result [6. 3.5 2.66666667 2.25 2. ] # works with a single value as well print(np.true_divide(a_1, 3)) # Result [2. 2.33333333 2.66666667 3. 3.33333333]
NumPy also allows the implicit use of true_divide
via the /
and //
operators when used between two NumPy arrays:
# Implicit use after converting to an array print(np.array(a_1) / np.array(a_2)) # Result [6. 3.5 2.66666667 2.25 2. ] # Implicit use after converting to an array, # and using static value print(np.array(a_1) / 3) # Result [2. 2.33333333 2.66666667 3. 3.33333333] # Use of floor division print(np.array(a_1) // np.array(a_2)) # Result [6 3 2 2 2] # Use of floor division with single value # Use of floor division print(np.array(a_1) // 3) # Result [2 2 2 3 3]
However, should one try to use these types of syntaxes with non-np arrays one will receive an error:
# Divide two lists print(a_1 // a_2) TypeError: unsupported operand type(s) for //: 'list' and 'list'
The closest pure-Python analog to the true_divide
function would be a custom list comprehension as such:
# Elementwise division of two lists vals = [x / a_2[i] for i, x in enumerate(a_1)] print(vals) # Result [6.0, 3.5, 2.6666666666666665, 2.25, 2.0] # Elementwise division of two lists, using floor division vals = [x // a_2[i] for i, x in enumerate(a_1)] print(vals) # Result [6, 3, 2, 2, 2]
While convenient to stay in the syntax of Python — and avoid a dependency — this syntax becomes clunky and unclear if used often. Now that we have an idea of how collections can be multiplied with or without NumPy, let’s consider some issues that may arise when using NumPy specifically.
The Issue: Invalid Value Encountered in true_divide
The true_divide
function, much like most division functions, does not accommodate the division via 0
, NaN
, or otherwise zero-ish values. Below we’ll create two NumPy arrays, each with a value of 0
included and attempt the true_divide
function.
# Create 2 np.array objects b_1 = np.array([5, 6, 7, 8, 0]) b_2 = np.array([1, 2, 3, 4, 0]) # do an explicit true_divide print(np.true_divide(b_1, b_2)) # Result [5. 3. 2.33333333 2. nan] RuntimeWarning: invalid value encountered in true_divide print(np.true_divide(b_1, b_2))
First off it’s important to note this isn’t an Exception
but rather a Warning
— a RuntimeWarning
to be exact. This won’t’ cause a program to crash but will result in an NaN
value in the resulting array. The fix is to remove the zeroes.
Another Issue: Divide by Zero Encountered in true_divide
Removing the 0
in the first array will sidestep the RuntimeWarning
issue regarding the invalid value but will present another RuntimeWarning
issue: dividing by zero. Consider the following code:
# Create 2 np.array objects b_1 = np.array([5, 6, 7, 8, 1]) b_2 = np.array([1, 2, 3, 4, 0]) # do an explicit true_divide print(np.true_divide(b_1, b_2)) # Result [5. 3. 2.33333333 2. inf] RuntimeWarning: divide by zero encountered in true_divide print(np.true_divide(b_1, b_2))
Note here the return value consists of an np.array
object in which the last element is the value inf
representing infinity. This might be desired behavior depending on one’s application hence the issuance of a Warning
rather than an Exception
.
Final Thoughts
NumPy is a powerful library and is an under-the-hood dependency of many of the most popular data science libraries like Pandas, Sci-kit Learn, and even Machine learning libraries like Tensor Flow. It can supercharge matrix-based calculations and provides enough convenience functions to write books about.
The odd behavior noted here comes from very contrived, intentional examples. In many cases, these errors may arise when a 0
or NaN
value is unknowingly present in an array. For example, perhaps such a value results after a first calculation such that the RuntimeWarning
is generated during the second — hard to check for that beforehand!