I want to build a Keras Model evaluating strings. If I do the following:
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(units=10, input_shape=(10,), activation='softmax'))
It works fine. And I can see the model.summary()
.
But, when I add the layer with ast.literal_eval()
from keras.models import Sequential
from keras.layers import Dense
import ast
model = Sequential()
code = "model.add( Dense( input_shape=(10,), units=10, activation='softmax' ) )"
ast.literal_eval(code)
It throws me the next ValueError
:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/ast.py", line 84, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.5/ast.py", line 83, in _convert
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Call object at 0x7efc40c90e10>
If I use eval
instead of ast.literal_eval
it works too.
I'm using python3.5.
ast. literal_eval() The ast module helps Python applications to process trees of the Python abstract syntax grammar. The literal_eval safely evaluate an expression node or a string containing a Python literal or container display.
The ast. literal_eval method is one of the helper functions that helps traverse an abstract syntax tree. This function evaluates an expression node or a string consisting of a Python literal or container display.
If you see this error, it usually means the the client is not able to transform the string you wrote to the character set acceptable to the Firebird server. Here's a short explanation how this works: In your client program, you type in some text, which is then shown on the screen.
A big mistake: literal_eval
only works for literals. In this case, I have a Call.
The function literal_eval
first parse the string.
From /usr/lib/python3.5/ast.py: lines 38-46
def literal_eval(node_or_string):
"""
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
sets, booleans, and None.
"""
if isinstance(node_or_string, str):
node_or_string = parse(node_or_string, mode='eval')
At this point, node_or_string
is an instance of Expression
. Then, literal_eval
get the body.
From /usr/lib/python3.5/ast.py: lines 47-48
if isinstance(node_or_string, Expression):
node_or_string = node_or_string.body
And finally, literal_eval
checks the type of the body (node_or_string
).
From /usr/lib/python3.5/ast.py: lines 49-84
def _convert(node):
if isinstance(node, (Str, Bytes)):
return node.s
elif isinstance(node, Num):
return node.n
elif isinstance(node, Tuple):
return tuple(map(_convert, node.elts))
elif isinstance(node, List):
return list(map(_convert, node.elts))
elif isinstance(node, Set):
return set(map(_convert, node.elts))
elif isinstance(node, Dict):
return dict((_convert(k), _convert(v)) for k, v
in zip(node.keys, node.values))
elif isinstance(node, NameConstant):
return node.value
elif isinstance(node, UnaryOp) and \
isinstance(node.op, (UAdd, USub)) and \
isinstance(node.operand, (Num, UnaryOp, BinOp)):
operand = _convert(node.operand)
if isinstance(node.op, UAdd):
return + operand
else:
return - operand
elif isinstance(node, BinOp) and \
isinstance(node.op, (Add, Sub)) and \
isinstance(node.right, (Num, UnaryOp, BinOp)) and \
isinstance(node.left, (Num, UnaryOp, BinOp)):
left = _convert(node.left)
right = _convert(node.right)
if isinstance(node.op, Add):
return left + right
else:
return left - right
raise ValueError('malformed node or string: ' + repr(node))
return _convert(node_or_string)
If the initial code was ast.literal_eval('1+1')
(for example), now node_or_string
would be an instance of BinOp
. But in the case of:
code = "model.add( Dense( input_shape=(10,), units=10, activation='softmax' ) )"
ast.literal_eval(code)
The body will be an instance of Call
, which does not appear among the valid types of the function.
E.g.:
import ast
code_nocall = "1+1"
node = ast.parse(code_nocall, mode='eval')
body = node.body
print(type(body)) # Returns <class '_ast.BinOp'>
code_call = "print('hello')"
node = ast.parse(code_call, mode='eval')
body = node.body
print(type(body)) # Returns <class '_ast.Call'>
The best solution I have found so far, to not use eval
directly, is to perform the process manually. With this function:
import ast
def eval_code(code):
parsed = ast.parse(code, mode='eval')
fixed = ast.fix_missing_locations(parsed)
compiled = compile(fixed, '<string>', 'eval')
eval(compiled)
Now it works:
eval_code("print('hello world')")
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
code = "model.add( Dense( input_shape=(10,), units=10, activation='softmax' ) )"
eval_code(code)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With