【问题标题】:What is the alternative method for one-hot or hashingone-hot 或 hashing 的替代方法是什么
【发布时间】:2020-12-24 02:13:05
【问题描述】:

我有一个包含 60k 句子的样本数据集,并试图创建一个序列模型。 清理后,预处理我的“y”长度为 573,806 行。唯一令牌的长度为 16207。

为了在嵌入层中使用它,我正在尝试将这个“y”转换为二进制类。我尝试过单热编码、to_categorical 和散列。所有这些方法都需要大量内存分配 (37Gb),我的 google Colab Pro 崩溃了。

似乎没有办法避免内存分配过多导致的崩溃。 Here is my related SO thread

鉴于此,我正在寻找有关此问题的一些指导。是否有任何其他可用于解决此问题的替代内存有效方法可用于顺序模型?

提前致谢。

【问题讨论】:

    标签: tensorflow keras google-colaboratory


    【解决方案1】:

    不要将数据表示为一个计算量很大的热编码向量,因为你发现你可以做的是利用embedding columns,它能够将高维数据嵌入到低维向量空间中,从而减少所需的总列数。

    使用 one-hot 编码表示一周中的几天

    使用嵌入表示一周中的几天

    Tensorflow 为此提供了tf.feature_column.embedding_column(),您可以通过here 了解更多信息。

    但请注意,categorical_column 参数需要由 tf.feature_column.categorical_column() 函数创建。

    embedding_column = tf.feature_column.embedding_column(
        categorical_column=categorical_column,
        dimension=dimension_of_embedding_vector)
    

    dimension_of_embedding_vector 公式更像是一个经验法则,它基于此公式,并且来自此 Google BlogPost 的更多信息他们使用类别数的第四根。 :

    embedding_dimensions =  number_of_categories**0.25
    

    另一个公式是 Jeremy Howard(fast.ai 的创始人),他建议使用:

    embedding size = min(50, number of categories/2).
    

    【讨论】:

    • @yudhish - 感谢您的建议。使用 categorical_column/embedding_column 有帮助,但 embedding_dimensions 数学不起作用。这两个公式都导致昏暗的数量非常少,并且我收到此错误“索引 [0,15] = 415 不在 [0, 50) 中”。增加暗淡有效,但会导致负损失增加,并且准确性永远不会提高。
    【解决方案2】:

    以下是我建议您处理句子的方法。为方便起见,我们将数据集中的列称为“句子”,并假设您已将数据帧作为变量数据读取 代码如下

    from tensorflow.keras.preprocessing.text import Tokenizer
    from tensorflow.keras.preprocessing.sequence import pad_sequences
    
    from sklearn.model_selection import train_test_split
    def get_sequences(texts):
        tokenizer = Tokenizer()
        tokenizer.fit_on_texts(texts)
        
        vocab_length = len(tokenizer.word_index) + 1
        print("Vocab length:", vocab_length)
        
        sequences = tokenizer.texts_to_sequences(texts)
        
        max_seq_length = np.max([len(sequence) for sequence in sequences])
        print("Max sequence length:", max_seq_length)
        
        sequences = pad_sequences(sequences, maxlen=max_seq_length, padding='post')
        
        return sequences
    
     sentence_sequences = get_sequences(data['sentence'])
     df = data.drop('sentence', axis=1)
    

    您现在可以将 sentence_sequences 输入模型中的 keras 嵌入层

    emb_dim =64  # user defined dimension I find 64 usually works well
    sentence_embedding = tf.keras.layers.Embedding(
        input_dim=max_seq_length,output_dim=emb_dim,
        input_length=sentence_sequences.shape[1],
        name='sentence_embedding')(sentence_sequences)
    

    如果除了句子之外您还有其他特征,那么您可以将它们创建为模型的单独输入。处理它们,展平结果,然后将它们与 句子嵌入。将结果放入一个密集层,其中神经元的数量 与类数相同,并使用 softmax 激活。 有关如何处理文本的好视频教程,我建议去here.

    【讨论】:

      【解决方案3】:

      我想在这里留下一个答案可能会帮助将来的人

      下面尝试的所有不同方法的模型架构都是相同的。

      当 y 使用 to_categrical 单热编码时

      10/10 纪元 30/30 [===============================] - 7s 245ms/步 - 损失:0.0116 - 准确度:0.6046

      当 y 是从 categorical_column_with_vocabulary_list 构建时 --> embedding_column 生成向量

      10/10 纪元 30/30 [==============================] - 8s 266ms/step - 损失:-0.0012 - 准确度:0.0084

      当 y 是从 feature_column.bucketized_column 构建时 --> 产生 one-hot 编码的 indicator_column

      10/10 纪元 30/30 [==============================] - 7s 248ms/步 - 损失:0.0113 - 准确度:0.6160

      当 y 由 categorical_column_with_hash_bucket(最大特征)构建时--> embedding_column(最大特征)生成向量

      10/10 纪元 30/30 [==============================] - 7s 229ms/步 - 损失:-0.0365 - 准确度:0.0398

      当y由crossed_column构建时,embedding_column产生向量,性能几乎与hash_bucket方法相同。

      鉴于这些实验,我重新设计了逻辑以使用 DataGenerator 方法并使用 one-hot 编码迭代训练整个数据集。此方法适合可用内存,需要更长的训练时间,但会产生更好的准确性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-01
        • 1970-01-01
        • 2022-11-13
        • 2019-01-05
        • 2015-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多