Toybrick

标题: 3399pro来做语音识别,pb模型转rknn后效果非常不好 [打印本页]

作者: Hhhhlnlnlnh    时间: 2019-5-14 18:47
标题: 3399pro来做语音识别,pb模型转rknn后效果非常不好
用tensorflow模型测试效果是可以识别音频转文字,但把pb转rknn后无法识别,输出结果相差非常大,不确定原因出在哪边,分析可能原因有以下几点:
1、模型转换:由于rknn.build(do_quantization=True, dataset='./dataset.txt')需要训练集,而我的是音频不是图片因此是将音频转换成模型输入input的格式后保存成npy文件,不知道这步是否出了问题?我没有在rknn-toolkit上找到详细的npy格式说明。(且设置do_quantization=False输出结果也完全不对)
[attach]275[/attach]
2、数据输入:我的模型输入是(1600,200,1),我在inference时是直接把音频转成(1600,200,1)的x_in然后输出out = rknn.inference(inputs=[x_in]),这个结果和tensorflow跑出来结果分布完全不对
备注:由于语音识别也是将音频信号转化成语音图谱即图像来用cnn识别,因此应该在板子上和图像识别不会有太大差异
[attach]276[/attach]
不知道问题是出在上面哪点,希望能有人帮忙解决

作者: bobby_jiang    时间: 2019-5-14 20:25
先试一下不要量化的,看看结果。
作者: Hhhhlnlnlnh    时间: 2019-5-14 21:13
不量化的也测试过了,结果还是完全不对,可是感觉模型数据的输入应该也没有问题,所以我还是没找到问题在哪
作者: Hhhhlnlnlnh    时间: 2019-5-14 23:04
发现了可能是数据输入的问题,我的模型输入是[0,2.5]范围的数据float32,因此模型转换改成rknn.config(channel_mean_value='0 0 0 1', reorder_channel='0 1 2'),且在inference过程中,输入数据默认是uint8,但我的是浮点数,因此在后面加data_type=float32,但这样会出错,因此改成data_type=np.float32,但inference一直等待了十几分钟还没结果,是npu对输入浮点数计算太慢导致的吗?改成np.float16依然等不到结果
作者: bobby_jiang    时间: 2019-5-15 11:29
先试浮点。
模型转换的时候:
1、rknn.config()xxx
2、rknn.load_tensorflow(tf_pb='./xxx.pb',inputs=['xxx'],outputs=['xxx'], input_size_list=[[1,1600, 200]])
3、rknn.build(do_quantization=False, dataset='./dataset.txt', pre_compile=False),浮点用不到dataset.txt

推理的时候:
1、outputs, = rknn.inference(inputs=xxx,data_type='float32')
作者: Hhhhlnlnlnh    时间: 2019-5-15 20:23
还是不行,下面是我的模型转换代码,由于模型输入是[1600,200,1],如果改成input_size_list=[[1,1600,200]]会报错,
rknn.config()
rknn.load_tensorflow(tf_pb='./model.pb',
                     inputs=['the_input'],
                     outputs=['Activation0/truediv'],
                     input_size_list=[[1600, 200, 1]])
rknn.build(do_quantization=False)
推理的代码是out = rknn.inference(inputs=[x_in], data_type='float32')。
最终是softmax得到的out应该总和为1,keras跑pb的时候是对的,但rknn inference后的out总和非常大,不是1,所以感觉不是数据输入的问题,应该是模型转换不知道哪边出了差错
作者: Hhhhlnlnlnh    时间: 2019-5-15 20:42
========================================================================
Layer ID    Name                                         Operator            Time(us)
2           ConvolutionReluPoolingLayer2_2               CONVOLUTION         9352
3           ConvolutionReluPoolingLayer2_2               CONVOLUTION         146823
4           ConvolutionReluPoolingLayer2_2               CONVOLUTION         78806
5           ConvolutionReluPoolingLayer2_2               CONVOLUTION         154880
6           ConvolutionReluPoolingLayer2_2               CONVOLUTION         89746
7           ConvolutionReluPoolingLayer2_2               CONVOLUTION         174313
8           ConvolutionReluPoolingLayer2_2               CONVOLUTION         43653
9           ConvolutionReluPoolingLayer2_2               CONVOLUTION         43651
10          PoolingLayer2_0                              POOLING             362
11          ConvolutionReluPoolingLayer2_2               CONVOLUTION         43651
12          ConvolutionReluPoolingLayer2_2               CONVOLUTION         43650
13          PoolingLayer2_0                              POOLING             396
14          TensorTranspose_0                            TENSOR_TRANS        9224
15          ConvolutionReluPoolingLayer2_2               CONVOLUTION         10956
16          TensorTranspose_0                            TENSOR_TRANS        191
17          TensorAdd_1                                  TENSOR_ADD          309
18          ActivationLayer_0                            ACTIVATION          148
19          TensorTranspose_0                            TENSOR_TRANS        180
20          ConvolutionReluPoolingLayer2_2               CONVOLUTION         4913
21          TensorTranspose_0                            TENSOR_TRANS        1725
22          TensorAdd_1                                  TENSOR_ADD          1249
23          SoftmaxLayer_0                               SOFTMAX             104672
Total Time(us): 962850
FPS: 1.04
========================================================================
我发现我的模型per_debug的时候不是从第一层开始算的,而且有的pool是综合再ConvolutionReluPoolingLayer2_2,有的pool再PoolingLayer2_0 ,但是我的网络是标准的vgg,和例程demo的debug出来的不一样,难道是哪些层不支持吗
作者: Hhhhlnlnlnh    时间: 2019-5-15 20:49
                input_data = Input(name='the_input', shape=(self.AUDIO_LENGTH, self.AUDIO_FEATURE_LENGTH, 1))
               
                layer_h1 = Conv2D(32, (3,3), use_bias=False, activation='relu', padding='same', kernel_initializer='he_normal')(input_data) # 卷积层
                layer_h1 = Dropout(0.05)(layer_h1)
                layer_h2 = Conv2D(32, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h1) # 卷积层
                layer_h3 = MaxPooling2D(pool_size=2, strides=None, padding="valid")(layer_h2) # 池化层
                #layer_h3 = Dropout(0.2)(layer_h2) # 随机中断部分神经网络连接,防止过拟合
                layer_h3 = Dropout(0.05)(layer_h3)
                layer_h4 = Conv2D(64, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h3) # 卷积层
                layer_h4 = Dropout(0.1)(layer_h4)
                layer_h5 = Conv2D(64, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h4) # 卷积层
                layer_h6 = MaxPooling2D(pool_size=2, strides=None, padding="valid")(layer_h5) # 池化层
               
                layer_h6 = Dropout(0.1)(layer_h6)
                layer_h7 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h6) # 卷积层
                layer_h7 = Dropout(0.15)(layer_h7)
                layer_h8 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h7) # 卷积层
                layer_h9 = MaxPooling2D(pool_size=2, strides=None, padding="valid")(layer_h8) # 池化层
               
                layer_h9 = Dropout(0.15)(layer_h9)
                layer_h10 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h9) # 卷积层
                layer_h10 = Dropout(0.2)(layer_h10)
                layer_h11 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h10) # 卷积层
                layer_h12 = MaxPooling2D(pool_size=1, strides=None, padding="valid")(layer_h11) # 池化层
               
                layer_h12 = Dropout(0.2)(layer_h12)
                layer_h13 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h12) # 卷积层
                layer_h13 = Dropout(0.2)(layer_h13)
                layer_h14 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h13) # 卷积层
                layer_h15 = MaxPooling2D(pool_size=1, strides=None, padding="valid")(layer_h14) # 池化层
               
                #test=Model(inputs = input_data, outputs = layer_h12)
                #test.summary()
               
                layer_h16 = Reshape((200, 3200))(layer_h15) #Reshape层
                #layer_h5 = LSTM(256, activation='relu', use_bias=True, return_sequences=True)(layer_h4) # LSTM层
                #layer_h6 = Dropout(0.2)(layer_h5) # 随机中断部分神经网络连接,防止过拟合
                layer_h16 = Dropout(0.3)(layer_h16)
                layer_h17 = Dense(128, activation="relu", use_bias=True, kernel_initializer='he_normal')(layer_h16) # 全连接层
                layer_h17 = Dropout(0.3)(layer_h17)
                layer_h18 = Dense(self.MS_OUTPUT_SIZE, use_bias=True, kernel_initializer='he_normal')(layer_h17) # 全连接层
               
                y_pred = Activation('softmax', name='Activation0')(layer_h18)
                model_data = Model(inputs = input_data, outputs = y_pred)

我的keras模型是上面的代码,不知道有没有rknn不支持的层吗?
作者: bobby_jiang    时间: 2019-5-16 11:47
你模型当中的层没有什么特殊的,都支持。
还是怀疑你input数据有问题,你试一下把数据拍平了,转成[320000,1]输入,然后在你的模型中reshape成[1600, 200, 1]。
作者: protossw512    时间: 2019-5-17 01:59
我之前报过错误,长宽不同的输入,rknn有bug。。。转换和inference的时候长宽的先后不同,代码和模型都提供了,结果也没人查。。
作者: bobby_jiang    时间: 2019-5-17 11:58
你按我的建议先做一下吧,目的是保证你的输入长和宽数据送入卷积。
这个方式我之前验证过可行的。
作者: Hhhhlnlnlnh    时间: 2019-5-17 15:26
感觉应该是rknn不支持长宽不同的输入,不过我后来看到官方例程车牌识别要识别的图片是32x40的单通道图片,他是先转化为一维向量输入模型,然后在模型里面reshape识别,我也打算先试试这种方法
作者: Hhhhlnlnlnh    时间: 2019-5-17 15:26
感觉应该是rknn不支持长宽不同的输入,不过我后来看到官方例程车牌识别要识别的图片是32x40的单通道图片,他是先转化为一维向量输入模型,然后在模型里面reshape识别,我也打算先试试这种方法
作者: Hhhhlnlnlnh    时间: 2019-5-17 15:28
bobby_jiang 发表于 2019-5-17 11:58
你按我的建议先做一下吧,目的是保证你的输入长和宽数据送入卷积。
这个方式我之前验证过可行的。 ...

好的我是测试一下
作者: Hhhhlnlnlnh    时间: 2019-5-18 23:04
我将模型的变成320000,再模型内部做reshape到(1600,200,1),这样转换之后pb模型可以正常使用,但rknn模型inference时候就报错:
E Catch exception when init model!
T Traceback (most recent call last):
T   File "rknn/api/rknn_base.py", line 625, in rknn.api.rknn_base.RKNNBase.inference
T   File "rknn/api/rknn_runtime.py", line 275, in rknn.api.rknn_runtime.RKNNRuntime.build_graph
T Exception: RKNN init failed. error code: RKNN_ERR_MODEL_INVALID

模型输入reshape代码
                input_data = Input(name='the_input', shape=(self.INPUT_SIZE, 1), dtype='float32')
                input_wavImage = Reshape((self.AUDIO_LENGTH, self.AUDIO_FEATURE_LENGTH, 1), name='Reshape')(input_data)
rknn模型转换代码
        rknn.config()
        # Load TensorFlow Model
        print('--> Loading model')
        rknn.load_tensorflow(tf_pb='./model.pb',
                             inputs=['the_input'],
                             outputs=['Activation0/truediv'],
                             input_size_list=[[320000, 1]])
作者: protossw512    时间: 2019-5-21 06:05
Hhhhlnlnlnh 发表于 2019-5-18 23:04
我将模型的变成320000,再模型内部做reshape到(1600,200,1),这样转换之后pb模型可以正常使用,但rknn模型i ...

对,因为它转换的时候和inference的时候长宽两个维度的顺序反了,所以可以正产转换,但是没办法读取来做inference
作者: bobby_jiang    时间: 2019-5-21 10:30
你现在用的rknn-toolkit是什么版本?
另外,你把原始模型和rknn模型,还有代码都贴上来。
作者: Hhhhlnlnlnh    时间: 2019-5-21 13:48
本帖最后由 Hhhhlnlnlnh 于 2019-5-21 13:49 编辑
bobby_jiang 发表于 2019-5-21 10:30
你现在用的rknn-toolkit是什么版本?
另外,你把原始模型和rknn模型,还有代码都贴上来。 ...

rknn-toolkit版本是0.9.9
原始pb模型和rknn模型放在百度云盘里
链接:https://pan.baidu.com/s/1doU0uLZXVBMv9EZ6C_r4rA
提取码:rlsq


keras模型代码
  1. input_data = Input(name='the_input', shape=(320000, 1), dtype='float32')

  2. input_wavImage = Reshape((1600, 200, 1), name='Reshape')(input_data)

  3. layer_h1 = Conv2D(32, (3,3), use_bias=False, activation='relu', padding='same', kernel_initializer='he_normal')(input_wavImage) # 卷积层
  4. layer_h1 = Dropout(0.05)(layer_h1)
  5. layer_h2 = Conv2D(32, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h1) # 卷积层
  6. layer_h3 = MaxPooling2D(pool_size=2, strides=None, padding="valid")(layer_h2) # 池化层
  7. #layer_h3 = Dropout(0.2)(layer_h2) # 随机中断部分神经网络连接,防止过拟合
  8. layer_h3 = Dropout(0.05)(layer_h3)
  9. layer_h4 = Conv2D(64, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h3) # 卷积层
  10. layer_h4 = Dropout(0.1)(layer_h4)
  11. layer_h5 = Conv2D(64, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h4) # 卷积层
  12. layer_h6 = MaxPooling2D(pool_size=2, strides=None, padding="valid")(layer_h5) # 池化层

  13. layer_h6 = Dropout(0.1)(layer_h6)
  14. layer_h7 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h6) # 卷积层
  15. layer_h7 = Dropout(0.15)(layer_h7)
  16. layer_h8 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h7) # 卷积层
  17. layer_h9 = MaxPooling2D(pool_size=2, strides=None, padding="valid")(layer_h8) # 池化层

  18. layer_h9 = Dropout(0.15)(layer_h9)
  19. layer_h10 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h9) # 卷积层
  20. layer_h10 = Dropout(0.2)(layer_h10)
  21. layer_h11 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h10) # 卷积层
  22. layer_h12 = MaxPooling2D(pool_size=1, strides=None, padding="valid")(layer_h11) # 池化层

  23. layer_h12 = Dropout(0.2)(layer_h12)
  24. layer_h13 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h12) # 卷积层
  25. layer_h13 = Dropout(0.2)(layer_h13)
  26. layer_h14 = Conv2D(128, (3,3), use_bias=True, activation='relu', padding='same', kernel_initializer='he_normal')(layer_h13) # 卷积层
  27. layer_h15 = MaxPooling2D(pool_size=1, strides=None, padding="valid")(layer_h14) # 池化层

  28. #test=Model(inputs = input_data, outputs = layer_h12)
  29. #test.summary()

  30. layer_h16 = Reshape((200, 3200))(layer_h15) #Reshape层
  31. #layer_h5 = LSTM(256, activation='relu', use_bias=True, return_sequences=True)(layer_h4) # LSTM层
  32. #layer_h6 = Dropout(0.2)(layer_h5) # 随机中断部分神经网络连接,防止过拟合
  33. layer_h16 = Dropout(0.3)(layer_h16)
  34. layer_h17 = Dense(128, activation="relu", use_bias=True, kernel_initializer='he_normal')(layer_h16) # 全连接层
  35. layer_h17 = Dropout(0.3)(layer_h17)
  36. layer_h18 = Dense(1422, use_bias=True, kernel_initializer='he_normal')(layer_h17) # 全连接层
复制代码


rknn模型转换代码,且log中没有error或warning
  1. from rknn.api import RKNN

  2. rknn = RKNN(verbose=True, verbose_file='./build.log')
  3. rknn.config()

  4. print('--> Loading model')
  5. rknn.load_tensorflow(tf_pb='./model.pb',
  6.                      inputs=['the_input'],
  7.                      outputs=['Activation0/truediv'],
  8.                      input_size_list=[[320000, 1]])
  9. print('done')

  10. # Build Model
  11. print('--> Building model')
  12. rknn.build(do_quantization=False)
  13. print('done')

  14. rknn.export_rknn('./model.rknn')

  15. rknn.release()
复制代码


rknn模型inference代码
  1. rknn = RKNN()
  2. rknn.load_rknn('./model.rknn')
  3. ret = rknn.init_runtime(target='rk3399pro')
  4. if ret != 0:
  5.     print('Init runtime environment failed')
  6.     exit(ret)
  7. print('done')

  8. # x_in.size  = (1, 320000, 1)
  9. x_in, in_len = load_wav_input(filename)

  10. out = rknn.inference(inputs=[x_in], data_type='float32')
复制代码


同样的环境原来模型没用Reshape直接输入(1600,200,1)可以inference,但最后softmax后np.sum(out)应该=200,pb模型是这样,但rknn模型np.sum(out)是几千完全不对,因此想输入一维向量在模型中reshape,但出之前的错误

作者: Hhhhlnlnlnh    时间: 2019-5-21 13:51
protossw512 发表于 2019-5-21 06:05
对,因为它转换的时候和inference的时候长宽两个维度的顺序反了,所以可以正产转换,但是没办法读取来做i ...

可是照你这样说的话模型中就不支持长宽不同的输入reshape操作了?
作者: bobby_jiang    时间: 2019-5-23 14:14
我们的rknn-toolkit1.0.0已经发布,另外toybrick prod的V1.2版本也已经发布了。
你把固件和rknn-toolkit升级到最新版本。




欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3