【问题标题】:How to determine classes with Keras?如何使用 Keras 确定类?
【发布时间】:2019-12-15 01:46:14
【问题描述】:

我正在研究一种使用 Keras 对邮件进行分类的方法。我阅读了已经分类的邮件,将它们标记化以创建一个链接到文件夹的字典。

所以我用熊猫创建了一个数据框:

data = pd.DataFrame(list(zip(lst, lst2)), columns=['text', 'folder'])

文本列是电子邮件中存在的所有单词所在的位置,文件夹列是电子邮件所属的类(路径)。

感谢我创建了我的模型,它给了我这些结果:

3018/3018 [==============================] - 0s 74us/步 - 损耗:0.0325 - acc: 0.9950 - val_loss:0.0317 - val_acc:0.9950

100 纪元

我的模型的评价

755/755 [===============================] - 0s 28us/步 测试成绩:0.0316697002592071 测试精度:0.995000006268356

所以最后我需要做的是预测随机邮件的类别,但model.predict_classes(numpy.array) 调用给了我一个充满整数的二维数组,但我仍然不知道它属于哪个“文件夹/类别”。

这是我的代码:

#lst contains all the words in the mail
#lst2 the class/path of lst
data = pd.DataFrame(list(zip(lst, lst2)), columns=['text', 'folder'])

train_size = int(len(data) * .8)
train_posts = data['text'][:train_size]
train_tags = data['folder'][:train_size]

test_posts = data['text'][train_size:]
test_tags = data['folder'][train_size:]

num_labels = 200 #The numbers of total classes

#the way I tokenize and encode my data
tokenizer = Tokenizer(num_words=len(lst))
tokenizer.fit_on_texts(pd.concat([train_posts, test_posts], axis = 1))

x_train = tokenizer.texts_to_matrix(train_posts, mode=TOKENISER_MODE)
x_test = tokenizer.texts_to_matrix(test_posts, mode=TOKENISER_MODE)

encoder = preprocessing.LabelBinarizer()
encoder.fit(train_tags)
y_train = encoder.transform(train_tags)
y_test = encoder.transform(test_tags)

#my model, vocab_size = len(lst) = number of the words present in the mails
model = Sequential()
model.add(Dense(16, input_shape=(vocab_size,)))
model.add(Activation('elu'))
model.add(Dropout(0.2))
model.add(Dense(32))
model.add(Activation('elu'))
model.add(Dropout(0.2))
model.add(Dense(16))
model.add(Activation('elu'))
model.add(Dropout(0.2))
model.add(Dense(num_labels))
model.add(Activation('sigmoid'))
model.summary()

#compile training and evaluate
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=100, verbose=1, validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, batch_size=batch_size, verbose=1)
print('Test score:', score[0])
print('Test accuracy:', score[1])

#read the random file
sentences = read_files("mail.eml")
sentences = ' '.join(sentences)
sentences = sentences.lower()
salut = unidecode.unidecode(sentences)

#predict
pred = model.predict_classes(salut, batch_size=batch_size, verbose=1)
print(pred)

pred的实际输出:

[125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125]

我不知道为什么,但每次启动时的输出总是充满相同的数字。我正在寻找的输出是:

['药物/艾滋病/',帮助/,项目/分类/]

按正确的概率排序。 read_files 调用只是一个读取邮件并返回邮件中所有单词列表的函数。

有没有办法用model.predict_classes() 获取邮件的类,还是我需要使用别的东西?

【问题讨论】:

  • 一个充满125 的数组肯定表示某些事情是非常错误的——你怎么能从这样的输出中取出任何有意义的东西呢?你有多少课(即num_labels是什么)?这是一个标准的多类分类问题(即样本只能属于一个类)吗?
  • num_labels 等于 200 是我拥有的类数
  • 请澄清(如上所述)如果您处于多类别设置(样本只能属于一个类别)或多标签设置(样本可以属于多个类别)同时上课)。
  • 只上一节课
  • 所以您不是处于多标签设置中;然后我的答案成立...

标签: python machine-learning keras nlp classification


【解决方案1】:

有没有办法通过 model.predict_classes() 来获取邮件的类别,还是我需要使用其他东西?

可以说,您的代码存在更严重的问题,因为从输出 pred 中应该已经很明显了。

对于初学者,并假设您处于多类设置中(每个样本只能属于一个类),并且不是 在一个多标签中(每个样本可以同时属于多个类):

  1. 由于您处于多类设置中,因此您最后一层的激活应该是softmax,而不是 sigmoid;所以,你应该把它改成

    model.add(Activation('softmax'))
    
  2. 同样,在你的模型编译中,你应该要求loss='categorical_crossentropy',而不是 binary_crossentropy(这是针对二元分类问题的);所以

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    

很可能,您在训练期间获得的高精度是侥幸,并不能反映现实。这是 Keras 的一种已知行为,当有人错误地将 binary_crossentropy 损失用于多类数据时 - 有关详细信息,请参阅我在 Keras binary_crossentropy vs categorical_crossentropy performance? 中的回答。

完成上述操作后,如果您仍有问题,请针对新情况提出一个问题 - 正如已经暗示的那样,无法获得课程是您最不正确的问题现在。

【讨论】:

  • 哦,我以为OP在做多标签分类?!!!我用这个假设写了我的答案!
  • @today 不太确定自己(尽管我在 cmets 中问过)-备用,我再次要求澄清...
  • 我想知道可能与邮件对应的所有标签,我尝试更改为 softmax 和 categorical_crossentropy,看来我的旧值只是垃圾,我现在几乎没有 1%
  • @DimitriFelix 并不意外,但请在我上面的最后一条评论中回答具体问题
  • 如果你说我想做多标签分类,答案是肯定的,我对这种东西很陌生,所以我不知道具体的词汇跨度>
【解决方案2】:

以后遇到相同问题的读者注意:如果每个样本只能属于其中一个类(例如“cat”或“dog”,请阅读@desertnaut 的回答“, 不是都)。否则(即它是多标签分类),请阅读我的答案。


predict_classes 用于分类模型,其中每个样本只有一个真实类。但是,您的模型似乎是一个多标签分类模型(即每个样本可能属于零个、一个或多个类)。因此,要找到预测标签,您需要将预测值阈值 0.5(因为输出值表示概率值,如果它足够高,即 > 0.5,我们可以认为相应的类存在于输入样本中) :

# this gives probability values, an array of shape (n_samples, n_labels)
preds_prob = model.predict(salut)

# this gives the name of classes with prob > 0.5
preds_cls = encoder.inverse_transform(preds_prob, 0.5)

【讨论】:

  • 感谢它确实提供了类而不是值
  • @desertnaut 这里也一样!很高兴见到你:)
猜你喜欢
  • 2017-09-17
  • 1970-01-01
  • 2019-09-17
  • 2020-08-12
  • 2020-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多