#NEWLINE# def search( self , input_values , eol_symbol , max_length , ignore_first_eol = False , as_arrays = False , char_discount = 0 , round_to_inf = 1000000000.0 , stop_on = 'patience' , validate_solution_function = None ) : #NEWLINE# #INDENT# 'Performs beam search.\n\n        If the beam search was not compiled, it also compiles it.\n\n        Parameters\n        ----------\n        input_values : dict\n            A {:class:`~theano.Variable`: :class:`~numpy.ndarray`}\n            dictionary of input values. The shapes should be\n            the same as if you ran sampling with batch size equal to\n            `beam_size`. Put it differently, the user is responsible\n            for duplicaling inputs necessary number of times, because\n            this class has insufficient information to do it properly.\n        eol_symbol : int\n            End of sequence symbol, the search stops when the symbol is\n            generated.\n        max_length : int\n            Maximum sequence length, the search stops when it is reached.\n        ignore_first_eol : bool, optional\n            When ``True``, the end if sequence symbol generated at the\n            first iteration are ignored. This useful when the sequence\n            generator was trained on data with identical symbols for\n            sequence start and sequence end.\n        as_arrays : bool, optional\n            If ``True``, the internal representation of search results\n            is returned, that is a (matrix of outputs, mask,\n            costs of all generated outputs) tuple.\n\n        Returns\n        -------\n        outputs : list of lists of ints\n            A list of the `beam_size` best sequences found in the order\n            of decreasing likelihood.\n        costs : list of floats\n            A list of the costs for the `outputs`, where cost is the\n            negative log-likelihood.\n\n        ' #NEWLINE# if ( not self . compiled ) : #NEWLINE# #INDENT# self . compile ( ) #NEWLINE# #UNINDENT# contexts = self . compute_contexts ( input_values ) #NEWLINE# large_contexts = OrderedDict ( contexts ) #NEWLINE# states = self . compute_initial_states ( contexts ) #NEWLINE# all_outputs = states [ 'outputs' ] [ None , : ] #NEWLINE# all_costs = numpy . zeros_like ( all_outputs , dtype = config . floatX ) #NEWLINE# done = [ ] #NEWLINE# min_cost = 1000 #NEWLINE# for i in range ( max_length ) : #NEWLINE# #INDENT# if ( len ( states . values ( ) [ 0 ] . flatten ( ) ) == 0 ) : #NEWLINE# #INDENT# break #NEWLINE# #UNINDENT# if ( stop_on == 'patience' ) : #NEWLINE# #INDENT# done = sorted ( done , key = ( lambda x : ( x [ 1 ] [ ( - 1 ) ] - ( char_discount * len ( x [ 1 ] ) ) ) ) ) #NEWLINE# done = done [ : self . beam_size ] #NEWLINE# if done : #NEWLINE# #INDENT# current_best_cost = ( done [ 0 ] [ 1 ] [ ( - 1 ) ] - ( char_discount * len ( done [ 0 ] [ 1 ] ) ) ) #NEWLINE# if ( current_best_cost < min_cost ) : #NEWLINE# #INDENT# min_cost = current_best_cost #NEWLINE# patience = 30 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# patience -= 1 #NEWLINE# if ( patience == 0 ) : #NEWLINE# #INDENT# break #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( stop_on == 'optimistic_future_cost' ) : #NEWLINE# #INDENT# if ( len ( done ) >= self . beam_size ) : #NEWLINE# #INDENT# optimistic_future_cost = ( all_costs [ ( - 1 ) , : ] . min ( ) - ( char_discount * max_length ) ) #NEWLINE# last_in_done = done [ ( self . beam_size - 1 ) ] [ 1 ] #NEWLINE# last_in_done_cost = ( last_in_done [ ( - 1 ) ] - ( char_discount * len ( last_in_done ) ) ) #NEWLINE# if ( last_in_done_cost < optimistic_future_cost ) : #NEWLINE# #INDENT# break #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# raise ValueError ( 'Unknown stopping criterion {}' . format ( stop_on ) ) #NEWLINE# #UNINDENT# #UNINDENT# if ( large_contexts . values ( ) [ 0 ] . shape [ 1 ] != states . values ( ) [ 0 ] . shape [ 0 ] ) : #NEWLINE# #INDENT# for ( name , ctx ) in contexts . items ( ) : #NEWLINE# #INDENT# large_contexts [ name ] = numpy . take ( ctx , ( [ 0 ] * states . values ( ) [ 0 ] . shape [ 0 ] ) , axis = 1 ) #NEWLINE# #UNINDENT# #UNINDENT# logprobs = self . compute_logprobs ( large_contexts , states ) #NEWLINE# assert numpy . isfinite ( logprobs ) . all ( ) #NEWLINE# next_costs = ( all_costs [ ( - 1 ) , : , None ] + logprobs ) #NEWLINE# ( ( indexes , outputs ) , chosen_costs ) = self . _smallest ( next_costs , self . beam_size ) #NEWLINE# for name in states : #NEWLINE# #INDENT# states [ name ] = numpy . take ( states [ name ] , indexes , axis = 0 ) #NEWLINE# #UNINDENT# all_outputs = numpy . take ( all_outputs , indexes , axis = 1 ) #NEWLINE# all_costs = numpy . take ( all_costs , indexes , axis = 1 ) #NEWLINE# if ( large_contexts . values ( ) [ 0 ] . shape [ 1 ] != states . values ( ) [ 0 ] . shape [ 0 ] ) : #NEWLINE# #INDENT# for ( name , ctx ) in contexts . items ( ) : #NEWLINE# #INDENT# large_contexts [ name ] = numpy . take ( ctx , ( [ 0 ] * states . values ( ) [ 0 ] . shape [ 0 ] ) , axis = 1 ) #NEWLINE# #UNINDENT# #UNINDENT# states = self . compute_next_states ( large_contexts , states , outputs ) #NEWLINE# all_outputs = numpy . vstack ( [ all_outputs , outputs [ None , : ] ] ) #NEWLINE# all_costs = numpy . vstack ( [ all_costs , chosen_costs [ None , : ] ] ) #NEWLINE# mask = ( outputs != eol_symbol ) #NEWLINE# if ( ignore_first_eol and ( i == 0 ) ) : #NEWLINE# #INDENT# mask [ : ] = 1 #NEWLINE# #UNINDENT# for idx in numpy . where ( ( ( all_outputs [ ( - 1 ) ] == eol_symbol ) & ( ( all_costs [ ( - 1 ) ] - all_costs [ ( - 2 ) ] ) < round_to_inf ) ) ) [ 0 ] : #NEWLINE# #INDENT# if ( ( validate_solution_function is None ) or validate_solution_function ( input_values , all_outputs [ : , idx ] ) ) : #NEWLINE# #INDENT# done . append ( ( all_outputs [ : , idx ] , all_costs [ : , idx ] ) ) #NEWLINE# #UNINDENT# #UNINDENT# unfinished = numpy . where ( ( mask == 1 ) ) [ 0 ] #NEWLINE# for name in states : #NEWLINE# #INDENT# states [ name ] = numpy . take ( states [ name ] , unfinished , axis = 0 ) #NEWLINE# #UNINDENT# all_outputs = numpy . take ( all_outputs , unfinished , axis = 1 ) #NEWLINE# all_costs = numpy . take ( all_costs , unfinished , axis = 1 ) #NEWLINE# #UNINDENT# if ( not done ) : #NEWLINE# #INDENT# raise CandidateNotFoundError ( ) #NEWLINE# #UNINDENT# done = sorted ( done , key = ( lambda x : ( x [ 1 ] [ ( - 1 ) ] - ( char_discount * len ( x [ 1 ] ) ) ) ) ) #NEWLINE# max_len = max ( ( seq [ 0 ] . shape [ 0 ] for seq in done ) ) #NEWLINE# all_outputs = numpy . zeros ( ( max_len , len ( done ) ) ) #NEWLINE# all_masks = numpy . zeros ( ( max_len , len ( done ) ) ) #NEWLINE# all_costs = numpy . zeros ( ( max_len , len ( done ) ) ) #NEWLINE# for ( i , ( seq , cost ) ) in enumerate ( done ) : #NEWLINE# #INDENT# all_outputs [ : len ( seq ) , i ] = seq #NEWLINE# all_masks [ : len ( seq ) , i ] = 1 #NEWLINE# all_costs [ : len ( cost ) , i ] = cost #NEWLINE# all_costs [ len ( cost ) : , i ] = cost [ ( - 1 ) ] #NEWLINE# #UNINDENT# all_outputs = all_outputs [ 1 : ] #NEWLINE# all_masks = all_masks [ 1 : ] #NEWLINE# all_costs = ( all_costs [ 1 : ] - all_costs [ : ( - 1 ) ] ) #NEWLINE# result = ( all_outputs , all_masks , all_costs ) #NEWLINE# if as_arrays : #NEWLINE# #INDENT# return result #NEWLINE# #UNINDENT# return self . result_to_lists ( result )