I was trying to program the perceptron learning rule for the case of an AND example. Graphically we will have:
where the value of x0=1, the algorithm for updating the weights is:
and I have made the following program in Python:
import math
def main():
theta=[-0.8,0.5,0.5]
learnrate=0.1
target=[0,0,0,1]
output=[0,0,0,0]
x=[[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
for i in range(0,len(x)):
output[i]=evaluate(theta,x[i])
for j in range(0,100):
update(theta,x,learnrate,target,output)
def evaluate(theta,x):
r=theta[0]*x[0]+theta[1]*x[1]+theta[2]*x[2]
r=1/(1+math.exp(-r))
return r
def update(theta,x,n,target,output):
for i in range(0,len(x)):
for j in range(0,len(x[i])):
delta=n*(target[i]-output[i])*x[i][j]
theta[j]=theta[j]+delta
print theta
r=evaluate(theta,x[i])
print r
print "\n"
if __name__=="__main__":
main()
The problem occurs when I run the program, for the first set of theta values:
theta=[-0.8,0.5,0.5]
I got the values:
[-7.869649929246505, 0.7436243430418894, 0.7436243430418894]
0.000382022127989
[-7.912205677565339, 0.7436243430418894, 0.7010685947230553]
0.000737772440166
[-7.954761425884173, 0.7010685947230553, 0.7010685947230553]
0.000707056388635
[-7.90974482561542, 0.7460851949918075, 0.7460851949918075]
0.00162995036457
the bracket terms are the updated theta values, while the other values are the results of the evaluation. In this case my results should be very close to 1 for the last case and close to 0 for the other, but this is not happening.
When I use this values:
theta=[-30,20,20]
they neatly approach to one the last data set, and 0 for the others:
[-30.00044943890137, 20.0, 20.0]
9.35341823401e-14
[-30.000453978688242, 20.0, 19.99999546021313]
4.53770586567e-05
[-30.000458518475114, 19.99999546021313, 19.99999546021313]
4.53768526644e-05
[-30.000453978688242, 20.0, 20.0]
0.999954581518
and even when I try with another set:
theta=[-5,20,20]
my results are not as good as the previous ones:
[-24.86692245237865, 10.100003028432075, 10.100003028432075]
1.5864734081e-11
[-24.966922421788425, 10.100003028432075, 10.000003059022298]
3.16190904073e-07
[-25.0669223911982, 10.000003059022298, 10.000003059022298]
2.86101378609e-07
[-25.0669223911982, 10.000003059022298, 10.000003059022298]
0.00626235903
am I missing some part or is there something wrong in this implementation? I know that there is another algorithm that uses derivatives, but I would like to implement this naive case.
Thanks
The problem is that you are not recomputing the output after the weights change so the error signal remains constant and the weights will change in the same way on every iteration.
Change the code as follows:
def update(theta,x,n,target,output):
for i in range(0,len(x)):
output[i] = evaluate(theta,x[i]) # This line is added
for j in range(0,len(x[i])):
delta=n*(target[i]-output[i])*x[i][j]
theta[j]=theta[j]+delta
print theta
r=evaluate(theta,x[i])
print r
print "\n"
and you should find it converges much better.
Related
For my current assignment, I am to establish the stability of intersection/equilibrium points between two nullclines, which I have defined as follows:
def fNullcline(F):
P = (1/k)*((1/beta)*np.log(F/(1-F))-c*F+v)
return P
def pNullcline(P):
F = (1/delta)*(pD-alpha*P+(r*P**2)/(m**2+P**2))
return F
I also have a method "stability" that applies the Hurwitz criteria on the underlying system's Jacobian:
def dPdt(P,F):
return pD-delta*F-alpha*P+(r*P**2)/(m**2+P**2)
def dFdt(P,F):
return s*(1/(1+sym.exp(-beta*(-v+c*F+k*P)))-F)
def stability(P,F):
x = sym.Symbol('x')
ax = sym.diff(dPdt(x, F),x)
ddx = sym.lambdify(x, ax)
a = ddx(P)
# shortening the code here: the same happens for b, c, d
matrix = [[a, b],[c,d]]
eigenvalues, eigenvectors = np.linalg.eig(matrix)
e1 = eigenvalues[0]
e2 = eigenvalues[1]
if(e1 >= 0 or e2 >= 0):
return 0
else:
return 1
The solution I was looking for was later provided. Basically, values became too small! So this code was added to make sure no too small values are being used for checking the stability:
set={0}
for j in range(1,210):
for i in range(1,410):
x=i*0.005
y=j*0.005
x,y=fsolve(System,[x,y])
nexist=1
for i in set:
if(abs(y-i))<0.00001:
nexist=0
if(nexist):
set.add(y)
set.discard(0)
I'm still pretty new to coding so the function in and on itself is still a bit of a mystery to me, but it eventually helped in making the little program run smoothly :) I would again like to express gratitude for all the help I have received on this question. Below, there are still some helpful comments, which is why I will leave this question up in case anyone might run into this problem in the future, and can find a solution thanks to this thread.
After a bit of back and forth, I came to realise that to avoid the log to use unwanted values, I can instead define set as an array:
set = np.arange(0, 2, 0.001)
I get a list of values within this array as output, complete with their according stabilities. This is not a perfect solution as I still get runtime errors (in fact, I now get... three error messages), but I got what I wanted out of it, so I'm counting that as a win?
Edit: I am further elaborating on this in the original post to improve the documentation, however, I would like to point out again here that this solution does not seem to be working, after all. I was too hasty! I apologise for the confusion. It's a very rocky road for me. The correct solution has since been provided, and is documented in the original question.
I'm new to Numpy and already read a few things about it. Repeatedly it says, that you should get rid of loops when using Numpy, because otherwise you have some Python-overhead which slows down your code. So for practicing I tried to implement a simple algorithm in a "numpythonic" way, but I can't manage to get rid of the for loop. Is there a way to improve this solution?
My main problem is, that I have some kind of "cumulative-conditional" situation and I have no idea how I can solve this without a loop.
import numpy as np
def process(data):
r = np.zeros(3)
for d in data:
ru = r / np.linalg.norm(r)
r = np.where(
np.dot(ru, d) < 0.0,
r + np.negative(d),
r + d
)
return r
data = [
[0.99558784, 0.03476669, -0.08715574],
[0.99194152, 0.1217951, -0.0348995],
[0.9864998, 0.08630755, -0.1391731]
]
print(process(data))
# Out: [ 2.97402916 0.24286934 -0.26122834]
(Besides of my main problem I'm open for general criticism or improvement suggestions of course)
A few comments:
In first loop, your ru = ... statement produces warning - it divides by 0.
In this case, np.dot() returns a single float, not an array. Hence, there is no point for using np.where(); if statement would be faster.
For the data you provided, your function is equivalent to np.sum(data, axis=0).
I have written a function for covariance matrix and the output I am getting is correct but the problem with the code is, it's taking too much time for high dimension dataset.
Could you please help me to modify the code below to take less time for output?
def cov_variance(norm_data,mean_of_mat):
col = len(norm_data)
row = len(norm_data[0])
out =[]
i = 0
sum_of_covar = 0
freezrow = 0
flag = 1
while flag<=len(mean_of_mat):
for r in range(row):
for c in range(col):
sum_of_covar+=(((norm_data[c][freezrow])-mean_of_mat[freezrow])*\
((norm_data[c][r])-mean_of_mat[i]))
freezrow=freezrow
out.append(sum_of_covar)
i+=1
sum_of_covar=0
freezrow=freezrow
flag+=1
freezrow+=1
i=0
out1 = map(lambda x : x/col-1,out)
cov_variance_output = reshape(out1,row)
return cov_variance_output
Like doctorlove already said, don't implement your own. It will almost certainly be slower and/or less versatile (speaking from my own experience).
I tried commenting with this info but my rep is too low. You can find information on calculating covariance matrices with numpy here: https://docs.scipy.org/doc/numpy/reference/generated/numpy.cov.html
I'm using the bisection method from the scipy.optimize package within a for loop.
The idea is to get a value of "sig" with the bisection method for each element (value) in the "eps_komp" vector. I've coded this much:
import numpy as np
import scipy.optimize as optimize
K=300
n = 0.43
E = 210000
Rm = 700
sig_a = []
RO_K = 300
RO_n = 0.43
eps_komp = [0.00012893048999999997,
0.018839115269999998,
0.01230539995,
0.022996934109999999,
-0.0037319012899999999,
0.023293921169999999,
0.0036927752099999997,
0.020621037629999998,
0.0063656587500000002,
0.020324050569999998,
-0.0025439530500000001,
0.018542128209999998,
0.01230539995,
0.019730076449999998,
0.0045837363899999999,
0.015275270549999997,
-0.0040288883499999999,
0.021215011749999999,
-0.0031379271699999997,
0.023590908229999999]
def eps_f(i):
return eps_komp[i]
for j in range(len(eps_komp)):
eps_komp_j = eps_f(j)
if j <= len(eps_komp):
def func(sig):
return eps_komp_j - sig/E - (sig/RO_K)**(1/RO_n)
sig_a.append(optimize.bisect(func, 0, Rm))
else:
break
print(sig_a)
Now if I change the the value of "j" in eps_f(j) to 0:
eps_komp_j = eps_f(0)
it works, and so it does for all other values that I insert by hand, but if I keep it like it is in the for loop, the "j" value doesnt change automatically and I get an error:
f(a) and f(b) must have different signs
Has anyone a clue what is the problem and how could this be solved?
Regards,
L
P.S. I did post another topic on this problem yesterday, but I wasnt very specific with the problem and got negative feedback. However, I do need to solve this today, so I was forced to post it again, however I did manage to get a bit further with the code then I did in the earlier post, so it isn't a repost...
If you read the docs you'll find that:
Basic bisection routine to find a zero of the function f between the arguments a and b. f(a) and f(b) cannot have the same signs. Slow but sure.
In your code:
def func(sig):
return eps_komp_j - sig/Emod - (sig/RO_K)**(1/RO_n)
sig_a.append(optimize.bisect(func, 0, Rm))
You're passing it func(0) and func(700).
By replacing the optimize.bisect line with print(func(0), func(700)) I get the following output:
0.00012893048999999997 -7.177181168628421
0.018839115269999998 -7.158470983848421
0.01230539995 -7.165004699168421
0.02299693411 -7.15431316500842
-0.00373190129 -7.1810420004084206
0.02329392117 -7.154016177948421
0.0036927752099999997 -7.173617323908421
0.02062103763 -7.156689061488421
0.00636565875 -7.17094444036842
0.02032405057 -7.156986048548421
-0.00254395305 -7.17985405216842
0.018542128209999998 -7.15876797090842
0.01230539995 -7.165004699168421
0.019730076449999998 -7.157580022668421
0.00458373639 -7.172726362728421
0.015275270549999997 -7.162034828568421
-0.00402888835 -7.181338987468421
0.02121501175 -7.156095087368421
-0.0031379271699999997 -7.1804480262884205
0.02359090823 -7.153719190888421
Note the multiple pairs that have the same signs. optimize.bisect can't handle those. I don't know what you're trying to accomplish, but this is the wrong approach.
I am trying to implement a simple formula with python . In the case of "RLSR" there two approach to calculate the coefficient "C" by C=k^-1*y where k is the kernel matrix and y is the target value vector.
The second way is by using eigenvalues(w) and eigenvectors(v) of the kernel method and using formula :
Sum(u(i)*<u(i),y> / w(i) ).
to check the answer of the result I'm checking whether y=kc or not! in the first case it's ok , but the latter case it's not.but the problem is my c vectors in both method look the same.
output from invers algorithm :
[ 19.49840251 18.82695226 20.08390355 15.01043404 14.79353281
16.75316736 12.88504257 16.92127176 16.77292954 17.81827473
20.90503787 17.09359467 18.76366701 18.14816903 20.03491117
22.56668264 21.45176136 25.44051036 30.40312692 22.61466379
22.86480382 19.34631818 17.0169598 19.85244414 16.63702471
20.35280156 20.58093488 22.42058736 20.54935198 19.35541575
20.39006958 19.74766081 20.41781019 22.33858797 17.57962283
22.61915219 22.54823733 24.96292824 22.82888425 34.18952603
20.7487537 24.82019935 22.40621769 21.15767304 27.58919263
18.39293156 21.55455108 18.69532341]
output from second(eigendecomposition ) algorithm :
[ 19.25280289 18.73927731 19.77184991 14.7650427 14.87364331
16.2273648 12.29183797 16.52024239 16.66669961 17.59282615
20.83059115 17.02815857 18.3635798 18.16931845 20.50528549
22.67690164 21.40479524 25.54544 30.94618128 22.72992565
23.06289609 17.6485592 15.2758427 19.50578691 16.45571607
20.19960765 20.35352859 22.60091638 20.36586912 18.90760728
20.57141151 19.43677153 20.43437031 22.39310576 17.72296978
22.82139991 22.50744791 25.10496617 22.30462867 34.80540213
20.77064617 25.18071618 22.5500315 20.71481252 27.91939784
18.29868659 22.00800019 18.71266093]
this how I have implemented it:
so let say if we have 48 samples the size of K is 48x48 , y is 48x1
def cpu_compute(y,k):
w, u=LA.eigh(k)
uDoty=np.dot(u,y)
temp=np.transpose(np.tile(w,(len(u),1)))
div=np.divide(u,temp)
r=np.tile(uDoty,(len(div),1))
a=div*r.T
c=sum(a)
return c
and the result from
print np.allclose(Y,np.dot(K,c))
is false.
also the norm of difference from the true result is 3.13014997999.
now I have no idea how can I fix this . I thought maybe some how by doing more precise answer.
Appreciate any help!
To solve k c = y with numpy, use numpy.linalg.solve:
c = solve(k, y)
This uses an algorithm that is much more robust than the methods you are trying.