- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊 | 接辅导、项目定制
🏡我的环境:
- 语言环境:Python3.11.4
- 编译器:Jupyter Notebook
- torcch版本:2.0.1
1.one-hot编码概念
想学习NLP绕不开的第一个概念就是词向量。什么是词向量,这个东西又是做什么用的呢?
文字对于计算机来说就仅仅只是一个个文字,计算机无法理解其中含义,更无法处理。因此,NLP第一步就是:将文字转换为计算机能看懂的 数字。在自然语言处理中最早期的方式就是将文本转换为字典序列:
如:“阿” 是新华字典中第1个单词 ,所以它的字典序列就是 1 。
词典中的第几个字
比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。
为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:
类别1:[1, 0, 0]
类别2:[0, 1, 0]
类别3:[0, 0, 1]
这样的表示方式有助于模型更好地理解文本含义。在深度学习中,神经网络的输入层通常使用one-hot编码来表示分类变量。这种编码方式不仅能够避免不必要的关系假设,还能够提供清晰的输入表示,有助于模型的学习和泛化。
例:
John likes to watch movies. Mary likes too
John also likes to watch football games.
以上两句可以构造一个词典:
{"John": 1, "likes": 2, "to": 3, "watch": 4, "movies": 5, "also": 6, "football": 7, "games": 8, "Mary": 9, "too": 10}
one-hot可表示为:
John: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
likes: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
.......等等,以此类推。
1.one-hot优点:
解决了分类器不好处理离散数据的问题,能够处理非连续型数值特征。
2.one-hot缺点:
在文本表征表示上有些缺点非常突出,首先one-hot 编码是一个词袋模型,是不考虑词和词之间的顺序问题,它是假设词和词之间是相互独立的,但是在大部分情况下词和词之间是相互影响的。
one-hot编码得到的特征是离散稀疏的,每个单词的one-hot编码维度是整个词汇表的大小,维度非常巨大,编码稀疏,会使得计算代价变大。
2. 英文文本文案例
import torch
import torch.nn.functional as F
#示例文本
texts = ['Hi, how are you','I feel great these days,thank you!','you are welcome.']
#构建词汇表
word_index = {}
index_word = {}
for i,word in enumerate(set(" ".join(texts).split())):
word_index[word] = i
index_word[i] = word
#将文本转化为整数序列
sequences =[[word_index[word]for word in text.split()]for text in texts]
#获取词汇表大小
vocab_size = len(word_index)
#将整数列转化为one-hot编码
one_hot_results = torch.zeros(len(texts),vocab_size)
for i,seq in enumerate(sequences):
one_hot_results[i,seq] = 1
#打印结果
print("词汇表")
print(word_index)
print("\n文本:")
print(texts)
print("\n文本序列:")
print(sequences)
print("\nOne-Hot编码:")
print(one_hot_results)
3.中文文本案例
import torch
import torch.nn.functional as F
#示例文本
texts = ['你好,最近怎么样?','感觉不错,谢谢!','客气了']
#构建词汇表
word_index = {}
index_word = {}
for i,word in enumerate(set(" ".join(texts))):
word_index[word] = i
index_word[i] = word
#将文本转化为整数序列
sequences = [[word_index[word] for word in text] for text in texts]
#获取词汇表大小
vocab_size = len(word_index)
#将整数列转化为one-hot编码
one_hot_results = torch.zeros(len(texts),vocab_size)
for i,seq in enumerate(sequences):
one_hot_results[i,seq] = 1
#打印结果
print("词汇表:")
print(word_index)
print("\n文本:")
print(texts)
print("\n文本序列:")
print(sequences)
print("\nOne-Hot编码:")
print(one_hot_results)
以上的案例是以字为基本单位的,但词语被拆分开后,显然会失去原有的意思。在下面的案例中,我们使用jieba分词工具对句子进行划分。
使用jieba结巴分词进行中文文本的分词处理,然后将分词后的结果转化为one-hot编码。首先,确保你已经安装了结巴分词库:pip install jieba
import torch
import torch.nn.functional as F
import jieba
#示例文本
texts = ['你好,最近怎么样?','感觉不错,谢谢!','客气了']
#使用结巴分词进行分词
tokenized_texts = [list(jieba.cut(text)) for text in texts]
#构建词汇表
word_index = {}
index_word = {}
for i,word in enumerate(set([word for text in tokenized_texts for word in text])):
word_index[word] = i
index_word[i] = word
#将文本转化为整数序列
sequences = [[word_index[word] for word in text] for text in tokenized_texts]
#获取词汇表大小
vocab_size = len(word_index)
#将整数列转化为one-hot编码
one_hot_results = torch.zeros(len(texts),vocab_size)
for i,seq in enumerate(sequences):
one_hot_results[i,seq] = 1
#打印结果
print("词汇表:")
print(word_index)
print("\n文本:")
print(texts)
print("\n分词结果")
print(tokenized_texts)
print("\n文本序列:")
print(sequences)
print("\nOne-Hot编码:")
print(one_hot_results)
4.小结
在中文文本案例中构建词汇表时,使用“.split()”和不使用时划分的结果是不同的,在中文划分时需要添加它,英文划分不需要这部分。