<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fmin(loss_fn, space, max_evals, trials, init_random_evals=30, explore_prob=0.2):
 """Find the minimum of function through hyper parameter optimization. Arguments --------- loss_fn : ``function(*args) -> float`` Function that takes in a dictionary and returns a real value. This is the function to be minimized. space : dictionary Custom dictionary specifying the range and distribution of the hyperparamters. E.g. ``space = {'x': {'dist':scipy.stats.uniform(0,1), 'lo':0, 'hi':1}}`` for a 1-dimensional space with variable x in range [0,1] max_evals : int Maximum number of evaluations of loss_fn allowed trials : list Holds the output of the optimization trials. Need not be empty to begin with, new trials are appended at the end. init_random_evals : Optional[int], default 30 Number of random trials to initialize the optimization. explore_prob : Optional[float], default 0.2 Controls the exploration-vs-exploitation ratio. Value should be in [0,1]. By default, 20% of trails are random samples. Returns ------- trial entry (dictionary of hyperparameters) Best hyperparameter setting found. E.g. {'x': 5.6, 'loss' : 0.5} where x is the best hyparameter value found and loss is the value of the function for the best hyperparameter value(s). Raises ------ ValueError If the distribution specified in space does not support a ``rvs()`` method to generate random numbers, a ValueError is raised. """


    for s in space:
        if not hasattr(space[s]['dist'], 'rvs'):
            raise ValueError('Unknown distribution type for variable')
        if 'lo' not in space[s]:
            space[s]['lo'] = -np.inf
        if 'hi' not in space[s]:
            space[s]['hi'] = np.inf

    if len(trials) > init_random_evals:
        init_random_evals = 0

    for t in range(max_evals):
        sdict = {}

        if t >= init_random_evals and np.random.random() > explore_prob:
            use_random_sampling = False
        else:
            use_random_sampling = True

        yarray = np.array([tr['loss'] for tr in trials])
        for s in space:
            sarray = np.array([tr[s] for tr in trials])
            if use_random_sampling:
                sdict[s] = space[s]['dist'].rvs()
            else:
                sdict[s] = get_next_sample(sarray, yarray,
                                           min_limit=space[s]['lo'],
                                           max_limit=space[s]['hi'])

        logger.debug('Explore' if use_random_sampling else 'Exploit')
        logger.info('Next point ', t, ' = ', sdict)

        y = loss_fn(sdict)
        sdict['loss'] = y
        trials.append(sdict)

    yarray = np.array([tr['loss'] for tr in trials])
    yargmin = yarray.argmin()

    logger.info('Best point so far = ', trials[yargmin])
    return trials[yargmin]