我在树莓派3中安装了张量流。它将预训练模型和饲料模型功能用于tf.estimator.Estimator
。我的项目是使用c ++,目前使用boost :: numpy嵌入python代码,将opencv矩阵转换为numpy类型,并将其传递给python函数进行预测并获得结果。我的模型函数定义如下。只有传播部分:
def cnn_estimator_fn(features, labels, mode):
inputs=tf.reshape(features[FEATURE_LABEL],[-1,24,16,1],name="input_node") #24 x 16 x 1, which is gray or binary image and same number of samples
conv1=tf.layers.conv2d(inputs=inputs,
filters=6,
kernel_size=[5,5],
padding='same',
activation=tf.nn.leaky_relu
)
#conv1 output shape: (batch_size,24,16,6)
pool1=tf.layers.max_pooling2d(inputs=conv1,pool_size=[2,2],strides=2,padding='valid')
#pool1 output shape: (batch_size,12,8,6)
conv2=tf.layers.conv2d(inputs=pool1,filters=12,kernel_size=[5,5],padding='same',activation=tf.nn.leaky_relu)
#conv2 output shape: (batch_size, 12,8,12)
pool2=tf.layers.max_pooling2d(inputs=conv2,pool_size=[2,2],strides=2,padding='valid')
#pool2 output shape: (batch_size, 6,4,12)
#dense fully connected layer
pool2_flat=tf.reshape(pool2,[-1,6*4*12]) #flatten pool2 output to feed in dense layer
dense1=tf.layers.dense(inputs=pool2_flat,units=144,activation=tf.nn.leaky_relu)
#apply dropout to avoid overfitting
dropout=tf.layers.dropout(inputs=dense1,rate=0.3,training=mode==tf.estimator.ModeKeys.TRAIN)
logits=tf.layers.dense(dropout,11) #input for softmax layer
嗯,它的制作很差但是我的网络规模足以满足rpi3规范。但是当我通过将这个函数输入到tf.estimator.Estimator并调用tf.estimator.predict进行预测时,预测20个图像需要3~5秒,每个形状都是[24,16,1]。这太慢了!!
我尝试了以下假设成为问题,没有一个是正确的:
(1)将vector<cv::Mat>>
转换为boost :: numpy需要太长时间:不,它不是因为花了0.00023秒。
(2)对于rpi3,可能20~30张形状[24,16,1]的图像仍然非常重:不,它不是。即使预测1张图像也需要3~4秒!!
(3)可能循环tf.Estimator.predict调用的生成器结果花费的时间太长了:不,它不是。我改为yield_single_examples=False
,在拨打next
后仍然需要3到4秒。
我调用下面的函数来传递图像并预测:
def predict_model(img_list: list):
predict_input = np.asarray(img_list,dtype=np.float32)
predict_input/=255
lpr_letter_classifier = tf.estimator.Estimator(cnn_estimator_fn,
model_dir=model_dir)
predict_input_fn = tf.estimator.inputs.numpy_input_fn({FEATURE_LABEL: predict_input},
y=None,
batch_size=len(img_list),
num_epochs=1,
shuffle=False)
pred_dict_gen = lpr_letter_classifier.predict(predict_input_fn, yield_single_examples=False)
t0=time.time()
pred_dict_list=next(pred_dict_gen)
print("pred time: "+str(time.time()-t0))
class_id = pred_dict_list["classes"]
probability = pred_dict_list["probabilities"]
所以我现在的猜测是,也许有一个代码,每当我调用predict_model(img_list: list)
时它会初始化图形,因此预测时间太长。在那里,在代码中,
t0=time.time()
pred_dict_list=next(pred_dict_gen)
print("pred time: "+str(time.time()-t0))
我在调用next(pred_dict_gen)之后测量了时间,在yield_single_examples=False
模式下,花了3~4秒。当我将预测模式更改为yield_single_examples=True
时,第一次拨打next(pred_dict_gen)
仍需要3~4秒和第二次next(pred_dict_gen)
来电,需要0.000034秒或更短时间。所以我想首先调用next
对整个输入图像执行预测,然后调用是每个图像预测的结果。哇...我强烈认为这不是rpi3性能问题,因为我看到squeezenet using raspberry pi 3执行的图像比我的输入图像更大,更大的网络大小花了不到2秒!!
即使我输入1张图像,而不是20~30张图像作为输入,仍然需要3~4秒...
是什么让tf.estimator.Estimator从我的情况变慢?