首页 > 解决方案 > 如何从权重/偏差中重现 Keras 模型?

问题描述

我想使用 Keras ML 模型中的权重和偏差在另一个没有安装 Keras(并且不能)的程序中进行数学预测函数。

我有一个简单的 MLP 模型,用于拟合数据。我在 Python 中运行 Keras 和 TensorFlow 后端;现在,我正在使用一个输入层、1 个隐藏层和 1 个输出层。所有层都是RELU,我的优化器是adam,损失函数是mean_squared_error。

据我了解,我为图层获得的权重应该以以下形式在数学上使用:

(SUM (w*i)) + b

其中总和是所有权重和输入的总和,b 是神经元上的偏差。例如,假设我有一个形状为 (33, 64) 的输入层。有 33 个输入和 64 个神经元。我将有一个昏暗 33 的向量输入和一个昏暗 64 的向量输出。这将使每个 SUM 33 个项 * 33 个权重,并且输出将是所有 64 个 SUM 加上 64 个偏差(分别)。

下一层,在我的例子中是 32 个神经元,将做同样的事情,但有 64 个输入和 32 个输出。我的输出层只有一个值,所以输入 32 并输出 1。

我已经编写了代码来尝试模仿该模型。这是进行单个预测的片段:

    def modelR(weights, biases, data):
       # This is the input layer.
       y = []
       for i in range(len(weights[0][0])):
           x = np.zeros(len(weights[0][0]))
           for j in range(len(data)):
               x[i] += weights[0][j][i]*data[j]
           y.append(x[i]+biases[0][i])

       # This is the hidden layer.
       z = []
       for i in range(len(weights[1][0])):
           x = np.zeros(len(weights[1][0]))
           for j in range(len(y)):
               x[i] += weights[1][j][i]*y[j]
           z.append(x[i]+biases[1][i])

       # This is the output layer.
       p = 0.0
       for i in range(len(z)):
           p += weights[-1][i][0]*z[i]
       p = p+biases[-1][0]

       return p

需要明确的是,“权重”和“偏差”是通过以下方式得出的:

    weights = []
    biases = []
    for i in range(len(model.layers)):
       weights.append(model.layers[i].get_weights()[0])
       biases.append(model.layers[i].get_weights()[1])

    weights = np.asarray(weights)
    biases = np.asarray(biases)

所以第一个输入的第一个神经元的第一个权重是 weight[0][0][0],第二个神经元的第一个输入的第一个权重是 weight[0][1][0],依此类推。这可能是错误的,这可能是我卡住的地方。但这很有意义,因为我们要从 (1 x 33) 向量到 (1 x 64) 向量,所以我们应该有一个 (33 x 64) 矩阵。

关于我哪里出错的任何想法?谢谢!

编辑:发现答案我将 jhso 的答案标记为正确,即使它在我的代码中无法正常工作(我可能在某处缺少导入语句)。关键是激活功能。我使用的是 RELU,所以我不应该传递任何负值。此外,jhso 展示了一种不使用循环而是简单地进行矩阵乘法的好方法(我不知道 Python 会这样做)。现在我只需要弄清楚如何在 C++ 中做到这一点!

标签: pythontensorflowmachine-learningkeras

解决方案


我认为在使用机器学习时熟悉线性代数是件好事。当我们有一个形式的方程时,sum(matrix elem times another matrix elem)它通常是形式的简单矩阵乘法matrix1 * matrix2.T。这大大简化了您的代码:

def modelR(weights, biases, data):
   # This is the input layer.
   y = np.matmul(data,weights[0])+biases[0][None,:] 
   y_act = relu(y) #also dropout or any other function you use here
   z = np.matmul(y_act,weights[1])+biases[1][None,:]
   z_act = relu(z) #also dropout and any other function you use here
   p = np.matmul(z_act,weights[2])+biases[2][None,:]
   p_act = sigmoid(p)   
   return p_act

我猜测您使用的是哪个激活函数。我也不确定您的数据是如何构造的,只要确保特征/权重始终是乘法的内部维度,即。如果您的输入是 (Bx10) 并且您的权重是 (10x64) 那么input*weights就足够了,并且会产生形状 (Bx64) 的输出。


推荐阅读