第N1周:one-hot编码案例

任务: ●加载下面的.txt文件,使用字典序列方法与one-hot编码进行数字化处理。

.txt文件的内容:

比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。
为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:

1.one-hot编码概念
自然语言处理(NLP)入门,绕不开的第一个概念就是词向量。什么是词向量,这个东西又是做什么用的呢?

文字对于计算机来说就仅仅只是一个个符号,计算机无法理解其中含义,更无法处理。因此,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 = ['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)

代码输出:

词汇表:
{'Hello,': 0, 'Goodbye.': 1, 'are': 2, 'I': 3, 'you!': 4, 'doing': 5, 'thank': 6, 'am': 7, 'well,': 8, 'you?': 9, 'how': 10}

文本:
['Hello, how are you?', 'I am doing well, thank you!', 'Goodbye.']

文本序列:
[[0, 10, 2, 9], [3, 7, 5, 8, 6, 4], [1]]

One-Hot编码:
tensor([[1., 0., 1., 0., 0., 0., 0., 0., 0., 1., 1.],
        [0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0.],
        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

3.中文文本文案例

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, 'K': 3, '么': 4, '怎': 5, '得': 6, '你': 7, '我': 8, '?': 9, '最': 10, '谢': 11, '很': 12, '!': 13, '过': 14, '样': 15, '同': 16, '学': 17, '啊': 18}

文本:
['你好,最近怎么样?', '我过得很好,谢谢!', 'K同学啊']

文本序列:
[[7, 2, 1, 10, 0, 5, 4, 15, 9], [8, 14, 6, 12, 2, 1, 11, 11, 13], [3, 16, 17, 18]]

One-Hot编码:
tensor([[1., 1., 1., 0., 1., 1., 0., 1., 0., 1., 1., 0., 0., 0., 0., 1., 0., 0.,
         0.],
        [0., 1., 1., 0., 0., 0., 1., 0., 1., 0., 0., 1., 1., 1., 1., 0., 0., 0.,
         0.],
        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.,
         1.]])

可以注意到上面的案例是以字为基本单位的,但词语被拆分开后,显然会失去原有的意思。在下面的案例中,我们使用jieba分词工具对句子进行划分。

使用结巴分词(jieba)进行中文文本的分词处理,然后将分词后的结果转化为one-hot编码。首先,确保你已经安装了结巴分词库。

pip安装语句: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)

代码输出:

词汇表:
{'你好': 0, '再见': 1, '最近': 2, '。': 3, '!': 4, ',': 5, '我过': 6, '好': 7, '?': 8, '谢谢': 9, '得': 10, '怎么样': 11, '很': 12}

文本:
['你好,最近怎么样?', '我过得很好,谢谢!', '再见。']

分词结果
[['你好', ',', '最近', '怎么样', '?'], ['我过', '得', '很', '好', ',', '谢谢', '!'], ['再见', '。']]

文本序列:
[[0, 5, 2, 11, 8], [6, 10, 12, 7, 5, 9, 4], [1, 3]]

One-Hot编码:
tensor([[1., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0.],
        [0., 0., 0., 0., 1., 1., 1., 1., 0., 1., 1., 0., 1.],
        [0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

4.打开txt文件内容并进行one-hot编码

#打开txt文件的方式
texts = open('./N1/任务文件.txt', 'r',encoding='utf-8').read().split('\n')
texts
['比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。',
 '为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:']
# 另外一种打开txt文件的方式
file_name = "./N1/任务文件.txt"
with open(file_name,"r",encoding = "utf-8") as file:
    context = file.read()
    texts = context.split()
texts
['比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。',
 '为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:']
# 使用结巴分词进行分词
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)

代码输出:

词汇表:
{'这些': 0, '一个': 1, '有': 2, '序列': 3, '编码': 4, '距离': 5, '1': 6, '基本': 7, '如下': 8, '元素': 9, '映射': 10, '避免': 11, '用': 12, '顺序': 13, '称': 14, '为了': 15, '独立': 16, '不': 17, '这样': 18, '使用': 19, '。': 20, '字典': 21, ')': 22, '向量': 23, '例如': 24, '地': 25, 'one': 26, '表示': 27, '只有': 28, '这种': 29, '类别': 30, '比较': 31, '实际上': 32, '相互': 33, '认为': 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, '3': 69, '其余': 70, '可能': 71, '0': 72, '为': 73, '三个': 74, '了': 75, ':': 76, 'hot': 77, '提到': 78, '情况': 79, '其中': 80, '是': 81, '可以': 82, '2': 83, '或者': 84, '采用': 85, '而': 86}

文本:
['比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。', '为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:']

分词结果
[['比较', '直观', '的', '编码方式', '是', '采用', '上面', '提到', '的', '字典', '序列', '。', '例如', ',', '对于', '一个', '有', '三个', '类别', '的', '问题', ',', '可以', '用', '1', '、', '2', '和', '3', '分别', '表示', '这', '三个', '类别', '。', '但是', ',', '这种', '编码方式', '存在', '一个', '问题', ',', '就是', '模型', '可能', '会', '错误', '地', '认为', '不同', '类别', '之间', '存在', '一些', '顺序', '或', '距离', '关系', ',', '而', '实际上', '这些', '关系', '可能', '是', '不', '存在', '的', '或者', '不', '具有', '实际意义', '的', '。'], ['为了', '避免', '这种', '问题', ',', '引入', '了', 'one', '-', 'hot', '编码', '(', '也', '称', '独热', '编码', ')', '。', 'one', '-', 'hot', '编码', '的', '基本', '思想', '是', '将', '每个', '类别', '映射', '到', '一个', '向量', ',', '其中', '只有', '一个', '元素', '的', '值', '为', '1', ',', '其余', '元素', '的', '值', '为', '0', '。', '这样', ',', '每个', '类别', '之间', '就是', '相互', '独立', '的', ',', '不', '存在', '顺序', '或', '距离', '关系', '。', '例如', ',', '对于', '三个', '类别', '的', '情况', ',', '可以', '使用', '如下', '的', 'one', '-', 'hot', '编码', ':']]

文本序列:
[[31, 61, 54, 48, 81, 85, 36, 78, 54, 21, 3, 20, 24, 46, 40, 1, 2, 74, 30, 54, 56, 46, 82, 12, 6, 37, 83, 58, 69, 57, 27, 39, 74, 30, 20, 49, 46, 29, 48, 60, 1, 56, 46, 63, 55, 71, 38, 68, 25, 34, 59, 30, 41, 60, 45, 13, 52, 5, 53, 46, 86, 32, 0, 53, 71, 81, 17, 60, 54, 84, 17, 51, 65, 54, 20], [15, 11, 29, 56, 46, 44, 75, 26, 67, 77, 4, 43, 66, 14, 42, 4, 22, 20, 26, 67, 77, 4, 54, 7, 62, 81, 47, 35, 30, 10, 50, 1, 23, 46, 80, 28, 1, 9, 54, 64, 73, 6, 46, 70, 9, 54, 64, 73, 72, 20, 18, 46, 35, 30, 41, 63, 33, 16, 54, 46, 17, 60, 13, 52, 5, 53, 20, 24, 46, 40, 74, 30, 54, 79, 46, 82, 19, 8, 54, 26, 67, 77, 4, 76]]
  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值