2017-10-20 30 views
0

Je suis un débutant à l'apprentissage automatique et c'est l'une des premières tâches de ML réelles mises au défi.Comment trouver si un ensemble de données peut entraîner un réseau de neurones?

Certaines données expérimentales contiennent 512 fonctions booléennes indépendantes et un résultat booléen.

Il y a environ 1e6 enregistrements d'expériences réelles dans l'ensemble de données fourni.

Dans un exemple XOR classique, tous les 4 états possibles sur 4 sont nécessaires pour former NN. Dans mon cas, c'est seulement 2^(10-512) = 2^-505 qui est proche de zéro.

Je n'ai plus d'informations sur la nature des données, seulement ces (512 + 1) * 1e6 bits.

Essayé NN avec 1 couche cachée sur les données disponibles. La sortie du NN formé sur les échantillons, même à partir du jeu d'apprentissage, est toujours proche de 0, pas un seul proche de "1". Joué avec l'initialisation des poids, le taux d'apprentissage de descente de gradient.

Mon code utilisant tensorflow 1.3, Python 3. Extrait du modèle:

with tf.name_scope("Layer1"): 
    #W1 = tf.Variable(tf.random_uniform([512, innerN], minval=-2/512, maxval=2/512), name="Weights_1") 
    W1 = tf.Variable(tf.zeros([512, innerN]), name="Weights_1") 
    b1 = tf.Variable(tf.zeros([1]), name="Bias_1") 

    Out1 = tf.sigmoid(tf.matmul(x, W1) + b1) 

with tf.name_scope("Layer2"): 
    W2 = tf.Variable(tf.random_uniform([innerN, 1], minval=-2/512, maxval=2/512), name="Weights_2") 
    #W2 = tf.Variable(tf.zeros([innerN, 1]), name="Weights_2") 
    b2 = tf.Variable(tf.zeros([1]), name="Bias_2") 

    y = tf.nn.sigmoid(tf.matmul(Out1, W2) + b2) 

with tf.name_scope("Training"): 
    y_ = tf.placeholder(tf.float32, [None,1]) 

    cross_entropy = tf.reduce_mean(
     tf.nn.softmax_cross_entropy_with_logits(
      labels = y_, logits = y) 
    ) 

    train_step = tf.train.GradientDescentOptimizer(0.005).minimize(cross_entropy) 

with tf.name_scope("Testing"): 
    # Test trained model 
    correct_prediction = tf.equal(tf.round(y), tf.round(y_)) 
# ... 
# Train 
for step in range(500): 
    batch_xs, batch_ys = Datasets.train.next_batch(300, shuffle=False) 
    _, my_y, summary = sess.run([train_step, y, merged_summaries], 
     feed_dict={x: batch_xs, y_: batch_ys}) 

je soupçonne que deux cas:

  1. ma faute - mauvaise mise en œuvre NN, mauvaise architecture;
  2. mauvaises données. Par rapport à l'exemple XOR, des données d'apprentissage incomplètes entraîneraient un NN défaillant. Cependant, les exemples d'entraînement fournis à la NN formée sont supposés donner des prédictions correctes, n'est-ce pas?

Comment évaluer s'il est possible de former du tout sur les données fournies un réseau de neurones (un perceptron 2 couches) pour prévoir le résultat? Un cas d'ensemble acceptable serait l'exemple XOR. Opposé à un bruit aléatoire.

+0

Je ne serais pas enclin à utiliser un réseau de neurones pour les données qui consistent uniquement en entrées booléennes. –

+0

@GordonLinoff Quelle est la meilleure approche dans ce cas? – Serge

+2

Je voudrais commencer avec un arbre de décision et passer rapidement aux forêts aléatoires. Selon la nature des données, vous pourriez avoir de la chance avec les SVM (selon la structure des données), mais je pense que les forêts aléatoires feraient probablement un meilleur travail. –

Répondre

1

Il existe seulement des moyens ad hoc de savoir s'il est possible d'apprendre une fonction avec un réseau différentiable à partir d'un ensemble de données. Cela dit, ces moyens ad hoc fonctionnent habituellement. Par exemple, le réseau devrait être capable de surpasser l'ensemble d'entraînement sans aucune régularisation.

Une technique courante pour évaluer cela consiste à adapter le réseau uniquement à un sous-ensemble de l'ensemble de données complet. Vérifiez que le réseau peut s'adapter à cela, puis augmentez la taille du sous-ensemble et augmentez également la taille du réseau. Malheureusement, décider d'ajouter des couches supplémentaires ou d'ajouter plus d'unités dans un calque caché est une décision arbitraire que vous devrez prendre.

Cependant, en regardant votre code, il y a quelques choses qui pourraient aller mal ici:

  1. sont vos sorties symétriques? Je veux dire par là, avez-vous le même nombre de 1 que de 0 dans les cibles du jeu de données?
  2. Votre initialisation dans la première couche est tous des zéros, le dégradé à ce sera zéro, donc elle ne peut rien apprendre (bien que vous ayez une initialisation réelle au-dessus de celle-ci commentée).
  3. Les non linéarités sigmoïdes sont plus difficiles à optimiser que les non-linéarités plus simples, comme les ReLU.

Je vous recommande d'utiliser le built-in definitions for layers dans tensorflow de ne pas se soucier de l'initialisation, et le passage à Relus dans toutes les couches cachées (dont vous avez besoin sigmoïde à la sortie de votre cible booléenne). Enfin, l'apprentissage en profondeur n'est pas vraiment très bon dans la plupart des problèmes d'apprentissage machine "sac de fonctionnalités" parce qu'ils manquent de structure. Par exemple, l'ordre des fonctionnalités n'a pas d'importance. D'autres méthodes fonctionnent souvent mieux, mais si vous voulez vraiment utiliser l'apprentissage en profondeur, vous pouvez regarder this recent paper, montrant des performances améliorées en utilisant simplement une initialisation de non-linéarité et de poids très spécifique (changer 4 lignes dans votre code ci-dessus).

+0

1. les sorties sont équilibrées, vérifiées. 2. bien sûr, j'ai aussi essayé avec random normal random; Essayer une approche de forêt aléatoire maintenant, cela prend longtemps. En attente des premiers résultats, le CPU est chargé à 100% et les ventilateurs tournent à haute voix. – Serge

+0

Vous pourriez vouloir essayer Naive Bayes, étant donné que vous avez des entrées et des cibles booléennes. Il fonctionnera beaucoup plus rapidement ([forme fermée et temps linéaire] (https://en.wikipedia.org/wiki/Naive_Bayes_classifier)) que la forêt aléatoire, et est optimal dans les hypothèses d'indépendance conditionnelle. –

+0

Merci encore! La forêt aléatoire a fini par donner une lamentable précision de 0.5239 après ~ 1 heure de chauffage CPU. [Testé les Naive Bayes] (https://gist.github.com/sergiks/f3197087b53eeca153b9c4cad3e25a7e), qui a atteint une précision de 0,47. Soit je fais quelque chose de mal ou les données ne sont pas suicidaires pour les algorithmes ML. – Serge