def do_add_unit_mutation(self, indi):
        self.log.info('Do the ADD mutation for indi:%s'%(indi.id))
        """
        choose one position to add one unit, adding one conv or pooling unit is determined by a probability of 0.5.
        However, if the maximal number of pooling units have been added into the current individual, only
        conv unit will be add here
        """
        # determine the position where a unit would be added
        mutation_position = int(np.floor(np.random.random()*len(indi.units)))
        self.log.info('Mutation position occurs at %d'%(mutation_position))
        # determine the unit type for adding
        u_ = random.random()
        type_ = 1 if u_ < 0.5 else 2
        self.log.info('A %s unit would be added due to the probability of %.2f'%('CONV' if type_ ==1 else 'POOLING', u_))
        if type_ == 2:
            num_exist_pool_units = 0
            for unit in indi.units:
                if unit.type == 2:
                    num_exist_pool_units +=1
            if num_exist_pool_units > StatusUpdateTool.get_pool_limit()[1]-1:
                type_ = 1
                self.log.info('The added unit is changed to CONV because the existing number of POOLING exceeds %d, limit size:%d'%(num_exist_pool_units, StatusUpdateTool.get_pool_limit()[1]))

        #do the details
        if type_ == 2:
            add_unit = indi.init_a_pool(mutation_position+1, _max_or_avg=None)
        else:
            for i in range(mutation_position, -1, -1):
                if indi.units[i].type == 1:
                    _in_channel = indi.units[i].out_channel
                    break
            add_unit = indi.init_a_conv(mutation_position+1, _in_channel=_in_channel, _out_channel=None)
            for i in range(mutation_position+1, len(indi.units)):
                if indi.units[i].type == 1:
                    indi.units[i].in_channel = add_unit.out_channel
                    break

        new_unit_list = []
        # add to the new list and update the number
        for i in range(mutation_position+1):
            new_unit_list.append(indi.units[i])
        new_unit_list.append(add_unit)
        for i in range(mutation_position+1, len(indi.units)):
            unit = indi.units[i]
            unit.number += 1
            new_unit_list.append(unit)
        indi.number_id += 1
        indi.units = new_unit_list
        indi.reset_acc()
Beispiel #2
0
 def __init__(self, individuals, prob_, _log):
     self.individuals = individuals
     self.prob = prob_
     self.log = _log
     self.pool_limit = StatusUpdateTool.get_pool_limit()[1]
Beispiel #3
0
    def do_add_unit_mutation(self, indi):
        self.log.info('Do the ADD mutation for indi:%s'%(indi.id))
        """
        choose one position to add one unit, adding one resnet/densenet or pooling unit is determined by a probability of 1/3.
        However, if the maximal number of pooling units have been added into the current individual, only
        resnet/densenet unit will be add here
        """
        # determine the position where a unit would be added
        mutation_position = int(np.floor(np.random.random()*len(indi.units)))
        self.log.info('Mutation position occurs at %d'%(mutation_position))
        # determine the unit type for adding
        u_ = random.random()
        if u_ < 0.333:
            type_ = 1
        elif u_ < 0.666:
            type_ = 2
        else:
            type_ = 3
        type_string_list = ['RESNET', 'POOLING', 'DENSENET']
        self.log.info('A %s unit would be added due to the probability of %.2f'%(type_string_list[type_-1], u_))
        if type_ == 2:
            num_exist_pool_units = 0
            for unit in indi.units:
                if unit.type == 2:
                    num_exist_pool_units +=1
            if num_exist_pool_units > StatusUpdateTool.get_pool_limit()[1]-1:
                u_ = random.random()
                type_ = 1 if u_ < 0.5 else 3
                self.log.info('The added unit is changed to %s because the existing number of POOLING exceeds %d, limit size:%d'%('RESNET' if type_ == 1 else 'DENSENET', num_exist_pool_units, StatusUpdateTool.get_pool_limit()[1]))

        #do the details
        if type_ == 2:
            add_unit = indi.init_a_pool(mutation_position+1, _max_or_avg=None)
        else:
            for i in range(mutation_position, -1, -1):
                if indi.units[i].type == 1 or indi.units[i].type == 3:
                    _in_channel = indi.units[i].out_channel
                    break
            if type_ == 1:
                add_unit = indi.init_a_resnet(mutation_position+1, _amount=None, _in_channel=_in_channel, _out_channel=None)
            if type_ == 3:
                add_unit = indi.init_a_densenet(mutation_position+1, _amount=None, _k=None, _max_input_channel=None, _in_channel=_in_channel)

            keep_out_channel = add_unit.out_channel
            for i in range(mutation_position+1, len(indi.units)):
                if indi.units[i].type == 1 or indi.units[i].type == 3 :
                    self.log.info('Due to the above mutation, unit at %d changes its input channel from %d to %d'%(i, indi.units[i].in_channel, keep_out_channel))
                    indi.units[i].in_channel = keep_out_channel
                    if indi.units[i].type == 1:
                        break
                    elif indi.units[i].type == 3:
                        estimated_out_channel = indi.units[i].k*indi.units[i].amount + indi.units[i].in_channel
                        if estimated_out_channel > indi.units[i].out_channel:
                            break
                        else:
                            self.log.info('Due to the above mutation, unit at %d changes its output channel from %d to %d'%(i, indi.units[i].out_channel, estimated_out_channel))
                            indi.units[i].out_channel = estimated_out_channel
                            keep_out_channel = estimated_out_channel


        new_unit_list = []
        # add to the new list and update the number
        for i in range(mutation_position+1):
            new_unit_list.append(indi.units[i])
        new_unit_list.append(add_unit)
        for i in range(mutation_position+1, len(indi.units)):
            unit = indi.units[i]
            unit.number += 1
            new_unit_list.append(unit)
        indi.number_id += 1
        indi.units = new_unit_list
        indi.reset_acc()