Search code examples
kerastensorflow2.0pyopenclamd-gpuplaidml

Anyway to work with Keras in Mac with AMD GPU?


I have a MacBook Pro with AMD processor and I want to run Keras (Tensorflow backend) in this GPU. I came to know Keras only works with NVIDIA GPUs. What is the workaround (if possible)?


Solution

  • You can OpenCL library to overcome this. I have tested it and it is working fine for me.

    Note: I have python version 3.7 and I will be using pip3 for package installation.

    Steps:

    1. Install OpenCL package with the following command

      pip3 install pyopencl

    2. Install PlaidML library using following command

      pip3 install pip install plaidml-keras

    3. Run setup for PlaidML. While setup you might get a prompt to select your GPU. If setup went correctly, you will get a success message at the end.

      plaidml-setup

    4. Install plaidbench to test plaidml on your GPU.

      pip3 install plaidbench

    5. Test it. If everything went well till here you will get benchmark scores.

      plaidbench keras mobilenet

    6. Now we have to set an environment path. Put this at the top of your code.

    import os
    os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"
    
    os.environ["RUNFILES_DIR"] = "/Library/Frameworks/Python.framework/Versions/3.7/share/plaidml"
    # plaidml might exist in different location. Look for "/usr/local/share/plaidml" and replace in above path
    
    os.environ["PLAIDML_NATIVE_PATH"] = "/Library/Frameworks/Python.framework/Versions/3.7/lib/libplaidml.dylib"
    # libplaidml.dylib might exist in different location. Look for "/usr/local/lib/libplaidml.dylib" and replace in above path
    
    1. Test in actual code. Use keras instead of tensorflow.keras in your code and run the following. (keras is installed in step 2 which runs in GPU)
    import os
    
    # IMPORTANT: PATH MIGHT BE DIFFERENT. SEE STEP 6
    os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"
    os.environ["RUNFILES_DIR"] = "/Library/Frameworks/Python.framework/Versions/3.7/share/plaidml"
    os.environ["PLAIDML_NATIVE_PATH"] = "/Library/Frameworks/Python.framework/Versions/3.7/lib/libplaidml.dylib"
    
    # Don't use tensorflow.keras anywhere, instead use keras
    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 = 12
    # 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))
    score = model.evaluate(x_test, y_test, verbose=0)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])
    

    When you run this you will get

    Using plaidml.keras.backend backend.
    INFO:plaidml:Opening device "metal_intel(r)_iris(tm)_graphics_6100.0"
    # or whatever GPU you selected in step 3
    

    which confirms that you are running it in GPU.

    Reference: https://towardsdatascience.com/gpu-accelerated-machine-learning-on-macos-48d53ef1b545