我正在構建一個自定義 Keras 層,它本質上是帶有可訓練基本引數的 softmax 函式。雖然該層獨立作業,但當放置在順序模型中時,model.summary()將其輸出形狀確定為None并model.fit()引發一個可能鏈接的例外:
ValueError: as_list() 未在未知的 TensorShape 上定義。
在其他自定義層(顯然包括來自 keras 的線性示例)中,可以在.build()呼叫之后確定輸出形狀。通過查看model.summary()的源代碼以及keras.layers.Layer,有這個@propertyLayer.output_shape無法自動確定輸出形狀。
然后我嘗試覆寫屬性并在保存后手動回傳input_shape傳遞給我的圖層.build()方法的引數(softmax 不會改變輸入的形狀),但這也不起作用:如果我呼叫super().output_shape before returning my value, model.summary()將形狀確定為?,而如果我不這樣做,則該值可能會顯示為看似正確,但在這兩種情況下,我都會在 .fit() 期間得到完全相同的錯誤。
代碼 iside call() 是否有什么特別之處會阻止 keras 理解輸出的形狀?
或者,是否有我遺漏的檔案?
我的層:
class B_Softmax(keras.layers.Layer):
def __init__(self, b_init_mean=10, b_init_var=0.001):
super(B_Softmax, self).__init__()
self.b_init = tf.random_normal_initializer(b_init_mean, b_init_var)
self._out_shape = None
def build(self, input_shape):
self.b = tf.Variable(
initial_value = self.b_init(shape=(1,), dtype='float32'),
trainable=True
)
self._out_shape = input_shape
def call(self, inputs):
# This is an implementation of Softmax for batched inputs
# where the factor b is added to the exponents
nominators = tf.math.exp(self.b * inputs)
denominator = tf.reduce_sum(nominators, axis=1)
denominator = tf.squeeze(denominator)
denominator = tf.expand_dims(denominator, -1)
s = tf.divide(nominators, denominator)
return s
@property
def output_shape(self): # If I comment out this function, summary prints 'None'
self.output_shape # If I leave this line, summary prints '?'
return self._out_shape # If the above line is commented out, summary prints '10' (correctly)
# but the same error is triggered in all three cases
該層獨立作業:
>>> A = tf.constant([[1,2,3], [7,5,6]], dtype="float32")
>>> layer = B_Softmax(1.0)
>>> layer(A)
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[0.08991686, 0.24461554, 0.6654676 ],
[0.6654677 , 0.08991687, 0.24461551]], dtype=float32)>
但是當我嘗試將它包含在模型中時,摘要看起來不正確:
input_dim = 5
model = keras.Sequential([
Dense(32, activation='relu', input_shape=(input_dim,)),
Dense(num_classes, activation="softmax"),
B_Softmax(1.0)
])
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_10 (Dense) (None, 32) 192
dense_11 (Dense) (None, 10) 330
b__softmax_18 (B_Softmax) None <-------------------1-------- "None", "?", or "10" (in a hacky way) may be printted
=================================================================
Total params: 523
Trainable params: 523
Non-trainable params: 0
訓練失敗:
batch_size = 128
epochs = 15
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1)
ValueError: in user code:
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1051, in train_function *
return step_function(self, iterator)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1040, in step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1030, in run_step **
outputs = model.train_step(data)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 894, in train_step
return self.compute_metrics(x, y, y_pred, sample_weight)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 987, in compute_metrics
self.compiled_metrics.update_state(y, y_pred, sample_weight)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 480, in update_state
self.build(y_pred, y_true)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 398, in build
y_pred)
File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 526, in _get_metric_objects
return [self._get_metric_object(m, y_t, y_p) for m in metrics]
File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 526, in <listcomp>
return [self._get_metric_object(m, y_t, y_p) for m in metrics]
File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 548, in _get_metric_object
y_p_rank = len(y_p.shape.as_list())
ValueError: as_list() is not defined on an unknown TensorShape.
uj5u.com熱心網友回復:
這并不能直接解決問題,而是回避它:我們不使用squeezeand expand_dims(前者似乎對 Tensorflow 的跟蹤有問題),而是keepdims=True在求和中使用以保持軸正確對齊 softmax 分母.
def call(self, inputs):
# This is an implementation of Softmax for batched inputs
# where the factor b is added to the exponents
nominators = tf.math.exp(self.b * inputs)
denominator = tf.reduce_sum(nominators, axis=1, keepdims=True)
s = tf.divide(nominators, denominator)
return s
可以說,最好使用內置的 softmax:
def call(self, inputs):
return tf.nn.softmax(self.b * inputs)
uj5u.com熱心網友回復:
compute_output_shape您可以在 Layer 子類中實作該方法:
def compute_output_shape(self, input_shape):
return [(None, out_shape)]
其中out_shape包含輸出的維度,或者您可以替換整個元組以具有您想要的任何輸出形狀。
uj5u.com熱心網友回復:
我發現代碼沒有問題,我認為輸入引數很重要,這樣做有一些注釋:
- 我使用資料集和 model.fit() 我也使用它而不使用拆分,因為我創建了一個帶有一條記錄的樣本。
- 模型輸入,我從 Input( 5, ) 修改為 Input ( 1, 5 ),它與資料集匹配創建了一個形狀(這就是我在摘要中添加選擇號 1 的原因)
- Categorize、BatchSize、Number of class、LossFN 和 Optimizers 通過 number_classes 引數根據網路的輸出維度進行調整。
示例:<< Loss FN 不決定模型,但 Input 和 Output 決定,不必說明它是如何創建的,洗掉了它不使用的內容或評論它>>
import tensorflow as tf
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Class / Definition
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
class B_Softmax(tf.keras.layers.Layer):
def __init__(self, b_init_mean=10, b_init_var=0.001):
super(B_Softmax, self).__init__()
self.b_init = tf.random_normal_initializer(b_init_mean, b_init_var)
self._out_shape = None
def build(self, input_shape):
self.b = tf.Variable(
initial_value = self.b_init(shape=(1,), dtype='float32'),
trainable=True
)
self._out_shape = input_shape
def call(self, inputs):
# This is an implementation of Softmax for batched inputs
# where the factor b is added to the exponents
nominators = tf.math.exp(self.b * inputs)
denominator = tf.reduce_sum(nominators, axis=1)
denominator = tf.squeeze(denominator)
denominator = tf.expand_dims(denominator, -1)
s = tf.divide(nominators, denominator)
return s
# @property
# def output_shape(self): # If I comment out this function, summary prints 'None'
# self.output_shape # If I leave this line, summary prints '?'
# return self._out_shape # If the above line is commented out, summary prints '10' (correctly)
# but the same error is triggered in all three cases
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Variables
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
A = tf.constant([[1,2,3], [7,5,6]], dtype="float32")
batch_size = 128
epochs = 15
input_dim = 5
num_classes = 1
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Dataset
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
start = 3
limit = 16
delta = 3
sample = tf.range( start, limit, delta )
sample = tf.cast( sample, dtype=tf.float32 )
sample = tf.constant( sample, shape=( 1, 1, 1, 5 ) )
dataset = tf.data.Dataset.from_tensor_slices(( sample, tf.constant( [0], shape=( 1, 1, 1, 1 ), dtype=tf.int64)))
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Model Initialize
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
layer = B_Softmax(1.0)
print( layer(A) )
model = tf.keras.Sequential([
tf.keras.layers.Dense(32, activation='relu', input_shape=(1, input_dim)),
tf.keras.layers.Dense(num_classes, activation="softmax"),
B_Softmax(1.0)
])
model.summary()
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Working
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
model.fit(dataset, batch_size=batch_size, epochs=epochs, validation_data=dataset)
輸出:
tf.Tensor(
[[0.09007736 0.24477491 0.6651477 ]
[0.66514784 0.09007736 0.24477486]], shape=(2, 3), dtype=float32)
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 1, 32) 192
dense_1 (Dense) (None, 1, 1) 33
b__softmax_1 (B_Softmax) None 1
=================================================================
Total params: 226
Trainable params: 226
Non-trainable params: 0
_________________________________________________________________
Epoch 1/15
1/1 [==============================] - 5s 5s/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 2/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 3/15
1/1 [==============================] - 0s 15ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 4/15
1/1 [==============================] - 0s 13ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 5/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 6/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 7/15
1/1 [==============================] - 0s 13ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 8/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 9/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 10/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 11/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 12/15
1/1 [==============================] - 0s 15ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 13/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 14/15
1/1 [==============================] - 0s 15ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 15/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
C:\Python310>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/531233.html
標籤:Python张量流喀拉斯
上一篇:圖表已斷開:無法在“input_20”層獲取張量Tensor("input_20:0",shape=(?,25,2),dtype=float32)的值
下一篇:NaN來自tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))
