DLS Course 2 - Wk 3 - Ex 3 One_hot_matrix - Reshape Errors

In this exercise, you have to reshape the vector into a (depth, ) or (depth,1) vector. But some of those vectors give errors in the assertion test of that exercise. However, if you have a reshaped vector that passes this assertion test (depth), later on in new_y_test = y_test.map(one_hot_matrix) you get an error.

Reading Course 2, Week 3, one_hot_matrix clarification - #5 by philgo the solution is given to use [depth] instead of (depth). For me that also works. It passes the assertion test in one_hot_matrix and the y_test.map call.

However, I have no clue why.

I did some testing, and this is what works and doesn’t work.

a) one_hot = tf.reshape(tf.one_hot(label, depth, axis=0), (depth))
passes one_hot_matrix assertion test and fails y_test.map call.
b) one_hot = tf.reshape(tf.one_hot(label, depth, axis=0), (depth, 1))
fails one_hot_matrix_assertion test and passes y_test.map.call
c) one_hot = tf.reshape(tf.one_hot(label, depth, axis=0), (depth, ))
passes one_hot_matrix_assertion test and passes y_test.map.call
d) one_hot = tf.reshape(tf.one_hot(label, depth, axis=0), [depth])
passes one_hot_matrix assertion test and passes y_test.map call.

I have no clue, why c & d work, but a & b give problems.

Furthermore if I look at the vector which you get from the reshaping:

a) ((depth)): tf.Tensor([0. 1. 0. 0.], shape=(4,), dtype=float32)
b) (depth,1): tf.Tensor(
[[0.]
 [1.]
 [0.]
 [0.]], shape=(4, 1), dtype=float32)
c)  (depth,): tf.Tensor([0. 1. 0. 0.], shape=(4,), dtype=float32)
d)   [depth]: tf.Tensor([0. 1. 0. 0.], shape=(4,), dtype=float32)

vectors a, c & d look completely the same to me. Yet vector a gives trouble further down the road when y_test.map is called.

Is there some logical explanation why this is the case, and why c & d work and a & b do not?

PS Worth noting is that if I look a bit ahead at, this line: print(next(iter(new_y_test)))
for vectors a & b, I get:

tf.Tensor(
[[1.]
 [0.]
 [0.]
 [0.]
 [0.]
 [0.]], shape=(6, 1), dtype=float32)

and for vectors c & d I get:
tf.Tensor([1. 0. 0. 0. 0. 0.], shape=(6,), dtype=float32)

So somehow rank 1 vectors are needed, but again, why? So far, we have been instructed in these courses to explicitly reshape vectors into the right shape.

4 Likes

I ran into the same error. I actually specified the shape in tf.reshape as:

one_hot = tf.reshape(tf.one_hot(label,depth,axis=0), shape=(4,1))

At first, this threw an error. Then I saw the expected output and modified it to:

one_hot = tf.reshape(tf.one_hot(label,depth,axis=0), shape=(4,))

This passed the first test, where it produces a column matrix.

However, the same function fails in the next cell, which is:

new_y_test = y_test.map(one_hot_matrix)
new_y_train = y_train.map(one_hot_matrix)

I am now looking into your answer but I still don’t understand why replacing shape=(4,) with [depth] works. The expected output clearly wanted the shape to be (4,1) then why are we reshaping it to the default depth of 6?

It is always a mistake to hard code the dimension to 4. They pass you the depth as an argument, right? There is no guarantee it will always be 4. E.g. it might be 6. Then what? :scream_cat:

We are trying to write “general” code here. It’s not a good idea to hard-wire sizes unless they specifically tell you to do that.

I ran into the same error but fixed it with this line of code
“one_hot = tf.reshape(tf.one_hot(label, depth), [-1,])”

The documentation for tf.reshape(tensor, shape, name=None) states that the shape argument must be:

A Tensor. Must be one of the following types: int32, int64. Defines the shape of the output tensor.

Every example on the documentation page passes the shape using square brackets:

tf.reshape(t, [ 2, -1, 3])

I suspect that within function parameters, anything inside [...] is assumed to be a numpy array, which qualifies as a tensor.

depth or (depth) are probably parsed as numeric types and definitely don’t work. I assume that (depth, ) or (depth, 1) are implicitly cast to tensor types by the function parser.

2 Likes

I had the same issue, and not in a million years would I have found the problem if it wasn’t for this forum…

one_hot = tf.reshape(one_hot, shape=(depth))

does work in the tests, but throws an error in the consecutive mapping, whereas

one_hot = tf.reshape(one_hot, shape=[depth])

works in both cases.

It’s just super weird behavior. If tensorflow demands tensors, it should explicitly enforce them, and not show weird behavior when you use a tuple for a shape, LIKE EVERYONE ON THE PLANET WOULD INTUITIVELY DO. I know nothing of tf, but I’d be really surprised to learn that a shape parameter MUST be a tensor, and is not at least converted implictly after the fact. In my understanding, a tuple is the correct datatype for the shape of a tensor, no? Rather than a mutable python list, at least…

This is just TF applying its own type coercion rules. The problem is not so much the type of the input, but the dimensions. You can use a tuple this way and it works:

shape = (depth,)

See the difference there? The problem is not that (depth) is a tuple, but that it ends up getting coerced to a 0D tensor. Whereas (depth,) ends up as a 1D tensor, which is what is required here.

Ahhh right, (depth) is in fact not a python-tuple at all, (depth,) however, is. My mistake!

one_hot = tf.reshape(one_hot, shape=(depth,))

works as well. So, defining shapes as tuples does work, as one would expect.

There is a legitimate complaint here: they really should fix the test cases for one_hot_matrix so that it throws if you use a 0D or 2D shape, rather than accepting it and then having it throw later. They could probably even produce an error message that gives a hint about the nature of the failure. Worth a try anyway. I will file a bug about this.

Yes, exactly.

The question is if tensorflow REQUIRES the shape to be 1D as the tests suggest (Which I do not think).
Because otherwise, the tests violate previously taught best-practices (“use explicit 2D-shapes for vectors”), and instead enforce exactly the opposite behavior in order to make the tests pass…

After all, the consecutive mapping works with explicit 2D-tuples used for the shapes, it’s only the custom tests that fail.