modAL-python / modAL

A modular active learning framework for Python
https://modAL-python.github.io/
MIT License
2.22k stars 324 forks source link

missing 'inputs' positional argument with ActiveLearner function #66

Open zbrasseaux opened 4 years ago

zbrasseaux commented 4 years ago

All of my relevant code:

#!/usr/bin/env python3.5

from data_generator import data_generator as dg

# standard imports
from keras.models import load_model
from keras.utils import to_categorical
from keras.wrappers.scikit_learn import KerasClassifier
from os import listdir
import pandas as pd
import numpy as np
from modAL.models import ActiveLearner

######## NEW STUFF ########

# get filenames and folder names
data_location = './sensor_preprocessed_dataset/flow_rates_pressures/'
subfolders = ['true','false']

###########################

classifier = KerasClassifier(load_model('./0.7917.h5'))

(X_train, y_train), (X_test, y_test) = dg.load_data_for_model(data_location, subfolders)
WINDOW_SIZE = X_train[0].shape[0]
CHANNELS = X_train[0].shape[1]

# reshape and retype the data for the classifier
X_train = X_train.reshape(X_train.shape[0], WINDOW_SIZE, CHANNELS, 1)
X_test = X_test.reshape(X_test.shape[0], WINDOW_SIZE, CHANNELS, 1)

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# assemble initial data
n_initial = 30
initial_idx = np.random.choice(range(len(X_train)), size=n_initial, replace=False)
X_initial = X_train[initial_idx]
y_initial = y_train[initial_idx]

learner = ActiveLearner(
    estimator=classifier,
    X_training=X_train,
    y_training=y_train,
    verbose=1
)

X_pool = X_test
y_pool = y_test

n_queries = 10
for idx in range(n_queries):
    print('Query no. %d' % (idx + 1))
    query_idx, query_instance = learner.query(X_pool, n_instances=100, verbose=0)
    learner.teach(
        X=X_pool[query_idx], y=y_pool[query_idx], only_new=True,
        verbose=1
    )
    X_pool = np.delete(X_pool, query_idx, axis=0)
    y_pool = np.delete(y_pool, query_idx, axis=0)

Messages, Warnings, and Errors:

Using TensorFlow backend.
WARNING:tensorflow:From /home/jazz/.local/lib/python3.5/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
2020-01-24 10:03:54.427147: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2020-01-24 10:03:54.447927: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2712000000 Hz
2020-01-24 10:03:54.448529: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x4c01c00 executing computations on platform Host. Devices:
2020-01-24 10:03:54.448599: I tensorflow/compiler/xla/service/service.cc:158]   StreamExecutor device (0): <undefined>, <undefined>
WARNING:tensorflow:From /home/jazz/.local/lib/python3.5/site-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.cast instead.
WARNING:tensorflow:From /home/jazz/.local/lib/python3.5/site-packages/tensorflow/python/ops/math_grad.py:102: div (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Deprecated in favor of operator or tf.math.divide.
Traceback (most recent call last):
  File "./classifier.py", line 45, in <module>
    y_training=y_train
  File "/home/jazz/.local/lib/python3.5/site-packages/modAL/models/learners.py", line 79, in __init__
    X_training, y_training, bootstrap_init, **fit_kwargs)
  File "/home/jazz/.local/lib/python3.5/site-packages/modAL/models/base.py", line 63, in __init__
    self._fit_to_known(bootstrap=bootstrap_init, **fit_kwargs)
  File "/home/jazz/.local/lib/python3.5/site-packages/modAL/models/base.py", line 106, in _fit_to_known
    self.estimator.fit(self.X_training, self.y_training, **fit_kwargs)
  File "/home/jazz/.local/lib/python3.5/site-packages/keras/wrappers/scikit_learn.py", line 210, in fit
    return super(KerasClassifier, self).fit(x, y, **kwargs)
  File "/home/jazz/.local/lib/python3.5/site-packages/keras/wrappers/scikit_learn.py", line 139, in fit
    **self.filter_sk_params(self.build_fn.__call__))
TypeError: __call__() missing 1 required positional argument: 'inputs'

I honestly don't even know where to begin to solve this, my code is based on your example here: [https://modal-python.readthedocs.io/en/latest/content/examples/Keras_integration.html] https://modal-python.readthedocs.io/en/latest/content/examples/Keras_integration.html)

And I've read the docs here: [https://modal-python.readthedocs.io/en/latest/content/apireference/models.html] https://modal-python.readthedocs.io/en/latest/content/apireference/models.html

Any input is appreciated.

cosmic-cortex commented 4 years ago

Hi!

Thanks for letting me know about this issue! I'll investigate this and get back to you as soon as possible.

guido-niku commented 4 years ago

anybody found something ? I have encountered the same. Am i missing something ?

cosmic-cortex commented 4 years ago

Ok, now I know what is wrong, it has been right in front of me :)

The classifier in the example of @zbrasseaux is

classifier = KerasClassifier(load_model('./0.7917.h5'))

This is unfortunately not how the scikit-learn wrapper of Keras works. You need to pass a build function to the KerasClassifier upon initialization, see the proper usage here.

In the example for the modAL library (https://github.com/modAL-python/modAL/blob/master/examples/keras_integration.py), I do this the following way:

# build function for the Keras' scikit-learn API
def create_keras_model():
    """
    This function compiles and returns a Keras model.
    Should be passed to KerasClassifier in the Keras scikit-learn API.
    """

    model = Sequential()
    model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)))
    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(10, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])

    return model

# create the classifier
classifier = KerasClassifier(create_keras_model)

Notice that I pass the build function instead of the model. So, you need to implement a function which loads the weights and returns a Keras model. In your example, you pass the model directly instead of the build function.

This might work in your case:

build_fn = lambda : load_model('./0.7917.h5')
classifier = KerasClassifier(build_fn)

I haven't tested this however.