Related
I want to find the value of the parameter m that minimizes my variable x subject to a system of differential equations. I have the following code
from gekko import GEKKO
def run_model_m(days, population, case, k_val, b_val, u0_val, sigma_val, Kmax0, a_val, c_val):
list_x =[]
list_u =[]
list_Kmax =[]
for i in range(len(days)):
list_xi=[]
list_ui=[]
list_Ki=[]
for j in range(len(days[i])):
#try:
m = GEKKO(remote=False)
#m.time= days[i][j]
eval = np.linspace(days[i][j][0], days[i][j][-1], 100, endpoint=True)
m.time = eval
x_data= population[i][j]
variable= np.linspace(population[i][j][0], population[i][j][-1], 100, endpoint=True)
x = m.Var(value=population[i][j][0], lb=0)
sigma= m.Param(sigma_val)
d = m.Param(c_val)
k = m.Param(k_val)
b = m.Param(b_val)
r = m.Param(a_val)
step = np.ones(len(eval))
step= 0.2*step
step[0]=1
m_param = m.CV(value=1, lb=0, ub=1, integer=True); m_param.STATUS=1
u = m.Var(value=u0_val, lb=0, ub=1)
#m.free(u)
a = m.Param(a_val)
c= m.Param(c_val)
Kmax= m.Param(Kmax0)
if case == 'case0':
m.Equations([x.dt()== x*(r*(1-x/(Kmax))-m_param/(k+b*u)-d), u.dt()== sigma*(m_param*b/((k+b*u)**2))])
elif case == 'case4':
m.Equations([x.dt()== x*(r*(1-u**2)*(1-x/(Kmax))-m_param/(k+b*u)-d), u.dt() == sigma*(-2*u*r*(1-x/(Kmax))+(b*m_param)/(b*u+k)**2)])
p = np.zeros(len(eval))
p[-1] = 1.0
final = m.Param(value=p)
m.Obj(x)
m.options.IMODE = 6
m.options.MAX_ITER=15000
m.options.SOLVER=1
# optimize
m.solve(disp=False, GUI=False)
#m.open_folder(dataset_path+'inf')
list_xi.append(x.value)
list_ui.append(u.value)
list_Ki.append(m_param.value)
list_x.append(list_xi)
list_Kmax.append(list_Ki)
list_u.append(list_ui)
return list_x, list_u, list_Kmax, m.options.OBJFCNVAL
scaled_days[i][j] =[-7.0, 42.0, 83.0, 125.0, 167.0, 217.0, 258.0, 300.0, 342.0]
scaled_pop[i][j] = [0.01762491277346285, 0.020592540360308997, 0.017870838266697213, 0.01690069378982034,0.015512320147187675,0.01506701796298272,0.014096420738841563,0.013991224004743027,0.010543380664478205]
k0,b0,group, case0, u0, sigma0, K0, a0, c0 = (100, 20, 'Size3, Inc', 'case0', 0.1, 0.05, 2, 0, 0.01)
list_x2, list_u2, list_Kmax2,final =run_model_m(days=[[scaled_days[i][j]]], population=
[[scaled_pop[i][j]]],case=case1, k_val=list_b1[i0][0], b_val=b1, u0_val=list_u1[i0][j0],
sigma_val=sigma1, Kmax0=K1, a_val=list_Kmax1[0][0], c_val=c1)
I get the error Data arrays must have the same length, and match time discretization in dynamic problems error but I don't understand why. I have tried making x and m_param arrays, with x=m.Var, m_param =m.MV... But still get the same error, even if they are all arrays of the same length. Is this the right way to find the solution of the minimization problem?
I think the error was just that in run_model_m I was passing a list as u0_val and it didn't have the same dimensions as m.time. So it should be u0_val=list_u1[0][0][0]
My problem has a single state and an infinite amount of actions on a certain interval (0,1). After quite some time of googling I found a few paper about an algorithm called zooming algorithm which can solve problems with a continous action space. However my implementation is bad at exploiting. Therefore I'm thinking about adding an epsilon-greedy kind of behavior.
Is it reasonable to combine different methods?
Do you know other approaches to my problem?
Code samples:
import portion as P
def choose_action(self, i_ph):
# Activation rule
not_covered = P.closed(lower=0, upper=1)
for arm in self.active_arms:
confidence_radius = calc_confidence_radius(i_ph, arm)
confidence_interval = P.closed(arm.norm_value - confidence_radius, arm.norm_value + confidence_radius)
not_covered = not_covered - confidence_interval
if not_covered != P.empty():
rans = []
height = 0
heights = []
for i in not_covered:
rans.append(np.random.uniform(i.lower, i.upper))
height += i.upper - i.lower
heights.append(i.upper - i.lower)
ran_n = np.random.uniform(0, height)
j = 0
ran = 0
for i in range(len(heights)):
if j < ran_n < j + heights[i]:
ran = rans[i]
j += heights[i]
self.active_arms.append(Arm(len(self.active_arms), ran * (self.sigma_square - lower) + lower, ran))
# Selection rule
max_index = float('-inf')
max_index_arm = None
for arm in self.active_arms:
confidence_radius = calc_confidence_radius(i_ph, arm)
# indexfunction from zooming algorithm
index = arm.avg_learning_reward + 2 * confidence_radius
if index > max_index:
max_index = index
max_index_arm = arm
action = max_index_arm.value
self.current_arm = max_index_arm
return action
def learn(self, action, reward):
arm = self.current_arm
arm.avg_reward = (arm.pulled * arm.avg_reward + reward) / (arm.pulled + 1)
if reward > self.max_profit:
self.max_profit = reward
elif reward < self.min_profit:
self.min_profit = reward
# normalize reward to [0, 1]
high = 100
low = -75
if reward >= high:
reward = 1
self.high_count += 1
elif reward <= low:
reward = 0
self.low_count += 1
else:
reward = (reward - low)/(high - low)
arm.avg_learning_reward = (arm.pulled * arm.avg_learning_reward + reward) / (arm.pulled + 1)
arm.pulled += 1
# zooming algorithm confidence radius
def calc_confidence_radius(i_ph, arm: Arm):
return math.sqrt((8 * i_ph)/(1 + arm.pulled))
You may find this useful, full algorithm description is here. They grid out the probes uniformly, informing this choice (e.g. normal centering on a reputed high energy arm) is also possible (but this might invalidate a few bounds I am not sure).
I am currently learning about how to code neural networks in numpy/python. I used the code from this tutorial and tried to adapt it to make an importable module. However, when i tried using my own dataset. It threw a numpy error ValueError: shapes (1,3) and (1,1) not aligned: 3 (dim 1) != 1 (dim 0).
I have already tried reshaping all of the matrices from (x,) to (x,1) but with no success. After a bit of reading around, transposing the arrays was also meant to fix the issue, but i tried that as well and no success there either.
Here is the module (called hidden_net):
import numpy as np
class network:
def __init__(self,layer_num,learning_rate=0.7,seed=None,logistic_coefficent=0.9):
self.logistic_coefficent=logistic_coefficent
self.learning_rate=learning_rate
self.w0 = np.random.random((layer_num[0],layer_num[1]))
self.w1 = np.random.random((layer_num[1],layer_num[2]))
np.random.seed(seed)
def sigmoid(self,x,reverse=False):
if(reverse==True):
return x*(1-x)
return 1/(1+np.exp(-x*self.logistic_coefficent))
def train(self,inps,outs):
inps=np.array(inps)
layer0 = inps
layer1 = self.sigmoid(np.dot(layer0,self.w0))
layer2 = self.sigmoid(np.dot(layer1,self.w1))
layer2_error = outs - layer2
layer2_delta = layer2_error*self.sigmoid(layer2,reverse=True)#*self.learning_rate
layer1_error = layer2_delta.dot(self.w1.T)
layer1_delta = layer1_error * self.sigmoid(layer1,reverse=True)#*self.learning_rate
layer1= np.reshape(layer1, (layer1.shape[0], 1))
layer2= np.reshape(layer2, (layer2.shape[0], 1))
layer1_delta= np.reshape(layer1_delta, (layer1_delta.shape[0], 1)) #Other attempts to reshape to avoid this error
layer2_delta= np.reshape(layer2_delta, (layer2_delta.shape[0], 1))
self.w1 += layer1.T.dot(layer2_delta)
self.w0 += layer0.T.dot(layer1_delta)
Here is the program importing that module:
import hidden_net
op=open('Mall_Customers_Mod.txt','r')
full=op.read()
op.close()
full_lines=full.split('\n')
training_lines=[]
for i in range(174):
training_lines.append(full_lines[0])
del full_lines[0]
training_inputs=[]
training_outputs=[]
for j in training_lines:
training_inputs.append([float(j.split(',')[0]),float(j.split(',')[1])])
training_outputs.append(float(j.split(',')[2]))
testing_lines=full_lines
testing_inputs=[]
testing_outputs=[]
for l in testing_lines:
testing_inputs.append([float(l.split(',')[0]),float(l.split(',')[1])])
testing_outputs.append(float(l.split(',')[2]))
nn=hidden_net.network([2,3,1],seed=10)
for i in range(1000):
for cur in range(len(training_inputs)):
nn.train(training_inputs[cur],training_outputs[cur])
and here is part of my data set (Mall_Customers_Mod.txt)
-1,19,15
-1,21,15
1,20,16
1,23,16
1,31,17
1,22,17
1,35,18
1,23,18
-1,64,19
1,30,19
-1,67,19
1,35,19
1,58,20
1,24,20
-1,37,20
-1,22,20
1,35,21
-1,20,21
-1,52,23
The error is on line 30:
self.w1 += layer1.T.dot(layer2_delta)
ValueError: shapes (1,3) and (1,1) not aligned: 3 (dim 1) != 1 (dim 0)
Also sorry, i know i am meant to avoid pasting entire files, but it seems pretty unavoidable here
The lines below are wrong, layer0 is the input layer and does not contain any neurons.
self.w1 += layer1.T.dot(layer2_delta)
self.w0 += layer0.T.dot(layer1_delta)
They should be:
self.w1 += layer2.T.dot(layer2_delta)
self.w0 += layer1.T.dot(layer1_delta)
All the reshape operations should be removed too. The updated train function
def train(self,inps,outs):
inps=np.array(inps)
layer0 = inps
layer1 = self.sigmoid(np.dot(layer0,self.w0))
layer2 = self.sigmoid(np.dot(layer1,self.w1))
layer2_error = outs - layer2
layer2_delta = layer2_error*self.sigmoid(layer2,reverse=True)#*self.learning_rate
layer1_error = layer2_delta.dot(self.w1.T)
layer1_delta = layer1_error * self.sigmoid(layer1,reverse=True)#*self.learning_rate
self.w1 += layer2.T.dot(layer2_delta)
self.w0 += layer1.T.dot(layer1_delta)
I am setting up an optimization in OpenMDAO v0.13 using several components that are used many times. My assembly seems to be working just fine with the default driver, but when I run with an optimizer it does not solve. The optimizer simply runs with the inputs given and returns the answer using those inputs. I am not sure what the issue is, but I would appreciate any insights. I have included a simple code mimicking my structure that reproduces the error. I think the problem is in the connections, summer.fs does not update after initialization.
from openmdao.main.api import Assembly, Component
from openmdao.lib.datatypes.api import Float, Array, List
from openmdao.lib.drivers.api import DOEdriver, SLSQPdriver, COBYLAdriver, CaseIteratorDriver
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='out')
a = Float(iotype='in', default_value=1)
def execute(self):
x = self.x
a = self.a
term1 = a*x**2
self.term1 = term1
print "In comp1", self.name, self.a, self.x, self.term1
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
def execute(self):
y = self.y
x = self.x
term1 = self.term1
f = term1 + x + y**2
self.f = f
print "In comp2", self.name, self.x, self.y, self.term1, self.f
class summer(Component):
total = Float(iotype='out', desc='sum of all f values')
def __init__(self, size):
super(summer, self).__init__()
self.size = size
self.add('fs', Array(np.ones(size), iotype='in', desc='f values from all cases'))
def execute(self):
self.total = sum(self.fs)
print 'In summer, fs = %s and total = %s' % (self.fs, self.total)
class assembly(Assembly):
x = Float(iotype='in')
y = Float(iotype='in')
total = Float(iotype='out')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
print 'in init a_vals = %s' % self.a_vals
def configure(self):
# self.add('driver', SLSQPdriver())
self.add('driver', pyOptDriver())
self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
print 'in configure a_vals = %s' % self.a_vals
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d'%i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x'%i, 'comp2_%d.x'%i])
self.connect('y', ['comp1_%d.y'%i, 'comp2_%d.y'%i])
self.connect('comp1_%d.term1'%i, 'comp2_%d.term1'%i)
self.connect('comp2_%d.f'%i, 'summer.fs[%d]'%i)
self.driver.workflow.add(['comp1_%d'%i, 'comp2_%d'%i])
self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# set up main driver (optimizer)
self.driver.iprint = 1
self.driver.maxiter = 100
self.driver.accuracy = 1.0e-6
self.driver.add_parameter('x', low=-5., high=5.)
self.driver.add_parameter('y', low=-5., high=5.)
self.driver.add_objective('summer.total')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print test.a_vals
test.x = 2.
test.y = 2.
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print test.fs
I played around with your model, and found that the following line caused problems:
#self.connect('summer.fs[:]', 'fs[:]')
When I commented it out, I got the optimization to move.
I am not sure what is happening there, but the graph transformations sometimes have some issues with component input nodes that are promoted as outputs on the assembly boundary. If you still want those values to be available on the assembly, you could try promoting the outputs from the comp2_n components instead.
In one of my GUIs I load DICOM images. Sometimes they are just a volume and another dimension and when I load them in Matlab everything ends up where I want it.
handles.inf = dicominfo([filepath filename]);
handles.dat = dicomread(handles.inf);
size(handles.dat)
ans = 128 128 128 512
For an 128 by 128 by 128 volume at 512 timepoints for example (actually the third dimension would not even be 128, the third dimension is stacks, of which I don't know what it is). However sometimes There are more dimensions in the dicom, but the reader just puts all of them in the fourth dimension.
handles.inf = dicominfo([filepath filename]);
handles.dat = dicomread(handles.inf);
size(handles.dat)
ans = 128 128 1 4082
For a single 128 by 128 slice with 512 timepoints, two echoes and magnitude, phase, real and imaginary data for example.
It is then very hard to unscramble them. Manually I can do this for every DICOM I load but when in a GUI I would want to have a general approach that just creates a dimension in the array for each dimension in the dicom.
This is especially important not just for data-analysis, but also to transform the coordinates from image space to patient space. My own approach was to look at the header, but there's no guarantee that certain entries will work, and the order in which they are applied I can't find. The header entries I found so far:
inf.Rows;%inf.width;%inf.MRAcquisitionFrequencyEncodingSteps;%inf.MRAcquisitionPhaseEncodingStepsInPlane
inf.Columns;% inf.height; % inf.NumberOfKSpaceTrajectories;
inf.MRSeriesNrOfSlices
inf.MRSeriesNrOfEchoes
inf.MRSeriesNrOfDynamicScans
inf.MRSeriesNrOfPhases
inf.MRSeriesReconstructionNumber % not sure about this one
inf.MRSeriesNrOfDiffBValues
inf.MRSeriesNrOfDiffGradOrients
inf.MRSeriesNrOfLabelTypes
reshapeddat = reshape(dat, [all dimension sizes from header here]);
I'm not sure how to check if I've got all variables and what the right order for the reshape. Anybody knows of a sure-fire way to get all dimension sizes from the DICOM header and the order in which they are stacked?
Ok so I now manually go by all possible dimensions. When a stack also contains reconstructed data which has less dimensions than the rest, remove those first.
This is how I check the dimensions:
info = dicominfo(filename);
datorig = dicomread(filename);
%dimension sizes per frame
nrX = double(info.Rows); %similar nX;% info.width;% info.MRAcquisitionFrequencyEncodingSteps;% info.MRAcquisitionPhaseEncodingStepsInPlane
nrY = double(info.Columns); %similar nY;% info.height;% info.NumberOfKSpaceTrajectories;
%dimensions between frames
nrEcho = double(info.MRSeriesNrOfEchoes);
nrDyn = double(info.MRSeriesNrOfDynamicScans);
nrPhase = double(info.MRSeriesNrOfPhases);
nrSlice = double(info.MRSeriesNrOfSlices); %no per frame struct entry, calculate from offset.
%nr of frames
nrFrame = double(info.NumberOfFrames);
nrSeq = 1; % nSeq not sure how to interpret this, wheres the per frame struct entry?
nrBval = double(info.MRSeriesNrOfDiffBValues); % nB
nrGrad = double(info.MRSeriesNrOfDiffGradOrients); % info.MRSeriesNrOfPhaseContrastDirctns;%similar nGrad?
nrASL = 1; % info.MRSeriesNrOfLabelTypes;%per frame struct entry?
imtype = cell(1, nrFrame);
for ii = 1:nrFrame
%imtype(ii) = eval(sprintf('info.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageTypeMR', ii));
imtype{ii} = num2str(eval(sprintf('info.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageTypeMR', ii)));
end
imType = unique(imtype, 'stable');
nrType = length(imType);
This is how I reformat the dimensions:
%% count length of same dimension positions from start
if nrEcho > 1
for ii = 1:nrFrame
imecno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.EchoNumber', ii));
end
lenEcho = find(imecno ~= imecno(1), 1, 'first') - 1;
else
lenEcho = nrFrame;
end
if nrDyn > 1
for ii = 1:nrFrame
imdynno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.TemporalPositionIdentifier', ii));
end
lenDyn = find(imdynno ~= imdynno(1), 1, 'first') - 1;
else
lenDyn = nrFrame;
end
if nrPhase > 1
for ii = 1:nrFrame
imphno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImagePhaseNumber', ii));
end
lenPhase = find(imphno~=imphno(1), 1, 'first') - 1;
else
lenPhase = nrFrame;
end
if nrType > 1
q = 1;
imtyno(1, 1) = q;
for ii = 2:nrFrame
if imtype{:, ii-1} ~= imtype{:, (ii)}
q = q+1;
end
imtyno(1, ii) = q;
%for jj = 1:nrType
%if imtype{:,ii} == imType{:,jj}
% imtyno(1, ii) = jj;
%end
%end
end
if q ~= nrType
nrType = q;
end
lenType = find(imtyno ~= imtyno(1), 1, 'first') - 1;
else
lenType = nrFrame;
end
% slices are not numbered per frame, so get this indirectly from location
% currently not sure if working for all angulations
for ii = 1:nrFrame
imslice(:,ii) = -eval(['inf.PerFrameFunctionalGroupsSequence.Item_',sprintf('%d', ii),'.PlanePositionSequence.Item_1.ImagePositionPatient']);
end
% stdsl = std(imslice,[],2); --> Assumption
% dirsl = max(find(stdsl == max(stdsl)));
imslices = unique(imslice', 'rows')';
if nrSlice > 1
for ii = 1:nrFrame
for jj = 1:nrSlice
if imslice(:,ii) == imslices(:,nrSlice - (jj-1)); %dirsl or :?
imslno(1, ii) = jj;
end
end
end
lenSlice = find(imslno~=imslno(1), 1, 'first')-1;
else
lenSlice = nrFrame;
end
if nrBval > 1
for ii = 1:nrFrame
imbno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageDiffBValueNumber', ii));
end
lenBval = find(imbno~=imbno(1), 1, 'first') - 1;
else
lenBval = nrFrame;
end
if nrGrad > 1
for ii = 1:nrFrame
imgradno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageGradientOrientationNumber', ii));
end
lenGrad = find(imgradno~=imgradno(1), 1, 'first')-1;
else
lenGrad = inf.NumberOfFrames;
end
lenSeq = nrFrame; % dont know how to get this information per frame, in my case always one
lenASL = nrFrame; % dont know how to get this information per frame, in my case always one
%this would have been the goal format
goaldim = [nrSlice nrEcho nrDyn nrPhase nrType nrSeq nrBval nrGrad nrASL]; % what we want
goallen = [lenSlice lenEcho lenDyn lenPhase lenType lenSeq lenBval lenGrad lenASL]; % what they are
[~, permIX] = sort(goallen);
dicomdim = zeros(1, 9);
for ii = 1:9
dicomdim(1, ii) = goaldim(permIX(ii));
end
dicomdim = [nrX nrY dicomdim];
%for any possible zero dimensions from header use a 1 instead
dicomdim(find(dicomdim == 0)) = 1;
newdat = reshape(dat, dicomdim);
newdim = size(newdat);
newnonzero = length(newdim(3:end));
goalnonzero = permIX(1:newnonzero);
[dummyy, goalIX] = sort(goalnonzero);
goalIX = [1 2 goalIX+2];
newdat = permute(newdat, goalIX);
newdat = reshape(newdat, [nrX nrY goaldim]);
When Ive used this as a function for a longer period and debugged it a bit I might post in on the file exchange of mathworks.