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

Licencié sous: CC-BY-SA avec attribution
scroll top