Luc*_*ari 6 python deep-learning keras tensorflow
我想使用 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
Run Code Online (Sandbox Code Playgroud)
首先,我应该在这个模型中添加任何 Dropout 或 BatchNormalization 层吗?
此外,输入数组的前 4 个元素是二进制的(如 [1,0,0,1] 或 [0,1,1,1]),而其他 3 个元素可以是任何实数。考虑到第一个在 0<x<1 范围内使用输入操作,而第二个没有,我是否应该将神经网络的第一个“列”与第二个“列”区别对待?
听起来不错,但我无法真正测试它是否应该工作,因为我必须重新编写大量代码以生成足够的数据来训练它。我是朝着正确的方向前进还是应该做一些不同的事情?这段代码会起作用吗?
编辑:我在训练期间遇到问题。假设我想像这样训练模型(值并不重要,重要的是数据类型):
#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.
Run Code Online (Sandbox Code Playgroud)
最终编辑:这里是 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.
Run Code Online (Sandbox Code Playgroud)
其余代码在 M. Innat 的回答下。
您的代码存在一些问题。我将尝试在这里回答主要问题,并放弃一些附带问题,例如您是否应该在模型中使用Dropout
or层,因为这完全超出了您的主要问题的范围,而且也不相关。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)]
Run Code Online (Sandbox Code Playgroud)
正确的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()
Run Code Online (Sandbox Code Playgroud)
更多详细信息,请参阅选择参数的输出形状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])
Run Code Online (Sandbox Code Playgroud)
测试模型
适合您的输入:
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)
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
不适合您的其他部分有几个问题,第一个模型输入应该是数组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)
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
107 次 |
最近记录: |