🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
* [ ] 每个**单词**与一个唯一的**整数索引**相关联 * [ ] 这个**整数索引*i***转换为长度为*N*的**二进制向量**(*N*是词表大小) 这个向量只有第*i*个元素是 1,其余元素都为 0 ***** **单词级的 one-hot 编码** ~~~ import numpy as np samples = ['The cat sat on the mat.', 'The dog ate my homework.'] #初始数据:每个样本是列表的一个元素(本例中的样本是一个句子,但也可以是一整篇文档) token_index = {} #构建数据中所有标记的索引 for sample in samples: for word in sample.split(): #利用split方法对样本进行分词。在实际应用中,还需要从样本中去掉标点和特殊字符 if word not in token_index: token_index[word] = len(token_index) + 1 #为每个唯一单词指定一个唯一索引。注意,没有为索引编号0指定单词 max_length = 10 #对样本进行分词。只考虑每个样本前max_length个单词 results = np.zeros(shape=(len(samples), max_length, max(token_index.values()) + 1)) #将结果保存在results中 for i, sample in enumerate(samples): for j, word in list(enumerate(sample.split()))[:max_length]: index = token_index.get(word) results[i, j, index] = 1. ~~~ **字符级的 one-hot 编码** ~~~ import string import numpy as np samples = ['The cat sat on the mat.', 'The dog ate my homework.'] characters = string.printable #所有可打印的ASCII字符 token_index = dict(zip(range(1, len(characters) + 1), characters)) max_length = 50 results = np.zeros((len(samples), max_length, max(token_index.keys()) + 1)) for i, sample in enumerate(samples): for j, character in enumerate(sample): index = token_index.get(character) results[i, j, index] = 1. ~~~ **Keras 实现单词级的 one-hot 编码** * Keras 的内置函数可以对原始文本数据进行单词级或字符级的 one-hot 编码 * 实现了许多重要的特性,比如从字符串中去除特殊字符、只考虑数据集中前*N*个最常见的单词(这是一种常用的限制,以避免处理非常大的输入向量空间) ~~~ from keras.preprocessing.text import Tokenizer samples = ['The cat sat on the mat.', 'The dog ate my homework.'] tokenizer = Tokenizer(num_words=1000) #创建一个分词器(tokenizer),设置为只考虑前1000个最常见的单词 tokenizer.fit_on_texts(samples) #构建单词索引 sequences = tokenizer.texts_to_sequences(samples) #将字符串转换为整数索引组成的列表 one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary') #也可以直接得到one-hot二进制表示。这个分词器也支持除one-hot编码外的其他向量化模式 word_index = tokenizer.word_index #找回单词索引 ~~~ **one-hot 散列技巧**(one-hot hashing trick) * 词表中唯一标记的数量太大而无法直接处理 * 将单词散列编码为固定长度的向量,通常用一个非常简单的散列函数来实现 * 优点:避免了维护一个显式的单词索引,从而节省内存并允许数据的在线编码(在读取完所有数据之前,你就可以立刻生成标记向量) * 缺点:可能会出现**散列冲突**(hash collision),即两个不同的单词可能具有相同的散列值,随后任何机器学习模型观察这些散列值,都无法区分它们所对应的单词。 * 如果散列空间的维度远大于需要散列的唯一标记的个数,散列冲突的可能性会减小。 ~~~ import numpy as np samples = ['The cat sat on the mat.', 'The dog ate my homework.'] dimensionality = 1000 #将单词保存为长度为1000的向量。 # 如果单词数量接近1000个(或更多),那么会遇到很多散列冲突,这会降低这种编码方法的准确性 max_length = 10 results = np.zeros((len(samples), max_length, dimensionality)) for i, sample in enumerate(samples): for j, word in list(enumerate(sample.split()))[:max_length]: index = abs(hash(word)) % dimensionality #将单词散列为0~1000范围内的一个随机整数索引 results[i, j, index] = 1. ~~~