第N1周:one-hot编码案例

目录

词向量

字典序列编码

One-hot编码

英文文本案例

中文文本案例

使用jieba分词案例

任务


词向量

词向量(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.]])

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值