Keras Import: java.lang.String cast to java.util.List

I’m trying to import a ConvNet that was created it Python. I tried both separated Json model with H5 weights and combined H5 model.

The java code is:

    String modelPath = "Model.h5";



    ComputationGraph model = KerasModelImport.importKerasModelAndWeights(modelPath, false);

and the error:

Exception in thread “main” java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.List (java.lang.String and java.util.List are in module java.base of loader ‘bootstrap’)
at org.deeplearning4j.nn.modelimport.keras.KerasModel.(KerasModel.java:150)
at org.deeplearning4j.nn.modelimport.keras.KerasModel.(KerasModel.java:97)
at org.deeplearning4j.nn.modelimport.keras.utils.KerasModelBuilder.buildModel(KerasModelBuilder.java:311)
at org.deeplearning4j.nn.modelimport.keras.KerasModelImport.importKerasModelAndWeights(KerasModelImport.java:167)
at kerasloadmodule.Main.main(Main.java:18)

@kelauder this gives me literally nothing to work with. What model are you trying to import? Which version of keras?

Here is the simple test test I tried:

print(tf.keras._version_)

inputs = tf.keras.layers.Input(shape=(48, 48, 3))

x = tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), strides=(2, 2), padding=‘valid’, activation=‘relu’, name=‘block1_conv1’)(inputs)

x = tf.keras.layers.MaxPool2D(pool_size=(2, 2), strides=(2, 2), name=‘block1_pool’)(x)

x = tf.keras.layers.Flatten(name=‘flatten’)(x)

x = tf.keras.layers.Dense(units=1024, activation=‘relu’, name=‘fc1’)(x)

outputs = tf.keras.layers.Dense(100, activation=‘softmax’, name=‘predictions’)(x)

model = tf.keras.Model(inputs=inputs, outputs=outputs, name=‘Simple’)

model.summary()

model.save(“Simple.h5”)

And the output:

Keras: 3.13.0

2026-01-16 06:49:51.010420: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: SSE3 SSE4.1 SSE4.2 AVX AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
Model: “Simple”
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ input_layer (InputLayer) │ (None, 48, 48, 3) │ 0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block1_conv1 (Conv2D) │ (None, 23, 23, 64) │ 1,792 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block1_pool (MaxPooling2D) │ (None, 11, 11, 64) │ 0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ flatten (Flatten) │ (None, 7744) │ 0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ fc1 (Dense) │ (None, 1024) │ 7,930,880 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ predictions (Dense) │ (None, 100) │ 102,500 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
Total params: 8,035,172 (30.65 MB)
Trainable params: 8,035,172 (30.65 MB)
Non-trainable params: 0 (0.00 B)
WARNING:absl:You are saving your model as an HDF5 file via model.save() or keras.saving.save_model(model). This file format is considered legacy. We recommend using instead the native Keras format, e.g. model.save('my_model.keras') or keras.saving.save_model(model, 'my_model.keras').

The Java Code:

public class Main {

public static void main(String\[\] args) throws Exception {



    String modelPath = "Simple.h5";



    ComputationGraph model = KerasModelImport.importKerasModelAndWeights(modelPath, false);



    model.init();



    

    System.out.println(model.summary());

}

}

OK, I downgraded to Keras 2 and the Import didn’t fail!

But I needed verify that it is importing correctly, so I did a test:

In Python I loaded VGG16 and processed two images from the ImageNet dataset (first one shown):

model = VGG16(weights=‘imagenet’, include_top=True)

Save the weights to an HDF5 file

model.save(“VGG16Model.h5”)
img_path = ‘n01440764_10026.JPEG’
img = image.load_img(img_path, target_size=(224, 224)) # VGG16 expects 224x224 input
x = image.img_to_array(img) # Convert PIL image to a numpy array (H, W, C)
x = np.expand_dims(x, axis=0) # Add a batch dimension (N, H, W, C)
x = preprocess_input(x) # Apply VGG16-specific preprocessing (BGR conversion, zero-centering)

Save input to compare with java

np.savetxt(‘n01440764_10026.csv’, x.flatten(), delimiter=‘,’)

predictions = model.predict(x)

print(np.max(predictions))
print(np.argmax(predictions))

Output:
0.75161654
0

Then in Java:
public class Main {
public static void main(String args) throws Exception {
ComputationGraph vgg16Network = KerasModelImport.importKerasModelAndWeights(“VGG16Model.h5”, false);

  vgg16Network.init();

  // System.out.println(vgg16Network.summary());

  File imageFile = new File("n01440764_10026.JPEG");

  // Load the image into an INDArray (DL4J's matrix format)
  NativeImageLoader loader = new NativeImageLoader(224, 224, 3); 
  INDArray image = loader.asMatrix(imageFile);

  // Preprocess the image (mean subtraction is specific to VGG16)
  VGG16ImagePreProcessor preProcessor = new VGG16ImagePreProcessor();
  preProcessor.transform(image); 
  image = image.permute(0, 2, 3, 1);  // fix INDArray order

  // Save INDArray to compare with Python
  INDArray flat = image.ravel();
  writeINDArrayToCsv(flat, "n01440764_10026.csv");  

  INDArray output = vgg16Network.outputSingle(image);

  System.out.println(output.maxNumber() + " " + output.argMax());

}

public static void writeINDArrayToCsv(INDArray array, String filePath) {
try (CSVWriter writer = new CSVWriter(new FileWriter(filePath))) {
long rows = array.shape()[0];

     for (long i = 0; i < rows; i++) {
        String[] rowData = new String[1];
        rowData[0] = String.valueOf(array.getDouble(i));
        writer.writeNext(rowData);
     }
  } catch (IOException e) {
     e.printStackTrace();
  }

}

}

Output: 0.47710591554641724 0

The other image: Python = 0.9145643, 2 and Java = 0.9373587369918823 2

Neither one matches.

Note in the code that I saved the input array post processing and the flattened arrays were identical. So now I’m confused as to why they aren’t working exactly the same.