Реализация CNN с использованием Keras и Tensorflow - PullRequest
0 голосов
/ 08 февраля 2019

Я создал модель CNN, используя Keras , и тренирую ее на наборе данных MNIST .Я получил разумную точность около 98%, что я и ожидал:

model = Sequential()
model.add(Conv2D(64, 5, activation="relu", input_shape=(28, 28, 1)))
model.add(MaxPool2D())
model.add(Conv2D(64, 5, activation="relu"))
model.add(MaxPool2D())
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', 
    loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(data.x_train, data.y_train, 
    batch_size=256, validation_data=(data.x_test, data.y_test))

Теперь я хочу построить ту же модель, но используя vanilla Tensorflow , вот как я это сделал:

X = tf.placeholder(shape=[None, 784], dtype=tf.float32, name="X")
Y = tf.placeholder(shape=[None, 10], dtype=tf.float32, name="Y")

net = tf.reshape(X, [-1, 28, 28, 1])
net = tf.layers.conv2d(
  net, filters=64, kernel_size=5, padding="valid", activation=tf.nn.relu)
net = tf.layers.max_pooling2d(net, pool_size=2, strides=2)
net = tf.layers.conv2d(
  net, filters=64, kernel_size=5, padding="valid", activation=tf.nn.relu)
net = tf.layers.max_pooling2d(net, pool_size=2, strides=2)
net = tf.contrib.layers.flatten(net)
net = tf.layers.dense(net, name="dense1", units=256, activation=tf.nn.relu)
model = tf.layers.dense(net, name="output", units=10)

А вот как я тренирую / проверяю это:

loss = tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y, logits=model)
opt = tf.train.AdamOptimizer().minimize(loss)
accuracy = tf.cast(tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1)), tf.float32)

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    for batch in range(data.get_number_of_train_batches(batch_size)):
        x, y = data.get_next_train_batch(batch_size)
        sess.run([loss, opt], feed_dict={X: x, Y: y})

    for batch in range(data.get_number_of_test_batches(batch_size)):
        x, y = data.get_next_test_batch(batch_size)
        sess.run(accuracy, feed_dict={X: x, Y: y})

Но полученная точность модели упала до ~ 80%.Каковы принципиальные различия между моей реализацией этой модели с использованием Keras и Tensorflow ?Почему точность так сильно меняется?

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Возможное улучшение ваших моделей.

Я использовал сети CNN для разных задач и всегда получал хорошие улучшения эффективности с помощью методов регуляризации, лучшие из них с отсева.

Я предлагаю использовать Dropout наПлотные слои и в случае с меньшей вероятностью на сверточных.

Также увеличение данных на входных данных очень важно, но применимость зависит от проблемной области.

Ps: в одном случаеМне пришлось изменить оптимизацию с Адама на SGD с Momentum.Таким образом, игра с оптимизацией имеет смысл.Также градиентное ограничение может учитываться, когда ваши сети испытывают недостаток в работе и не повышают эффективность, это может быть числовой проблемой.

0 голосов
/ 10 февраля 2019

Я не вижу ошибок в вашем коде.Обратите внимание, что ваша текущая модель сильно параметризована для такой простой проблемы из-за слоев Dense, которые вводят более 260 тыс. Обучаемых параметров:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_3 (Conv2D)            (None, 24, 24, 64)        1664      
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 8, 8, 64)          102464    
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 4, 4, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1024)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 256)               262400    
_________________________________________________________________
dense_3 (Dense)              (None, 10)                2570      
=================================================================
Total params: 369,098
Trainable params: 369,098
Non-trainable params: 0
_________________________________________________________________

Ниже, я буду запускать ваш код с:

  • незначительные изменения, чтобы код работал с набором данных MNIST в keras.datasets
  • упрощенной модели: в основном я удаляю слой Dense из 256 узлов, резко сокращая количество обучаемых параметров, и вводимнекоторые исключения из-за регуляризации.

С этими изменениями обе модели достигают 90% + точность набора проверки после первой эпохи. Так что, похоже, проблема, с которой вы столкнулись, связана с некорректной задачей оптимизации, которая приводит к очень переменным результатам, а не с ошибкой в ​​вашем коде .

# Import the datasets
import numpy as np
from keras.datasets import mnist
from keras.utils import to_categorical

(x_train, y_train), (x_test, y_test) = mnist.load_data()

# Add batch dimension
x_train = np.expand_dims(x_train, axis=-1)
x_test = np.expand_dims(x_test, axis=-1)

# One-hot encode the labels
y_train = to_categorical(y_train, num_classes=None)
y_test = to_categorical(y_test, num_classes=None)

batch_size = 64

# Fit model using Keras
import keras
import numpy as np
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout
from keras.models import Sequential

model = Sequential()
model.add(Conv2D(32, 5, activation="relu", input_shape=(28, 28, 1)))
model.add(MaxPool2D())
model.add(Conv2D(32, 5, activation="relu"))
model.add(MaxPool2D())
model.add(Flatten())
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', 
    loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, 
    batch_size=32, validation_data=(x_test, y_test), epochs=1)

Результат:

Train on 60000 samples, validate on 10000 samples
Epoch 1/1
60000/60000 [==============================] - 35s 583us/step - loss: 1.5217 - acc: 0.8736 - val_loss: 0.0850 - val_acc: 0.9742

Обратите внимание, что количество обучаемых параметров теперь является лишь долей от суммы в вашей модели:

model.summary()
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_3 (Conv2D)            (None, 24, 24, 32)        832       
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 12, 12, 32)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 8, 8, 32)          25632     
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 4, 4, 32)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 512)               0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                5130      
=================================================================
Total params: 31,594
Trainable params: 31,594
Non-trainable params: 0

Теперь,делать то же самое с TensorFlow:

# Fit model using TensorFlow
import tensorflow as tf

X = tf.placeholder(shape=[None, 28, 28, 1], dtype=tf.float32, name="X")
Y = tf.placeholder(shape=[None, 10], dtype=tf.float32, name="Y")

net = tf.layers.conv2d(
  X, filters=32, kernel_size=5, padding="valid", activation=tf.nn.relu)
net = tf.layers.max_pooling2d(net, pool_size=2, strides=2)
net = tf.layers.conv2d(
  net, filters=32, kernel_size=5, padding="valid", activation=tf.nn.relu)
net = tf.layers.max_pooling2d(net, pool_size=2, strides=2)
net = tf.contrib.layers.flatten(net)
net = tf.layers.dropout(net, rate=0.25)
model = tf.layers.dense(net, name="output", units=10)

loss = tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y, logits=model)
opt = tf.train.AdamOptimizer().minimize(loss)
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1)), tf.float32))

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    L = []
    l_ = 0
    for i in range(x_train.shape[0] // batch_size):
        x, y = x_train[i*batch_size:(i+1)*batch_size],\
            y_train[i*batch_size:(i+1)*batch_size]
        l, _ = sess.run([loss, opt], feed_dict={X: x, Y: y})
        l_ += np.mean(l)
    L.append(l_ / (x_train.shape[0] // batch_size))
    print('Training loss: {:.3f}'.format(L[-1]))

    acc = []
    for j in range(x_test.shape[0] // batch_size):
        x, y = x_test[j*batch_size:(j+1)*batch_size],\
            y_test[j*batch_size:(j+1)*batch_size]
        acc.append(sess.run(accuracy, feed_dict={X: x, Y: y}))
    print('Test set accuracy: {:.3f}'.format(np.mean(acc)))

Результат:

Training loss: 0.519
Test set accuracy: 0.968
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...