- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
一、实验目的
- 加载任务文件,使用字典序列方法与one-hot编码进行数字化处理。
二、实验环境
- 语言环境:python 3.8
- 编译器:Jupyter notebook
- 深度学习环境:Pytorch
- torch==2.1.0+cu118
- torchvision==0.16.0+cu118
三、one-hot编码概念
概念
- 基本定义
-
One - hot编码(独热编码)是一种将类别型数据转换为机器学习算法能够处理的数值型数据的方法。简单来说,它是把一个具有多个类别的特征,转换为多个只有0和1的新特征。
-
例如,假设有一个特征是"颜色",它有三个类别:红、绿、蓝。One - hot编码后,就会变成三个新的特征,比如"是红色""是绿色""是蓝色"。如果原来的数据是红色,那么在新的编码中,"是红色"这个特征就为1,"是绿色"和"是蓝色"这两个特征就为0。
-
- 具体操作过程
-
假设我们有一个类别变量,它有(n)个不同的类别。我们会创建一个长度为(n)的向量来表示这个变量。
-
当数据属于某个特定类别时,这个类别对应的位置就设为1,其他位置都设为0。比如,有一个水果类别变量,有苹果、香蕉、橙子这3种类别。如果某个数据是香蕉,那么对应的One - hot编码可能是([0,1,0]),这里的顺序是按照苹果、香蕉、橙子来排列的。
-
优点
-
能够处理非数值数据
-
在机器学习中,很多算法只能处理数值型数据。像决策树这种算法还好,它本身可以处理类别型数据。但是像线性回归、神经网络等算法就不行了。One - hot编码就可以把类别型数据很好地转换为数值型数据,这样这些算法就能使用这些数据了。
-
例如,在一个预测用户购买商品类型(服装、电子产品、食品)的神经网络模型中,我们可以把商品类型这个类别变量用One - hot编码转换后输入到神经网络中进行训练。
-
-
避免了类别型数据的大小关系问题
-
如果我们直接把类别型数据用数字来表示(比如用1代表苹果,2代表香蕉,3代表橙子),机器学习算法可能会误解这些数字之间的关系,认为3(橙子)比1(苹果)大,它们之间有某种顺序关系。但实际上,这些类别之间可能并没有这种大小关系。One - hot编码就不存在这个问题,因为每个类别都被平等地用0和1来表示,没有大小之分。
-
比如在一个预测动物种类(猫、狗、兔子)对某种药物反应的模型中,我们不能认为狗(假设编码为2)比猫(编码为1)在这个模型中有更"高级"的反应,One - hot编码就可以避免这种错误的理解。
-
-
简单易懂且容易实现
- 从概念和操作上来说,One - hot编码比较简单。无论是编程实现还是理解它的工作原理,都相对容易。在很多编程语言和机器学习库中,都有现成的函数可以用来进行One - hot编码。
- 例如,在Python的
pandas
库中,就可以很方便地使用get_dummies
函数来对数据进行One - hot编码。
缺点
- 维度灾难
- 当类别数量很多的时候,One - hot编码会产生大量的新特征。例如,如果有一个类别变量有1000个类别,那么经过One - hot编码后就会产生1000个新特征。这会导致数据的维度急剧增加。
- 这在计算资源有限的情况下是个大问题,因为高维度的数据会占用更多的存储空间,并且模型训练和预测的时间也会变长。而且高维度数据还可能导致过拟合,因为模型有太多的参数可以学习。
- 稀疏性问题
- One - hot编码后的数据是很稀疏的。因为每个数据点在编码后的向量中只有一个位置是1,其他位置都是0。这种稀疏的数据在存储和计算时效率不高。
- 例如,在处理文本分类任务时,如果词汇表很大,对每个单词进行One - hot编码后,大部分位置都是0,这会给模型的训练和存储带来挑战。而且一些机器学习算法在处理稀疏数据时可能会遇到困难,比如某些基于距离计算的算法,在稀疏数据上计算距离可能会得到不太准确的结果。
四、实验结果
英文文本案例
python
import torch
import torch.nn.functional as F
# 示例文本
texts = ['Hello, how are you?', 'I am doing well, thank you!', 'Goodbye.']
# 构建词汇表
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)
结果输出如下:
中文文本案例
python
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)
结果输出如下:
可以注意到上面的案例是以字为基本单位的,但词语被拆分开后,显然会失去原有的意思。在下面的案例中,我们使用jieba分词工具对句子进行划分。
使用==结巴分词(jieba)==进行中文文本的分词处理,然后将分词后的结果转化为one-hot编码。首先,确保你已经安装了结巴分词库。
python
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)
结果输出如下:
任务
加载"任务文件.txt",并使用字典序列方法和one-hot编码进行数字化处理。
python
# 导入torch和jieba库
import torch
import jieba
# 定义文件路径
file_name = ".\任务文件.txt"
# 打开文件并读取内容
with open(file_name, "r", encoding="utf-8") as file:
context = file.read()
# 将内容分割成句子
sentences = context.split()
# 使用jieba对每个句子进行分词
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编码
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)
结果输出如下:
python
====词汇表:====
{'3': 0, '这': 1, '"': 2, '啊': 3, '这些': 4, '如下': 5, '这种': 6, '用': 7, '比较': 8, '存在': 9, '映射': 10, '学习': 11, '教案': 12, '为了': 13, '训练营': 14, '内容': 15, '实际上': 16, '是': 17, '认为': 18, '一个': 19, '采用': 20, '或': 21, '了': 22, '而': 23, 'one': 24, '例如': 25, '三个': 26, '基本': 27, '、': 28, '编码': 29, '之间': 30, '天': 31, '顺序': 32, '为': 33, '也': 34, '思想': 35, '会': 36, '关系': 37, '的': 38, '。': 39, '问题': 40, '值': 41, '序列': 42, '其中': 43, '地': 44, '深度': 45, '将': 46, '1': 47, '对于': 48, '不': 49, '-': 50, '一些': 51, '不同': 52, '向量': 53, '提到': 54, '这样': 55, '只有': 56, '分别': 57, ',': 58, '具有': 59, '错误': 60, '称': 61, '实际意义': 62, '这是': 63, '和': 64, 'hot': 65, '可能': 66, ')': 67, '相互': 68, '365': 69, '但是': 70, '元素': 71, '上面': 72, '直观': 73, 'K': 74, '避免': 75, '独立': 76, '同学': 77, '就是': 78, '模型': 79, '每个': 80, '类别': 81, '使用': 82, '"': 83, '字典': 84, '情况': 85, '引入': 86, '表示': 87, '0': 88, '到': 89, '独热': 90, '有': 91, ':': 92, '其余': 93, '可以': 94, '(': 95, '2': 96, '距离': 97, '编码方式': 98, '或者': 99}
====文本:====
['比较直观的编码方式是采用上面提到的字典序列。', '例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。', '但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系', '而实际上这些关系可能是不存在的或者不具有实际意义的,为了避免这种问题,引入了one-hot编码(也称独热编码)。', 'one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。', '这样,每个类别之间就是相互独立的,不存在顺序或距离关系。', '例如,对于三个类别的情况,可以使用如下的one-hot编码:', '这是K同学啊的"365天深度学习训练营"教案内容']
====分词结果:====
[['比较', '直观', '的', '编码方式', '是', '采用', '上面', '提到', '的', '字典', '序列', '。'],
['例如', ',', '对于', '一个', '有', '三个', '类别', '的', '问题', ',', '可以', '用', '1', '、', '2', '和', '3', '分别', '表示', '这', '三个', '类别', '。'],
['但是', ',', '这种', '编码方式', '存在', '一个', '问题', ',', '就是', '模型', '可能', '会', '错误', '地', '认为', '不同', '类别', '之间', '存在', '一些', '顺序', '或', '距离', '关系'],
['而', '实际上', '这些', '关系', '可能', '是', '不', '存在', '的', '或者', '不', '具有', '实际意义', '的', ',', '为了', '避免', '这种', '问题', ',', '引入', '了', 'one', '-', 'hot', '编码', '(', '也', '称', '独热', '编码', ')', '。'],
['one', '-', 'hot', '编码', '的', '基本', '思想', '是', '将', '每个', '类别', '映射', '到', '一个', '向量', ',', '其中', '只有', '一个', '元素', '的', '值', '为', '1', ',', '其余', '元素', '的', '值', '为', '0', '。'],
['这样', ',', '每个', '类别', '之间', '就是', '相互', '独立', '的', ',', '不', '存在', '顺序', '或', '距离', '关系', '。'],
['例如', ',', '对于', '三个', '类别', '的', '情况', ',', '可以', '使用', '如下', '的', 'one', '-', 'hot', '编码', ':'],
['这是', 'K', '同学', '啊', '的', '"', '365', '天', '深度', '学习', '训练营', '"', '教案', '内容']]
====文本序列:====
[[8, 73, 38, 98, 17, 20, 72, 54, 38, 84, 42, 39],
[25, 58, 48, 19, 91, 26, 81, 38, 40, 58, 94, 7, 47, 28, 96, 64, 0, 57, 87, 1, 26, 81, 39],
[70, 58, 6, 98, 9, 19, 40, 58, 78, 79, 66, 36, 60, 44, 18, 52, 81, 30, 9, 51, 32, 21, 97, 37],
[23, 16, 4, 37, 66, 17, 49, 9, 38, 99, 49, 59, 62, 38, 58, 13, 75, 6, 40, 58, 86, 22, 24, 50, 65, 29, 95, 34, 61, 90, 29, 67, 39],
[24, 50, 65, 29, 38, 27, 35, 17, 46, 80, 81, 10, 89, 19, 53, 58, 43, 56, 19, 71, 38, 41, 33, 47, 58, 93, 71, 38, 41, 33, 88, 39],
[55, 58, 80, 81, 30, 78, 68, 76, 38, 58, 49, 9, 32, 21, 97, 37, 39],
[25, 58, 48, 26, 81, 38, 85, 58, 94, 82, 5, 38, 24, 50, 65, 29, 92],
[63, 74, 77, 3, 38, 2, 69, 31, 45, 11, 14, 83, 12, 15]]
====One-Hot编码:====
tensor([[0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1.,
0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[1., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 1., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0.,
0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0.,
0., 1., 0., 0., 1., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
1., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0.,
1., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 1., 0.,
0., 0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0.,
0., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 1., 1., 0.],
[0., 0., 0., 0., 1., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 1.,
0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0.,
0., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0.,
0., 0., 0., 0., 1., 1., 0., 1., 1., 0., 0., 1., 1., 1., 0., 0., 0., 0.,
0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
1., 0., 0., 0., 0., 1., 0., 0., 0., 1.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1.,
0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 1., 0., 0., 0., 1., 0., 1.,
0., 0., 1., 1., 0., 1., 0., 1., 0., 0., 1., 1., 0., 0., 1., 0., 0., 1.,
0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 1., 1.,
0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0.,
0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.,
0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
0., 0., 0., 0., 1., 0., 1., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0.,
0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0.,
0., 0., 1., 0., 1., 0., 0., 0., 0., 0.],
[0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 1., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.,
0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0.,
0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
五、总结
本周主要学习了one--hot 编码的概念、优缺点以及通过 Python 代码实现对英文、中文文本进行 one--hot 编码,并使用 jieba 分词工具处理中文文本。