Python中deep tensorflow keras模型的输出与tensorflowjs转换之间的显著差异

Python中deep tensorflow keras模型的输出与tensorflowjs转换之间的显著差异,keras,tf.keras,tensorflow.js,Keras,Tf.keras,Tensorflow.js,我一直在尝试使用tensorflowjs在浏览器中直接在预先训练好的Keras模型中运行推理,我正在努力获得相同的性能 在调查中,我注意到,在所有层面上,产量的累积差异都很小,到最后变得相当糟糕 下面的简化示例可以用来说明。这是用tensorflow 2.1.0、tensorflowjs 1.7.2和Chrome 80.0.3987.163测试的 首先,我们在tf.keras中构建一个简单的deep模型,将权重初始化为随机值,并将其转换为tensorflowjs 将tensorflowjs导入为

我一直在尝试使用tensorflowjs在浏览器中直接在预先训练好的Keras模型中运行推理,我正在努力获得相同的性能

在调查中,我注意到,在所有层面上,产量的累积差异都很小,到最后变得相当糟糕

下面的简化示例可以用来说明。这是用tensorflow 2.1.0、tensorflowjs 1.7.2和Chrome 80.0.3987.163测试的

首先,我们在tf.keras中构建一个简单的deep模型,将权重初始化为随机值,并将其转换为tensorflowjs

将tensorflowjs导入为tfjs
从tensorflow.keras.models导入模型,保存_模型
从tensorflow.keras将图层导入为L
从tensorflow.keras导入后端为K
从tensorflow.keras导入初始值设定项
K.清除会话()
def build_模型(深度、大小):
x=L.Input((大小),name='Input')
输入=[x]
输出=[]
uniform_init=I.RandomUniform(minval=-1,maxval=1,seed=123)
对于范围内的i(深度):
x=L.密度(尺寸,
数据类型='float32',
内核初始化器=统一初始化,
偏差\初始值设定项=一致\初始值,
名称='densite_uz'+str(i))(x)
输出+=[x]
模型=模型(输入=输入,输出=输出)
返回(模型、输入、输出)
模型、输入、输出=构建模型(10,50)
compile(优化器='adam',loss='mean_squared_error')
model.summary()
保存_模型(模型“./keras_模型.h5”)
tfjs.converters.save_keras_model(model'。/keras_converted')
输出:

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input (InputLayer)           [(None, 50)]              0         
_________________________________________________________________
dense_0 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_1 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_2 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_3 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_4 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_5 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_6 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_7 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_8 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_9 (Dense)              (None, 50)                2550      
=================================================================
Total params: 25,500
Trainable params: 25,500
Non-trainable params: 0
dense_0_weights[0]: different values = 0, average difference = 0.0
dense_0_weights[1]: different values = 0, average difference = 0.0
dense_0_output[0]: different values = 0, average difference = 0.0
dense_1_weights[0]: different values = 0, average difference = 0.0
dense_1_weights[1]: different values = 0, average difference = 0.0
dense_1_output[0]: different values = 40, average difference = 1.7833709716796876e-06
dense_2_weights[0]: different values = 0, average difference = 0.0
dense_2_weights[1]: different values = 0, average difference = 0.0
dense_2_output[0]: different values = 43, average difference = 1.2047290802001953e-05
dense_3_weights[0]: different values = 0, average difference = 0.0
dense_3_weights[1]: different values = 0, average difference = 0.0
dense_3_output[0]: different values = 38, average difference = 5.3539276123046876e-05
dense_4_weights[0]: different values = 0, average difference = 0.0
dense_4_weights[1]: different values = 0, average difference = 0.0
dense_4_output[0]: different values = 43, average difference = 0.00024005889892578125
dense_5_weights[0]: different values = 0, average difference = 0.0
dense_5_weights[1]: different values = 0, average difference = 0.0
dense_5_output[0]: different values = 45, average difference = 0.0010586166381835937
dense_6_weights[0]: different values = 0, average difference = 0.0
dense_6_weights[1]: different values = 0, average difference = 0.0
dense_6_output[0]: different values = 46, average difference = 0.00515625
dense_7_weights[0]: different values = 0, average difference = 0.0
dense_7_weights[1]: different values = 0, average difference = 0.0
dense_7_output[0]: different values = 47, average difference = 0.0254345703125
dense_8_weights[0]: different values = 0, average difference = 0.0
dense_8_weights[1]: different values = 0, average difference = 0.0
dense_8_output[0]: different values = 46, average difference = 0.11546875
dense_9_weights[0]: different values = 0, average difference = 0.0
dense_9_weights[1]: different values = 0, average difference = 0.0
dense_9_output[0]: different values = 44, average difference = 0.42203125
接下来,我们针对tensorflowjs中的单位向量运行模型,并将每个层的输出以及权重导出到json

异步函数运行(){
const model=await tf.loadLayersModel('/keras\u converted/model.json')
model.summary()
让input_size=model.inputLayers[0]。batchInputShape[1]
let one=[…数组(输入大小)].map(x=>1)
设x=tf.张量(个)。重塑([1,输入大小])
让yhat=model.predict(x.map)(x=>x.arraySync())
设i=0
设vals={}
model.outputLayers.forEach(输出=>{
VAL[output.name+'_output']=yhat[i]
i+=1
})
model.layers.forEach(层=>{
VAL[layer.name+'_weights']=layer.getWeights().map(w=>w.arraySync())
})
设a=document.createElement('a')
let file=new Blob([JSON.stringify(vals)],{type:'text/plain'})
a、 href=URL.createObjectURL(文件)
a、 下载='keras\u model\u tfjs\u output.json'
a、 单击()
}
运行()
我们在Python中针对相同的输入向量运行该模型,并比较不同层的输出以及权重,以排除权重的任何变化

重新导入
导入json
将numpy作为np导入
从tensorflow.keras.models导入负载_模型
模型=负荷模型('./keras_模型.h5')
#负载tensorflow js输出和重量
将open('./keras_model_tfjs_output.json','r')作为json_文件:
tfjs_vals=json.load(json_文件)
#通过在Python中运行推理创建类似的字典
keras_vals=dict()
#在1的单个向量上运行模型
yhat=model.predict(np.one((1,输入[0]。形状[1]))
对于i,枚举中的层(model.layers[1:]):
keras_vals[layer.name+'_weights']=layer.get_weights()
keras_vals[layer.name+'_output']=yhat[i]
#比较keras\u vals和tfjs\u vals中的值
def比较值(键a、b):
对于范围内的i(len(a)):
print({0}[{1}]:不同的值={2},平均差={3}\
格式(键,i,
np.sum(a[i]!=b[i]),
np.sum(np.abs(a[i]-b[i]))/np.size(a[i])
))
对于dict.keys中的键(keras_vals):
比较变量(键、keras变量[key]、tfjs变量[key])
输出:

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input (InputLayer)           [(None, 50)]              0         
_________________________________________________________________
dense_0 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_1 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_2 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_3 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_4 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_5 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_6 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_7 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_8 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_9 (Dense)              (None, 50)                2550      
=================================================================
Total params: 25,500
Trainable params: 25,500
Non-trainable params: 0
dense_0_weights[0]: different values = 0, average difference = 0.0
dense_0_weights[1]: different values = 0, average difference = 0.0
dense_0_output[0]: different values = 0, average difference = 0.0
dense_1_weights[0]: different values = 0, average difference = 0.0
dense_1_weights[1]: different values = 0, average difference = 0.0
dense_1_output[0]: different values = 40, average difference = 1.7833709716796876e-06
dense_2_weights[0]: different values = 0, average difference = 0.0
dense_2_weights[1]: different values = 0, average difference = 0.0
dense_2_output[0]: different values = 43, average difference = 1.2047290802001953e-05
dense_3_weights[0]: different values = 0, average difference = 0.0
dense_3_weights[1]: different values = 0, average difference = 0.0
dense_3_output[0]: different values = 38, average difference = 5.3539276123046876e-05
dense_4_weights[0]: different values = 0, average difference = 0.0
dense_4_weights[1]: different values = 0, average difference = 0.0
dense_4_output[0]: different values = 43, average difference = 0.00024005889892578125
dense_5_weights[0]: different values = 0, average difference = 0.0
dense_5_weights[1]: different values = 0, average difference = 0.0
dense_5_output[0]: different values = 45, average difference = 0.0010586166381835937
dense_6_weights[0]: different values = 0, average difference = 0.0
dense_6_weights[1]: different values = 0, average difference = 0.0
dense_6_output[0]: different values = 46, average difference = 0.00515625
dense_7_weights[0]: different values = 0, average difference = 0.0
dense_7_weights[1]: different values = 0, average difference = 0.0
dense_7_output[0]: different values = 47, average difference = 0.0254345703125
dense_8_weights[0]: different values = 0, average difference = 0.0
dense_8_weights[1]: different values = 0, average difference = 0.0
dense_8_output[0]: different values = 46, average difference = 0.11546875
dense_9_weights[0]: different values = 0, average difference = 0.0
dense_9_weights[1]: different values = 0, average difference = 0.0
dense_9_output[0]: different values = 44, average difference = 0.42203125
从keras到tensorflowjs再往返后,重量相同。然而,到最后,每一层的输出都有相当大的差异

有没有办法确保Python和JS版本的模型具有相同的性能?我试着用WebGL和cpu后端运行这个程序,但同样的问题仍然存在