我想使用 Functional API 创建一个 Tensorflow 神经网络模型,但我不确定如何将输入分成两个。我想做这样的事情:给定一个输入,它的前半部分进入神经网络的第一部分,它的后半部分进入第二部分,每个输入通过层,直到它们连接起来,通过另一层,然后最终到达输出。我想到了类似下面的代码片段,以及一个快速草图。
from tensorflow.keras.layers import Dense
def define_model(self):
input1 = tf.keras.Input(shape=(4,)) #input is a 1D vector containing 7 elements, split as 4 and 3
input2 = tf.keras.Input(shape=(3,))
layer1_1 = Dense(4, activation=tf.nn.leaky_relu)(input1)
layer2_1 = Dense(4, activation=tf.nn.leaky_relu)(layer1_1)
layer1_2 = Dense(4, activation=tf.nn.leaky_relu)(input2)
layer2_2 = Dense(3, activation=tf.nn.leaky_relu)(layer1_2)
concat_layer = tf.keras.concatenate([layer2_1,layer2_2], axis = 0)
layer3 = Dense(6, activation=tf.nn.leaky_relu)(concat_layer)
output = Dense(4)(layer3) #no activation
self.model = tf.keras.Model(inputs = [input1,input2],outputs = output)
self.model.compile(loss = 'mean_squared_error', optimizer = 'rmsprop')
return self.model
首先,我应该在这个模型中添加任何 Dropout 或 BatchNormalization 层吗?
此外,输入数组的前 4 个元素是二进制的(如 [1,0,0,1] 或 [0,1,1,1]),而其他 3 个元素可以是任何实数。考虑到第一个使用 0
编辑:我在训练期间遇到问题。假设我想像这样训练模型(值并不重要,重要的是数据类型):
#this snippet generates training data - nothing real, just test examples. Also, I changed the output layer from 4 elements to just 1 to test it.
A1=[np.array([[1.,0,0,1]]),np.array([[0,1.,0]])]
B1=np.array([7])
c=np.array([[5,-4,1,-1],[2,3,-1]], dtype = object)
A2 = [[np.random.randint(2, size= [1,4]),np.random.randint(2, size= [1,3])] for i in range(1000)]
B2 = np.array([np.sum(A[i][0]*c[0])+np.sum(A[i][1]*c[1]) for i in range(1000)])
model.fit(A1,B1, epochs = 50, verbose=False) #this works!
model.fit(A2,B2, epochs = 50, verbose=False) #but this doesn't.
最终编辑:这里是 predict() 和 predict_on_batch() 函数。def predict(a,b):
pred = m.predict([a,b])
return pred
def predict_b(c,d):
preds = m.predict_on_batch([c,d])
return preds
#a, b, c and d must look like this:
a = [np.array([0,1,0,1])]
b = [np.array([0,0,1])]
c = [np.array([1, 0, 0, 1]),
np.array([0, 1, 1, 1]),
np.array([0, 1, 0, 0]),
np.array([1, 0, 0, 0]),
np.array([0, 0, 1, 0])]
d = [np.array([1, 0, 1]),
np.array([0, 0, 1]),
np.array([0, 1, 1]),
np.array([1, 1, 1]),
np.array([0, 0, 0])]
#notice that all of those should follow the same pattern, which is a list of arrays.
其余代码在 M. Innat 的回答下。
最佳答案
您的代码存在一些问题。我将尝试回答这里的主要问题,并丢弃一些附带问题,例如您是否应该使用 Dropout
或 BatchNormalization
是否在您的模型中添加图层,因为这完全超出了您的主要问题的范围,而且也不相关。
如果您尝试构建模型,请使用 m = define_model()
,我很确定你会遇到以下错误:
layer2_1 = Dense(4, activation=tf.nn.leaky_relu)(layer1_1)
layer2_2 = Dense(3, activation=tf.nn.leaky_relu)(layer1_2)
concat_layer = tf.keras.layers.concatenate([layer2_1, layer2_2], axis = 0)
ValueError: A `Concatenate` layer requires inputs with matching shapes
except for the concat axis. Got inputs shapes: [(None, 4), (None, 3)]
正确 axis
默认情况下应该是 -1
或 1
但不是 0
同时连接不相同的形状(例如 Dense(4)
、 Dense(3)
)。您可以设置相同的输出形状,即 Dense(3)
至 Dense(4)
或设置 axis = 1
.让我们选择一个(根据您的抽奖):from tensorflow.keras import Input
from tensorflow.keras import layers
def define_model():
input1 = Input(shape=(4,))
input2 = Input(shape=(3,))
layer1_1 = layers.Dense(4, activation=tf.nn.leaky_relu)(input1)
layer2_1 = layers.Dense(4, activation=tf.nn.leaky_relu)(layer1_1)
layer1_2 = layers.Dense(4, activation=tf.nn.leaky_relu)(input2)
layer2_2 = layers.Dense(3, activation=tf.nn.leaky_relu)(layer1_2)
concat_layer = layers.concatenate([layer2_1, layer2_2], axis = 1)
layer3 = layers.Dense(6, activation=tf.nn.leaky_relu)(concat_layer)
output = layers.Dense(4)(layer3)
model = tf.keras.Model(inputs = [input1,input2],outputs = output)
model.compile(loss = 'mean_squared_error', optimizer = 'rmsprop')
return model
m = define_model()
更多详细信息,请参阅选择 axis
的输出形状参数:x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
print(x1.shape, x2.shape)
# (5, 8) (5, 8)
# using axis = 0
concatted = tf.keras.layers.Concatenate(axis=0)([x1, x2])
concatted.shape
# TensorShape([10, 8])
# using axis = 1
concatted = tf.keras.layers.Concatenate(axis=1)([x1, x2])
concatted.shape
# TensorShape([5, 16])
测试模型
适合您的输入:
A1_i = np.array([[1.,0, 0,1]])
A1_j = np.array([[0, 1., 0]])
B1 = np.array([4])
print(type(A1_i), type(A1_j), type(B1))
print(A1_i.shape, A1_j.shape, B1.shape)
m.fit([A1_i, A1_j], B1, epochs = 2, verbose=2)
<class 'numpy.ndarray'> <class 'numpy.ndarray'> <class 'numpy.ndarray'>
(1, 4) (1, 3) (1,)
Epoch 1/2
584ms/step - loss: 15.9902
Epoch 2/2
4ms/step - loss: 15.8900
<tensorflow.python.keras.callbacks.History at 0x7fb1b484b890>
其他对您不起作用的部分有几个问题,第一个模型输入应该是 numpy
数组,不是 list
.第二个问题来自建模部分,它连接起来。但是,正确的方法应该如下:c = np.array([[5,-4,1,-1],[2,3,-1]], dtype = object)
A2_i = np.random.randint(10, size = [100,4])
A2_j = np.random.randint(10, size = [100,3])
B2 = np.array( [np.sum(A2_i[i][0]*c[0]) +
np.sum(A2_j[i][1]*c[1]) for i in range(100)])
print(type(A2_i), type(A2_j), type(B2))
print(A2_i.shape, A2_j.shape, B2.shape)
m.fit([A2_i, A2_j], B2, epochs = 2, verbose=2)
<class 'numpy.ndarray'> <class 'numpy.ndarray'> <class 'numpy.ndarray'>
(100, 4) (100, 3) (100,)
Epoch 1/2
4ms/step - loss: 683.9537
Epoch 2/2
4ms/step - loss: 681.0673
<tensorflow.python.keras.callbacks.History at 0x7fb1600a8d50>
关于python - 如何构建具有多个输入的 Tensorflow 模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67171002/