未在 PyGAD 中训练的二元分类神经网络模型权重

问题描述

这是我正在编写的代码Fake News Detection Google Colab Notebook

我使用的数据集: fake_or_real_news

手套嵌入层: glove.twitter.27B.200d

我一直在尝试 PyGAD,这是一个用于机器学习的遗传算法的 Python 库。

我想要实现的是假新闻检测。我所做的是对文章进行预处理,并将它们转换为向量。我使用 glove 作为 NN 中的嵌入层。我尝试使用没有 GA 的 NN 模型进行训练,并且效果很好。然后我按照教程:How To Train Keras Models Using the Genetic Algorithm with PyGAD 将 NN 应用于 PyGAD GA,该过程似乎运行良好,但即使经过 200 代,适应度分数也根本没有上升。我试图改变变异方法和其他一些超参数,但它似乎并没有改变结果。我在构建 PyGAD GA 模型的过程中做错了什么?大多数 PyGAD 模型设置与上面教程中的示例相同。

指定我遇到的问题:以下是我使用的主要 PyGAD 代码

训练输入(X_train):

array([[ 4981,2484,22458,...,1019,135,892],[ 7075,189,26439,4982,43,2],[ 6168,335,2,73,27,73],[  374,10,162,736,1744,484],[  500,118,348,2890,5689],[ 8194,2404,117,357,6332,186]],dtype=int32)
shape: (3753,50)

训练输出(y_train):

array([[1.,0.],[0.,1.],[1.,1.]],dtype=float32)
shape:  (3753,)

Python 代码

import tensorflow.keras
import pygad.kerasga
import numpy
import pygad
def fitness_func(solution,sol_idx):
    global data_inputs,data_outputs,keras_ga,model

    model_weights_matrix = pygad.kerasga.model_weights_as_matrix(model=model,weights_vector=solution)

    model.set_weights(weights=model_weights_matrix)

    predictions = model.predict(data_inputs)
    
    bce = tensorflow.keras.losses.BinaryCrossentropy()
    solution_fitness = 1.0 / (bce(data_outputs,predictions).numpy() + 0.00000001)

    return solution_fitness

def callback_generation(ga_instance):
    print("Generation = {generation}".format(generation=ga_instance.generations_completed))
    print("fitness    = {fitness}".format(fitness=ga_instance.best_solution()[1]))

sequence_length = X_train.shape[1]
filter_sizes = [3,4]
num_filters = 100
drop = 0.4
#the NN 
inputs = Input(shape=(sequence_length,))
embedding = embedding_layer(inputs)
reshape = Reshape((sequence_length,EMbedDING_DIM,1))(embedding)

conv_0 = Conv2D(num_filters,(filter_sizes[0],EMbedDING_DIM),activation='relu',kernel_regularizer=regularizers.l2(0.01))(reshape)
conv_1 = Conv2D(num_filters,(filter_sizes[1],kernel_regularizer=regularizers.l2(0.01))(reshape)

maxpool_0 = MaxPooling2D((sequence_length - filter_sizes[0] + 1,1),strides=(1,1))(conv_0)
maxpool_1 = MaxPooling2D((sequence_length - filter_sizes[1] + 1,1))(conv_1)

merged_tensor = concatenate([maxpool_0,maxpool_1],axis=1)
flatten = Flatten()(merged_tensor)
reshape = Reshape((2*num_filters,))(flatten)
dropout = Dropout(drop)(flatten)
conc = Dense(40)(dropout)
output = Dense(units=2,activation='sigmoid',kernel_regularizer=regularizers.l2(0.01))(conc)
#create model
model = Model(inputs,output)
keras_ga = pygad.kerasga.KerasGA(model=model,num_solutions=10)

# Data inputs
data_inputs = X_train
# Data outputs
data_outputs = y_train
data_outputs = tensorflow.keras.utils.to_categorical(data_outputs)
num_generations = 200
num_parents_mating = 8
initial_population = keras_ga.population_weights

ga_instance = pygad.GA(num_generations=num_generations,num_parents_mating=num_parents_mating,initial_population=initial_population,fitness_func=fitness_func,on_generation=callback_generation,)
ga_instance.run()

这是我在 ga_instance.run() 之后得到的结果:

Generation = 1
fitness    = 1.4091019376092528
Generation = 2
fitness    = 1.4091019376092528
...
Generation = 200
fitness    = 1.4091019376092528

预测结果:

Ground Truth:
array([[1.,dtype=float32)

Without GA:
Predictions : 
[[0.9889404  0.00634338]
[0.03020517 0.9684899 ]
[0.28220823 0.76921546]
...
[0.08805525 0.92023355]
[0.9115724  0.08401334]
[0.15908712 0.8055146 ]]

With PyGAD GA:
Predictions : 
[[0.4274468  0.47953305]
[0.40091008 0.38568377]
[0.3937818  0.41261795]
...
[0.3366004  0.43762493]
[0.43253532 0.4112898 ]
[0.40255183 0.4059006 ]]

经过 200 代后,fitness score 保持不变,最终模型准确率低于 50%,这意味着它比随机猜测更糟糕。我想我的模型权重根本没有经过训练。当我使用二元交叉熵作为损失函数(也用于 GA 适应度函数)在没有 ga 的情况下训练相同的 NN 模型时,它起作用了。我可以看到每个 epoch 的准确率都在上升,最终的 acc 超过了 90%;但是,当我尝试使用 PyGAD 库用遗传算法训练模型时,它不起作用。是NN模型的问题还是我使用的适应度函数的问题?我已经尝试更改模型结构和我可以在 PyGAD 库中使用的一些超参数,例如突变类型或父母交配的数量,但似乎对我没有任何作用。

编辑:我尝试创建 nn 模型,并在没有任何训练的情况下进行预测。然后我运行 ga_instance.run() 代码用 ga 训练模型(仍然,适应度根本没有上升),然后用那个应该训练的模型进行预测,有和没有 ga 训练的预测输出是一样的,这意味着在 ga 过程中没有发现更好的预测。为什么会发生这种情况?

我打印了每一代 ga 解决方案的适应度,我可以看到每一代产生了不同的适应度分数(每一代的适应度分数都有很小的改进),这意味着 ga 确实产生了不同的输出,但它们只是比模型的初始重量差很多。即使经过许多代,也没有产生比初始权重更好的解决方案。这是否意味着我只需要更多代(例如数千代)来获得更好的解决方案?还是我选择的适应度函数有问题,导致改进进度变慢?

解决方法

您的模型有大量参数 (>6.1M)。只有embedding层自己有6M。对于诸如此类的许多参数,遗传算法预计需要花费大量时间来训练模型。这并不意味着你有问题。我之前已经尝试过与大型 CNN 合作,取得了进展,但非常小。

根据您机器的能力,您应该尽可能增加解决方案的数量。也尽可能多地使用代。

感谢您使用 PyGAD