- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊 | 接辅导、项目定制
- 🚀 文章来源:K同学的学习圈子
目录
词向量
词向量(Word Embedding)是将单词表示成计算机可以理解和处理的数字向量的一种方法。
简单来说,就是将文字转换为数字。
字典序列编码
字典序列编码是一种将分类变量的每一个独特值(类别)映射为一个唯一整数的编码方法。这样,原始的分类数据可以被表示为一个整数序列。
举例:
- 假设我们有一个颜色分类变量,有五个取值:红色(red)、绿色(green)、蓝色(blue)、黄色(yellow)和紫色(purple)。
- 构建词典:
- 红色:0
- 绿色:1
- 蓝色:2
- 黄色:3
- 紫色:4
- 使用词典对数据进行编码:
- 原始数据:["red", "green", "blue", "yellow", "purple", "red", "blue"]
- 编码后数据:[0, 1, 2, 3, 4, 0, 2]
但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。
One-hot编码
one-hot编码(one-hot encoding)是一种将分类变量转换为二进制向量的方法。对于一个具有N个可能取值的分类变量,one-hot编码会生成一个长度为N的二进制向量,其中只有一个位置为1,其他位置为0。这个位置对应于该分类变量的某一个具体取值。
举例:
- 假设我们有一个颜色分类变量,有三个可能的取值:红色(red)、绿色(green)和蓝色(blue)。
- 我们可以为这三个值分别分配一个唯一的索引:
- 红色:0
- 绿色:1
- 蓝色:2
- 对应的one-hot编码如下:
- 红色:[1, 0, 0]
- 绿色:[0, 1, 0]
- 蓝色:[0, 0, 1]
英文文本案例
"""
空字符串("")没有任何字符,长度为零。
空白字符串(例如'" "'、'\t'、'\n')包含一个或多个空白字符,长度大于零。
"""
import torch
import torch.nn.functional as F
#示例文本
texts = ['Hello, how are you? ','I am doing well, thank you! ','Goodbye.']
# "".join(texts)将texts列表中的所有字符串合并成一个单独的字符串。
# 这里使用空字符串""作为连接符。
words = "".join(texts)
print("完整文本:", words)
#构建词汇表
word_index = {}
index_word = {}
# 分割字符串:split()方法将合并后的字符串按空白字符分割成单词列表。
# 去重:set()函数用于创建一个包含所有唯一单词的集合,自动去掉重复的单词。
# 枚举单词:enumerate()函数对集合中的每个单词进行编号,生成一个唯一的索引。
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)
完整文本: Hello, how are you? I am doing well, thank you! Goodbye.
词汇表:
{'you?': 0, 'you!': 1, 'thank': 2, 'I': 3, 'are': 4, 'well,': 5, 'doing': 6, 'how': 7, 'Hello,': 8, 'am': 9, 'Goodbye.': 10}文本:
['Hello, how are you? ', 'I am doing well, thank you! ', 'Goodbye.']文本序列:
[[8, 7, 4, 0], [3, 9, 6, 5, 2, 1], [10]]One-Hot编码:
tensor([[1., 0., 0., 0., 1., 0., 0., 1., 1., 0., 0.],
[0., 1., 1., 1., 0., 1., 1., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
中文文本案例
import torch
import torch.nn.functional as F
#示例中文文本
texts = ['你好,最近怎么样? ', '我过得很好,谢谢!', 'K同学啊']
#构建词汇表
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)
词汇表:
{'么': 0, '最': 1, '谢': 2, '我': 3, '样': 4, '很': 5, '得': 6, 'K': 7, '啊': 8, '过': 9, '你': 10, ' ': 11, ',': 12, '同': 13, '!': 14, '怎': 15, '近': 16, '好': 17, '学': 18, '?': 19}文本:
['你好,最近怎么样? ', '我过得很好,谢谢!', 'K同学啊']文本序列:
[[10, 17, 12, 1, 16, 15, 0, 4, 19, 11], [3, 9, 6, 5, 17, 12, 2, 2, 14], [7, 13, 18, 8]]One-Hot编码:
tensor([[1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 1., 1., 1.,
0., 1.],
[0., 0., 1., 1., 0., 1., 1., 0., 0., 1., 0., 0., 1., 0., 1., 0., 0., 1.,
0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0.,
1., 0.]])
可以注意到上面的案例是以字为基本单位的,但词语被拆分开后,显然会失去原有的意思。在下面的案例中,我们使用iieba分词工具对句子进行划分。
使用结巴分词(iieba)进行中文文本的分词处理,然后将分词后的结果转化为one-hot编码。
使用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(sequences)
print("\nOne-Hot编码:")
print(one_hot_results)
Building prefix dict from the default dictionary ...
Dumping model to file cache C:\WINDOWS\TEMP\jieba.cache
Loading model cost 0.834 seconds.
Prefix dict has been built successfully.
词汇表:
{'谢谢': 0, '你好': 1, '怎么样': 2, '!': 3, '再见': 4, '得': 5, '?': 6, '好': 7, '。': 8, ',': 9, '很': 10, ' ': 11, '最近': 12, '我过': 13}文本:
['你好,最近怎么样? ', '我过得很好,谢谢!', '再见。']文本序列:
[[1, 9, 12, 2, 6, 11], [13, 5, 10, 7, 9, 0, 3], [4, 8]]One-Hot编码:
tensor([[0., 1., 1., 0., 0., 0., 1., 0., 0., 1., 0., 1., 1., 0.],
[1., 0., 0., 1., 0., 1., 0., 1., 0., 1., 1., 0., 0., 1.],
[0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])
任务
加载任务文件.txt文件并使用one-hot编码进行处理
import torch
import jieba
file_name = ".\任务文件.txt"
with open(file_name,"r",encoding = "utf-8") as file:
context = file.read()
sentences = context.split()
tokenized_texts = [list(jieba.lcut(sentence)) for sentence in sentences]
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_results = torch.zeros(len(sentences), vocab_size)
for i,seq in enumerate(sequences):
one_hot_results[i,seq] = 1
print("====词汇表:====\n", word_index)
print("====文本:====\n", sentences)
print("====分词结果:====\n", tokenized_texts)
print("====文本序列:====\n",sequences)
print("====One-Hot编码:====\n", one_hot_results)
Building prefix dict from the default dictionary ...
Loading model from cache C:\WINDOWS\TEMP\jieba.cache
Loading model cost 0.559 seconds.
Prefix dict has been built successfully.
====词汇表:====
{'2': 0, '避免': 1, '到': 2, '关系': 3, 'one': 4, '模型': 5, '可能': 6, '的': 7, '或': 8, '不': 9, '会': 10, '-': 11, '用': 12, '直观': 13, '这': 14, '提到': 15, '。': 16, '是': 17, ',': 18, '将': 19, '值': 20, '对于': 21, 'hot': 22, '独 立': 23, '就是': 24, '(': 25, '一些': 26, '编码': 27, '为了': 28, '距离': 29, '这些': 30, '序列': 31, '问题': 32, '相互': 33, '3': 34, '这样': 35, '实际意义': 36, ')': 37, '或者': 38, '和': 39, '引入': 40, '具有': 41, '三个': 42, '表示': 43, '存在': 44, '这种': 45, '地': 46, '了': 47, '顺序': 48, '比较': 49, '例如': 50, '不同': 51, '也': 52, '认为': 53, ' 基本': 54, '类别': 55, '思想': 56, '其中': 57, '分别': 58, '只有': 59, '上面': 60, '之间': 61, '实际上': 62, '编码方式': 63, '独热': 64, '元素': 65, '如下': 66, '有': 67, '错误': 68, '为': 69, '称': 70, '但是': 71, '使用': 72, '而': 73, '采用': 74, '一个': 75, '可以': 76, ':': 77, '映射': 78, '字典': 79, '1': 80, '、': 81, '向量': 82, '其余': 83, '情况': 84, '每个': 85, '0': 86}
====文本:====
['比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。', '为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:']
====分词结果:====
[['比较', '直观', '的', '编码方式', '是', '采用', '上面', '提到', '的', '字典', '序列', '。', '例如', ',', '对于', '一个', '有', '三个', '类别', '的', '问题', ',', '可以', '用', '1', '、', '2', '和', '3', '分别', '表示', '这', '三个', ' 类别', '。', '但是', ',', '这种', '编码方式', '存在', '一个', '问题', ',', '就是', '模型', '可能', '会', '错误', '地', '认为', '不同', '类别', '之间', '存在', '一些', '顺序', '或', '距离', '关系', ',', '而', '实际上', '这些', '关系', '可能', '是', '不', '存在', '的', '或者', '不', '具有', '实际意义', '的', '。'], ['为了', '避免', '这种', '问题', ',', '引入', '了', 'one', '-', 'hot', '编码', '(', '也', '称', '独热', '编码', ')', '。', 'one', '-', 'hot', '编码', '的', '基本', '思想', '是', '将', '每个', '类别', '映射', '到', '一个', '向量', ',', '其中', '只有', '一个', '元素', '的', '值', '为', '1', ',', '其余', '元素', '的', '值', '为', '0', '。', '这样', ',', '每个', '类别', '之间', '就是', '相互', '独立', '的', ',', '不', '存在', '顺序', '或', '距离', '关系', '。', '例如', ',', '对于', '三个', '类别', '的', '情况', ',', '可以', '使用', '如下', '的', 'one', '-', 'hot', '编码', ':']]
====文本序列:====
[[49, 13, 7, 63, 17, 74, 60, 15, 7, 79, 31, 16, 50, 18, 21, 75, 67, 42, 55, 7, 32, 18, 76, 12, 80, 81, 0, 39, 34, 58, 43, 14, 42, 55, 16, 71, 18, 45, 63, 44, 75, 32, 18, 24, 5, 6, 10, 68, 46, 53, 51, 55, 61, 44, 26, 48, 8, 29, 3, 18, 73, 62, 30, 3, 6, 17, 9, 44, 7, 38, 9, 41, 36, 7, 16], [28, 1, 45, 32, 18, 40, 47, 4, 11, 22, 27, 25, 52, 70, 64, 27, 37, 16, 4, 11, 22, 27, 7, 54, 56, 17, 19, 85, 55, 78, 2, 75, 82, 18, 57, 59, 75, 65, 7, 20, 69, 80, 18, 83, 65, 7, 20, 69, 86, 16, 35, 18, 85, 55, 61, 24, 33, 23, 7, 18, 9, 44, 48, 8, 29, 3, 16, 50, 18, 21, 42, 55, 7, 84, 18, 76, 72, 66, 7, 4, 11, 22, 27, 77]]
====One-Hot编码:====
tensor([[1., 0., 0., 1., 0., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1.,
1., 0., 0., 1., 0., 0., 1., 0., 1., 0., 0., 1., 1., 1., 1., 0., 1., 0.,
1., 0., 1., 1., 0., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 0., 1.,
0., 1., 0., 0., 1., 0., 1., 1., 1., 1., 0., 0., 0., 1., 1., 0., 0., 1.,
0., 1., 1., 1., 1., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
[0., 1., 1., 1., 1., 0., 0., 1., 1., 1., 0., 1., 0., 0., 0., 0., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 0., 0., 1., 1., 0., 1.,
0., 1., 0., 0., 1., 0., 1., 0., 1., 1., 0., 1., 1., 0., 1., 0., 1., 0.,
1., 1., 1., 1., 0., 1., 0., 1., 0., 0., 1., 1., 1., 0., 0., 1., 1., 0.,
1., 0., 0., 1., 1., 1., 1., 0., 1., 0., 1., 1., 1., 1., 1.]])