如何读取tensorflow中的utf-8编码二进制字符串? [英] How to read a utf-8 encoded binary string in tensorflow?

查看:1610
本文介绍了如何读取tensorflow中的utf-8编码二进制字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将编码的字节串转换回张量流图中的原始数组(使用张量流操作)以便在张量流模型中进行预测。字节转换的数组基于这个答案,它是谷歌云计算引擎上的tensorflow模型预测的建议输入。
$ b $ pre $ def array_request_example(input_array):
input_array = input_array.astype(np.float32)
byte_string = input_array.tostring()
string_encoded_contents = base64.b64encode(byte_string)
return string_encoded_contents.decode('utf-8')}

Tensorflow代码

  byte_string = tf.placeholder(dtype = tf.string )
audio_samples = tf.decode_raw(byte_string,tf.float32)

audio_array = np.array([1,2,3,4])
bstring = array_request_example(audio_array )
fdict = {byte_string:bstring}
with tf.Session()as sess:
[tf_samples] = sess.run([audio_samples],feed_dict = fdict)

我曾尝试使用 decode_raw decode_base64 ,但不返回原始值。



我试着将解码raw_out_type设置为不同的可能数据类型,并尝试改变我将原始数组转换为的数据类型。



那么,如何读取tensorflow中的字节数组?感谢:)



额外信息



这个目标背后的目的是为自定义估算器创建服务输入功能使用gcloud ml-engine局部预测(用于测试)和使用存储在云中的模型使用REST API进行预测。

Estimator的服务输入函数是

  def serving_input_fn():
feature_placeholders = {'b64':tf.placeholder(dtype = tf.string,
shape = [None],
name ='source')}
audio_samples = tf.decode_raw(feature_placeholders ['b64'],tf.float32)
#虚拟函数节省空间
power_spectrogram = create_spectrogram_from_audio(audio_samples)
inputs = {'spectrogram':power_spectrogram}
return tf.estimator.export.ServingInputReceiver(inputs,feature_placeholders)



Json请求



我使用.decode('utf-8'),因为当试图执行json转储base64编码的字节字符串时,我收到此错误

  raise TypeError(repr(o)+不是JSON可序列化的)
TypeError:b'longbytestring'



预测错误



传递json请求{'audio_bytes':'b64':bytestring } with gcloud local我得到错误

  PredictionError:无效输入:期望张量名称:b64,得到张量名称:[u' audio_bytes'] 

那么Google Cloud本地预测可能不会自动处理音频字节和base64转换?或者我的Estimator设置可能有些问题。



以及对REST API的请求{'instances':[{'audio_bytes':'b64':bytestring}]}给出

  {'error':'预测失败:模型执行期间出错:AbortionError(code = StatusCode.INVALID_ARGUMENT,details =Input DecodeRaw的长度为793713,不是4的倍数,float的大小是\\\\\\\\\\\\\\\\\\\\\\\\\\\ =/ job:localhost / replica:0 / task:0 / device:CPU:0](_ arg_source_0_0)]])'} 

这让我感到困惑,因为我明确地将请求定义为float,并在服务输入接收器中执行相同的操作。



删除audio_bytes来自请求和utf-8编码的字节字符串允许我得到预测,尽管在本地测试解码时,我认为音频被错误地从字节串转换而来。

解决方案

您引用的答案是假定您在CloudML上运行模型引擎的服务。该服务实际上负责JSON(包括UTF-8)和base64编码。



为了让您的代码在本地或其他环境中工作,您需要以下更改:

  def array_request_example(input_array):
input_array = input_array.astype(np.float32)
返回input_array.tostring()

byte_string = tf.placeholder(dtype = tf.string)
audio_samples = tf.decode_raw(byte_string,tf.float32)

audio_array = np.array([1,2,3,4])
bstring = array_request_example(audio_array)
fdict = {byte_string:bstring}
with tf.Session()as sess:
tf_samples = sess.run([audio_samples],feed_dict = fdict)

也就是说,基于你的代码,我怀疑你正在寻找发送数据为JSON;您可以使用 gcloud local predict 来模拟CloudML Engine的服务。或者,如果您更愿意编写自己的代码,可能是这样的:

  def array_request_examples,(input_arrays):
input_arrays是np_arrays的列表(批处理))
input_arrays =(a.astype(np.float32)for in input_arrays)
#将每个图像转换为字节串
bytes_strings =(a.tostring()for a input_arrays)
#Base64编码数据
encoded =(base64.b64encode(b)for b in bytes_strings)
#创建一个列表适合作为JSON发送到服务的图像:
instances = [{'audio_bytes':{'b64':e}} for e in encoded]
#创建一个JSON请求
return json.dumps({'instances':instances})

def parse_request(request):
#非TF来模拟不希望
#这个的CloudML服务在提交的图表中。
instances = json.loads(request)['instances']
return [base64.b64decode(i ['audio_bytes'] ['b64'])for my in]

byte_strings = tf.placeholder(dtype = tf.string,shape = [None])
decode = lambda raw_byte_str:tf.decode_raw(raw_byte_str,tf.float32)
audio_samples = tf.map_fn(decode ,byte_strings,dtype = tf.float32)

audio_array = np.array([1,2,3,4])
request = array_request_examples([audio_array])
fdict = {byte_strings:parse_request(request)}
with tf.Session()as sess:
tf_samples = sess.run([audio_samples],feed_dict = fdict)


I am trying to convert an encoded byte string back into the original array in the tensorflow graph (using tensorflow operations) in order to make a prediction in a tensorflow model. The array to byte conversion is based on this answer and it is the suggested input to tensorflow model prediction on google cloud's ml-engine.

def array_request_example(input_array):
    input_array = input_array.astype(np.float32)
    byte_string = input_array.tostring()
    string_encoded_contents = base64.b64encode(byte_string)
    return string_encoded_contents.decode('utf-8')}

Tensorflow code

byte_string = tf.placeholder(dtype=tf.string)
audio_samples = tf.decode_raw(byte_string, tf.float32)

audio_array = np.array([1, 2, 3, 4])
bstring = array_request_example(audio_array)
fdict = {byte_string: bstring}
with tf.Session() as sess:
    [tf_samples] = sess.run([audio_samples], feed_dict=fdict)

I have tried using decode_raw and decode_base64 but neither return the original values.

I have tried setting the the out_type of decode raw to the different possible datatypes and tried altering what data type I am converting the original array to.

So, how would I read the byte array in tensorflow? Thanks :)

Extra Info

The aim behind this is to create the serving input function for a custom Estimator to make predictions using gcloud ml-engine local predict (for testing) and using the REST API for the model stored on the cloud.

The serving input function for the Estimator is

def serving_input_fn():
    feature_placeholders = {'b64': tf.placeholder(dtype=tf.string,
                                                  shape=[None],
                                                  name='source')}
    audio_samples = tf.decode_raw(feature_placeholders['b64'], tf.float32)
    # Dummy function to save space
    power_spectrogram = create_spectrogram_from_audio(audio_samples)
    inputs = {'spectrogram': power_spectrogram}
    return tf.estimator.export.ServingInputReceiver(inputs, feature_placeholders)

Json request

I use .decode('utf-8') because when attempting to json dump the base64 encoded byte strings I receive this error

raise TypeError(repr(o) + " is not JSON serializable")
TypeError: b'longbytestring'

Prediction Errors

When passing the json request {'audio_bytes': 'b64': bytestring} with gcloud local I get the error

PredictionError: Invalid inputs: Expected tensor name: b64, got tensor name: [u'audio_bytes']

So perhaps google cloud local predict does not automatically handle the audio bytes and base64 conversion? Or likely somethings wrong with my Estimator setup.

And the request {'instances': [{'audio_bytes': 'b64': bytestring}]} to REST API gives

{'error': 'Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details="Input to DecodeRaw has length 793713 that is not a multiple of 4, the size of float\n\t [[Node: DecodeRaw = DecodeRaw[_output_shapes=[[?,?]], little_endian=true, out_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_source_0_0)]]")'}

which confuses me as I explicitly define the request to be a float and do the same in the serving input receiver.

Removing audio_bytes from the request and utf-8 encoding the byte strings allows me to get predictions, though in testing the decoding locally, I think the audio is being incorrectly converted from the byte string.

解决方案

The answer that you referenced, is written assuming you are running the model on CloudML Engine's service. The service actually takes care of the JSON (including UTF-8) and base64 encoding.

To get your code working locally or in another environment, you'll need the following changes:

def array_request_example(input_array):
    input_array = input_array.astype(np.float32)
    return input_array.tostring()

byte_string = tf.placeholder(dtype=tf.string)
audio_samples = tf.decode_raw(byte_string, tf.float32)

audio_array = np.array([1, 2, 3, 4])
bstring = array_request_example(audio_array)
fdict = {byte_string: bstring}
with tf.Session() as sess:
    tf_samples = sess.run([audio_samples], feed_dict=fdict)

That said, based on your code, I suspect you are looking to send data as JSON; you can use gcloud local predict to simulate CloudML Engine's service. Or, if you prefer to write your own code, perhaps something like this:

def array_request_examples,(input_arrays):
  """input_arrays is a list (batch) of np_arrays)"""
  input_arrays = (a.astype(np.float32) for a in input_arrays)
  # Convert each image to byte strings
  bytes_strings = (a.tostring() for a in input_arrays)
  # Base64 encode the data
  encoded = (base64.b64encode(b) for b in bytes_strings)
  # Create a list of images suitable to send to the service as JSON:
  instances = [{'audio_bytes': {'b64': e}} for e in encoded]
  # Create a JSON request
  return json.dumps({'instances': instances})

def parse_request(request):
  # non-TF to simulate the CloudML Service which does not expect
  # this to be in the submitted graphs.
  instances = json.loads(request)['instances']
  return [base64.b64decode(i['audio_bytes']['b64']) for i in instances]

byte_strings = tf.placeholder(dtype=tf.string, shape=[None])
decode = lambda raw_byte_str: tf.decode_raw(raw_byte_str, tf.float32)
audio_samples = tf.map_fn(decode, byte_strings, dtype=tf.float32)

audio_array = np.array([1, 2, 3, 4])
request = array_request_examples([audio_array])
fdict = {byte_strings: parse_request(request)}
with tf.Session() as sess:
  tf_samples = sess.run([audio_samples], feed_dict=fdict)

这篇关于如何读取tensorflow中的utf-8编码二进制字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆