这个案例有一个潜在的故事,但我基本上把它归结为尽可能简单的可重现的例子。
基本上让我们认为我有多达 1000 个节点,每个节点由一个小的(本例是一个 3 单元向量)向量表示,我将这些节点连接起来并表示为一个填充的 3*1000 输入向量,需要找出哪个一个更合适。所以模型试图预测 1000 个浮点值,每个节点一个。
让我们想象对节点进行评分的函数是这个任意代码:
def score_vector(v):
a, b, c = tuple(v)
if a == 0 or b == 0 or a - c < 2:
return float(Defs.INVALID_SCORE)
return float(a * math.sqrt(a - c) / math.log(b + 2, 5))
基本上我的模型应该学习这个函数加上一个 argmax 来找到得分最高的节点。与我迄今为止解决的问题相比,这在我看来是一个非常简单的问题(但它也不同)。
所以我的问题是为什么这个模型不收敛?我认为这可能是由于它的可区分性,但真的有点迷失并开始怀疑我对 NN 的了解(这不是很多)。
这是重现代码:
import numpy as np
import math
from keras import Sequential, Input
from keras.layers import Flatten, Activation, Dense
from keras.optimizers import Adam
class Defs:
VECTOR_SIZE=3
NODE_COUNT=1000
MAX_REAL_NODE_COUNT=400
MIN_REAL_NODE_COUNT=20
INVALID_SCORE=0
def score_vector(v):
a, b, c = tuple(v)
if a == 0 or b == 0 or a - c < 2:
return float(Defs.INVALID_SCORE)
return float(a * math.sqrt(a - c) / math.log(b + 2, 5))
def build_vector():
a = np.random.randint(1, 100)
c = np.random.randint(1, 50) if np.random.choice([False, True, True]) else 0
b = 0 if c == 0 else np.random.randint(c, c*3)
return [float(a), float(b), float(c)]
def build_vectorset_score():
n = np.random.randint(Defs.MIN_REAL_NODE_COUNT, Defs.MAX_REAL_NODE_COUNT)
vectorset = []
for i in range(0, n):
vectorset += build_vector()
# pad it
vectorset += [0. for i in range((Defs.NODE_COUNT-n) * Defs.VECTOR_SIZE)]
scores = [score_vector(vectorset[i*Defs.VECTOR_SIZE:(i+1)*Defs.VECTOR_SIZE]) for i in range(0, Defs.NODE_COUNT)]
index = np.argmax(scores)
scores = [1. if index == i else 0. for i in range(0, len(scores))]
return vectorset, scores
def build_model():
model = Sequential()
model.add(Dense(Defs.VECTOR_SIZE * Defs.NODE_COUNT, input_dim=Defs.VECTOR_SIZE * Defs.NODE_COUNT, activation='relu'))
model.add(Dense(Defs.NODE_COUNT, activation='relu'))
model.add(Dense(Defs.NODE_COUNT))
model.add(Activation('softmax'))
print(model.summary())
model.compile(loss="categorical_crossentropy",
optimizer=Adam(lr=0.001), metrics=['categorical_accuracy'])
return model
if __name__ == '__main__':
SAMPLE_SIZE = 1 * 1000
X = []
Y = []
for i in range(0, SAMPLE_SIZE):
x, y = build_vectorset_score()
X.append(np.array(x))
Y.append(np.array(y))
model = build_model()
model.fit(np.array(X),
np.array(Y), batch_size=100, epochs=200, verbose=1)