我想为粒子物理设置一个神经网络。我将评估假设有2000个事件,每个事件中粒子的数量是可变的,但每个粒子有5个变量,因此形状将是(2000, 粒子数量, 5)。目前我设置了一个形状为(2000,500,5)的张量,对于第二维度中不存在的粒子的变量只是0。但我认为这是误导性的,因为即使网络的准确性没有提高,它也会提升准确性。特别是当我在寻找二进制输出时。现在我需要一个多类别、单标签的分类。我如何为可变输入维度设置层?我的第一种方法是否走错了方向?
model = tf.keras.models.Sequential()model.add(tf.keras.Input(shape=(500,5)))model.add(tf.keras.layers.Dense(500*5, activation="relu"))model.add(tf.keras.layers.Dense(1,activation="softmax"))model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])model.fit(INPUT, OUTPUT, epochs=10, batch_size=1)
回答:
为什么你可能需要另一种架构
读了你的问题陈述后,听起来你是在对最多500个粒子进行模拟,每个粒子都有类似于x, y, dx, dy和质量属性(每个粒子的5个变量)。
如果我要手动解决一个二维的500粒子模拟问题,我可能会在二维中画出这些粒子,因为对于这个问题,二维格式是有意义的。另一方面,如果我们只是给某人一个包含500行和5列数字的电子表格,而不告诉他们这意味着什么,只是告诉他们自己弄清楚,我打赌他们会很难理解。
基于这种直觉,再加上现代机器学习在图像和二维数据方面的表现特别好,我建议将你的数据表示为一个二维网格,或许是一个128x128x3的网格,其中3个值是该网格空间中的总dx, dy和质量。这样,你就可以拥有任意数量的粒子,或少量的粒子。
粒子将与它们邻域中的其他粒子相互作用,卷积将非常有助于这一点。
model = tf.keras.models.Sequential()model.add(tf.keras.Input(shape=(128,128,3)))model.add(tf.keras.layers.Conv2D(16, 5, activation="tanh", padding="same"))model.add(tf.keras.layers.MaxPool2D(2)) # 64x54model.add(tf.keras.layers.Conv2D(16, 5, activation="tanh", padding="same"))model.add(tf.keras.layers.MaxPool2D(2)) # 32x32model.add(tf.keras.layers.Conv2D(16, 5, activation="tanh", padding="same"))model.add(tf.keras.layers.MaxPool2D(2)) # 16x16model.add(tf.keras.layers.Conv2D(16, 5, activation="tanh", padding="same"))model.add(tf.keras.layers.MaxPool2D(2)) # 8x8model.add(tf.keras.layers.Conv2D(16, 5, activation="tanh", padding="same"))model.add(tf.keras.layers.MaxPool2D(2)) # 4x4model.add(tf.keras.layers.Conv2D(16, 4, activation="tanh", padding="valid"))model.add(tf.keras.layers.Conv2D(2, 1, activation="softmax", padding="same"))model.add(tf.keras.layers.Flatten())model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])model.fit(INPUT, OUTPUT, epochs=10)
你的输出现在是对两个类别的softmax。你可以训练它来回答类似这样的问题:是否有两个粒子靠得很近,是否有三个粒子靠得很近,总质量是否超过42。它可能无法回答类似的问题:总角速度是否是顺时针的,所有的粒子最终是否会碰撞。
为什么密集层可能不会起作用
让我们再看看你的当前架构,看看它需要学习什么才能表现得好
2) model.add(tf.keras.Input(shape=(500,5)))3) model.add(tf.keras.layers.Dense(500*5, activation="relu"))4) model.add(tf.keras.layers.Dense(1,activation="softmax"))
如果我们看第3行,它接受500×5的输入(2,500个浮点数)并对其进行全连接的密集操作,输出2,500个浮点数。这是一个包含2,500 x 2,500参数的矩阵=6,250,000个参数,每个输入到输出的组合都有一个参数。它必须学习这些参数中的每一个。为了引起对这有多难的注意,想象一下你只有4个粒子,A, B, C, 和D的情况。
如果你用这样的顺序训练模型:ABCD,ACDB和ADBC,它将无法泛化到新的情况BACD。它从未见过B在第一位,而密集网络没有机制来泛化这个问题。
与上面的卷积示例相比。每个卷积仅学习如何将2D世界的一个5×5补丁映射到下一层较小的层。每个5×5补丁仅接受5×5上的16个参数,并将其映射到16个输出,总共每个层6,400个参数。有7个卷积层(最后几个较小,但我们忽略这一点),大约是7 * 6,400 = 44,000个参数。远低于600万。此外,这些参数在每个位置上一次又一次地被重用,如果它们在右上角“学习”了某些东西,这种知识将应用于图像的每个部分。
你可以尝试打乱你的数据,使第2行的密集层起作用,打乱ABCD的顺序,以便你训练每个粒子在每个位置。对于500个位置,组合的数量是500的阶乘,因此计算是不切实际的。