Creating a zero vector,and modifying it in theano - python

I need to create a some fixed length(length equal to size of some other tensor vector which is passed) zero vector in theano.
def some_fun(self, y)
x_h = T.fvector('x_h')
ret = T.alloc(0, x_h)
vec_h = theano.function(inputs=[x_h], outputs=ret)
vec=vec_h(y.shape[0])
vec[T.arange(y.shape[0]),y]=1
When I am running this I am getting error "Shape arguments to Alloc must be integers, but argument 0 is not for apply node: x_h"
It may very big mistake, as I am new to theano.
Thanks

Have you tried theano.tensor.zeros_like? It seems like that should be a shortcut to what you're trying to do.
Then, when you get
"TypeError: 'TensorVariable' object does not support item assignment"
you can replace the line vec[T.arange(y.shape[0]),y]=1 by using theano.tensor.set_subtensor instead.

Related

How to iterate over external input list in pyomo objective function?

I am trying to run a simple LP pyomo Concrete model with Gurobisolver :
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
model = pyo.ConcreteModel()
nb_years = 3
nb_mins = 2
step = 8760*1.5
delta = 10000
#Range of hour
model.h = pyo.RangeSet(0,8760*nb_years-1)
#Individual minimums
model.min = pyo.RangeSet(0, nb_mins-1)
model.mins = pyo.Var(model.min, within=model.h, initialize=[i for i in model.min])
def maximal_step_between_mins_constraint_rule(model, min):
next_min = min + 1 if min < nb_mins-1 else 0
if next_min == 0: # We need to take circularity into account
return 8760*nb_years - model.mins[min] + model.mins[next_min] <= step + delta
return model.mins[next_min] - model.mins[min] <= step + delta
def minimal_step_between_mins_constraint_rule(model, min):
next_min = min + 1 if min < nb_mins-1 else 0
if next_min == 0: # We need to take circularity into account
return 8760*nb_years - model.mins[min] + model.mins[next_min] >= step - delta
return model.mins[next_min] - model.mins[min] >= step - delta
model.input_list = pyo.Param(model.h, initialize=my_input_list, within=pyo.Reals, mutable=False)
def objective_rule(model):
return sum([model.input_list[model.mins[min]] for min in model.min])
model.maximal_step_between_mins_constraint= pyo.Constraint(model.min, rule=maximal_step_between_mins_constraint_rule)
model.minimal_step_between_mins_constraint= pyo.Constraint(model.min, rule=minimal_step_between_mins_constraint_rule)
model.objective = pyo.Objective(rule=objective_rule, sense=pyo.minimize)
opt = SolverFactory('gurobi')
results = opt.solve(model, options={'Presolve':2})
Basically I am trying to find two hours in my input list (which looks like this) spanning over 3 years of data, with constraints on the distance separating them, and where the sum of both value is minimized by the model.
I implemented my list as a parameter of fixed value, however even if mutable is set to False running my model produces this error :
ERROR: Rule failed when generating expression for Objective objective with
index None: RuntimeError: Error retrieving the value of an indexed item
input_list: index 0 is not a constant value. This is likely not what you
meant to do, as if you later change the fixed value of the object this
lookup will not change. If you understand the implications of using non-
constant values, you can get the current value of the object using the
value() function.
ERROR: Constructing component 'objective' from data=None failed: RuntimeError:
Error retrieving the value of an indexed item input_list: index 0 is not a
constant value. This is likely not what you meant to do, as if you later
change the fixed value of the object this lookup will not change. If you
understand the implications of using non-constant values, you can get the
current value of the object using the value() function.
Any idea why I get this error and how to fix it ?
Obviously, changing the objective function to sum([pyo.value(model.input_list[model.mins[min]]) for min in model.min]) is not a solution to my problem.
I also tried not to use pyomo parameters (with something like sum([input_list[model.mins[min]] for min in model.min]), but pyomo can't iterate over it and raises the following error :
ERROR: Constructing component 'objective' from data=None failed: TypeError:
list indices must be integers or slices, not _GeneralVarData
You have a couple serious syntax and structure problems in your model. Not all of the elements are included in the code you provide, but you (minimally) need to fix these:
In this snippet, you are initializing the value of each variable to a list, which is invalid. Start with no variable initializations:
model.mins = pyo.Var(model.min, within=model.h, initialize=[i for i in model.min])
In this summation, you appear to be using a variable as the index for some data. This is an invalid construct. The value of the variable is unkown when the model is built. You need to reformulate:
return sum([model.input_list[model.mins[min]] for min in model.min])
My suggestion: Start with a very small chunk of your data and pprint() your model and read it carefully for quality before you attempt to solve.
model.pprint()

TF Metric ChosenActionHistogram crashes with error

When using TF's tf_agents.metrics.tf_metrics.ChosenActionHistogram with TF's dynamic step driver and my own environment, I encounter the following error:
ValueError: Shapes must be equal rank, but are 1 and 0 for '{{node ResourceScatterUpdate}} = ResourceScatterUpdate[Tindices=DT_INT32, dtype=DT_INT32](ResourceScatterUpdate/resource, FloorMod, value)' with input shapes: [], [], [1]
I've attached observers to the step driver like so:
self.average_episode_length_metric = tf_metrics.AverageEpisodeLengthMetric()
self.average_return_metric = tf_metrics.AverageReturnMetric()
self.selected_action_histogram_metric = tf_metrics.ChosenActionHistogram()
self.observers = [self.average_episode_length_metric,
self.average_return_metric,
self.selected_action_histogram_metric
]
self.eval_step_driver = dynamic_step_driver.DynamicStepDriver(
self.eval_env,
self.agent.policy,
num_steps=self.num_eval_steps,
observers=self.observers
)
and then run the step driver like such:
self.eval_step_driver.run()
Some more of the error trace is as follows:
File "./bot/DQN.py", line 109, in record_policy_metrics
self.eval_step_driver.run()
tf_agents-0.4.0-py3.8.egg/tf_agents/metrics/tf_metrics.py:50 extend *
self.add(v)
I understand the premise of the issue, that tensor shapes are not matching, but I can't figure out why that might be happening. Removing ChosenActionHistorgram from the observers resolves the error and the other metrics work correctly. What could be going on here? Could the trajectory tensors be missing some value?
For anyone who comes across this issue I solved it for my case. I had mistakenly defined the action spec as (1,), a 1 dimensional vector, instead of (), a scalar value. This seemed to work for every other metric except for the tf_metrics.ChosenActionHistogram().
Ensuring my action spec complied with () instead of (1,) resolved the issue.

OperatorNotAllowedInGraphError: using a `tf.Tensor` as a Python `bool` is not allowed in Graph execution

I'm trying to execute these functions
def evaluate(sentence):
sentence = preprocess_sentence(sentence)
sentence = tf.expand_dims(
START_TOKEN + tokenizer.encode(sentence) + END_TOKEN, axis=0)
output = tf.expand_dims(START_TOKEN, 0)
for i in range(MAX_LENGTH):
predictions = model(inputs=[sentence, output], training=False)
# select the last word from the seq_len dimension
predictions = predictions[:, -1:, :]
predicted_id = tf.cast(tf.argmax(predictions, axis=-1), tf.int32)
# return the result if the predicted_id is equal to the end token
if tf.equal(predicted_id, END_TOKEN[0]):
break
#check()
#tf.cond(tf.equal(predicted_id, END_TOKEN[0]),true_fn=break,false_fn=lambda: tf.no_op())
# concatenated the predicted_id to the output which is given to the decoder
# as its input.
output = tf.concat([output, predicted_id], axis=-1)
return tf.squeeze(output, axis=0)
def predict(sentence):
prediction = evaluate(sentence)
predicted_sentence = tokenizer.decode(
[i for i in prediction if i < tokenizer.vocab_size])
print('Input: {}'.format(sentence))
print('Output: {}'.format(predicted_sentence))
return predicted_sentence
however, I'm having the following error:
OperatorNotAllowedInGraphError: using a `tf.Tensor` as a Python `bool` is not allowed in Graph execution. Use Eager execution or decorate this function with #tf.function.
I do understand that I have to rewrite the if condtion in a form of tf.cond(). however, i don't know how to write break in tensor flow, also I'm not sure which if condition is causing the problem as the same function exactly in this notebook is working properly?
https://colab.research.google.com/github/tensorflow/examples/blob/master/community/en/transformer_chatbot.ipynb#scrollTo=_NURhwYz5AXa
Any help?
The code in the notebook works because it uses TF 2.0, which has eager execution enabled by default. You can turn it on in older versions with tf.enable_eager_execution.
Alternatively, you can use break in graph mode without writing tf.cond if you use tf.function or tf.autograph, but they have some restrictions on the code you can run.
There is nothing wrong with the break statement. The problem is elsewhere.
if tf.equal(predicted_id, END_TOKEN[0]):
break
will give error something about using Python bool in tensor ops. Since you have already used tf.equal condition this could be confusing. The solution is simple. The error is being thrown for the
if (boolean): python syntax.
You would have to take care of this (bool) Python syntax and convert to tensor-style, based on what you are planning to achieve. Remember, the condition returns a tensor of boolean values. Read this tensor and then proceed to do what you want.. So for e.g. below would work unconditionally irrespective of the value of the condition:
if tf.equal(predicted_id, END_TOKEN[0]) is not None:
break

Why does scan upcast?

This code to calculate the trace of a matrix (based on an example in the Theano "loop" tutorial) works fine:
import numpy as np
import theano as th
import theano.tensor as T
floatX = 'float32'
X = T.matrix()
results = th.scan(lambda i,j,t_f : T.cast(X[i,j] + t_f, floatX),
sequences=[T.arange(X.shape[0]), T.arange(X.shape[1])],
outputs_info=np.asarray(0., dtype=floatX))[0]
result = results[-1]
compute_trace = th.function([X], result)
x = np.eye(5, dtype=floatX)
x[0] = np.arange(5, dtype=floatX)
print compute_trace(x)
But if I remove the cast operation from the lambda function like this:
lambda i,j,t_f : X[i,j] + t_f
The following error message is produced:
ValueError: When compiling the inner function of scan the following error has been encountered: The initial state (outputs_info in scan nomenclature) of variable IncSubtensor{Set;:int64:}.0 (argument number 2) has dtype float32, while the result of the inner function (fn) has dtype float64. This can happen if the inner function of scan results in an upcast or downcast.
Why so? X and outputs_info are explicitly set to float32. How does the result of adding them get to be float64?
This is a very late answer, but we're working on a fork of Theano called Aesara, and, since people still run into problems like this, it seems worthwhile to provide a public explanation.
That said, the issue is X = T.matrix(). T.matrix creates a float64 matrix when theano.config.floatX == "float64" (the default), and the result is an upcast to float64 for the sum in the body of the scan's loop function.
If X = T.fmatrix() is used, a float32 matrix is created instead and the problem is no longer present; otherwise, as mentioned in the comments, one can also set theano.config.floatX to "float32".

How to index an array value in a MATLAB-Function in Simulink?

I'm using a matlab-function in simulink to call a python script, that do some calculations from the input values. The python-script gives me a string back to the matlab-function, that I split to an array. The splitted string has always to be a cell array with 6 variable strings:
dataStringArray = '[[-5.01 0.09785429][-8.01 0.01284927]...' '10.0' '20.0' '80.0' '80.0' '50.0'
To call the functions like strsplit or the python-script itself with a specific m-file, I'm using coder.extrinsic('*') method.
Now I want to index to a specific value for example with dataStringArray(3) to get '20.0' and define it as an output value of the matlab-function, but this doesn't work! I tried to predefine the dataStringArray with dataStringArray = cell(1,6); but get always the same 4 errors:
Subscripting into an mxArray is not supported.
Function 'MATLAB Function' (#23.1671.1689), line 42, column 24:
"dataStringArray(3)"
2x Errors occurred during parsing of MATLAB function 'MATLAB Function'
Error in port widths or dimensions. Output port 1 of 's_function_Matlab/MATLAB Function/constIn5' is a one dimensional vector with 1 elements.
What do I'm wrong?
SAMPLE CODE
The commented code behind the output definitions is what I need.:
function [dataArrayOutput, constOut1, constOut2, constOut3, constOut4, constOut5] = fcn(dataArrayInput, constIn1, constIn2, constIn3, constIn4, constIn5)
coder.extrinsic('strsplit');
% Python-Script String Output
pythonScriptOutputString = '[[-5.01 0.088068861]; [-4.96 0.0]]|10.0|20.0|80.0|80.0|50.0';
dataStringArray = strsplit(pythonScriptOutputString, '|');
% Outputs
dataArrayOutput = dataArrayInput; % str2num(char((dataStringArray(1))));
constOut1 = constIn1; % str2double(dataStringArray(2));
constOut2 = constIn2; % str2double(dataStringArray(3));
constOut3 = constIn3; % str2double(dataStringArray(4));
constOut4 = constIn4; % str2double(dataStringArray(5));
constOut5 = constIn5; % str2double(dataStringArray(6));
SOLUTION 1
Cell arrays are not supported in Matlab function blocks, only the native Simulink datatypes are possible.
A workaround is to define the whole code as normal function and execute it from the MATLAB-Function defined with extrinsic. It`s important to initialize the output variables with a known type and size before executing the extrinsic function.
SOLUTION 2
Another solution is to use the strfind function, that gives you a double matrix with the position of the splitter char. With that, you can give just the range of the char positions back that you need. In this case, your whole code will be in the MATLAB-Function block.
function [dataArrayOutput, constOut1, constOut2, constOut3, constOut4, constOut5] = fcn(dataArrayInput, constIn1, constIn2, constIn3, constIn4, constIn5)
coder.extrinsic('strsplit', 'str2num');
% Python-Script String Output
pythonScriptOutputString = '[[-5.01 0.088068861]; [-4.96 0.0]; [-1.01 7.088068861]]|10.0|20.0|80.0|80.0|50.0';
dataStringArray = strfind(pythonScriptOutputString,'|');
% preallocate
dataArrayOutput = zeros(3, 2);
constOut1 = 0;
constOut2 = 0;
constOut3 = 0;
constOut4 = 0;
constOut5 = 0;
% Outputs
dataArrayOutput = str2num(pythonScriptOutputString(1:dataStringArray(1)-1));
constOut1 = str2num(pythonScriptOutputString(dataStringArray(1)+1:dataStringArray(2)-1));
constOut2 = str2num(pythonScriptOutputString(dataStringArray(2)+1:dataStringArray(3)-1));
constOut3 = str2num(pythonScriptOutputString(dataStringArray(3)+1:dataStringArray(4)-1));
constOut4 = str2num(pythonScriptOutputString(dataStringArray(4)+1:dataStringArray(5)-1));
constOut5 = str2num(pythonScriptOutputString(dataStringArray(5)+1:end));
When using an extrinsic function, the data type returned is of mxArray, which you cannot index into as the error message suggests. To work around this problem, you first need to initialise the variable(s) of interest to cast them to the right data type (e.g. double). See Working with mxArrays in the documentation for examples of how to do that.
The second part of the error message is a dimension. Without seeing the code of the function, the Simulink model and how the inputs/outputs of the function are defined, it's difficult to tell what's going on, but you need to make sure you have the correct size and data type defined in the Ports and Data manager.

Categories

Resources