我遇到了参数值错误(解包时预期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相关。