Obtain torch.tensor from string of floats - python

We can convert 1 dimensional array of floats, stored as a space separated numbers in text file, in to a numpy array or a torch tensor as follows.
line = "1 5 3 7 4"
np_array = np.fromstring(line, dtype='int', sep=" ")
np_array
>> array([1, 5, 3, 7, 4])
And to convert above numpy array to a torch tensor, we can do following :
torch_tensor = torch.tensor(np_array)
torch_tensor
>>tensor([1, 5, 3, 7, 4])
How can I convert a string of numbers separated by space in to a torch.Tensor directly without
converting them to a numpy array? We can also do this by fist splitting the string at a space, mapping them to int or float, and then feeding it to torch.tensor. But like numpy's fromstring, is there any such method in pytorch?

What about
x = torch.tensor(list(map(float, line.split(' '))), dtype=torch.float32)

PyTorch currently has no analogous function to numpy's fromstring. You can either use the numpy function itself, or by splitting and mapping as you say.

Related

Remove elements by index from a string within numpy array

I have the following example array with strings:
['100000000' '101010100' '110101010' '111111110']
I would like to be able to remove some elements by index in each of the strings in the array simultaneously. For example if I will remove elements with index 6 and 8, I should receive the following outcome:
['1000000' '1010110' '1101000' '1111110']
All my attempts failed so far maybe because the string is immutable, but am not sure whether I have to convert and if so - to what and how.
import numpy as np
a = np.array(['100000000', '101010100', '110101010', '111111110'])
list(map(lambda s: "".join([c for i, c in enumerate(str(s)) if i not in {5, 7}]), a))
Returns:
['1000000', '1010110', '1101000', '1111110']
Another way to do this is to convert a into a 2D array of single characters, mask out the values you don't want, and then convert back into a 1D array of strings.
import numpy as np
a = np.array(['100000000', '101010100', '110101010', '111111110'])
b = a.view('U1').reshape(*a.shape, -1)
mask = np.ones(b.shape[-1], dtype=bool)
mask[[5, 7],] = False
b = b[:, mask].reshape(-1).view(f'U{b.shape[-1] - (~mask).sum()}')

Is a set converted to numpy array?

I am creating a ndarray using:
import numpy as np
arr=np.array({1,2})
print(arr, type(arr))
which outputs
{1, 2} <class 'numpy.ndarray'>
If its type is numpy.ndarray, then o/p must be in square brackets like [1,2]?
Thanks
Yes, but it's because you put on the function np.array a set and not a list
if you try this:
import numpy as np
arr=np.array([1,2])
print(arr, type(arr))
you get:
[1 2] <class 'numpy.ndarray'>
This does something slightly different than you might imagine. Instead of constructing an array with the data you specify, the numbers 1 and 2, you're actually building an array of type object. See below:
>>> np.array({1, 2)).dtype
dtype('O')
This is because sets are not "array-like", in NumPy's terminology, in particular they are not ordered. Thus the array construction does not build an array with the contents of the set, but with the set itself as a single object.
If you really want to build an array from the set's contents you could do the following:
>>> x = np.fromiter(iter({1, 2}), dtype=int)
>>> x.dtype
dtype('int64')
Edit: This answer helps explain how various types are used to build an array in NumPy.
It returns a numpy array object with no dimensions. A set is an object. It is similar to passing numpy.array a number (without brackets). See the difference here:
arr=np.array([1])
arr.shape: (1,)
arr=np.array(1)
arr.shape: ()
arr=np.array({1,2})
arr.shape: ()
Therefore, it treats your entire set as a single object and creates a numpy array with no dimensions that only returns the set object. Sets are not array-like and do not have order, hence according to numpy array doc they are not converted to arrays like you expect. If you wish to create a numpy array from a set and you do not care about its order, use:
arr=np.fromiter({1,2},int)
arr.shape: (2,)
The repr display of ipython may make this clearer:
In [162]: arr=np.array({1,2})
In [163]: arr
Out[163]: array({1, 2}, dtype=object)
arr is a 0d array, object dtype, contain 1 item, the set.
But if we first turn the set into a list:
In [164]: arr=np.array(list({1,2}))
In [165]: arr
Out[165]: array([1, 2])
now we have a 1d (2,) integer dtype array.
np.array(...) converts list (and list like) arguments into a multdimensional array. A set is not sufficiently list-like.

How to convert the 'dtype = object' NumPy array into 'dtype = float' array?

This problem is caused by using SymPy to find reduced row echelon matrix, I have screen capture below. By using SymPy, I can get a NumPy array of object, it is quite confusing for me here. First, I don't see numbers in the rref matrix is wrapped by ' ' or " ",how come they are 'object'. Second, is there any way to convert it into a 'dtype = float' np.array?
M = sy.Matrix([[4, 0, 11, 3], [7, 23, -3, 7], [12, 11, 3, -4]])
M_rref = M.rref()
M_rref = np.array(M_rref[0])
M_rref.astype(float)
Short answer:
M_rref.astype(float) will fix your problem.
Long answer:
Why does this happen?
In order to find out, try going back to your matrix M and try the following:
>>> print(M[0])
>>> print(type(M[0]))
You will get:
4
sympy.core.numbers.Integer
That's why. Even though it says it's 4, it's actually a SymPy object that is stored inside the SymPy matrices. And that's the way it should be: SymPy is for symbolic mathematics. Therefore, when you convert it to a numpy array, NumPy will recognize sympy.core.numbers.Integer as an object.
Hope that answers your question.
In this PR there is a note about incorrect conversion of numpy matrices to SymPy matrices. Using that (and not float, which I don' think is intended to convert contents of an object to floats) I would do:
>>> sy.Matrix(M.rows, M.cols, [sympify(x) for x in M_rref]).n()
This should give you a SymPy matrix with entries evaluated as floats.

How to convert string formed by numpy.array2string back to array?

I have a string of numpy array which is converted by using numpy.array2string
Now, I want back my numpy array.
Any suggestions for how I can achieve it?
My Code:
img = Image.open('test.png')
array = np.array(img)
print(array.shape)
array_string = np.array2string(array, precision=2, separator=',',suppress_small=True)
P.S My array is a 3D array not 1D and I am using , separators, not the default blank
This is kind of a hack, but may be the simplest solution.
import numpy as np
array = np.array([[[1,2,3,4]]]) # create a 3D array
array_string = np.array2string(array, precision=2, separator=',', suppress_small=True)
print(array_string) #=> [[[1,2,3,4]]]
# Getting the array back to numpy
new_array = eval('np.array(' + array_string + ')')
Since the string representation of the array matches the argument we pass to build such array, using eval successfully creates the same array.
Probably is best if you enclose this in a try except in case the string format isn't valid.
Update: I just tried this and it worked for me:
import numpy as np
from PIL import Image
img = Image.open('2.jpg')
arr = np.array(img)
# get shape and type
array_shape = arr.shape
array_data_type = arr.dtype.name
# converting to string
array_string = arr.tostring()
# converting back to numpy array
new_arr = np.frombuffer(array_string, dtype=array_data_type).reshape(array_shape)
print(new_arr)
For converting numpy array to string, I used arr.tostring() instead of arr.array2string(). After that converting back to numpy array works with np.frombuffer().
numpy.array2string() gives output string as : '[1, 2]' so you need to remove the braces to get to the elements just separated by some separator.
Here is a small example to extract the list elements from the string by removing the braces and then using np.fromstring(). As you have used ',' as the separator when creating the string, I am using the same to delimit the string for conversion.
import numpy as np
x = '[1, 2]'
x = x.replace('[','')
x = x.replace(']','')
a = np.fromstring(x, dtype=int, sep=",")
print(a)
#Output: [1 2]
import numpy as np
def fromStringArrayToFloatArray(stringArray):
array = [float(s) for s in stringArray[1:-1].split(' ')]
return np.array(array)
x = np.array([1.1, 2.2, 3.3, 4.4])
y = np.array2string(x)
z = fromStringArrayToFloatArray(y)
x == z
You can use a list comprehension to split your array into different strings and then, convert them to float (or whatever)

Converting a matrix created with MATLAB to Numpy array with a similar syntax

I'm playing with the code snippets of the course I'm taking which is originally written in MATLAB. I use Python and convert these matrices to Python for the toy examples. For example, for the following MATLAB matrix:
s = [2 3; 4 5];
I use
s = array([[2,3],[4,5]])
It is too time consuming for me to re-write all the toy examples this way because I just want to see how they work. Is there a way to directly give the MATLAB matrix as string to a Numpy array or a better alternative for this?
For example, something like:
s = myMagicalM2ArrayFunction('[2 3; 4 5]')
numpy.matrix can take string as an argument.
Docstring:
matrix(data, dtype=None, copy=True)
[...]
Parameters
----------
data : array_like or string
If `data` is a string, it is interpreted as a matrix with commas
or spaces separating columns, and semicolons separating rows.
In [1]: import numpy as np
In [2]: s = '[2 3; 4 5]'
In [3]: def mag_func(s):
...: return np.array(np.matrix(s.strip('[]')))
In [4]: mag_func(s)
Out[4]:
array([[2, 3],
[4, 5]])
How about just saving a set of example matrices in Matlab and load them directly into python:
http://docs.scipy.org/doc/scipy/reference/tutorial/io.html
EDIT:
or not sure how robust this is (just threw together a simple parser which is probably better implemented in some other way), but something like:
import numpy as np
def myMagicalM2ArrayFunction(s):
tok = []
for t in s.strip('[]').split(';'):
tok.append('[' + ','.join(t.strip().split(' ')) + ']')
b = eval('[' + ','.join(tok) + ']')
return np.array(b)
For 1D arrays, this will create a numpy array with shape (1,N), so you might want to use np.squeeze to get a (N,) shaped array depending on what you are doing.
If you want a numpy array rather than a numpy matrix
def str_to_mat(x):
x = x.strip('[]')
return np.vstack(list(map(lambda r: np.array(r.split(','), dtype=np.float32), x.split(';'))))

Categories

Resources