@register_canonicalize
@gof.local_optimizer([T.Reshape])
def local_reshape_to_dimshuffle(node):
 op = node.op
 if (not isinstance(op, Reshape)):
  return False
 input = node.inputs[0]
 output = node.outputs[0]
 output_shape = node.inputs[1]
 dimshuffle_new_order = []
 new_output_shape = []
 index = 0
 for i in xrange(output.ndim):
  dim = extract_constant(output_shape[i], only_process_constants=False, elemwise=False)
  if (dim == 1):
   dimshuffle_new_order.append('x')
  else:
   dimshuffle_new_order.append(index)
   new_output_shape.append(dim)
   index = (index + 1)
 if (index != output.ndim):
  inner = op.__class__(len(new_output_shape))(input, new_output_shape)
  copy_stack_trace(output, inner)
  new_node = [DimShuffle(inner.type.broadcastable, dimshuffle_new_order)(inner)]
  copy_stack_trace(output, new_node)
  return new_node

@ register_canonicalize @ gof . local_optimizer ( [ T . Reshape ] ) def local_reshape_to_dimshuffle ( node ) : op = node . op if ( not isinstance ( op , Reshape ) ) : return False input = node . inputs [ 0 ] output = node . outputs [ 0 ] output_shape = node . inputs [ 1 ] dimshuffle_new_order = [ ] new_output_shape = [ ] index = 0 for i in xrange ( output . ndim ) : dim = extract_constant ( output_shape [ i ] , only_process_constants = False , elemwise = False ) if ( dim == 1 ) : dimshuffle_new_order . append ( 'x' ) else : dimshuffle_new_order . append ( index ) new_output_shape . append ( dim ) index = ( index + 1 ) if ( index != output . ndim ) : inner = op . __class__ ( len ( new_output_shape ) ) ( input , new_output_shape ) copy_stack_trace ( output , inner ) new_node = [ DimShuffle ( inner . type . broadcastable , dimshuffle_new_order ) ( inner ) ] copy_stack_trace ( output , new_node ) return new_node
broadcastable dimensions in reshape are replaced with dimshuffle .