文本分类问题
Text classification issue
我是 ML 新手,我尝试 class 将文本分为两类。我的数据集是用医学文本中的 Tokenizer 制作的,它是不平衡的,有 572 条记录用于训练,471 条用于测试。
我真的很难制作具有不同预测输出的模型,几乎所有值都相同。我已经厌倦了使用 this 等示例中的模型并自己调整参数,但输出总是没有意义
这里是标记化和准备好的data
这是脚本:Gist
我使用的示例模型
sequential_model = keras.Sequential([
layers.Dense(15, activation='tanh',input_dim=vocab_size),
layers.BatchNormalization(),
layers.Dense(8, activation='relu'),
layers.BatchNormalization(),
layers.Dense(1, activation='sigmoid')
])
sequential_model.summary()
sequential_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['acc'])
train_history = sequential_model.fit(train_data,
train_labels,
epochs=15,
batch_size=16,
validation_data=(test_data, test_labels),
class_weight={1: 1, 0: 0.2},
verbose=1)
很遗憾,我无法共享数据集。
我也厌倦了使用带有 class 标签的 keras.utils.to_categorical 但它没有帮助
你的损失曲线是有意义的,因为我们看到网络过度拟合训练集,而我们看到通常的 bowl-shaped 验证曲线。
为了让你的网络表现得更好,你总是可以加深它(更多层),加宽它(每个隐藏层更多的单元)and/or 为你的层添加更多非线性激活函数以便能够映射到更广泛的价值。
另外,我相信你最初得到这么多重复值的原因是由于你的网络规模。显然,每个数据点都有大约 20,000 个特征(相当大的特征 space);您的网络规模太小,因此可以映射到的可能 space 输出值更小。我对一些较大的隐藏单元层进行了一些测试(并增加了层数),并且能够看到预测值确实有所不同:[0.519]、[0.41]、[0.37]...
您的网络性能有所不同也是可以理解的,因为您拥有的特征数量大约是训练规模的 50 倍(通常您希望比例更小)。请记住,为如此小的训练和测试数据集训练太多时期(例如超过 10 个时期)以查看损失的改善并不是很好的做法,因为您可能会严重过度拟合,并且可能表明您的网络需要 wider/deeper.
所有这些因素,例如层大小、隐藏单元大小甚至 epoch 数都可以视为超参数。换句话说,将一定比例的训练数据作为验证拆分的一部分,逐一检查每一类因素并进行优化以获得最高的验证准确性。公平地说,你的训练集不是太高,但我认为你应该保留大约 10-20% 的训练作为一种验证集来调整这些超参数,因为每个数据点都有如此多的特征.在此过程结束时,您应该能够确定您的真实测试准确性。这就是我将如何优化以获得该网络的最佳性能。希望这可以帮助。
More about training, test, val split
我是 ML 新手,我尝试 class 将文本分为两类。我的数据集是用医学文本中的 Tokenizer 制作的,它是不平衡的,有 572 条记录用于训练,471 条用于测试。
我真的很难制作具有不同预测输出的模型,几乎所有值都相同。我已经厌倦了使用 this 等示例中的模型并自己调整参数,但输出总是没有意义
这里是标记化和准备好的data
这是脚本:Gist
我使用的示例模型
sequential_model = keras.Sequential([
layers.Dense(15, activation='tanh',input_dim=vocab_size),
layers.BatchNormalization(),
layers.Dense(8, activation='relu'),
layers.BatchNormalization(),
layers.Dense(1, activation='sigmoid')
])
sequential_model.summary()
sequential_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['acc'])
train_history = sequential_model.fit(train_data,
train_labels,
epochs=15,
batch_size=16,
validation_data=(test_data, test_labels),
class_weight={1: 1, 0: 0.2},
verbose=1)
很遗憾,我无法共享数据集。 我也厌倦了使用带有 class 标签的 keras.utils.to_categorical 但它没有帮助
你的损失曲线是有意义的,因为我们看到网络过度拟合训练集,而我们看到通常的 bowl-shaped 验证曲线。
为了让你的网络表现得更好,你总是可以加深它(更多层),加宽它(每个隐藏层更多的单元)and/or 为你的层添加更多非线性激活函数以便能够映射到更广泛的价值。
另外,我相信你最初得到这么多重复值的原因是由于你的网络规模。显然,每个数据点都有大约 20,000 个特征(相当大的特征 space);您的网络规模太小,因此可以映射到的可能 space 输出值更小。我对一些较大的隐藏单元层进行了一些测试(并增加了层数),并且能够看到预测值确实有所不同:[0.519]、[0.41]、[0.37]...
您的网络性能有所不同也是可以理解的,因为您拥有的特征数量大约是训练规模的 50 倍(通常您希望比例更小)。请记住,为如此小的训练和测试数据集训练太多时期(例如超过 10 个时期)以查看损失的改善并不是很好的做法,因为您可能会严重过度拟合,并且可能表明您的网络需要 wider/deeper.
所有这些因素,例如层大小、隐藏单元大小甚至 epoch 数都可以视为超参数。换句话说,将一定比例的训练数据作为验证拆分的一部分,逐一检查每一类因素并进行优化以获得最高的验证准确性。公平地说,你的训练集不是太高,但我认为你应该保留大约 10-20% 的训练作为一种验证集来调整这些超参数,因为每个数据点都有如此多的特征.在此过程结束时,您应该能够确定您的真实测试准确性。这就是我将如何优化以获得该网络的最佳性能。希望这可以帮助。
More about training, test, val split