scipy dblquad providing the wrong result in simple double integral - scipy

I am trying to calculate a straightforward doble definite integral in Python: function Max(0, (4-12x) + (6-12y)) in the square [0,1] x [0,1].
We can do it with Mathematica and get the exact result:
Integrate[Max[0, 4-12*u1 + 6-12*u2], {u1, 0, 1}, {u2, 0,1}] = 125/108.
With a simple Monte Carlo simulation I can confirm this result. However, using scipy.integrate.dblquad I am getting a value of 0.0005772072907971, with error 0.0000000000031299
from scipy.integrate import dblquad
def integ(u1, u2):
return max(0, (4 - 12*u1) + (6 - 12*u2))
sol_int, err = dblquad(integ, 0, 1, lambda _:0, lambda _:1, epsabs=1E-12, epsrel=1E-12)
print("dblquad: %0.16f. Error: %0.16f" % (sol_int, err) )
Agreed that the function is not derivable, but it is continuous, I see no reason for this particular integral to be problematic.
I thought maybe dblquad has an 'options' argument where I can try different numerical methods, but I found nothing like that.
So, what am I doing wrong?

try different numerical methods
That's what I would suggest, given the trouble that iterated quad has on Windows. After changing it to an explicit two-step process, you can replace one of quad with another method, romberg seems the best alternative to me.
from scipy.integrate import quad, romberg
def integ(u1, u2):
return max(0, (4 - 12*u1) + (6 - 12*u2))
sol_int = romberg(lambda u1: quad(lambda u2: integ(u1, u2), 0, 1)[0], 0, 1)
print("romberg-quad: %0.16f " % sol_int)
This prints 1.1574073959987758 on my computer, and hopefully you will get the same.

Related

Why does scipy.signal.windows.gaussian produce different numbers than Matlab and Octave's gausswin?

For example we can use a length 16 window with 3 as the deviation:
scipy.signal.windows.gaussian(16,3)
#returns :
array([0.04393693, 0.09563444, 0.18627046, 0.32465247, 0.50633562,
0.70664828, 0.8824969 , 0.98620712, 0.98620712, 0.8824969 ,
0.70664828, 0.50633562, 0.32465247, 0.18627046, 0.09563444,
0.04393693])
Where as octave produces :
gausswin(16,3)
#returns :
0.011109
0.034047
0.088922
0.197899
0.375311
0.606531
0.835270
0.980199
0.980199
0.835270
0.606531
0.375311
0.197899
0.088922
0.034047
0.011109
Matlab produces similar results as Octave. I don't really understand why the numbers would be different on purpose? Is it a bug?
The function gaussian(M, std) from scipy.signal.windows and the Octave function gausswin(m, a) from the Octave signal package do not treat the second parameter in the same way. To translate the Octave parameters m and a to the scipy parameter, you can use
std = (m - 1)/(2*a)
For example, here's how you can get the same values that you produced in Octave with gausswin(16, 3):
In [74]: from scipy.signal.windows import gaussian
In [75]: m = 16
In [76]: a = 3
In [77]: gaussian(m, (m - 1)/(2*a))
Out[77]:
array([0.011109 , 0.03404745, 0.08892162, 0.1978987 , 0.3753111 ,
0.60653066, 0.83527021, 0.98019867, 0.98019867, 0.83527021,
0.60653066, 0.3753111 , 0.1978987 , 0.08892162, 0.03404745,
0.011109 ])

3-layered Neural network doesen't learn properly

So, I'm trying to implement a neural network with 3 layers in python, however I am not the brightest person so anything with more then 2 layers is kinda difficult for me. The problem with this one is that it gets stuck at .5 and does not learn I have no actual clue where it went wrong. Thank you for anyone with the patience to explain the error to me. (I hope the code makes sense)
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def reduce(x):
return x*(1-x)
l0=[np.array([1,1,0,0]),
np.array([1,0,1,0]),
np.array([1,1,1,0]),
np.array([0,1,0,1]),
np.array([0,0,1,0]),
]
output=[0,1,1,0,1]
syn0=np.random.random((4,4))
syn1=np.random.random((4,1))
for justanumber in range(1000):
for i in range(len(l0)):
l1=sigmoid(np.dot(l0[i],syn0))
l2=sigmoid(np.dot(l1,syn1))
l2_err=output[i]-l2
l2_delta=reduce(l2_err)
l1_err=syn1*l2_delta
l1_delta=reduce(l1_err)
syn1=syn1.T
syn1+=l0[i].T*l2_delta
syn1=syn1.T
syn0=syn0.T
syn0+=l0[i].T*l1_delta
syn0=syn0.T
print l2
PS. I know that it might be a piece of trash as a script but that is why I asked for assistance
Your computations are not fully correct. For example, the reduce is called on the l1_err and l2_err, where it should be called on l1 and l2.
You are performing stochastic gradient descent. In this case with such few parameters, it oscilates hugely. In this case use a full batch gradient descent.
The bias units are not present. Although you can still learn without bias, technically.
I tried to rewrite your code with minimal changes. I have commented your lines to show the changes.
#!/usr/bin/python3
import matplotlib.pyplot as plt
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def reduce(x):
return x*(1-x)
l0=np.array ([np.array([1,1,0,0]),
np.array([1,0,1,0]),
np.array([1,1,1,0]),
np.array([0,1,0,1]),
np.array([0,0,1,0]),
]);
output=np.array ([[0],[1],[1],[0],[1]]);
syn0=np.random.random((4,4))
syn1=np.random.random((4,1))
final_err = list ();
gamma = 0.05
maxiter = 100000
for justanumber in range(maxiter):
syn0_del = np.zeros_like (syn0);
syn1_del = np.zeros_like (syn1);
l2_err_sum = 0;
for i in range(len(l0)):
this_data = l0[i,np.newaxis];
l1=sigmoid(np.matmul(this_data,syn0))[:]
l2=sigmoid(np.matmul(l1,syn1))[:]
l2_err=(output[i,:]-l2[:])
#l2_delta=reduce(l2_err)
l2_delta=np.dot (reduce(l2), l2_err)
l1_err=np.dot (syn1, l2_delta)
#l1_delta=reduce(l1_err)
l1_delta=np.dot(reduce(l1), l1_err)
# Accumulate gradient for this point for layer 1
syn1_del += np.matmul(l2_delta, l1).T;
#syn1=syn1.T
#syn1+=l1.T*l2_delta
#syn1=syn1.T
# Accumulate gradient for this point for layer 0
syn0_del += np.matmul(l1_delta, this_data).T;
#syn0=syn0.T
#syn0-=l0[i,:].T*l1_delta
#syn0=syn0.T
# The error for this datpoint. Mean sum of squares
l2_err_sum += np.mean (l2_err ** 2);
l2_err_sum /= l0.shape[0]; # Mean sum of squares
syn0 += gamma * syn0_del;
syn1 += gamma * syn1_del;
print ("iter: ", justanumber, "error: ", l2_err_sum);
final_err.append (l2_err_sum);
# Predicting
l1=sigmoid(np.matmul(l0,syn0))[:]# 1 x d * d x 4 = 1 x 4;
l2=sigmoid(np.matmul(l1,syn1))[:] # 1 x 4 * 4 x 1 = 1 x 1
print ("Predicted: \n", l2)
print ("Actual: \n", output)
plt.plot (np.array (final_err));
plt.show ();
The output I get is:
Predicted:
[[0.05214011]
[0.97596354]
[0.97499515]
[0.03771324]
[0.97624119]]
Actual:
[[0]
[1]
[1]
[0]
[1]]
Therefore the network was able to predict all the toy training examples. (Note in real data you would not like to fit the data at its best as it leads to overfitting). Note that you may get a bit different result, as the weight initialisations are different. Also, try to initialise the weight between [-0.01, +0.01] as a rule of thumb, when you are not working on a specific problem and you specifically know the initialisation.
Here is the convergence plot.
Note that you do not need to actually iterate over each example, instead you can do matrix multiplication at once, which is much faster. Also, the above code does not have bias units. Make sure you have bias units when you re-implement the code.
I would recommend you go through the Raul Rojas' Neural Networks, a Systematic Introduction, Chapter 4, 6 and 7. Chapter 7 will tell you how to implement deeper networks in a simple way.

scala return matrix of average pixels

Here's the thing: I want to modify (and then return) a matrix of integers that is given in the parameters of the function. The funcion average (of the class MatrixMotionBlur) gives the average between the own pixel, upper, down and left pixels. Follows the following formula:
result(x, y) = (M1(x, y)+M1(x-1, y)+M1(x, y-1)+M1(x, y+1)) / 4
This is the code i've implemented so far
MatrixMotionBlur - Average function
MotionBlurSingleThread - run
The objetive here is to apply "average" method to alter the matrix value and return that matrix. The thing is the program gives me error when I to insert the value on the matrix.
Any ideas how to do this ?
The functional way
val updatedData = data.map{ outter =>
outter(i).map{ inner =>
mx.average(i.j)
}
}
Pay attention that Seq is immutable collection type and you can't just modify it, you can create new, modified collection only.
By the way, why you iterate starting 1, but not 0. Are you sure you want it?

GCD test - to test dependency between loop statements

I understand how the GCD works on a trivial example as below:
for(i=1; i<=100; i++)
{
X[2*i+3] = X[2*i] + 50;
}
we first transform it into the following form:
X[a*i + b] and X[c*i + d]
a=2, b=3, c=2, d=0 and GCD(a,c)=2 and (d-b) is -3. Since 2 does not divide -3, no dependence is possible.
But how can we do this GCD test on a doubly nested loop?
For example:
for (i=0; i<10; i++){
for (j=0; j<10; j++){
A[1+2*i + 20*j] = A[2+20*i + 2*j);
}
}
While the subscripts can be delinearized, the GCD test is simple to apply directly. In your example, the subscript pair is [1+2*i + 20*j] and [2+20*i + 2*j], so we're looking for an integer solution to the equation
1 + 2*i + 20*j = 2 + 20*i' + 2*j'
Rearranging, we get
2*i - 20*i' + 20*j - 2*j = 1
Compute the GCD of all the coefficients, 2, -20, 20, and -2, and see if it divides the constant. In this case, the GCD is 2. Since 2 doesn't divide 1, there's no dependence.
The "easy" way to apply GCD in the nested loop case is to apply it only in cases where the arrays themselves are multidemsional; i.e., the original source code uses multiple subscripts rather than already linearized expressions. Of course if you can "back transform" these linearized subscripts then you'll have the equivalent.
Once you've cast the problem as a multidemsional problem then you may simply apply the GCD test "dimension by dimension". If any dimension shows no dependence then you can stop and declare there is no dependence for the entire multidemsional subscripting sequence.
The key of course is that casting as a multidimensional indexing problem gives you the nice property that there's a one-to-one mapping between individual index values and the corresponding index expression tuples. Without this the problem is harder.
This is the approach I took in the ASC Fortran vectorizing compiler back in the 70's and it worked pretty well, particularly used in conjunction with directional subscript analysis for the non disjoint case. The GCD test by itself is really not sufficient, but it does give you a relatively inexpensive way of making an early decision in your analysis in those cases where you then can avoid the more expensive dependence analysis.

Pythonic way to write a for loop that doesn't use the loop index [duplicate]

This question already has answers here:
Is it possible to implement a Python for range loop without an iterator variable?
(15 answers)
Closed 7 months ago.
This is to do with the following code, which uses a for loop to generate a series of random offsets for use elsewhere in the program.
The index of this for loop is unused, and this is resulting in the 'offending' code being highlighted as a warning by Eclipse / PyDev
def RandomSample(count):
pattern = []
for i in range(count):
pattern.append( (random() - 0.5, random() - 0.5) )
return pattern
So I either need a better way to write this loop that doesn't need a loop index, or a way to tell PyDev to ignore this particular instance of an unused variable.
Does anyone have any suggestions?
Just for reference for ignoring variables in PyDev
By default pydev will ignore following variables
['_', 'empty', 'unused', 'dummy']
You can add more by passing supression parameters
-E, --unusednames ignore unused locals/arguments if name is one of these values
Ref:
http://eclipse-pydev.sourcearchive.com/documentation/1.0.3/PyCheckerLauncher_8java-source.html
How about itertools.repeat:
import itertools
count = 5
def make_pat():
return (random() - 0.5, random() - 0.5)
list(x() for x in itertools.repeat(make_pat, count))
Sample output:
[(-0.056940506273799985, 0.27886450895662607),
(-0.48772848046066863, 0.24359038079935535),
(0.1523758626306998, 0.34423337290256517),
(-0.018504578280469697, 0.33002406492294756),
(0.052096928160727196, -0.49089780124549254)]
randomSample = [(random() - 0.5, random() - 0.5) for _ in range(count)]
Sample output, for count=10 and assuming that you mean the Standard Library random() function:
[(-0.07, -0.40), (0.39, 0.18), (0.13, 0.29), (-0.11, -0.15),\
(-0.49, 0.42), (-0.20, 0.21), (-0.44, 0.36), (0.22, -0.08),\
(0.21, 0.31), (0.33, 0.02)]
If you really need to make it a function, then you can abbreviate by using a lambda:
f = lambda count: [(random() - 0.5, random() - 0.5) for _ in range(count)]
This way you can call it like:
>>> f(1)
f(1)
[(0.03, -0.09)]
>>> f(2)
f(2)
[(-0.13, 0.38), (0.10, -0.04)]
>>> f(5)
f(5)
[(-0.38, -0.14), (0.31, -0.16), (-0.34, -0.46), (-0.45, 0.28), (-0.01, -0.18)]
>>> f(10)
f(10)
[(0.01, -0.24), (0.39, -0.11), (-0.06, 0.09), (0.42, -0.26), (0.24, -0.44) , (-0.29, -0.30), (-0.27, 0.45), (0.10, -0.41), (0.36, -0.07), (0.00, -0.42)]
>>>
you get the idea...
Late to the party, but here's a potential idea:
def RandomSample(count):
f = lambda: random() - 0.5
r = range if count < 100 else xrange # or some other number
return [(f(), f()) for _ in r(count)]
Strictly speaking, this is more or less the same as the other answers, but it does two things that look kind of nice to me.
First, it removes that duplicate code you have from writing random() - 0.5 twice by putting that into a lambda.
Second, for a certain size range, it chooses to use xrange() instead of range() so as not to unnecessarily generate a giant list of numbers you're going to throw away. You may want to adjust the exact number, because I haven't played with it at all, I just thought it might be a potential efficiency concern.
There should be a way to suppress code analysis errors in PyDev, like this:
http://pydev.org/manual_adv_assistants.html
Also, PyDev will ignore unused variables that begin with an underscore, as shown here:
http://pydev.org/manual_adv_code_analysis.html
Try this:
while count > 0:
pattern.append((random() - 0.5, random() - 0.5))
count -= 1
import itertools, random
def RandomSample2D(npoints, get_random=lambda: random.uniform(-.5, .5)):
return ((r(), r()) for r in itertools.repeat(get_random, npoints))
uses random.uniform() explicitly
returns an iterator instead of list