I am trying to create function using numpy something like f=(x-a1)^2+(y-a2)^2+a3
Where a1,a2,a3 are random generated numbers and x,y are parameters.
But I cant work with it, I want to find f(0,0) where [0,0] is [x,y] and [a1,a2,a3] were set before,but my code doesnt work.
And then I want to convert this function to tensorflow tensor.Here is my code, string with "##" dont work.
import tensorflow as tf
from random import random, seed
import numpy as np
def mypolyval(x, min_point, min_value):
res = min_value
for i in range(len(min_point)):
res += (x[i] - min_point[i]) ** 2
return res
class FunGen:
def __init__(self, dim, n):
self.dim = dim
self.n = n
self.functions = []
self.x = []
def c2(self):
seed(10)
for _ in range(self.n):
min_point = [random() for _ in range(self.dim)]
min_value = random()
f = np.vectorize(mypolyval, excluded=['x'])
##print(f(x=np.array([0, 0]), min_point=min_point, min_value=min_value))
self.functions.append((f, min_point, min_value))
return self.functions
functions = FunGen(2, 1).c2()
for i in functions:
print(type(i[0]))
f=i[0]
## print(f(x=[0, 0], min_value=i[1], min_point=i[2]))
##a=tf.convert_to_tensor(f,dtype=np.float32)
The problem is not related to tensorflow. The line
min_point = [random() for _ in range(self.dim)]
creates a list and lists don't have the .size() property.
You can turn it into a numpy array using min_point = np.array([random() for _ in range(self.dim)])), then the .size() will work.
Or if you want to stick to the list use for i in range(len(min_point)), which calculates the length of a list.
Also you need to add min_point and min_value them to the excluded list:
from random import random, seed
import numpy as np
def mypolyval(x, min_point, min_value):
print('x', x)
print('min_point', min_point)
print('min_value', min_value)
res = min_value
for i in range(len(min_point)):
res += (x[i] - min_point[i]) ** 2
return res
class FunGen:
def __init__(self, dim, n):
self.dim = dim
self.n = n
self.functions = []
self.x = []
def c2(self):
seed(10)
for _ in range(self.n):
min_point = [random() for _ in range(self.dim)]
min_value = random()
f = np.vectorize(mypolyval, excluded=['x', 'min_point', 'min_value'])
#print(f(x=[0, 0], min_value=min_value, min_point=min_point))
self.functions.append((f, min_point, min_value))
return self.functions
functions = FunGen(2, 1).c2()
for i in functions:
print(type(i[0]))
print(i)
f=i[0]
print(f(x=[0, 0], min_value=i[2], min_point=i[1]))
To create a TensorFlow function from a numpy function, you should use tf.py_func:
Wraps a python function and uses it as a TensorFlow op.
From the TensorFlow API:
def my_func(x):
# x will be a numpy array with the contents of the placeholder below
return np.sinh(x)
inp = tf.placeholder(tf.float32)
y = tf.py_func(my_func, [inp], tf.float32)
Related
I have an array of Pe of shape (5100,5100). I am trying to find the neighbor indices using the code below but for this shape of Pe, the computational time is 100 seconds. Is there a more time efficient way to do it?
def get_neighbor_indices(position, dimensions):
'''
dimensions is a shape of np.array
'''
i, j = position
indices = [(i+1,j), (i-1,j), (i,j+1), (i,j-1)]
return [
(i,j) for i,j in indices
if i>=0 and i<dimensions[0]
and j>=0 and j<dimensions[1]
]
def iterate_array(init_i, init_j, arr, condition_func):
'''
arr is an instance of np.array
condition_func is a function (value) => boolean
'''
indices_to_check = [(init_i,init_j)]
checked_indices = set()
result = []
t0 = None
t1 = None
timestamps = []
while indices_to_check:
pos = indices_to_check.pop()
if pos in checked_indices:
continue
item = arr[pos]
checked_indices.add(pos)
if condition_func(item):
result.append(item)
t1=time.time()
if(t0==None):
t0=t1
timestamps.append(t1-t0)
indices_to_check.extend(
get_neighbor_indices(pos, arr.shape)
)
return result,timestamps
Visited_Elements,timestamps=iterate_array(0,0, Pe, lambda x : x < Pin0)
With scipy and a slight change in the way the filter condition is described this can be made rather fast:
import numpy as np
from scipy.ndimage import label
import time
def collect_array(init_i, init_j, arr, condition_arr):
t0=time.time()
if not condition_arr[init_i, init_j]:
return [], time.time() - t0
islands = label(condition_arr)[0]
mask = islands != islands[init_i, init_j]
mx = np.ma.masked_array(Pe, mask)
return mx.compressed(), time.time() - t0
# Trying it out
Pe = np.random.rand(5100, 5100)
Pin0 = 0.7
Visited_Elements, timestamp = collect_array(0,0, Pe, Pe < Pin0)
print(Visited_Elements,timestamp)
The core of the code is the label function and the fact that the condition function is replaced by a boolean array.
So I wrote a new way to create a matrix without the use of numpy or np zeros.
import numpy as np
import time
x = [1,2,3,4,5,6,7,8,9,10]
x1 = 1
def fakenpzeros(size):
rows, cols = 1, size
matrix = [([0]*cols) for i in range(rows)]
return matrix
print(np.zeros(x1))
print(fakenpzeros(x1))
The console would output
[[0]] (for the function I created) and [0.] (for the numpy function)
I want to introduce my function into my code as I am trying to create a random sampling function without numpy or random
This is my following code:
def pseudo_uniform_bad(mult=5,
mod=11,
seed=1,
size=1):
"""
A bad pseudo random generator with small multipliers and modulus
"""
U = np.zeros(size)
#U = fakenpzeros(size)
x = (seed*mult+1)%mod
U[0] = x/mod
for i in range(1,size):
x = (x*mult+1)%mod
U[i] = x/mod
return U
def pseudo_uniform_good(mult=16807,
mod=(2**31)-1,
seed=123456789,
size=1):
"""
A reasoanbly good pseudo random generator
"""
U = np.zeros(size)
#U = fakenpzeros(size)
x = (seed*mult+1)%mod
U[0] = x/mod
for i in range(1,size):
x = (x*mult+1)%mod
U[i] = x/mod
return U
def pseudo_uniform(low=0,
high=1,
seed=123456789,
size=1):
"""
Generates uniformly random number between `low` and `high` limits
"""
return low+(high-low)*pseudo_uniform_good(seed=seed,size=size)
def sample_pick(lst):
"""
Picks up a random sample from a given list
"""
# Sets seed based on the decimal portion of the current system clock
t = time.perf_counter()
seed = int(10**9*float(str(t-int(t))[0:]))
# Random sample as an index
l = len(lst)
s = pseudo_uniform(low=0,high=l,seed=seed,size=1)
idx = int(s)
return (lst[idx]) #SAMPLING
print(sample_pick(x1))
However, when I replace np.zeros(size) with fakenpzeros(size) it says something along the lines of:
unsupported operand type(s) for +: 'int' and 'list'
So how exactly can I convert my matrix into an integer/tuple of integers like how numpy does it?
I am trying to speed up the below operation by doing some sort of matrix/vector-multiplication, can anyone see a nice quick solution?
It should also work for a special case where a tensor has shape 0 (torch.Size([])) but i am not able to initialize such a tensor.
See the image below for the type of tensor i am referring to:
tensor to add to test
def adstock_geometric(x: torch.Tensor, theta: float):
x_decayed = torch.zeros_like(x)
x_decayed[0] = x[0]
for xi in range(1, len(x_decayed)):
x_decayed[xi] = x[xi] + theta * x_decayed[xi - 1]
return x_decayed
def adstock_multiple_samples(x: torch.Tensor, theta: torch.Tensor):
listtheta = theta.tolist()
if isinstance(listtheta, float):
return adstock_geometric(x=x,
theta=theta)
x_decayed = torch.zeros((100, 112, 1))
for idx, theta_ in enumerate(listtheta):
x_decayed_one_entry = adstock_geometric(x=x,
theta=theta_)
x_decayed[idx] = x_decayed_one_entry
return x_decayed
if __name__ == '__main__':
ones = torch.tensor([1])
hundreds = torch.tensor([idx for idx in range(100)])
x = torch.tensor([[idx] for idx in range(112)])
ones = adstock_multiple_samples(x=x,
theta=ones)
hundreds = adstock_multiple_samples(x=x,
theta=hundreds)
print(ones)
print(hundreds)
I came up with the following, which is 40 times faster on your example:
import torch
def adstock_multiple_samples(x: torch.Tensor, theta: torch.Tensor):
arange = torch.arange(len(x))
powers = (arange[:, None] - arange).clip(0)
return ((theta[:, None, None] ** powers[None, :, :]).tril() * x).sum(-1)
It behaves as expected:
>>> x = torch.arange(112)
>>> theta = torch.arange(100)
>>> adstock_multiple_samples(x, theta)
... # the same output
Note that I considered that x was a 1D-tensor, as for your example the second dimension was not needed.
It also works with theta = torch.empty((0,)), and it returns an empty tensor.
I have a #tf.function decorated function. Inside the function, I would like to draw from a distribution and compute some value several times (let's call this proceduce f(x)).
How can I do this in Tensorflow 2.0? I can't use numpy arrays as I would like to use the #tf.function decorator.
A numpy implementation would look like:
reps = 4
store = np.zeros((n, reps))
for i in range(reps):
store[:, i] = f(x) #f(x) is shape (n,)
The goal would then be to compute the row means of store.
This should be easy but I haven't been able to work out how to do it!
Something like this maybe:
import tensorflow as tf
def f():
return tf.random.normal((10,))
#tf.function
def store_this():
reps = 4
n = 10
store = tf.zeros((n, reps))
values = [f() for _ in range(reps)]
indices = tf.stack([tf.tile(tf.range(n), multiples=[reps]), tf.repeat(tf.range(reps), repeats=n)], axis=-1)
return tf.tensor_scatter_nd_update(store, indices, tf.reshape(values, [-1]))
store_this()
If f takes a one-dimensional tensor as input, this is a shorter alternative:
#tf.function
def f(x):
return tf.random.normal((10,))
x = tf.constant([1.0, 2.0])
reps = 4
def store_this(fp, x, reps):
return tf.transpose(tf.map_fn(fp, tf.tile(tf.expand_dims(x, 0),[reps,1])))
store_this(f, x, reps)
My code is the following:
import cv2; import numpy as np
class MyClass:
def __init__(self,imagefile):
self.image = cv2.imread(imagefile)
#image details
self.h,self.w = self.image.shape[:2]
#self.bPoints, self.wPoints = np.array([[0,0]]),np.array([[0,0]])
self.bPoints, self.wPoints = [],[]
#CAUTION! Points are of the form (y,x)
# Point filtering
for i in xrange(self.h):
for j in xrange(self.w):
if self.th2.item(i,j) == 0:
#self.bPoints = np.append([[i,j]], self.bPoints, axis=0)
self.bPoints.append((i,j))
else:
self.wPoints.append((i,j))
#self.wPoints = np.append([[i,j]], self.wPoints, axis=0)
#self.bPoints = self.bPoints[:len(self.bPoints) - 1]
#self.wPoints = self.wPoints[:len(self.wPoints) - 1]
self.bPoints, self.wPoints = np.array(self.bPoints), np.array(self.wPoints)
I want to find and separate the white from the black points. I have commented the lines that show a possible (but very-very slow) solution via numpy. Can you recommend me a better and faster solution? I will appreciate it if you do so!
Thanks
I'm assuming self.th2 is a numpy array. This might take some adjustment if that is not the case. Basically, this uses the np.where function to determine all the indices which are 0 or 255.
import cv2; import numpy as np
class MyClass:
def __init__(self,imagefile):
self.image = cv2.imread(imagefile)
#image details
self.h,self.w = self.image.shape[:2]
#self.bPoints, self.wPoints = np.array([[0,0]]),np.array([[0,0]])
self.bPoints, self.wPoints = [],[]
#CAUTION! Points are of the form (y,x)
# use the np.where method instead of a double loop.
# make sure self.th2 is a numpy array
indx = np.where(self.th2==0)
for i,j in zip(indx[0], indx[1]):
self.bPoints.append((i,j))
indx = np.where(self.th2==255)
for i,j in zip(indx[0], indx[1]):
self.wPoints.append((i,j))
# Point filtering
#for i in xrange(self.h):
# for j in xrange(self.w):
# if self.th2.item(i,j) == 0:
# #self.bPoints = np.append([[i,j]], self.bPoints, axis=0)
# self.bPoints.append((i,j))
# else:
# self.wPoints.append((i,j))
# #self.wPoints = np.append([[i,j]], self.wPoints, axis=0)
#self.bPoints = self.bPoints[:len(self.bPoints) - 1]
#self.wPoints = self.wPoints[:len(self.wPoints) - 1]
self.bPoints, self.wPoints = np.array(self.bPoints), np.array(self.wPoints)