【发布时间】:2018-03-12 16:08:39
【问题描述】:
我正在尝试使用 keras 构建字符级 lstm 模型,为此我需要为字符创建一个热编码以输入模型。每行大约有 1000 个字符,大约 160,000 行。
我尝试创建一个 numpy 零数组并将相应的条目设为 1,但由于矩阵的大小过大而出现内存错误是否有任何其他方法可以做到这一点。
【问题讨论】:
我正在尝试使用 keras 构建字符级 lstm 模型,为此我需要为字符创建一个热编码以输入模型。每行大约有 1000 个字符,大约 160,000 行。
我尝试创建一个 numpy 零数组并将相应的条目设为 1,但由于矩阵的大小过大而出现内存错误是否有任何其他方法可以做到这一点。
【问题讨论】:
当然:
创建批次。一次只处理 10,000 个条目(字符),在需要它们之前计算并将它们输入到您的神经网络中(例如,通过使用生成器而不是列表)。 Keras 有一个fit_generator 训练函数来执行此操作。
将数据块组合在一起。比如说,不是一行是其字符的 one-hot 编码的矩阵,而是使用所有这些列的总和/最大值来为该行生成一个向量。现在,每一行只是一个向量,维数等于数据集中唯一字符的数量。例如,代替[[0, 0, 1], [0, 1, 0], [0, 0, 1]],使用[0, 1, 1] 来表示整行。
【讨论】:
也许更简单、更直观的解决方案是在您的 Keras 模型架构中添加一个自定义的 one-hot 编码层。
def build_model(self, batch_size, print_summary=False):
X = Input(shape=(self.sequence_length,), batch_size=batch_size)
embedding = OneHotEncoding(num_classes=self.vocab_size+1,
sequence_length=self.sequence_length)(X)
encoder = Bidirectional(CuDNNLSTM(units=self.recurrent_units,
return_sequences=True))(embedding)
...
我们可以定义OneHotEncoding层如下:
from tensorflow.keras.layers import Lambda
from tensorflow.keras import backend as K
from tensorflow.keras.layers import Layer # for creating custom layers
class OneHotEncoding(Layer):
def __init__(self, num_classes=None, sequence_length=None):
if num_classes is None or sequence_length is None:
raise ValueError("Can't leave params @num_classes or @sequence_length empty")
super(OneHotEncoding, self).__init__()
self.num_classes = num_classes
self.sequence_length = sequence_length
def encode(self, inputs):
return K.one_hot(indices=inputs,
num_classes=self.num_classes)
def call(self, inputs):
return Lambda(function=self.encode,
input_shape=(self.sequence_length,))(inputs)
在这里,我们利用 Keras 模型以适当的批量大小(使用标准 fit 函数)输入训练样本这一事实,而这反过来不会产生 MemoryError。
【讨论】: