Sto scrivendo un classificatore di rete neurale in TensorFlow/Python per il set di dati notMNIST. Ho implementato la regolarizzazione l2 e il dropout sui livelli nascosti. Funziona bene finché c'è un solo livello nascosto, ma quando ho aggiunto più livelli (per migliorare l'accuratezza), la funzione di perdita aumenta rapidamente ad ogni passaggio, diventando NaN dal punto 5. Ho provato a disattivare temporaneamente la regolarizzazione Dropout e L2, ma Ho lo stesso comportamento finché ci sono 2+ livelli. Ho anche riscritto il mio codice da zero (facendo alcuni refactoring per renderlo più flessibile), ma con gli stessi risultati. Il numero e la dimensione dei livelli è controllato da hidden_layer_spec
. Cosa mi manca?L'aggiunta di più livelli a TensorFlow fa sì che la funzione di perdita diventi Nan
#works for np.array([1024]) with about 96.1% accuracy
hidden_layer_spec = np.array([1024, 300])
num_hidden_layers = hidden_layer_spec.shape[0]
batch_size = 256
beta = 0.0005
epochs = 100
stepsPerEpoch = float(train_dataset.shape[0])/batch_size
num_steps = int(math.ceil(float(epochs) * stepsPerEpoch))
l2Graph = tf.Graph()
with l2Graph.as_default():
#with tf.device('/cpu:0'):
# Input data. For the training data, we use a placeholder that will be fed
# at run time with a training minibatch.
tf_train_dataset = tf.placeholder(tf.float32,
shape=(batch_size, image_size * image_size))
tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))
tf_valid_dataset = tf.constant(valid_dataset)
tf_test_dataset = tf.constant(test_dataset)
weights = []
biases = []
for hi in range(0, num_hidden_layers + 1):
width = image_size * image_size if hi == 0 else hidden_layer_spec[hi - 1]
height = num_labels if hi == num_hidden_layers else hidden_layer_spec[hi]
weights.append(tf.Variable(tf.truncated_normal([width, height]), name = "w" + `hi + 1`))
biases.append(tf.Variable(tf.zeros([height]), name = "b" + `hi + 1`))
print(`width` + 'x' + `height`)
def logits(input, addDropoutLayer = False):
previous_layer = input
for hi in range(0, hidden_layer_spec.shape[0]):
previous_layer = tf.nn.relu(tf.matmul(previous_layer, weights[hi]) + biases[hi])
if addDropoutLayer:
previous_layer = tf.nn.dropout(previous_layer, 0.5)
return tf.matmul(previous_layer, weights[num_hidden_layers]) + biases[num_hidden_layers]
# Training computation.
train_logits = logits(tf_train_dataset, True)
l2 = tf.nn.l2_loss(weights[0])
for hi in range(1, len(weights)):
l2 = l2 + tf.nn.l2_loss(weights[0])
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(train_logits, tf_train_labels)) + beta * l2
# Optimizer.
global_step = tf.Variable(0) # count the number of steps taken.
learning_rate = tf.train.exponential_decay(0.5, global_step, int(stepsPerEpoch) * 2, 0.96, staircase = True)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
# Predictions for the training, validation, and test data.
train_prediction = tf.nn.softmax(train_logits)
valid_prediction = tf.nn.softmax(logits(tf_valid_dataset))
test_prediction = tf.nn.softmax(logits(tf_test_dataset))
saver = tf.train.Saver()
with tf.Session(graph=l2Graph) as session:
tf.initialize_all_variables().run()
print("Initialized")
for step in range(num_steps):
# Pick an offset within the training data, which has been randomized.
# Note: we could use better randomization across epochs.
offset = (step * batch_size) % (train_labels.shape[0] - batch_size)
# Generate a minibatch.
batch_data = train_dataset[offset:(offset + batch_size), :]
batch_labels = train_labels[offset:(offset + batch_size), :]
# Prepare a dictionary telling the session where to feed the minibatch.
# The key of the dictionary is the placeholder node of the graph to be fed,
# and the value is the numpy array to feed to it.
feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}
_, l, predictions = session.run(
[optimizer, loss, train_prediction], feed_dict=feed_dict)
if (step % 500 == 0):
print("Minibatch loss at step %d: %f" % (step, l))
print("Learning rate: " % learning_rate)
print("Minibatch accuracy: %.1f%%" % accuracy(predictions, batch_labels))
print("Validation accuracy: %.1f%%" % accuracy(
valid_prediction.eval(), valid_labels))
print("Test accuracy: %.1f%%" % accuracy(test_prediction.eval(), test_labels))
save_path = saver.save(session, "l2_degrade.ckpt")
print("Model save to " + `save_path`)
Mi sono reso conto che era un po 'di tempo fa, ma potresti anche voler esaminare alcuni metodi di regolarizzazione, e in particolare in [normalizzazione batch] (https://arxiv.org/pdf/1502.03167.pdf). Se funziona funziona bene, ma BN aiuta con la sensibilità della rete alle distribuzioni di peso iniziali, tra le altre cose. – Engineero
Per 'truncated_normal', provare a impostare' stddev = sqrt (2/N) ', dove' N' è il numero di righe nella matrice peso. O semplicemente imposta 'stddev' su [valore più basso] (https://discussions.udacity.com/t/problem-3-3-dropout-does-not-improve-test-accuarcy/46286/13). Ecco un [esempio] (http://www.ritchieng.com/machine-learning/deep-learning/tensorflow/regularization/), anche se ci sono alcuni errori, come includere il dropout nella fase di valutazione. – orodbhen
In realtà, ecco l'originale [articolo] (https://arxiv.org/pdf/1502.01852v1.pdf) che deriva da 'sqrt (2/N)'. – orodbhen