InvalidArgumentError: невозможно вычислить MatMul, так как ожидалось, что вход № 0(с нуля) будет тензором с плавающей точкой, но является двойным тензором [Op:MatMul]
Может кто-нибудь объяснить, как тензор потока eager-mode
работает. Я пытаюсь построить простую регрессию следующим образом:
РЕДАКТИРОВАТЬ: я обновляю свою проблему, это мой полный код, теперь проблема заключается в вычислении градиентов, он возвращает ноль. Я должен проверить значение потери, которое не равно нулю.
import tensorflow as tf
tfe = tf.contrib.eager
tf.enable_eager_execution()
import numpy as np
def make_model():
net = tf.keras.Sequential()
net.add(tf.keras.layers.Dense(4, activation='relu'))
net.add(tf.keras.layers.Dense(1))
return net
def compute_loss(pred, actual):
return tf.reduce_mean(tf.square(tf.subtract(pred, actual)))
def compute_gradient(model, pred, actual):
"""compute gradients with given noise and input"""
with tf.GradientTape() as tape:
loss = compute_loss(pred, actual)
grads = tape.gradient(loss, model.variables)
return grads, loss
def apply_gradients(optimizer, grads, model_vars):
optimizer.apply_gradients(zip(grads, model_vars))
model = make_model()
optimizer = tf.train.AdamOptimizer(1e-4)
x = np.linspace(0,1,1000)
y = x+np.random.normal(0,0.3,1000)
y = y.astype('float32')
train_dataset = tf.data.Dataset.from_tensor_slices((y.reshape(-1,1)))
epochs = 2# 10
batch_size = 25
itr = y.shape[0] // batch_size
for epoch in range(epochs):
for data in tf.contrib.eager.Iterator(train_dataset.batch(25)):
preds = model(data)
grads, loss = compute_gradient(model, preds, data)
print(grads)
apply_gradients(optimizer, grads, model.variables)
# with tf.GradientTape() as tape:
# loss = tf.sqrt(tf.reduce_mean(tf.square(tf.subtract(preds, data))))
# grads = tape.gradient(loss, model.variables)
# print(grads)
# optimizer.apply_gradients(zip(grads, model.variables),global_step=None)
Gradient output: [None, None, None, None, None, None]
Ошибка следующая:
----------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-a589b9123c80> in <module>
35 grads, loss = compute_gradient(model, preds, data)
36 print(grads)
---> 37 apply_gradients(optimizer, grads, model.variables)
38 # with tf.GradientTape() as tape:
39 # loss = tf.sqrt(tf.reduce_mean(tf.square(tf.subtract(preds, data))))
<ipython-input-3-a589b9123c80> in apply_gradients(optimizer, grads, model_vars)
17
18 def apply_gradients(optimizer, grads, model_vars):
---> 19 optimizer.apply_gradients(zip(grads, model_vars))
20
21 model = make_model()
~/anaconda3/lib/python3.6/site-packages/tensorflow/python/training/optimizer.py in apply_gradients(self, grads_and_vars, global_step, name)
589 if not var_list:
590 raise ValueError("No gradients provided for any variable: %s." %
--> 591 ([str(v) for _, v, _ in converted_grads_and_vars],))
592 with ops.init_scope():
593 self._create_slots(var_list)
ValueError: No gradients provided for any variable:
2 ответа
Часть 1: Проблема действительно в типе данных вашего ввода. По умолчанию ваша модель keras ожидает float32, но вы передаете float64. Вы можете либо изменить dtype модели, либо изменить ввод на float32.
Чтобы изменить свою модель:
def make_model():
net = tf.keras.Sequential()
net.add(tf.keras.layers.Dense(4, activation='relu', dtype='float32'))
net.add(tf.keras.layers.Dense(4, activation='relu'))
net.add(tf.keras.layers.Dense(1))
return net
Чтобы изменить свой ввод:y = y.astype('float32')
Часть 2: Вам нужно вызвать функцию, которая вычисляет вашу модель (т.е. model(data)
) под tf.GradientTape(). Например, вы можете заменить compute_loss
метод со следующим:
def compute_loss(model, x, y):
pred = model(x)
return tf.reduce_mean(tf.square(tf.subtract(pred, y)))
Если вы пришли к этому вопросу/ответу из-за того, что получили ошибку в заголовке, а ваши входные данные представляют собой EagerTensor, то вы можете привести одну из матриц при умножении матриц к соответствующему типу dtype, используяtf.cast()
.
Например, в следующем примереx
имеет тип dfloat
покаy
имеет тип d(float64
является double
), поэтому попытка выполнить умножение матриц как есть приведет к ошибкеInvalidArgumentError: cannot compute MatMul as input #1(zero-based) was expected to be a float tensor but is a double tensor [Op:MatMul]
. Чтобы устранить эту ошибку, приведите одну из матриц к dtype другой.
import tensorflow as tf
x = tf.constant([[1, 2]], dtype='float32')
y = tf.constant([[3], [4]], dtype='float64')
tf.matmul(x, y) # <---- InvalidArgumentError
z = tf.matmul(x, tf.cast(y, x.dtype)) # <----- OK
z.dtype # tf.float32
w = tf.matmul(tf.cast(x, y.dtype), y) # <----- OK
w.dtype # tf.float64