我正在嘗試對基礎 Keras 層進行子類化,以創建一個層,該層將通過輸出 2 個張量的點積來合并跳過連接的 2 層的 rank 1 輸出。2 個傳入的張量是由神經架構搜索演算法決議的密集層創建的,該演算法隨機選擇密集單元的數量,從而選擇 2 個張量的長度。當然,這些通常不會具有相同的長度。我正在嘗試一個實驗,看看是否通過在較短的張量上附加具有數學意義的插補來將它們投射到相同的長度:[例如平均值 | 中位數 | 斜邊 | COS | ...等]然后通過點積將它們合并將優于 Add 或 Concatenate 合并策略。要使它們具有相同的長度:
我嘗試了整體策略:
- 找到較短的張量。
- 將其傳遞給 tf.reduce_mean() (為了討論,將生成的均值別名為“rm”)。
- 為范圍內的 rm 創建一個 [rm 串列(['較長張量和較短張量的長度差異'])。如有必要,轉換為張量。
- [墊| 連接]較短的張量與上述操作的結果,使其長度相等。
這是我遇到一堵死墻的地方:
由于 tf 操作 reduce_mean 回傳一個形狀設定為 None(不假定為 1 的標量)的未來,它們處于形狀為“(None,)”的狀態,tf.keras.layers .Dot 層拒絕攝取并拋出 ValueError,因為它認為它們的長度不同,盡管它們總是:
KerasTensor(type_spec=TensorSpec(shape=(None,), dtype=tf.float32, name=None), name='tf.math.reduce_mean/Mean:0', description="created by layer 'tf.math.reduce_mean'")
ValueError: A 連接 layer should be called on a list of at least 1 input. Received: input_shape=[[(None,), (None,)], [(None, 3)]]
我的代碼(在包/模塊中):
import tensorflow as tf
import numpy as np
class Linear1dDot(tf.keras.layers.Layer):
def __init__(self, input_dim=None,):
super(Linear1dDot, self).__init__()
def __call__(self, inputs):
max_len = tf.reduce_max(tf.Variable(
[inp.shape[1] for inp in inputs]))
print(f"max_len:{max_len}")
for i in range(len(inputs)):
inp = inputs[i]
print(inp.shape)
inp_lenght = inp.shape[1]
if inp_lenght < max_len:
print(f"{inp_lenght} < {max_len}")
# pad_with = inp.reduce_mean()
pad_with = tf.reduce_mean(inp, axis=1)
print(pad_with)
padding = [pad_with for _ in range(max_len - inp_lenght)]
inputs[i] = tf.keras.layers.concatenate([padding, [inp]])
# inputs[i] = tf.reshape(
# tf.pad(inp, padding, mode="constant"), (None, max_len))
print(inputs)
return tf.keras.layers.Dot(axes=1)(inputs)
...
# Alternatively substituting the last few lines with:
pad_with = tf.reduce_mean(inp, axis=1, keepdims=True)
print(pad_with)
padding = tf.keras.layers.concatenate(
[pad_with for _ in range(max_len - inp_lenght)])
inputs[i] = tf.keras.layers.concatenate([padding, [inp]])
# inputs[i] = tf.reshape(
# tf.pad(inp, padding, mode="constant"), (None, max_len))
print(inputs)
return tf.keras.layers.Dot(axes=1)(inputs)
......以及無數其他嘗試的排列......
有誰知道解決方法或有任何建議?(除了“不要嘗試這樣做。”)?
在此模塊包的父檔案夾中...
測驗以模擬跳過連接合并到當前層:
from linearoneddot.linear_one_d_dot import Linear1dDot
x = tf.constant([1, 2, 3, 4, 5])
y = tf.constant([0, 9, 8])
inp1 = tf.keras.layers.Input(shape=3)
inp2 = tf.keras.layers.Input(shape=5)
xd = tf.keras.layers.Dense(3, "relu")(inp1)
yd = tf.keras.layers.Dense(5, 'elu')(inp2)
combined = Linear1dDot()([xd, yd]) # tf.keras.layers.Dot(axes=1)([xd, yd])
z = tf.keras.layers.Dense(2)(combined)
model = tf.keras.Model(inputs=[inp1, inp2], outputs=z) # outputs=z)
print(model([x, y]))
print(model([np.random.random((3, 3)), np.random.random((3, 5))]))
有誰知道一種解決方法,可以將較短的 1 階張量的平均值作為標量,然后我可以將其附加/填充到較短的張量到設定的預期長度(與較長的張量長度相同)。
uj5u.com熱心網友回復:
試試這個,希望這能奏效,嘗試用 1 填充最短的輸入,然后將其與輸入連接,然后取點積,最后減去添加到點積中的額外輸入......
class Linear1dDot(tf.keras.layers.Layer):
def __init__(self,**kwargs):
super(Linear1dDot, self).__init__()
def __call__(self, inputs):
_input1 , _input2 = inputs
_input1_shape = _input1.shape[1]
_input2_shape = _input2.shape[1]
difference = tf.math.abs(_input1_shape - _input2_shape)
padded_input = tf.ones(shape=(1,difference))
if _input1_shape > _input2_shape:
padded_tensor = tf.concat([_input2 ,padded_input],axis=1)
scaled_output = tf.keras.layers.Dot(axes=1)([padded_tensor, _input1])
scaled_output -= tf.reduce_sum(padded_input)
return scaled_output
else:
padded_tensor = tf.concat([_input1 , padded_input],axis=1)
scaled_output = tf.keras.layers.Dot(axes=1)([padded_tensor, _input2])
scaled_output -= tf.reduce_sum(padded_input)
return scaled_output
x = tf.constant([[1, 2, 3, 4, 5, 9]])
y = tf.constant([[0, 9, 8]])
inp1 = tf.keras.layers.Input(shape=3)
inp2 = tf.keras.layers.Input(shape=5)
xd = tf.keras.layers.Dense(5, "relu")(x)
yd = tf.keras.layers.Dense(3, 'elu')(y)
combined = Linear1dDot()([xd, yd]) # tf.keras.layers.Dot(axes=1)([xd, yd])
輸出:
<tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[4.4694786]], dtype=float32)>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/525321.html
