当前位置:   article > 正文

Python文本处理(3)——文本表示之 one-hot 词向量(1)——纯小白都能懂!_python词向量

python词向量


python 文本处理小结-供自己复习使用(对应“1127_文本处理之 one-hot 编码”)

1. 问题及概念

1.1 文本表示

文本表示最基础的怕是最基础的 one-hot 编码,基础的东西有利于我们从源头和本质上进行思考。比如,现在给一堆文本数据给你,你会如何思考将文本信息传递出去并让计算机识别?

text = ['Today is Friday, it is Sunny.',
       'And yesterday is Thursday, it was cloudy.',
       'Tomorrow is Saturday, it will be Sunny too.']
  • 1
  • 2
  • 3

——单词作为文本的最小单位,我们自然而然的会想到从单词入手。

的确,自然语言就是一套用来表达含义的系统,在这套系统中,词,就是表义的基本单元。
词向量 被用来表示词的向量表征,也可被认为是词的特征向量

在大的方向上,有两种思路:One-hot 词向量的表示方法 和 word2vec 词向量的表示方法,这先总结前者。顺带提一下,这种把词映射为实数域向量的技术叫做词嵌入(word embedding)。

1.2 one-hot 表达

所谓 one-hot 词向量,就是用一个很长的向量来表示一个词,向量的长度为词典的大小N,向量的分量只有一个1,其他全为0,1的位置对应该词在词典中的索引。直观理解如下:

1.2.1 直观理解:

# 直观理解:
['Toeday', 'is', 'Friday'] # 就可以这样表示:

today = [1, 0, 0]
is_ = [010]
Friday = [0, 0 ,1] 

## 需注意一点,平时我们句子中的单词很可能是可能重复的!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

1.2.2 本质理解:

这里可以将有信息价值的单词当做这个文本的“特征”,
那么如果文本中有k个不重复的单词,我们可以初略地认为该文本有 k 个”特征“;
特征组成了文本的“语料库”;
所以我们编码的目的:就是为这些不重复的单词进行编码。

2. 代码

接下来,以一个具体的、从头到尾的完整例子来仔细看看 如何使用one-hot 编码对文本进行编码。(纯属个人的思路)

记住上面所说的一点,既然词向量是特征,那么它必定不能重复。

2.1 代码思路

  • 文本
text = ['Today is Friday it is Sunny',
       'And yesterday is Thursday it was cloudy']
  • 1
  • 2
  • 语料库

先找出所有文档本中不重复的单词(总数记为N),放在一起, 并以出现的先后顺序(也可以按照首字母排序)作为语料库,如下图所示

# 语料库长这样:
corpus = ['Today', 'is', 'Friday', 'it', 'Sunny', 'And''Yesterday', 'Thursday', 'was', 'cloudy']
N = len(corpus)
print('语料库的大小为 {}'.format(N))
  • 1
  • 2
  • 3
  • 4
  • one-hot 向量编码

每单词词和从0到N-1的连续整数一一对应(每个词度都会有一个索引 i );
除了第i位置设置为1,其他为均设置为0(用1表示一个词出现在文本中,用0表示一个词没有出现)

即,我们要达到的效果如下:


# 应该长成这样,共 10 个 one-hot 向量:

Today = [1, 0, 0, 0, 0, 0, 0, 0, 0]
is_ = [0, 1, 0, 0, 1, 0, 0, 0, 0]
Friday = [0, 0, 1, 0, 0, 0, 0, 0, 0]
#... ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2. 2 代码实现

  • 代码实现:
    这里使用 Pandas 里的 get_dummies()函数
import numpy as np
import pandas as pd 

text = ['Today is Friday it is Sunny',
       'Yesterday is Thursday it was cloudy']
  • 1
  • 2
  • 3
  • 4
  • 5
# 先分词处理
text = [s.split() for s in text]
text = pd.Series(text)
print(text)
  • 1
  • 2
  • 3
  • 4
0                 [Today, is, Friday, it, is, Sunny]
1    [and, yesterday, is, Thursday, it, was, cloudy]
dtype: object

  • 1
  • 2
  • 3
  • 4
# 第一行文本,每个单词的 one-hot 表示
text1 = pd.get_dummies(text[0])
print(text1)
print(text1.shape)
  • 1
  • 2
  • 3
  • 4
   Friday  Sunny  Today  is  it
0       0      0      1   0   0
1       0      0      0   1   0
2       1      0      0   0   0
3       0      0      0   0   1
4       0      0      0   1   0
5       0      1      0   0   0
(6, 5)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
# 第一个单词的词向量表示
print(text1['Friday'])
print(text1['Friday'].shape)
  • 1
  • 2
  • 3
0    0
1    0
2    1
3    0
4    0
5    0
Name: Friday, dtype: uint8
(6,)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

第二行的文本同理:
在这里插入图片描述

  • 注意:

① 观察 one-hot 文本词向量的大小/其每句文本的输出格式是:

shape = ( 行 * 列 ) = 无重复单词数量 * 句子长度 (因为单词向量列向排列)

可以形象地看到:顺着从上到下的方向,选取每一行对应的单词,连起来即是整个文本

注意: ② 这意味着,输出的大小是不定长的!

3. 总结:

归根到底,one-hot 不过是词向量的其中一种方式,是文本的一一种表示方法。
所以清楚了需要编码的特征(不重复单词),以及 特征表达方式(one-out-of-N coding) 就OK 了。

4. 最后附:

《python 深度学习》中的两个手实现例子和一个 Keras 实现 one-hot对文本进行编码的例子
(第一个使用的是我自己的例子,对比)

1.单词级的one-hot编码

import numpy as np

samples = ['Today is Friday it is Sunny',
       'and yesterday is Thursday it was cloudy']  # 初始数据,本例中是一个句子,当然也可以是一篇文章

token_index = {}   # 构建数据中所有标记的索引
for sample in samples:
    for word in sample.split():   # 用split方法对样本进行分词,实际应用中,可能还需要考虑到标点符号
        if word not in token_index:

            token_index[word] = len(token_index) + 1  #为每个唯一单词指定唯一索引,注意我们没有为索引编号0指定单词

max_length = 10  # 对样本进行分词,只考虑样本前max_length单词

results = np.zeros((len(samples), max_length, max(token_index.values()) + 1))    # 将结果保存到results中
for i, sample in enumerate(samples):
    for j, word in list(enumerate(sample.split()))[:max_length]:
        index = token_index.get(word)
        results[i, j, index] = 1.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
print(token_index)
print(results) 
print(results.shape)
  • 1
  • 2
  • 3

结果:

{'Today': 1, 'is': 2, 'Friday': 3, 'it': 4, 'Sunny': 5, 'and': 6, 'yesterday': 7, 'Thursday': 8, 'was': 9, 'cloudy': 10}
[[[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. 1. 0. 0. 0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
  [0. 0. 1. 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. 0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
  [0. 0. 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. 1. 0. 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.]
  [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. 0. 0. 0.]
  [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]]
(2, 10, 11)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

这里需要注意的是:
① 有一个max_length参数,可以设置只考虑样本前max_length单词;
② 这里设置的索引从 1 开始

2.字符级的one-hot编码

import string

samples = ['The cat sat on the mat.', 'The dog ate my homework.']
characters = string.printable   # 所有可打印的ASCII字符
token_index = dict(zip(characters, range(1, len(characters) + 1)))

max_length = 50
results = np.zeros((len(samples), max_length, max(token_index.values()) + 1))
for i, sample in enumerate(samples):
    for j, character in enumerate(sample[:max_length]):
        index = token_index.get(character)
        results[i, j, index] = 1.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3.Keras 自带的

from keras.preprocessing.text import Tokenizer

samples = ['The cat sat on the mat.', 'The dog ate my homework.']

tokenizer = Tokenizer(num_words=1000)  # i创建一个分词器(tokenizer),设置为只考虑前1000个最常见的单词

tokenizer.fit_on_texts(samples)   # 构建索引单词


sequences = tokenizer.texts_to_sequences(samples)   # 将字符串转换为整数索引组成的列表


one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary')  #可以直接得到one-hot二进制表示。这个分词器也支持除

word_index = tokenizer.word_index  # 得到单词索引
print('Found %s unique tokens.' % len(word_index))


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/664311
推荐阅读
相关标签
  

闽ICP备14008679号