You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遗传算法优化CNN触发negative dimensions are not allowed报错

CNN结构搜索遗传算法运行报错定位

报错现象

程序在第一代训练完成后抛出如下错误:
ValueError: negative dimensions are not allowed

报错前曾修改卷积层滤波器配置:将原配置nfilters=[74,27,23]调整为nfilters=[64,128,256],暂未确认该修改是否为报错诱因。

相关实现代码

自定义CNN模型类(继承自Sequential)

class CNN(Sequential):
    def __init__(self,nfilters,sfilters):
        super().__init__()
        tf.random.set_seed(0)
        self.add(Conv2D(nfilters[0],kernel_size=(sfilters[0],sfilters[0]),padding='same',activation='relu',input_shape=(50,50,3)))
        self.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))
        self.add(Conv2D(nfilters[1],kernel_size=(sfilters[1],sfilters[1]),padding='same',activation='relu'))
        self.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))
        self.add(Conv2D(nfilters[2],kernel_size=(sfilters[2],sfilters[2]),padding='same',activation='relu'))
        self.add(Conv2D(nfilters[2], kernel_size=(sfilters[2], sfilters[2]), padding='same', activation='relu'))
        self.add(Flatten())
        self.add(Dropout(0.5))
        self.add(Dense(128,activation='relu'))
        self.add(Dropout(0.5))
        self.add(Dense(128, activation='relu'))
        self.add(Dense(num_classes, activation='sigmoid'))
        self.compile(loss=keras.losses.binary_crossentropy,
                      optimizer=tf.optimizers.Adam(learning_rate=0.001),
                      metrics=['accuracy'])

nfilters = [64,128,256] # 原配置为nfilters = [74,27,23]
sfilters = [9,3,2] # 卷积核尺寸配置

遗传算法核心类Genetic

类中实现了种群初始化、父代选择、交叉、变异、适应度计算、准确率曲线平滑绘制等功能:

class Genetic:
    
    def __init__(self,pop_size,nlayers,max_nfilters,max_sfilters):
        self.pop_size = pop_size
        self.nlayers = nlayers
        self.max_nfilters = max_nfilters
        self.max_sfilters = max_sfilters
        self.max_acc = 0
        self.best_arch = np.zeros((1,6))
        self.gen_acc = []
    
    def generate_population(self):
        np.random.seed(0)
        pop_nlayers = np.random.randint(1,self.max_nfilters,(self.pop_size,self.nlayers))
        pop_sfilters = np.random.randint(1,self.max_sfilters,(self.pop_size,self.nlayers))
        pop_total = np.concatenate((pop_nlayers,pop_sfilters),axis=1)
        return pop_total
    
    def select_parents(self,pop,nparents,fitness):
        parents = np.zeros((nparents,pop.shape[1]))
        for i in range(nparents):
            best = np.argmax(fitness)
            parents[i] = pop[best]
            fitness[best] = -99999
        return parents
    
    def crossover(self,parents):
        nchild = self.pop_size - parents.shape[0]
        nparents = parents.shape[0]
        child = np.zeros((nchild,parents.shape[1]))
        for i in range(nchild):
            first = i % nparents
            second = (i+1) % nparents
            child[i,:2] = parents[first][:2]
            child[i,2] = parents[second][2]
            child[i,3:5] = parents[first][3:5]
            child[i,5] = parents[second][5]
        return child

    def mutation(self,child):
        for i in range(child.shape[0]):
            val = np.random.randint(1,6)
            ind = np.random.randint(1,4) - 1
            if child[i][ind] + val > 100:
                child[i][ind] -= val
            else:
                child[i][ind] += val
            val = np.random.randint(1,4)
            ind = np.random.randint(4,7) - 1
            if child[i][ind] + val > 20:
                child[i][ind] -= val
            else:
                child[i][ind] += val
        return child
    
    def fitness(self,pop,X,Y,epochs):
        pop_acc = []
        for i in range(pop.shape[0]):
            nfilters = pop[i][0:3]
            sfilters = pop[i][3:]
            model = CNN(nfilters,sfilters)
            #H = model.fit_generator(datagen.flow(X,Y,batch_size=256),epochs=epochs,callbacks=[early_stopping_monitor])
            H = model.fit_generator(datagen.flow(X,Y,batch_size=256),steps_per_epoch=len(X_trainRusReshaped) / batch_size,epochs=epochs,validation_data=(X_testRusReshaped, Y_testRusHot),callbacks=[early_stopping_monitor])
            acc = H.history['accuracy']
            pop_acc.append(max(acc)*100)
        if max(pop_acc) > self.max_acc:
            self.max_acc = max(pop_acc)
            self.best_arch = pop[np.argmax(pop_acc)]
        self.gen_acc.append(max(pop_acc))
        return pop_acc
    
    def smooth_curve(self,factor,gen):
        smoothed_points = []
        for point in self.gen_acc:
            if smoothed_points:
                prev = smoothed_points[-1]
                smoothed_points.append(prev*factor + point * (1-factor))
            else:
                smoothed_points.append(point)
        plt.plot(range(gen+1),smoothed_points,'g',label='Smoothed training acc')
        plt.xticks(np.arange(gen+1))
        plt.legend()
        plt.title('Fitness Accuracy vs Generations')
        plt.xlabel('Generations')
        plt.ylabel('Fitness (%)')
        plt.show()
        plt.savefig('smoothCurve.png')

遗传算法主执行流程

#Starting Genetic Algoritm
pop_size = 2 #10
nlayers = 3 #3
max_nfilters = 500 #100
max_sfilters = 20
epochs = 20
num_generations = 2 #10

genCNN = Genetic(pop_size,nlayers,max_nfilters,max_sfilters)
pop = genCNN.generate_population()

for i in range(num_generations+1):
    pop_acc = genCNN.fitness(pop,X_trainRusReshaped,Y_trainRusHot,epochs)
    print('Best Accuracy at the generation {}: {}'.format(i,genCNN.max_acc))
    parents = genCNN.select_parents(pop,5,pop_acc.copy())
    child = genCNN.crossover(parents)
    child = genCNN.mutation(child)
    pop = np.concatenate((parents,child),axis=0).astype('int')

已尝试排查操作

  • 将max_nfilters参数从100上调至500,报错仍存在,需要定位错误产生的根本原因。

内容的提问来源于stack exchange,提问作者user979974

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:12:20