How to serialize tensorflow tensor as raw byte string - python

I'm trying to get tensorflow to write a tensor to something that would be ingestible by ffmpeg (e.g. PCM 32-bit floating-point little-endian). I'm not seeing a simple way to do this. tf.io.serialize_tensor seems to transform to TensorProto proto.
I can't use tensorflow-io because this needs to work in tensorflow-serving. tf.audio.write_wav doesn't work because it only supports a bit-depth of int16 and I need float32.
I'd like something like:
serialized_foo = magic_encoding(foo) # foo is a tensor of type float32 and serialized_foo is a string
tf.io.write_file("foo.raw", serialized_foo)
It seems like tf.io.serialize_tensor gets part of the way there. From what I can tell quickly inspecting the file, the protobuf format appears to be the raw byte string plus some sort of short header? Would it be possible just to modify the output of tf.io.serialize_tensor slightly, dropping the header?

Related

How to read complex data from TB size binary file, fast and keep the most accuracy?

Use Python 3.9.2 read the beginning of TB size binary file (piece of it) as below:
file=open(filename,'rb')
bytes=file.read(8)
print(bytes)
b'\x14\x00\x80?\xb5\x0c\xf81'
I tried np.fromfile np.fromfile(np.complex64) ways to read the file filename.
float_data1 = np.fromfile(filename,np.float32)
float_data2 = np.fromfile(filename,np.complex64)
As the binary file always bigger than 500GB,even TB size,how to read complex data from TB size binary file, fast and keep the most acuuracy?
This is related to your ham post.
samples = np.fromfile(filename, np.complex128)
and
Those codes equal to -1.9726906072368233e-31,+3.6405886029665884e-23.
No, they don't equal that. That's just your interpretation of bytes as float64. That interpretation is incorrect!
You assume these are 64-bit floating point numbers. They are not; you really need to stop assuming that; it's wrong, and we can't help you if you still act as if it were 64-bit floats forming a 128 bit complex value.
Besides documents,I compare the byte content in the answer,that is more than reading docs.
As I already pointed out, that is wrong. Your computer can read anything as any type, just as you tell them, even if it's not the original type it's been stored in. You stored complex64, but read complex128. That's why your values are so inplausible.
It's 32-bit floats, forming a 64 bit complex value. The official block documentation for the file sink also points that out, and even explains the numpy dtype you need to use!
Anyways, you can use numpy's memmap functionality to map the file contents without reading them all to RAM. That works. Again, you need to use the right dtype, which is, to repeat this the 10th time, not complex128.
It's really easy:
data = numpy.memmap(filename, dtype=numpy.complex64)
done.

How to inspect the structure of a TFRecord file in TensorFlow 1.13?

I am rather confused by the TFRecord file format, and how to use it. I have a TFRecord, but have little idea as to what it exactly contains and what its structure is. How can I print and inspect a TFRecord and/or its TFExamples? I am essentially asking the same as this question, but the answers to that one are outdated. Printing the output_shapes, output_types or output_classes of my TFRecord tells me nothing (why?). The tf.io.tf_record_iterator() function is deprecated, but TFRecord datasets now appear themselves iterable (but then why would one still need the other iterators?). However, simply printing each iteration returns gibberish, and tf.train.Example.FromString(example) throws a TypeError: a bytes-like object is required, not 'tensorflow.python.framework.ops.EagerTensor'. It's all rather confusing. Simply initializing a tf.data.Dataset using from_tensor_slices() seems so much easier to inspect, and actually gives information on its shape and type.
You can use tf.python_io.tf_record_iterator to inspect tfrecords file. It creates a generato. To access single example you need to iterate over it:
for str_rec in tf.python_io.tf_record_iterator('file.tfrecords'):
example = tf.train.Example()
example.ParseFromString(str_rec)
print(dict(example.features.feature).keys())
This will outputs feature names and type(bytes_list in this case)
dict_keys(['label', 'width', 'image_raw', 'height'])
To output datatypes also, you'd need
print(dict(example.features.feature).values())
But this will print raw string as well, and you can hit screen length limit.
When you know how it was encoded you can access values by
string = example.features.feature['image_raw'].bytes_list.value[0]
output = np.fromstring(string, dtype)
You can read more about it here https://www.tensorflow.org/tutorials/load_data/tf_records
EDIT:
IF eager mode is on, you can directly iterate over dataset object, using either numpy to decode
for str_rec in tf.data.TFRecordDataset('file.tfrecords'):
output = np.fromstring(str_rec.numpy(), dtype))
or native TF. tf.io.decode_raw(str_rec, tf.uint8))
However, this will give you a flatten array, which will not carry any information about sizes of image dimensions for example

Converting a string to a wav file in python

I'm new to Python, and to programming in general, so please don't take it too hard on me
I am currently trying to figure out how to write a new wav file using a string (which was derived from another wave file's data)
I performed a fourier transform on that file's data, so now I'm trying to get the values from the Fourier transform written into a new wav file.
I can only use numpy and the included Python library, not scipy
According to the documentation, I have to use wave_write(), but I have no idea what the code is supposed to look like for this function.
I think I'm supposed to do something pertaining to
wave_write.writeframesraw(data)
Then again, not totally sure of what to do.
Any help is greatly appreciated!
Two functions in NumPy can help you with this: astype and tostring.
If you have an array of sound samples, say X then you can convert it to the right format using astype. This will depend on what data type is used in the wav file, and the library you are using to save it. But let us for this example say you want to store it as 16 bit integer. You'll need to scale X according to the data type selected - so in this case the range will be -32768 to 32767 for a signed 16 bit int. If you sample goes from -1.0 to 1.0 then you can simply multiply with 32767.
The next part is simply to convert it to a string using tostring, it could look something the following:
scaled = X * 32767
scaled.astype('<i2').tostring()
You can find the documentation for the functions here:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.astype.html
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.tostring.html

Why do we need endianness here?

I am reading a source-code which downloads the zip-file and reads the data into numpy array. The code suppose to work on macos and linux and here is the snippet that I see:
def _read32(bytestream):
dt = numpy.dtype(numpy.uint32).newbyteorder('>')
return numpy.frombuffer(bytestream.read(4), dtype=dt)
This function is used in the following context:
with gzip.open(filename) as bytestream:
magic = _read32(bytestream)
It is not hard to see what happens here, but I am puzzled with the purpose of newbyteorder('>'). I read the documentation, and know what endianness mean, but can not understand why exactly developer added newbyteorder (in my opinion it is not really needed).
That's because data downloaded is in big endian format as described in source page: http://yann.lecun.com/exdb/mnist/
All the integers in the files are stored in the MSB first (high
endian) format used by most non-Intel processors. Users of Intel
processors and other low-endian machines must flip the bytes of the
header.
It is just a way of ensuring that the bytes are interpreted from the resulting array in the correct order, regardless of a system's native byteorder.
By default, the built in NumPy integer dtypes will use the byteorder that is native to your system. For example, my system is little-endian, so simply using the dtype numpy.dtype(numpy.uint32) will mean that values read into an array from a buffer with the bytes in big-endian order will not be interpreted correctly.
If np.frombuffer is to meant to recieve bytes that are known to be in a particular byteorder, the best practice is to modify the dtype using newbyteorder. This is mentioned in the documents for np.frombuffer:
Notes
If the buffer has data that is not in machine byte-order, this should be specified as part of the data-type, e.g.:
>>> dt = np.dtype(int)
>>> dt = dt.newbyteorder('>')
>>> np.frombuffer(buf, dtype=dt)
The data of the resulting array will not be byteswapped, but will be
interpreted correctly.

Saving mat files in different numerical data formats in scipy.io.savemat

I know this is very simple and I can't believe I haven't found anything on this anywhere but here it goes:
I have a large, high dimensional matrix in python that I want to save in .mat format (for matlab).
I'm using the scipy.io.savemat method to save this matrix but it's always saved as double. I would like to save it as something of lower precision, like single or 16 bit float.
I convert the array to a low-precision data type before saving but it's always saved as double. Is there really no way of saving mat files in a lower-precision float type?
.savemat does not seem to take a dtype argument.
import scipy as sp
sp.io.savemat('test.mat', {'test': sp.array([0.001, 1, 1.004], dtype='Float16')})
Apparently it needs to be either single or double. scipy.io.savemat() does not support other float precisions and it'll casually default to double if it doesn't like your dtype without warning.

Categories

Resources