使用keras时的错误' sk-learn API

时间:2016-09-13 10:13:56

标签: python machine-learning scikit-learn keras

我这些天学习keras,并且在使用scikit-learn API时遇到了错误。这里有用的东西:

环境

python:3.5.2  
keras:1.0.5  
scikit-learn:0.17.1

CODE

import pandas as pd
from keras.layers import Input, Dense
from keras.models import Model
from keras.models import Sequential
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.cross_validation import train_test_split
from sklearn.cross_validation import cross_val_score
from sqlalchemy import create_engine
from sklearn.cross_validation import KFold


def read_db():
    "get prepared data from mysql."
    con_str = "mysql+mysqldb://root:0000@localhost/nbse?charset=utf8"
    engine = create_engine(con_str)
    data = pd.read_sql_table('data_ml', engine)
    return data

def nn_model():
    "create a model."
    model = Sequential()
    model.add(Dense(output_dim=100, input_dim=105, activation='softplus'))
    model.add(Dense(output_dim=1, input_dim=100, activation='softplus'))
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

data = read_db()
y = data.pop('PRICE').as_matrix()
x = data.as_matrix()
model = nn_model()
model = KerasRegressor(build_fn=model, nb_epoch=2)
model.fit(x,y)  #something wrong here!

错误

Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/forecast/gridsearch.py", line 43, in <module>
    model.fit(x,y)
  File "D:\Program Files\Python35\lib\site-packages\keras\wrappers\scikit_learn.py", line 135, in fit
    **self.filter_sk_params(self.build_fn.__call__))
TypeError: __call__() missing 1 required positional argument: 'x'

Process finished with exit code 1

该模型运行良好,无需使用kerasRegressor打包,但我想在此之后使用sk_learn的gridSearch,所以我在这里寻求帮助。我试过但仍然不知道。

可能有用的东西:

keras.warappers.scikit_learn.py  

class BaseWrapper(object):  


    def __init__(self, build_fn=None, **sk_params):
        self.build_fn = build_fn
        self.sk_params = sk_params
        self.check_params(sk_params)  


    def fit(self, X, y, **kwargs):
        '''Construct a new model with build_fn and fit the model according
        to the given training data.
    # Arguments
        X : array-like, shape `(n_samples, n_features)`
            Training samples where n_samples in the number of samples
            and n_features is the number of features.
        y : array-like, shape `(n_samples,)` or `(n_samples, n_outputs)`
            True labels for X.
        kwargs: dictionary arguments
            Legal arguments are the arguments of `Sequential.fit`

    # Returns
        history : object
            details about the training history at each epoch.
    '''

    if self.build_fn is None:
        self.model = self.__call__(**self.filter_sk_params(self.__call__))
    elif not isinstance(self.build_fn, types.FunctionType):
        self.model = self.build_fn(
            **self.filter_sk_params(self.build_fn.__call__))
    else:
        self.model = self.build_fn(**self.filter_sk_params(self.build_fn))

    loss_name = self.model.loss
    if hasattr(loss_name, '__name__'):
        loss_name = loss_name.__name__
    if loss_name == 'categorical_crossentropy' and len(y.shape) != 2:
        y = to_categorical(y)

    fit_args = copy.deepcopy(self.filter_sk_params(Sequential.fit))
    fit_args.update(kwargs)

    history = self.model.fit(X, y, **fit_args)

    return history
此行中出现

错误:

    self.model = self.build_fn(
        **self.filter_sk_params(self.build_fn.__call__))

self.build_fn这里是keras.models.Sequential

models.py  

class Sequential(Model):

    def call(self, x, mask=None):
        if not self.built:
            self.build()
        return self.model.call(x, mask)

那么,x是什么意思以及如何解决这个错误?
谢谢!

2 个答案:

答案 0 :(得分:12)

xiao,我遇到了同样的问题!希望这会有所帮助:

背景和问题

documentation for Keras指出,在为scikit-learn实现Wrappers时,有两个参数。第一个是构建函数,它是一个&#34;可调用函数或类实例&#34;。具体而言,它声明:

  

build_fn应构造,编译并返回一个Keras模型,然后用于拟合/预测。可以将以下三个值之一传递给build_fn:

     
      
  1. 功能
  2.   
  3. 实现调用方法
  4. 的类的实例   
  5. 无。这意味着您实现了一个继承自KerasClassifierKerasRegressor的类。然后,将此类的调用方法视为默认的build_fn。
  6.   

在代码中,创建模型,然后在创建build_fn包装器时将模型作为参数KerasRegressor的值传递:

model = nn_model()
model = KerasRegressor(build_fn=model, nb_epoch=2)

这就是问题所在。您可以传递Keras nn_model模型的实际实例,而不是将build_fn 函数作为Sequential传递。因此,当调用fit()时,它无法找到call方法,因为它未在您返回的类中实现。

提议的解决方案

我所做的工作是将函数传递给build_fn,而不是实际的模型:

data = read_db()
y = data.pop('PRICE').as_matrix()
x = data.as_matrix()
# model = nn_model() # Don't do this!
# set build_fn equal to the nn_model function
model = KerasRegressor(build_fn=nn_model, nb_epoch=2) # note that you do not call the function!
model.fit(x,y)  # fixed!

这不是唯一的解决方案(您可以将build_fn设置为适当地实现call方法的类),但是对我有效的方法。我希望它可以帮到你!

答案 1 :(得分:0)

用户定义的关键字参数传递给__init__(),也就是说,所有传递给__init__()的关键字参数都将直接传递给model_build_fn。例如,调用 KerasClassifier(myparam=10) 将导致 model_build_fn(my_param=10)

这是一个例子:

class MyMultiOutputKerasRegressor(KerasRegressor):
    
    # initializing
    def __init__(self, **kwargs):
        KerasRegressor.__init__(self, **kwargs)
        
    # simpler fit method
    def fit(self, X, y, **kwargs):
        KerasRegressor.fit(self, X, [y]*3, **kwargs)

(...)

def get_quantile_reg_rpf_nn(layers_shape=[50,100,200,100,50], inDim= 4, outDim=1, act='relu'):
          # do model stuff...

(...) 初始化 Keras 回归器:

base_model = MyMultiOutputKerasRegressor(build_fn=get_quantile_reg_rpf_nn,
                                         layers_shape=[50,100,200,100,50], inDim= 4, 
                                         outDim=1, act='relu', epochs=numEpochs, 
                                         batch_size=batch_size, verbose=0)