无法使用Sklearn和Keras包装器使pipeline.fit()工作

我遇到了参数值错误(解包时预期2个值,但只得到1个)。我有一个想要训练的网络:

def build(self):    numpy.random.seed(self.seed)    self.estimators.append(('standardize', StandardScaler))    self.estimators.append(('mlp', KerasClassifier(build_fn=self.build_fn, epochs=50, batch_size=5, verbose=0)))    self.pipeline = Pipeline(self.estimators)

现在如果我想将数据拟合到一些值上:比如self.X, self.Y

self.model = self.pipeline.fit(self.X, self.Y, verbose=1)

我得到了

Traceback (most recent call last):File "C:/Users/jaehan/PycharmProjects/cerebro/cerebro.py", line 257, in <module>model.run()File "C:/Users/jaehan/PycharmProjects/cerebro/cerebro.py", line 138, in runself.model = self.pipeline.fit(self.X, self.Y, verbose=1)File "C:\Users\jaehan\AppData\Local\Continuum\anaconda3\envs\py36\lib\site- packages\sklearn\pipeline.py", line 248, in fitXt, fit_params = self._fit(X, y, **fit_params)File "C:\Users\jaehan\AppData\Local\Continuum\anaconda3\envs\py36\lib\site- packages\sklearn\pipeline.py", line 197, in _fitstep, param = pname.split('__', 1)ValueError: not enough values to unpack (expected 2, got 1)

我在这里做错了什么吗?我原以为我可以直接运行一个fit操作,它会返回一个历史对象,我可以随时保存和加载它

我甚至尝试了…

self.pipeline.fit(self.X, self.Y)

这抛出了…

AttributeError: 'numpy.ndarray' object has no attribute 'fit'

我完全不知道这里发生了什么。

完整代码

class Cerebro:    def __init__(self):        self.model = None        self.build_fn = None        self.data = None        self.X = None        self.Y = None        #这些三个用于将字符串值编码为整数编码/独热编码        self.encoder = LabelEncoder()        self.encodings = {}        self.one_hot_encodings = {}        self.seed = numpy.random.seed(7) #这确保我们有可复制的结果。        self.estimators = []        self.pipeline = None        self.kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=self.seed)        self.cross_validation_score = 0.0    def preprocess(self):        """        这个方法将预处理我们想要训练网络的数据集。         示例:            import preproccessing            ...            dataset, X, Y = preprocessing.main()        """        self.data = pandas.read_csv('src_examples/hwtxn_final_for_influx.txt', sep='\t').values        self.X = numpy.delete(self.data, 13, axis=1)        self.Y = self.data[:, 13].astype(numpy.float16)    def build(self):        self.build_fn = self.base_model()        self.preprocess()        numpy.random.seed(self.seed)        self.estimators.append(('standardize', StandardScaler()))        self.estimators.append(('mlp', KerasClassifier(build_fn=self.build_fn, epochs=50, batch_size=5, verbose=0)))        self.pipeline = Pipeline(self.estimators)    def run(self):        """这将实际使用管道(预处理标准化、模型)        并将其拟合到我们的数据集(X, Y)(我们不需要测试/训练集,因为我们使用分层k折交叉验证。)        参数:            无        返回:            无        """        # 这是'model'        # self.pipeline        print(type(self.pipeline))        print(self.X.shape)        self.model = self.pipeline.fit(self.X, self.Y)    def load(self, fn):        """这将加载一个保存的模型(历史对象)        参数:            fn (文件名): 表示保存的模型文件        返回:            model (pkl对象): 表示模型        """        return pickle.load(open(fn, 'rb'))    def save(self, fn):        """这将保存一个模型(历史对象)        参数:            fn (文件名): 表示用于保存模型的文件名        返回:            无        """        pickle.dump(self.model, open(fn, 'wb'))    def encode(self, vals, key):        """ 这个方法将编码一个值列表,并接受一个键(表示列名或索引)以保存        在类对象(self.encodings)中        这将帮助我们跟踪我们需要翻译/解密的值的编码。        参数:            vals(np.array): 要编码的值数组            key(str): 表示用于编码这组特定值的键        返回:            转换后的值(np.array)表示编码后的值版本        """        # 非整数值的整数编码        self.encodings[key] = self.encoder.fit_transform(vals)        return self.encoder.fit_transform(vals)    def decoder(self, vals, key):        """这个方法将解码类变量的整数编码。它将接受vals,        表示要解码的值列表(例如[1,2,3] -- [apple, pear, orange])        它还将接受一个键(因为每个解码都有一个对应的编码)以找到要映射的编码        方案        参数:            vals(np.array) : 要解码的值数组            key(str) : 表示用于编码值的键(用于解码它)        返回:            编码值的反向转换(np.array)        """        # 将整数编码翻译为原始值(encoder._classes)        return self.encodings[key].inverse_transform(vals)    def cross_validate(self):        """        这将使用分层k折方法执行交叉验证分数。(想象传统的K折但        对每个子样本的值均匀分布)        参数:            无        返回:            无        """        self.cross_validation_score = cross_val_score(self.pipeline, self.X, self.Y, cv=self.kfold)        return self.cross_validation_score    @staticmethod    def base_model():        """        这将为我们返回一个基本模型来尝试。这个实现的好处是        当我们决定想要更复杂的东西时,我们所需要做的就是定义一个类函数并替换        构建函数中的值        参数:            无        返回:            model (keras.models.Sequential): 基于Keras的DNN模型        """        # 创建模型        model = Sequential()        model.add(Dense(60, input_dim=60, kernel_initializer='normal', activation='relu'))        model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))        # 编译模型        model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])        return model    @staticmethod    def one_hot_encoder(int_encoding):        """        这将接受字符串变量的整数编码(传统的预处理步骤,可能会        移动到预处理包中。        本质上它返回我们希望编码的值的二进制‘独热’编码        示例        #数据集值        [apple, orange, pear]        #整数编码        [1, 2, 3]        #独热编码        [[1, 0, 0]         [0, 1, 0]         [0, 0, 1]]        参数:            无        返回:            矩阵(np.array): 表示一类值的独热向量的矩阵        """        # 我们可能不需要这个...所以现在我们将它保持静态        return OneHotEncoder(sparse=False).fit_transform(int_encoding.reshape(len(int_encoding), 1))if __name__ == '__main__':    # 第一步是初始化类(seed == 7)    model = Cerebro()    model.build()    model.cross_validate()    print("这里是我们的估计器:\n {}".format(model.estimators))    print("这里是我们的管道:\n {}".format(model.pipeline))    model.run()

编辑答案是.fit()的build_fn参数需要一个函数指针而不是模型本身。

个人意见我觉得应该为这种特定情况抛出一个错误。


回答:

这是由于以下这行代码引起的:

self.build_fn = self.base_model()

这实际上应该是:

self.build_fn = self.base_model

KerasClassifier需要指向创建模型的函数的指针,但通过在末尾添加(),你将build_fn赋值为实际的模型,这是错误的。

除了上述错误之外,我建议检查代码中的以下几行,如果不纠正,未来使用代码时会出错。

1) self.encodings[key] = self.encoder.fit_transform(vals)

这里你将转换后的数据赋值给了encodings[key]而不是模型。所以当你这样做时:-

self.encodings[key].inverse_transform(vals)

在转换后的数据上调用inverse_transform()是没有意义的。

inverse_transform()是scikit-learn变换器的方法。但self.encodings[key]将输出一个ndarray,因为你保存了fit_transform()的输出数组。

2) 与2类似的事情也发生在one_hot_encoder()

错误"AttributeError: 'numpy.ndarray' object has no attribute 'fit'"似乎与1和2相关。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注