Using theano.scan within PyMC3 gives TypeError: slice indices must be integers or None or have an __index__ method - theano

I would like to to use theano.scan within pymc3. I run into problems when I add more than two variables as sequences. Here is a simple example:
import numpy as np
import pymc3 as pm
import theano
import theano.tensor as T
a = np.ones(5)
b = np.ones(5)
basic_model = pm.Model()
with basic_model:
a_plus_b, _ = theano.scan(fn=lambda a, b: a + b, sequences=[a, b])
results in the following error:
Traceback (most recent call last):
File "StackOverflowExample.py", line 23, in <module>
sequences=[a, b])
File "\Anaconda3\lib\site-packages\theano\scan_module\scan.py", line 586, in scan
scan_seqs = [seq[:actual_n_steps] for seq in scan_seqs]
File "\Anaconda3\lib\site-packages\theano\scan_module\scan.py", line 586, in <listcomp>
scan_seqs = [seq[:actual_n_steps] for seq in scan_seqs]
TypeError: slice indices must be integers or None or have an __index__ method
However, when I run the same theano.scan outside a pymc model block, everything works fine:
a = T.vector('a')
b = T.vector('b')
a_plus_b, update = theano.scan(fn=lambda a, b: a + b, sequences=[a, b])
a_plus_b_function = theano.function(inputs=[a, b], outputs=a_plus_b, updates=update)
a = np.ones(5)
b = np.ones(5)
print(a_plus_b_function(a, b))
prints [2. 2. 2. 2. 2.], like it should.
In addition, the problem seems to be specific to adding more than one sequences. Everything works just fine when there is one variable in sequences and one in non-sequences. The following code works:
a = np.ones(5)
c = 2
basic_model = pm.Model()
with basic_model:
a_plus_c, _ = theano.scan(fn=lambda a, c: a + c, sequences=[a], non_sequences=[c])
a_plus_c_print = T.printing.Print('a_plus_c')(a_plus_c)
prints a_plus_c __str__ = [ 3. 3. 3. 3. 3.], as expected.
Note: I can't just use a + b instead of theano.scan because my actual function is more complex. I actually want to have something like this:
rewards = np.array([1, 1, 1, 1]) # reward (1) or no reward (0)
choices = np.array([1, 0, 1, 0]) # action left (1) or right (0)
Q_old = 0 # initial Q-value
alpha = 0.1 # learning rate
def update_Q(reward, choice, Q_old, alpha):
return Q_old + choice * alpha * (reward - Q_old)
Q_left, _ = theano.scan(fn=update_Q,
sequences=[rewards, choices],
outputs_info=[Q_old],
non_sequences=[alpha])

Turns out it was a simple mistake! Everything is working as soon as I define a and b as tensor variables. Adding those two lines did the job:
a = T.as_tensor_variable(np.ones(5))
b = T.as_tensor_variable(np.ones(5))

Related

How to appending 1 value to array A to match the dimensions of array B?

The program I have here is simulating the velocity of a falling object.
The velocity is calculated by subtracting the y position from time_1 and time_2.
The problem that I have is that the dimensions of array v and array t don't match. Instead of shortening array t I would like to add 0 at the beginning of the v array. So that the graph will show v = 0 at t= 0. Yes, I know it is a small interval and that it does not really matter. But I want to know it for educational purpose.
I'm wondering if i can write the line v = (y[1:] - y[:-1])/0.1 in a from where i keep the dimension.
The ideal thing that would happen is that the array y will be substracted with an array y[:-1] and that this subtraction will happen at the end of the y array so the result will be an array of dimension 101 with a 0 as start value.
I would like to know your thoughts about this.
import matplotlib.pyplot as plt
t = linspace(0,10,101)
g = 9.80665
y = 0.5*g*t*t
v = (y[1:] - y[:-1])/0.1
plt.plot(t,v)
plt.show()
is there a function where i can add a certain value to the beginning of an array? np.append will add it to the end.
Maybe you could just pre-define the length of the result at the beginning and then fill up the values:
import numpy as np
dt = .1
g = 9.80665
t_end = 10
t = np.arange(0,t_end+dt,dt)
y = 0.5*g*t*t
v = np.zeros(t.shape[0])
v[1:] = (y[1:] - y[:-1])/dt
if you simply looking for the append at index function it would be this one:
np.insert([1,2,3,4,5,6], 2, 100)
>> array([ 1, 2, 100, 3, 4, 5, 6])
another possible solution to this would be to use np.append but inverse your order :
import numpy as np
v = np.random.rand(10)
value = 42 # value to append at the beginning of v
value_arr = np.array([value]) # dimensions should be adjust for multidimensional array
v = np.append(arr = value_arr, values = v, axis=0)
and the possible variants following the same idea, using np.concatenate or np.hstack ...
regarding your second question in comments, one solution may be :
t = np.arange(6)
condlist = [t <= 2, t >= 4]
choicelist = [1, 1]
t = np.select(condlist, choicelist, default=t)

Vectors in python

Hi i have just started using python and coding in general. This is the last question of my assignment and i honestly have no clue as to how to even start this question.
I need to write a program to do basic vector calculations in 3 dimensions:
addition, dot product and normalization.
I have no clue what to do after this step or if this step is even right please help.
The expected result is:
Enter vector A:
1 3 2
Enter vector B:
2 3 0
A+B = [3, 6, 2]
A.B = 11
|A| = 3.74
|B| = 3.61
Using numpy:
import numpy as np
A = np.array([1,3,2])
B = np.array([2,3,0])
# sum
print(A+B) # -> array([3, 6, 2])
# dot product
print(np.dot(A)) # -> 11
#normalization
print(np.linalg.norm(A)) # -> 3.741...
print(np.linalg.norm(B)) # -> 3.605...
Without numpy:
A = [1,3,2]
B = [2,3,0]
# sum
print([i+j for i,j in zip(A,B)])
# dot product
print(sum(i*j for i, j in zip(A,B)))
#normalization
print(sum(i**2 for i in A)**(0.5))
print(sum(i**2 for i in B)**(0.5))

Networkx error :" in _not_implemented_for terms = {'directed': graph.is_directed()}"

I am trying to implement some clustering problem, however I meet following problem:
error imformtionis here is here:
File "/Users/shaoyupei/Desktop/project ", line 99, in <module>
c=new_clustering(H,list_)
File "/Users/shaoyupei/Desktop/project ", line 83, in new_clustering
c = nx.connected_component_subgraphs(G)
File "<decorator-gen-232>", line 2, in connected_component_subgraphs
File "/anaconda3/lib/python3.6/site- packages/networkx/utils/decorators.py", line 58, in _not_implemented_for
terms = {'directed': graph.is_directed(),
AttributeError: 'NoneType' object has no attribute 'is_directed'
The things code do is here: input a graph ,and the edge list with weighted, repeat to move the first element in the edge list until the partition is appearing
here is the the form of input list :
list_=[(('name', 'year'), 0.9), (('aunt', 'work'), 0.5173567819580527), (('family', 'world'), 0.5154954800891427), (('aunt', 'moment'), 0.5096782251214088), (('full', 'glad'), 0.5080586691030745), (('bed', 'miserable'), 0.5074225221081745), (('miserable', 'name'), 0.5074225221081745) ...]
and here is the code:
def new_clustering(G,_list):
c= nx.connected_component_subgraphs(G) # postion1
c =list(c)
l= len(c)
l2=-1
while (l2 < l+1):
e = _list.pop(0)[0]
G = G.remove_edge(*e)
c = nx.connected_component_subgraphs(G) #postion2
c = list(c)
l2= len(c)
return c
H= H.to_undirected()
k=new_clustering(H,list_)
here is what things happens, I know
nx.connected_component_subgraphs(G) is only implement for undirected graph, however the error do not raising in postion1 of code , and I move the edge successfully , but the it happens at the first iteration of position2 , how come it happens?
The problem is in this line G = G.remove_edge(*e).
G.remove_edge modifies G "in place". That is, it directly removes the edge from G. It doesn't return a new graph that looks like G with the edge removed. So when you do G = G.remove_edge(*e), you are removing the edge from G and then creating a new variable G which is whatever gets returned from G.remove_edge(*e). But nothing is returned. So G has now become None.
Here's an example:
import networkx as nx
G= nx.Graph()
G.add_edge(1,2)
print(G.edges())
> [(1, 2)]
A=G.remove_edge(1,2) #it's removing the edge directly from `G` and assigning the returned value to be `A`.
print(G.edges()) #no edges,
> []
print(A) #since `G.remove_edge` doesn't return anything, this is None
> None

calculate Matrix Vector multiplication with python in cuda

I'm trying to use numbapro to write a simple matrix vector multiplication below:
from numbapro import cuda
from numba import *
import numpy as np
import math
from timeit import default_timer as time
m = 100000
n = 100
#cuda.jit('void(f4[:,:], f4[:], f4[:])')
def cu_matrix_vector(A, b, c):
row = cuda.grid(1)
if (row < m):
sum = 0
for i in range(n):
sum += A[row, i] * b[i]
c[row] = sum
A = np.array(np.random.random((m, n)), dtype=np.float32)
B = np.array(np.random.random(m), dtype=np.float32)
C = np.empty_like(B)
s = time()
dA = cuda.to_device(A)
dB = cuda.to_device(B)
dC = cuda.to_device(C)
cu_matrix_vector[(m+511)/512, 512](dA, dB, dC)
dC.to_host()
print ( C)
But when I start running I get an error in function **cu_matrix_vector ** argument 2: : wrong type
cu_matrix_vector[(m+511)/512, 512](dA, dB, dC)
File "C:\Anaconda3\lib\site-packages\numba\cuda\compiler.py", line 359, in call
sharedmem=self.sharedmem)
File "C:\Anaconda3\lib\site-packages\numba\cuda\compiler.py", line 433, in _kernel_call
cu_func(*kernelargs)
File "C:\Anaconda3\lib\site-packages\numba\cuda\cudadrv\driver.py", line 1116, in call
self.sharedmem, streamhandle, args)
File "C:\Anaconda3\lib\site-packages\numba\cuda\cudadrv\driver.py", line 1160, in launch_kernel
None)
File "C:\Anaconda3\lib\site-packages\numba\cuda\cudadrv\driver.py", line 221, in safe_cuda_api_call
retcode = libfn(*args)
ctypes.ArgumentError: argument 2: : wrong type
The problem lies here:
cu_matrix_vector[(m+511)/512, 512](dA, dB, dC)
in Python 3, (m+511)/512 = 196.310546875. Passing a floating point value as a launch parameter is illegal, which is the source of the type conflict error you are seeing. You want to do:
cu_matrix_vector[(m+511)//512, 512](dA, dB, dC)
which will produce an integer value and should allow the code to run correctly.

python numba fingerprint error

I'm attempting numba to optimise some code. I've worked through the initial examples in section 1.3.1 in the 0.26.0 user guide (http://numba.pydata.org/numba-doc/0.26.0/user/jit.html) and get the expected results, so I don't think the problem is installation.
Here's my code:
import numba
import numpy
import random
a = 8
b = 4
def my_function(a, b):
all_values = numpy.fromiter(range(a), dtype = int)
my_array = []
for n in (range(a)):
some_values = (all_values[all_values != n]).tolist()
c = random.sample(some_values, b)
my_array.append(sorted([n] + c))
return my_array
print(my_function(a, b))
my_function_numba = numba.jit()(my_function)
print(my_function_numba(a, b))
Which after printing out the expected results from the my_function call returns the following error message:
ValueError Traceback (most recent call last)
<ipython-input-8-b5d8983a58f6> in <module>()
19 my_function_numba = numba.jit()(my_function)
20
---> 21 print(my_function_numba(a, b))
ValueError: cannot compute fingerprint of empty list
Fingerprint of empty list?
I'm not sure about that error in particular, but in general, to be fast numba requires a particular subset of numpy/python (see here and here for more). So I might rewrite it like this.
#numba.jit(nopython=True)
def fast_my_function(a, b):
all_values = np.arange(a)
my_array = np.empty((a, b + 1), dtype=np.int32)
for n in range(a):
some = all_values[all_values != n]
c = np.empty(b + 1, dtype=np.int32)
c[1:] = np.random.choice(some, b)
c[0] = n
c.sort()
my_array[n, :] = c
return my_array
Main things to note:
no lists, I'm pre-allocating everything.
no use of generators (in both python 2 & 3 for n in range(a) will get converted to a fast native loop)
adding nopython=True to the decorator makes it so numba will complain if I use something that can't be efficiently JITed.

Resources