2

Je suis en train d'écrire un MLP avec tensorflow (que je viens de commencer à apprendre, donc mes excuses pour le code!) Pour multivariée REGRESSION (pas MNIST, s'il vous plaît). Voici mon MWE, où j'ai choisi d'utiliser le jeu de données linnerud de sklearn. (En réalité, j'utilise un ensemble de données beaucoup plus grand, ici aussi je n'utilise qu'une seule couche parce que je voulais réduire le MWE, mais je peux ajouter, si nécessaire). En passant, j'utilise shuffle = False dans train_test_split parce que, en réalité, je travaille avec un jeu de données de séries temporelles.tensorflow réseau de neurones à plusieurs couches Perceptron pour la régression par exemple

MWE

######################### import stuff ########################## 
import numpy as np 
import pandas as pd 
import tensorflow as tf 
from sklearn.datasets import load_linnerud 
from sklearn.model_selection import train_test_split 


######################## prepare the data ######################## 
X, y = load_linnerud(return_X_y = True) 
X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle = False, test_size = 0.33) 


######################## set learning variables ################## 
learning_rate = 0.0001 
epochs = 100 
batch_size = 3 


######################## set some variables ####################### 
x = tf.placeholder(tf.float32, [None, 3], name = 'x') # 3 features 
y = tf.placeholder(tf.float32, [None, 3], name = 'y') # 3 outputs 

# input-to-hidden layer1 
W1 = tf.Variable(tf.truncated_normal([3,300], stddev = 0.03), name = 'W1') 
b1 = tf.Variable(tf.truncated_normal([300]), name = 'b1') 

# hidden layer1-to-output 
W2 = tf.Variable(tf.truncated_normal([300,3], stddev = 0.03), name= 'W2')  
b2 = tf.Variable(tf.truncated_normal([3]), name = 'b2') 


######################## Activations, outputs ###################### 
# output hidden layer 1 
hidden_out = tf.nn.relu(tf.add(tf.matmul(x, W1), b1)) 

# total output 
y_ = tf.nn.relu(tf.add(tf.matmul(hidden_out, W2), b2)) 


####################### Loss Function ######################### 
mse = tf.losses.mean_squared_error(y, y_) 


####################### Optimizer  ######################### 
optimizer = tf.train.GradientDescentOptimizer(learning_rate = learning_rate).minimize(mse) 


###################### Initialize, Accuracy and Run ################# 
# initialize variables 
init_op = tf.global_variables_initializer() 

# accuracy for the test set 
accuracy = tf.reduce_mean(tf.square(tf.subtract(y, y_))) # or could use tf.losses.mean_squared_error 

#run 
with tf.Session() as sess: 
    sess.run(init_op) 
    total_batch = int(len(y_train)/batch_size) 
    for epoch in range(epochs): 
     avg_cost = 0 
     for i in range(total_batch): 
       batch_x, batch_y = X_train[i*batch_size:min(i*batch_size + batch_size, len(X_train)), :], y_train[i*batch_size:min(i*batch_size + batch_size, len(y_train)), :] 
       _, c = sess.run([optimizer, mse], feed_dict = {x: batch_x, y: batch_y}) 
       avg_cost += c/total_batch 
     print('Epoch:', (epoch+1), 'cost =', '{:.3f}'.format(avg_cost)) 
    print(sess.run(mse, feed_dict = {x: X_test, y:y_test})) 

Ceci affiche quelque chose comme ça

... 
Epoch: 98 cost = 10992.617 
Epoch: 99 cost = 10992.592 
Epoch: 100 cost = 10992.566 
11815.1 

Alors, évidemment, il y a quelque chose de mal. Je soupçonne que le problème est soit dans la fonction de coût/précision ou dans la façon dont j'utilise des lots, mais je ne peux pas tout à fait comprendre ..

+0

peut-être l'un des problèmes est que je n'utilise pas la régularisation? –

+0

J'ai essayé de faire quelque chose comme 'regularizer1 = tf.nn.l2_loss (W1)' et 'regularizer2 = tf.nn.l2_loss (W2)' puis de les ajouter à la fonction de perte 'mse = tf.losses.mean_squared_error (y, y_) + 0.001 * regularizer1 + 0.001 * regularizer2' mais ça ne fait qu'empirer .. –

Répondre

1

Autant que je peux voir, le modèle est en train d'apprendre. J'ai essayé de régler certains des hyperparamètres (le plus important - le taux d'apprentissage et la taille de la couche cachée) et obtenu de bien meilleurs résultats. Voici le code complet:

######################### import stuff ########################## 
import numpy as np 
import pandas as pd 
import tensorflow as tf 
from sklearn.datasets import load_linnerud 
from sklearn.model_selection import train_test_split 

######################## prepare the data ######################## 
X, y = load_linnerud(return_X_y=True) 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, shuffle=False) 

######################## set learning variables ################## 
learning_rate = 0.0005 
epochs = 2000 
batch_size = 3 

######################## set some variables ####################### 
x = tf.placeholder(tf.float32, [None, 3], name='x') # 3 features 
y = tf.placeholder(tf.float32, [None, 3], name='y') # 3 outputs 

# hidden layer 1 
W1 = tf.Variable(tf.truncated_normal([3, 10], stddev=0.03), name='W1') 
b1 = tf.Variable(tf.truncated_normal([10]), name='b1') 

# hidden layer 2 
W2 = tf.Variable(tf.truncated_normal([10, 3], stddev=0.03), name='W2') 
b2 = tf.Variable(tf.truncated_normal([3]), name='b2') 

######################## Activations, outputs ###################### 
# output hidden layer 1 
hidden_out = tf.nn.relu(tf.add(tf.matmul(x, W1), b1)) 

# total output 
y_ = tf.nn.relu(tf.add(tf.matmul(hidden_out, W2), b2)) 

####################### Loss Function ######################### 
mse = tf.losses.mean_squared_error(y, y_) 

####################### Optimizer  ######################### 
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(mse) 

###################### Initialize, Accuracy and Run ################# 
# initialize variables 
init_op = tf.global_variables_initializer() 

# accuracy for the test set 
accuracy = tf.reduce_mean(tf.square(tf.subtract(y, y_))) # or could use tf.losses.mean_squared_error 

# run 
with tf.Session() as sess: 
    sess.run(init_op) 
    total_batch = int(len(y_train)/batch_size) 
    for epoch in range(epochs): 
    avg_cost = 0 
    for i in range(total_batch): 
     batch_x, batch_y = X_train[i * batch_size:min(i * batch_size + batch_size, len(X_train)), :], \ 
         y_train[i * batch_size:min(i * batch_size + batch_size, len(y_train)), :] 
     _, c = sess.run([optimizer, mse], feed_dict={x: batch_x, y: batch_y}) 
     avg_cost += c/total_batch 
    if epoch % 10 == 0: 
     print 'Epoch:', (epoch + 1), 'cost =', '{:.3f}'.format(avg_cost) 
    print sess.run(mse, feed_dict={x: X_test, y: y_test}) 

Sortie:

Epoch: 1901 cost = 173.914 
Epoch: 1911 cost = 171.928 
Epoch: 1921 cost = 169.993 
Epoch: 1931 cost = 168.110 
Epoch: 1941 cost = 166.277 
Epoch: 1951 cost = 164.492 
Epoch: 1961 cost = 162.753 
Epoch: 1971 cost = 161.061 
Epoch: 1981 cost = 159.413 
Epoch: 1991 cost = 157.808 
482.433 

Je pense que vous pouvez accorder encore plus loin, mais il n'a pas de sens puisque les données est si faible. Je n'ai pas expérimenté avec la régularisation, mais je suis sûr que vous en aurez besoin L2 reg ou dropout pour éviter le surajustement.

+0

Merci! Auriez-vous d'autres conseils? En outre, pensez-vous qu'il serait utile d'utiliser la similitude de cosinus au lieu de produit scalaire? Par exemple (je ne suis même pas sûr que ce soit la façon correcte de le faire dans tensorflow) 'hidden_out = tf.nn.relu (tf.add (tf.divide (tf.matmul (x, W1), tf.multiply (tf .norm (x), tf.norm (W1))), b1)) 'et' y_ = tf.nn.relu (tf.add (tf.divide (tf.matmul (hidden_out, W2), tf.multipli (tf.norm (hidden_out), tf.norm (W2)), b2)) ' –

+1

Pour l'implémentation, voir https://stackoverflow.com/q/43357732/712995 – Maxim

+1

@Euler_Salter Il est difficile de donner des conseils spécifiques sans regarder à des données de séries temporelles réelles (je crois que votre objectif n'est pas un ensemble de données Linnerrud). En général, je considérerais ajouter la couche de batchnorm et/ou la perte, qui aide contre le surajustement et tend également à apprendre plus rapidement. Considérez d'autres fonctions d'activation: ELU, SELU. Lorsque vous atteignez une limite stricte avec 1 couche cachée, il est peut-être temps de passer à un réseau profond. Mais chaque modèle nécessite un examen attentif, avant de prendre des décisions - comment les gradients circulent, quelle est la distribution des activations, etc – Maxim