【问题标题】:TensorFlow/Keras - how to transform text properly?TensorFlow/Keras - 如何正确转换文本?
【发布时间】:2018-12-08 23:19:32
【问题描述】:

我正在尝试创建一个模型来确定句子的主要主题是否是布拉格城市。

句子是斯洛伐克语。即:

“V Prahe bolo dobre”、“Praha je v Česku”...

我的csv 文件如下所示:

Praha je v Česku,1 
Chodím do Blavy,0 
Neviem čo to je za vetu,0
Pražský hrad,1

正如您所见,布拉格一词有多种形式,因此我不想将 csv 中的每个词都替换为某个数字。我的目标是在字符级别检测它。

试过这个:

train = pandas.read_csv("prague_train_set.csv",
                        usecols=[ "title"])

train['title'] = train['title'].fillna("None")
train['title'] = le.fit_transform(train['title'])

results = pandas.read_csv("prague_train_set.csv",
                        usecols=["result"])    

# create model
model = Sequential()
model.add(Dense(12, input_dim=1, init='uniform', activation='relu'))
model.add(Dense(10, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(train, results, epochs=150, batch_size=10, verbose=2)
# calculate predictions
predictions = model.predict(train)

但输出就像是完全随机的:

编辑大约 1/4 的标题是关于布拉格的

...
Epoch 145/150
 - 0s - loss: 0.1826 - acc: 0.7589
Epoch 146/150
 - 0s - loss: 0.1827 - acc: 0.7589
Epoch 147/150
 - 0s - loss: 0.1826 - acc: 0.7589
Epoch 148/150
 - 0s - loss: 0.1827 - acc: 0.7589
Epoch 149/150
 - 0s - loss: 0.1827 - acc: 0.7589
Epoch 150/150
 - 0s - loss: 0.1827 - acc: 0.7589

我认为这是因为train['title'] = le.fit_transform(train['title']) 将整个句子转换为数字但不确定。你知道该怎么做吗?

【问题讨论】:

  • 你的 csv 文件有多大?
  • 大约 5000 篇文章
  • 你在做二进制分类,对吧?我将首先使用“binary_crossentropy”作为您的损失函数,而不是均方误差,因为如果它是线性回归/输出层,您会想使用它......在这里使用没有意义。另外,读过 words2vec 吗?
  • 如果le 是一个标签转换器,那么你是对的。此外,input_dim=1 意味着每个样本都表示为一个具有一个值的向量。如果您不想使用迁移学习并且您有一个非常小的训练集,我会通过标记句子、将标记填充到相同长度以及使用内核大小等于该长度的卷积来帮助分类器。这样你也许能够识别一个句子是否至少包含城市名称。

标签: python tensorflow machine-learning keras


【解决方案1】:

既然你想在字符级别上进行分类,我建议使用 CHAR-CNN:

https://papers.nips.cc/paper/5782-character-level-convolutional-networks-for-text-classification.pdf

要对数据进行预处理,您只需要做两件事:

1) 获取一组您要使用的字符 - 这可能是每个字符(包括标点符号)或只是最常见的字符

2) 建立字符编码并将其保存为整数。如果您没有使用 1) 中定义的集合内的所有字符,还为未知字符创建一个整数

3) 修剪或填充句子以具有标准长度

以下是一个简单的 CHAR-CNN 示例,旨在预测字符串中是否存在“a”:

首先对数据进行预处理: 代码可能如下所示:

from random import choice

lowercase = 'abcdefghijklmnopqrstuvwxyz'
x = [''.join(choice(lowercase) for _ in range(10)) for _ in range(5000)]
y = [int('a' in i) for i in x]

char_set = set(char for word in x for char in word)
encoding = {i: char+1 for char, i in enumerate(char_set)} # let 0 be the unknown character

将编码字典保存在某处,您可以将所有输入转换为整数:

x = [[encoding.get(char, 0) for char in sentence] for sentence in x]

然后填充序列:

max_len = max(len(i) for i in x)

from keras.preprocessing.sequence import pad_sequences
x = pad_sequences(x, maxlen=max_len)

每个句子都变成一个整数列表。

数据经过预处理后,您将构建模型。由于我们的预处理数据是一个整数列表,我们会遇到一个大问题:

如果 "a" => 2 和 "b" => 7,模型会天真地假设 "b" > "a",即使这不是真的。

为了解决这个问题(并让模型构建每个字符的内部表示),我将使用嵌入层将每个字符映射到 N 维向量。

from keras.models import Sequential
from keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Dense

VOCAB_SIZE = len(encoding) + 1
N_VECTORS = 12

model = Sequential()
model.add(Embedding(VOCAB_SIZE, N_VECTORS, input_length = max_len))

在这个阶段,我们可以使用 Conv1D 层开始检测特征。不幸的是,我无法为您提供准确的超参数,因为我无法访问您的整个数据集,因此这只是一个示例模型。

model.add(Conv1D(64, kernel_size=(3,)))
model.add(Conv1D(32, kernel_size=(3,)))

由于我们在此阶段处理的是 3D 张量(嵌入层返回 (batch_size, max_len, N_VECTORS)) 的 3D 输出,并且我们希望返回 2D 输出 (batch_size, one_or_zero),因此我们将输出最大池化并将其馈送到密集层。

model.add(GlobalMaxPooling1D())
model.add(Dense(1, activation='sigmoid')) #sigmoid activation to return number from 0-1

model.compile(loss='binary_crossentropy', optimizer='adam')
model.summary()
model.fit(x, y, epochs=1000)

最后,为了您的方便,我上传了我在 pastebin 上使用的代码的完整副本:https://pastebin.com/SvvJaQJv。在玩具数据集上运行模型可以在 2 个 epoch 内获得 100% 的准确率。

我希望这个答案能让您更好地理解为 nlp 预处理您的文本以及您可以使用的一些技术。祝你好运!

【讨论】:

  • 谢谢,我要试试这个方法。我创建了一个似乎运行得更好但结果并不令人满意的新代码 - stackoverflow.com/questions/53693188/…
  • 你要我做什么?将此复制粘贴到您的新问题中?
猜你喜欢
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 2020-07-14
  • 1970-01-01
相关资源
最近更新 更多