遗传算法优化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
相关产品推荐
相关产品推荐

