Pourquoi ce modèle ne converge pas dans les keras?
-
31-10-2019 - |
Question
Cette affaire a une histoire sous-jacente, mais je l'ai essentiellement réprimandée à l'exemple le plus simple possible que je pourrais.
Présentez-nous essentiellement que j'ai jusqu'à 1000 nœuds et chaque nœud représenté par un vecteur petit (ce cas est un vecteur à 3 cellules) et je concatenate et représente ces nœuds comme un vecteur d'entrée 3 * 1000 rembourré et besoin de découvrir qui L'un est plus approprié. Le modèle essaie donc de prédire 1000 valeurs flottantes, une pour chaque nœud.
Imaginons que la fonction pour noter les nœuds est ce code arbitraire:
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))
Et essentiellement, mon modèle est censé apprendre cette fonction plus un argmax pour trouver le nœud qui a le score le plus élevé. Cela me ressemble à un problème assez simple par rapport aux problèmes que j'ai résolus jusqu'à présent (mais c'est différent aussi).
Ma question est donc pourquoi ce modèle ne converge-t-il pas? Je pense que cela pourrait être dû à sa différenciation mais vraiment un peu perdu et a commencé à douter de tout ce que je sais sur NN (ce qui n'est pas beaucoup).
Voici le code de repro:
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)
Pas de solution correcte