我使用Sklearn在12个特征和一个输出上训练多层感知器回归。StandardScalar((适用于训练数据,并应用于所有输入数据。经过一段时间的架构优化培训,我得到了一个看起来非常准确的模型(<10%的误差(。我现在需要提取权重和偏差,以便在与人交互的系统上实时实现预测。这是用my_model.coefs(权重(和my_model.intercepts(偏差(来完成的。权重的形状适合我的模型中的节点数量,偏差的长度适合每一层。
现在的问题是,我在MatLab中实现了矩阵代数,并得到了与my_model.product((产生的结果截然不同的预测。
我对2层MLP的重建过程(第一层有11个节点,第二层有10个节点(:
scale() % elementwise subtract feature mean and divide by feature stdev
scaled_obs = scale(raw_obs)
% Up to this point results from MatLab == Sklearn
weight1 = [12x11] % weights to transition from the input layer to the first hidden layer
weight2 = [11x10]
weight3 = [10x1]
bias1 = [11x1] % bias to add to the first layer after weight1 has been applied
bias2 = [10x1]
bias3 = [1x1]
my_prediction = ((( scaled_obs * w1 + b1') * w2 + b2') * w3 + b3);
我也试过
my_prediction2 = ((( scaled_obs * w1 .* b1') * w2 .* b2') * w3 .* b3); % because nothing worked...```
对于我的特定数据:
Sklearn prediction = 1.731
my_prediction = -50.347
my_prediction2 = -3.2075
从my_model中提取相关参数时,我是否跳过了另一个权重/偏差?我在重建中的行动顺序有缺陷吗?
在我看来my_prediction = ((( scaled_obs * w1 + b1') * w2 + b2') * w3 + b3);
是正确的,但只缺少一个部分,那就是激活函数。你传递给模型的激活函数是什么。默认情况下,MLPRegressor
具有从第一层到倒数第三层(包括第一层(的relu
作为激活函数。倒数第二层没有任何激活功能。输出层有一个单独的激活函数,它是identity
函数,基本上是f(x) = x
,所以你不需要为此做任何事情。
如果你选择了relu
,或者你根本没有选择激活(那么relu
是默认的(,那么你必须在numpy中作为np.maximum(0, your_layer1_calculation)
做这样的事情,我不确定在matlab 中是如何做到的
所以最终的公式是:
layer1 = np.dot(scaled_inputs, weight0) + bias0
layer2 = np.dot(np.maximum(0, layer1), weight1) + bias1
layer......
layer(n-1) = np.dot(np.maximum(0, layer(n-2), weight(n-1)) + bias(n-1)
layer(n) = layer(n-1) # identity function