4

I use the following code (courtesy to here) which runs CNN for training MNIST images:

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

batch_size = 128
num_classes = 10
epochs = 1

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))

print(model.save_weights('file.txt')) # <<<<<----

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

My goal is to use CNN model to extract MNIST features into a dataset that I can use as an input for another classifier. In this example, I don't care about the classification operation since all I need is the features of the trained images. The only method I found is save_weights as:

print(model.save_weights('file.txt'))

How can I extract features into a dataset from keras model?

Kristy
  • 211
  • 3
  • 11

1 Answers1

8

After training or loading the existing trained model, you can create another model:

extract = Model(model.inputs, model.layers[-3].output) # Dense(128,...)
features = extract.predict(data)

and use the .predict method to return the vectors from a specific layer, in this case every image will become (128,), the output of the Dense(128, ...) layer.

You can also train these networks jointly with 2 outputs using the functional API. Follow the guide and you'll see that you can chain models together and have multiple outputs each possibly with a separate loss. This will allow your model to learn shared features that is useful for both classifying the MNIST image and your task at the same time.

u3l
  • 3,284
  • 4
  • 29
  • 49
nuric
  • 9,656
  • 3
  • 19
  • 37
  • Thank you very very much. Do you mean `data` by `x_test`? Also, do we always consider the results from `.predict(x_test)` to be the features extracted from the trained images? – Kristy Jun 08 '18 at 09:26
  • Yes, by `data` I mean the `x_test` the data you want the features of. In this case `.predict(x_test)` will be the features extracted from the trained images. – nuric Jun 08 '18 at 10:36
  • 6
    I get an ValueError: Output tensors to a Model must be the output of a Keras `Layer` (thus holding past layer metadata). I think this should be `extract = Model(model.inputs, model.layers[-3].output)` – Alexander Jan 22 '19 at 11:12