在完成了文本清洗和标准化后,自然语言处理(NLP)的下一个关键步骤就是特征工程。机器无法直接理解文本中的词语和句子,它们只能处理数字。而特征工程的目标,正是将原始文本数据转化为机器可以理解和处理的数值表示。从最基础的 One-Hot 编码、词频向量,到 TF-IDF、词嵌入和 fastText,这些方法不仅是模型建构的起点,也直接影响着模型最终的性能和表现。
文章目录
1 特征工程
1.1 One Hot Encoding
One Hot 编码是传统的特征工程方法之一,用于将分类变量转换为数值特征。该方法将每个类别作为一个新的特征列,对应值为 1 或 0,表示该类别是否存在。
One Hot 编码会将字符或单词转换成二进制形式:
I | love | NLP | is | future | |
---|---|---|---|---|---|
I love NLP | 1 | 1 | 1 | 0 | 0 |
NLP is future | 0 | 0 | 1 | 1 | 1 |
我们使用 pandas 的 get_dummies()
方法对文本进行 One Hot 编码。
# 将文本存入变量
Text = "I am learning NLP"
# 使用 pandas 方法生成特征
import pandas as pd
pd.get_dummies(Text.split())
输出:
其中True代表1,False代表0。
1.2 Count Vectorizer
One Hot 编码无法捕捉单词出现的频率。而 Count Vectorizer 可以统计每个单词在文本中出现的次数,从而保留更多信息。
Count Vectorizer与One Hot类似,但还会统计每个词的出现次数。
I | love | NLP | is | future | will | learn | in | 2month | |
---|---|---|---|---|---|---|---|---|---|
I love NLP and I will learn NLP in 2month | 2 | 1 | 2 | 0 | 0 | 1 | 1 | 1 | 1 |
NLP is future | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
I
和NLP
在第一个文本中出现了两次
我们使用 sklearn
的 CountVectorizer
来提取文本特征,在此之前我们需要知道CountVectorizer
默认会执行以下操作:
- 把所有词转换为小写(所以 “I” 变成 “i”)
- 忽略长度为 1 的词(像 “a”、“I” 这样只有一个字母的词)
- 不包含在正则表达式匹配范围内的词也会被过滤掉
接下来看一下代码:
# 导入方法
from sklearn.feature_extraction.text import CountVectorizer
# 文本数据
text = ["I love NLP and I will learn NLP in 2month "]
# 创建转换器
vectorizer = CountVectorizer()
# 拟合文本
vectorizer.fit(text)
# 编码文档
vector = vectorizer.transform(text)
# 输出词汇表和向量
print(vectorizer.vocabulary_)
print(vector.toarray())
- 词汇表:每个单词在向量中的位置(列索引)。
输出:
{'love': 4, 'nlp': 5, 'and': 1, 'will': 6, 'learn': 3, 'in': 2, '2month': 0}
[[1 1 1 1 1 2 1]]
其中 'nlp'
出现了两次,因此索引为5的位置的值为 2。
1.3 N-grams
前两个方法每个词独立建模,无法捕捉上下文。如 “not bad” 被拆开后会丧失原意。N-grams 则能将多个词组合成一体进行建模。
- Unigram:单词
- Bigram:两个词组成的组合
- Trigram:三个词组成的组合
示例:
原句:“I am learning NLP”
- Unigrams: “I”, “am”, “learning”, “NLP”
- Bigrams: “I am”, “am learning”, “learning NLP”
- Trigrams: “I am learning”, “am learning NLP”
我们可以使用 TextBlob 或 Sklearn 来生成 N-grams。
(1)使用TextBlob
import nltk
nltk.download('punkt_tab')
from textblob import TextBlob
Text = "I am learning NLP"
# Unigram(n=1)
TextBlob(Text).ngrams(1)
# 输出: [WordList(['I']), WordList(['am']), WordList(['learning']), WordList(['NLP'])]
# Bigram(n=2)
TextBlob(Text).ngrams(2)
# 输出:
# [WordList(['I', 'am']),
# WordList(['am', 'learning']),
# WordList(['learning', 'NLP'])]
(2)使用 CountVectorizer 提取 Bigram 特征
from sklearn.feature_extraction.text import CountVectorizer
text = ["I love NLP and I will learn NLP in 2month "]
# 设置 ngram_range 为 (2,2) 生成 Bigrams
vectorizer = CountVectorizer(ngram_range=(2,2))
vectorizer.fit(text)
vector = vectorizer.transform(text)
print(vectorizer.vocabulary_)
print(vector.toarray())
先来理解一下代码,对于ngram_range
来说:
(1, 1)
:只提取 unigrams(单个词)(2, 2)
:只提取 bigrams(两个词连起来)(1, 2)
:提取 unigrams 和 bigrams(2, 3)
:提取 bigrams 和 trigrams
输出:
{'love nlp': 3, 'nlp and': 4, 'and will': 0, 'will learn': 6,
'learn nlp': 2, 'nlp in': 5, 'in 2month': 1}
[[1 1 1 1 1 1 1]]
每个 Bigram 出现一次,形成相应特征。
1.4 Co-occurrence Matrix(共现矩阵)
共现矩阵(Co-occurrence Matrix
)是NLP中一种基于上下文的文本特征表示方法。它的本质是一个二维矩阵,用于表示词语与词语之间在上下文窗口中共同出现的次数。如果两个词经常出现在彼此附近,它们的共现值就会更高。
共现矩阵类似于CountVectorizer
,但它不是统计单词单独出现的频次,而是统计单词两两一起出现的频次(如Bigram 搭配频率)。
下面我们来实现它的代码:
(1)导入库
import numpy as np
import nltk
from nltk import bigrams
import itertools
(2)创建共现矩阵函数
def co_occurrence_matrix(corpus):
# 第一步:获取词汇表,去重后转为列表
vocab = set(corpus) # 用 set 去重,得到所有不同的词
vocab = list(vocab) # 再转为列表,后续用来做矩阵索引
# 输出:{'tolearn': 0, 'I': 1, 'is': 2, 'cool': 3, 'love': 4, 'nlp': 5, 'future': 6}
vocab_to_index = {word: i for i, word in enumerate(vocab)}
# 第二步:创建 bigram(相邻两个词的组合)
bi_grams = list(bigrams(corpus)) # nltk 的 bigrams 会返回一个二元组的生成器
# 第三步:统计每个 bigram 的出现频率(也可以理解为共现次数)
bigram_freq = nltk.FreqDist(bi_grams).most_common(len(bi_grams))
# FreqDist 会统计频次,most_common(n) 返回前 n 个常见 bigram
# 第四步:初始化共现矩阵,大小为 词汇表大小 x 词汇表大小
co_occurrence_matrix = np.zeros((len(vocab), len(vocab)))
# 第五步:填充共现矩阵
for bigram in bigram_freq:
current = bigram[0][1] # 当前词(出现在后面)
previous = bigram[0][0] # 上一个词(出现在前面)
count = bigram[1] # 这个 bigram 出现的频数
# 找到两个词在矩阵中对应的行列索引
pos_current = vocab_to_index[current]
pos_previous = vocab_to_index[previous]
# 把频率填到矩阵的对应位置(行:当前词,列:前一个词)
co_occurrence_matrix[pos_current][pos_previous] = count
# 将 numpy 数组转为矩阵格式(可选)
co_occurrence_matrix = np.matrix(co_occurrence_matrix)
# 返回共现矩阵和词到索引的映射
return co_occurrence_matrix, vocab_to_index
(3)生成矩阵
import pandas as pd
sentences = [
['I', 'love', 'nlp'],
['I', 'love', 'tolearn'],
['nlp', 'is', 'future'],
['nlp', 'is', 'cool']
]
# 合并所有单词,输出
# ['I', 'love', 'nlp', 'I', 'love', 'tolearn', 'nlp', 'is', 'future', 'nlp', 'is', 'cool']
merged = list(itertools.chain.from_iterable(sentences))
# 生成共现矩阵
matrix, vocab_to_index = co_occurrence_matrix(merged)
# 创建 DataFrame 输出
CoMatrixFinal = pd.DataFrame(matrix, index=vocab_to_index, columns=vocab_to_index)
print(CoMatrixFinal)
输出:
1.5 Hashing Vectorizer(哈希向量)
当词汇量非常大时,CountVectorizer
或共现矩阵会消耗大量内存和计算资源。
我们可以使用 HashingVectorizer
,它不存储词汇表,而是通过 哈希函数 将每个词映射到固定长度的向量维度。
- 缺点:不可逆,无法还原出原始单词。
下面我们通过代码来理解一下:
(1)导入库并准备文档
from sklearn.feature_extraction.text import HashingVectorizer
text = ["The quick brown fox jumped over the lazy dog."]
(2)生成哈希向量
vectorizer = HashingVectorizer(n_features=10) # 向量维度设置为10
vector = vectorizer.transform(text)
print(vector.shape)
print(vector.toarray())
- 维度为10表示不管你原文中有多少个不同的单词,我们强制把它们映射到一个长度为 10 的向量中(即 10 个“格子”)。即使重复
- 如果多个词“碰巧”映射到同一个维度,就会发生哈希冲突,但通常可以接受。维度设置得越大,哈希冲突越少。
输出:
(1, 10)
[[ 0. 0.57735027 0. 0. 0. 0.
0. -0.57735027 -0.57735027 0. ]]
为什么数值是小数
每个维度的数值是单词通过哈希函数映射后再进行加权(如TF)的结果。默认情况下,HashingVectorizer
不仅告诉你“这个词落在哪个维度(格子)”,还会告诉你:这个词在文本中出现了几次?它在整个句子里占多大比重?这就是所谓的TF(Term Frequency
)加权,即:某词出现次数 ÷ 总词数。
接着,这里默认会进行L2 归一化,即把整行向量标准化为单位长度,以防止某些词出现频率太高而支配一切。
为什么有正负号
在 HashingVectorizer
中,哈希函数的返回值用于确定特征在向量中的位置和符号(正或负)。默认情况下,HashingVectorizer
使用 alternate_sign=True
参数,这意味着哈希函数生成的索引会交替赋予正负号(输出时进行判断,来决定该词对应的特征值是正还是负),以近似保持哈希空间中的内积。这种方法类似于稀疏随机投影,特别适用于特征数量较少的情况(例如 n_features < 10000
)。
如果希望所有特征值为非负,可以将 alternate_sign
参数设置为 False
:
from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer(n_features=10, alternate_sign=False)
1.6 TF-IDF
在前面的⽅法中,常⻅词频率太⾼可能会被⾼估其重要性,⽽ TF-IDF 能纠正这个问题。
使⽤ TF-IDF(Term Frequency – Inverse Document Frequency
)将词语的频率和稀有度结合起来,评估它在⽂档中的重要性。
TF-IDF原理
-
TF(词频):单词在句⼦中出现的次数 ÷ 句⼦总词数
-
IDF(逆⽂档频率):
N
是总⽂档数,n
是包含该词的⽂档数I D F = log ( N n ) IDF = \log\left(\frac{N}{n}\right) IDF=log(nN)
- 某个词在所有文档都出现的时候,说明太常见了,没啥区分度,IDF 趋近于 0;某个词只出现在少数文档,说明比较稀有,可能很关键,IDF 趋近于无穷大。
- 实际在
sklearn
中,这个公式为 IDF ( t ) = log ( 1 + N 1 + n t ) + 1 \text{IDF}(t) = \log\left(\frac{1 + N}{1 + n_t}\right) + 1 IDF(t)=log(1+nt1+N)+1,这是为了避免除 0(如果某词没出现在任何文档中),也避免 log(1) = 0 导致完全归零
-
TF-IDF
:TF × IDF,就是在TF的基础上乘以IDF这个权重。
下面我们来看一下代码:
(1)准备文本数据
Text = [
"The quick brown fox jumped over the lazy dog.",
"The dog.",
"The fox"
]
(2)生成 TF-IDF 特征
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()
vectorizer.fit(Text)
print(vectorizer.vocabulary_)
print(vectorizer.idf_)
输出结果:
{'the': 7, 'quick': 6, 'brown': 0, 'fox': 2, 'jumped': 3, 'over': 5, 'lazy': 4, 'dog': 1}
[1.6931 1.2876 1.2876 1.6931 1.6931 1.6931 1.6931 1.0000]
可以看到,'the'
出现在所有句子中,IDF = 1.0(最低,说明没什么用),而其他词较为稀有,因此 IDF 更高。
1.7 Word Embeddings(词嵌入)
1.7.1 介绍
虽然我们之前学习的所有文本向量化方法(如 One-Hot
、TF-IDF
、CountVectorizer
、Co-occurrence
等)已经能解决大部分 NLP 问题,但它们都存在一个共同的局限:无法捕捉词语的上下文与语义关系
举个例子:
a. I am eating an apple.
b. I am using apple.
在 a 中,“apple” 是 水果,在 b 中,“apple” 是苹果公司。传统方法只知道“apple 出现了”,却无法理解它的含义随上下文改变。
词嵌入(Word Embeddings
) 是一种将词表示为稠密向量(dense vectors
)的方式,目的是:让相似的词在向量空间中彼此靠近,自动学习语义关系
- 每个词用一个实数向量表示(如 100 维、300 维等)
- 向量不仅编码了词的语义,也编码了上下文环境
- 可以使用在分类、聚类、相似度计算、翻译等任务中
它有如下特性:
特性 | 说明 |
---|---|
稠密 | 每个词由多个非零数值表示,不再是稀疏向量 |
语义距离 | 相似含义的词向量距离更近 |
可用训练数据自学习 | 不需手工设定词义规则 |
可用于下游任务 | 可直接作为神经网络输入或用于文本匹配 |
下表为部分词的词向量:
Words | Vectors |
---|---|
text | [0.36, 0.36, -0.43, 0.36] |
idea | [-0.56, -0.56, 0.72, -0.56] |
word | [0.35, -0.43, 0.12, 0.72] |
encode | [0.19, 0.19, 0.19, 0.43] |
document | [-0.43, 0.19, -0.43, 0.43] |
grams | [0.72, -0.43, 0.72, 0.12] |
process | [0.43, 0.72, 0.43, 0.43] |
feature | [0.12, 0.45, 0.12, 0.87] |
这张表说明:
- 每个单词被表示成一个 长度为 4 的向量
- 向量中的数字没有具体“含义”,但整体上可以反映词语之间的语义空间结构
1.7.2 Word2Vec
Word Embeddings 是一种基于预测的模型,通常使用浅层神经网络来训练,最后将学到的权重矩阵当作词向量。
Word2Vec 是什么?
- 由 Google 提出,通过预测词与上下文之间的关系,生成具有语义结构的词向量
- 被广泛用于:文本分类、语义相似度分析和信息检索、推荐系统等应用中
Word2Vec 的两种架构包含:CBOW(Continuous Bag of Words
)和Skip-Gram,下图展示了 CBOW 和 Skip-Gram 两种神经网络结构,它们都是用来训练词嵌入的。
1.7.2.1 Skip-Gram原理
Skip-Gram 是 Google 提出的 Word2Vec 两大核心算法之一。它的目标是:给定一个词,预测它周围的上下文词(对比 CBOW 是反过来的)。
基本原理
每个句子都会被拆解成多个训练样本,每个样本由两部分组成:
- 目标词(Target word):中心词
- 上下文词(Context words):目标词左右若干词
可调参数:
window size
:表示从目标词左右各取多少个词作为上下文(窗口大小越大,模型捕捉到的语义关系越广,但计算量也越大)
例
假设我们有以下文本:
I love NLP and I will learn NLP in 2 months
如果窗口大小设为 2,我们就会从这段文本中生成如下训练对:
片段 | 目标词 | 上下文词 |
---|---|---|
I love NLP | I | love, NLP |
I love NLP and | love | I, NLP, and |
I love NLP and I | NLP | I, love, and, I |
… | … | … |
in 2 months | month | in, 2 |
- 注意:上下文词的数量可能少于窗口设定值,尤其当目标词在句首或句尾时。
Skip-Gram 模型做了什么?
每一对 (目标词, 上下文词)
都会被视为一个训练样本,例如:
(“NLP”, “learn”) → 模型尝试预测 “learn” 是 “NLP” 的上下文
如此一来,模型就会学习到:
- “love” 常和 “NLP” 一起出现
- “I” 常和 “love”、“and” 等出现
- “NLP” 可能表示学习内容,因为和 “learn” 高相关
模型训练
由于 Skip-Gram 需要生成大量的目标-上下文对,因此:
- 训练数据量很大
- 计算资源消耗高
因此通常会先做如下准备:
- 将原始文本切分成句子
- 清洗数据(去除标点符号、数字等)
- 分词 / token 化
然后再用这些句子生成训练样本(target + context 对)用于训练词向量。
1.7.2.2 Skip-Gram代码
我们定义一个小语料库(多句子组成的列表),用于训练词向量模型:
sentences = [
['I', 'love', 'nlp'],
['I', 'will', 'learn', 'nlp', 'in', '2', 'months'],
['nlp', 'is', 'future'],
['nlp', 'saves', 'time', 'and', 'solves', 'lot', 'of', 'industry', 'problems'],
['nlp', 'uses', 'machine', 'learning']
]
(1)导入库并安装 gensim
# !pip uninstall -y numpy
# !pip install numpy==1.23.5
# !pip install --upgrade gensim
from gensim.models import Word2Vec
from sklearn.decomposition import PCA
from matplotlib import pyplot
- Gensim 是一个用于NLP中主题建模和文档相似度计算的开源 Python 库。它的名字来自 “Generate Similarity”。
(2)训练 Skip-Gram 模型
# 训练 Word2Vec 模型(使用 Skip-Gram 架构)
skipgram = Word2Vec(
sentences,
vector_size=50, # 向量维度(每个词用50维表示)
window=3, # 窗口大小(前后各看3个词)
min_count=1, # 最小词频为1(出现1次也保留)
sg=1 # 使用 Skip-Gram 模型(sg=1)
)
print(skipgram)
(3)查看某个词的向量
print(skipgram.wv['nlp'])
输出是一个长度为 50 的向量:
说明:你为词 'nlp'
生成了一个50维的稠密词向量,可以用于后续的相似度计算、聚类、文本分析等。
(4)错误示例:词不在词汇表中
print(skipgram.wv['deep'])
输出错误:
KeyError: "word 'deep' not in vocabulary"
说明:
'deep'
并没有出现在训练语料中- Word2Vec 只能生成在训练数据中实际出现过的词语的词向量
为避免缺词问题,应使用尽可能丰富的语料库进行训练
- 如需处理 OOV(
Out-of-Vocabulary
)词,可通过词形预处理(Stemming或Lemmatization)或改用 TF-IDF(不需要认识它)来绕过问题。
(5)保存与加载模型
# 保存模型
skipgram.save('skipgram.bin')
# 加载模型
skipgram = Word2Vec.load('skipgram.bin')
(6)PCA 可视化词向量
词向量是高维(这里是50维)的,我们通过主成分分析(Principal Component Analysis
, PCA)将其降维到2D,再用 Matplotlib 可视化:
X = skipgram.wv[skipgram.wv.index_to_key] # 获取所有词的向量
pca = PCA(n_components=2)
result = pca.fit_transform(X) # 降维
# 绘制散点图
pyplot.scatter(result[:, 0], result[:, 1])
words = skipgram.wv.index_to_key
for i, word in enumerate(words):
pyplot.annotate(word, xy=(result[i, 0], result[i, 1])) # 添加词标签
pyplot.show()
结果如下图所示:
- 每个点表示一个词
- 相邻的词可能语义相关或上下文共现频繁
- 帮助我们直观理解词向量学习的语义结构
1.7.2.3 Continuous Bag of Words(CBOW)
现在我们看一下如何使用 gensim
库来构建 CBOW(Continuous Bag-of-Words
)模型,以及如何可视化词向量。
from gensim.models import Word2Vec
from sklearn.decomposition import PCA
from matplotlib import pyplot
# 示例句子
sentences = [['I', 'love', 'nlp'],
['I', 'will', 'learn', 'nlp', 'in', '2','months'],
['nlp', 'is', 'future'],
['nlp', 'saves', 'time', 'and', 'solves','lot', 'of', 'industry', 'problems'],
['nlp', 'uses', 'machine', 'learning']]
# 训练 CBOW 模型(注意:sg=1 实际是 Skip-gram,这里应设为 sg=0 才是 CBOW)
cbow = Word2Vec(sentences, vector_size=50, window=3, min_count=1, sg=1)
# 查看某个词的词向量
print(cbow.wv['nlp'])
# 保存与加载模型
cbow.save('cbow.bin')
cbow = Word2Vec.load('cbow.bin')
接下来,我们使用 PCA 对词向量进行降维并可视化:
X = cbow.wv[cbow.wv.index_to_key] # 获取所有词向量
pca = PCA(n_components=2)
result = pca.fit_transform(X)
# 画图展示词的空间分布
pyplot.scatter(result[:, 0], result[:, 1])
words = list(cbow.wv.index_to_key)
for i, word in enumerate(words):
pyplot.annotate(word, xy=(result[i, 0], result[i, 1]))
pyplot.show()
输出:
可视化结果展示了词向量在二维空间中的分布,相近的词语聚集在一起,体现语义相关性。
1.7.2.4 预训练词向量模型
训练高质量的词向量需要海量的计算资源。为此,我们可以直接使用 Google 训练好的 Word2Vec 模型(300维向量,基于 1000 亿词训练):
import gensim
# 加载 Google 训练好的模型
model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
# 计算词语相似度
print(model.similarity('this', 'is')) # 输出:0.4079
print(model.similarity('post', 'book')) # 输出:0.0572
可以看出,“this” 和 “is” 相似度较高,而 “post” 和 “book” 的语义关联较弱。
词向量的更多用法
1.找出不属于同类的词
model.doesnt_match('breakfast cereal dinner lunch'.split())
# 输出:'cereal'
意思是:在这几个词中,‘cereal’ 不属于另外三个的同一类(主餐)。
2.词向量之间的“类比推理”
model.most_similar(positive=['woman', 'king'], negative=['man'])
# 输出:'queen',相似度约为 0.77
即:
king - man + woman ≈ queen
词向量成功捕捉了语义上的关系。
3.T-SNE 可视化示例
现在我们使用 T-SNE 对大规模词向量进行可视化:
可以发现:
- 与电器相关的词会聚集在一起;
- 与卫浴相关的词也会形成自己的聚类;
- 同一语义类的词在向量空间中距离更近。
这正是 词嵌入(Word Embedding) 的魅力:它能让机器从“数学空间”上理解语义关联。
1.8 fastText词嵌入
传统的 Word2Vec 将每个“词”作为最小单位进行嵌入学习。但它存在一个缺点:
对于未在训练集中出现的词(
Out-Of-Vocabulary
, OOV),模型无法给出向量表示。
而fastText(由 Facebook 提出)的改进之处在于:它是以“字符 n-gram”为基础训练词向量,即使遇到新词,也可以通过已有字符组合进行向量预测。
- fastText 更强大的地方在于 对 OOV 词的支持;
- 它能学习字符级别的子结构信息,在处理语言变形(如复数、词缀)方面表现更优;
- 可用于改进文本分类、实体识别、机器翻译等任务中的词表示质量。
模型训练与基本使用
from gensim.models import FastText
from sklearn.decomposition import PCA
from matplotlib import pyplot
# 示例语句
sentences = [['I', 'love', 'nlp'],
['I', 'will', 'learn', 'nlp', 'in', '2','months'],
['nlp', 'is', 'future'],
['nlp', 'saves', 'time', 'and', 'solves', 'lot', 'of', 'industry', 'problems'],
['nlp', 'uses', 'machine', 'learning']]
# 训练 FastText 模型
fast = FastText(
sentences,
vector_size=20, # 每个词的向量维度
window=1, # 上下文窗口大小
min_count=1, # 最小词频
workers=5, # 多线程数
min_n=1, # 最小 n-gram 字符长度
max_n=2 # 最大 n-gram 字符长度
)
查看词向量:
print(fast.wv['nlp']) # 输出 'nlp' 的向量
print(fast.wv['deep']) # 输出 'deep' 的向量(注意该词不在训练集中)
结果中 deep
词虽然不在训练数据中,但 fastText 仍然能为它生成向量,这是因为它基于字符组合(如 ‘de’, ‘eep’ 等)进行嵌入。这正是 fastText 的强大之处。
保存与加载模型:
fast.save('fast.bin') # 保存模型
fast = FastText.load('fast.bin') # 加载模型
可视化词向量(使用 PCA 降维)
X = fast.wv[fast.wv.index_to_key] # 获取所有词向量
pca = PCA(n_components=2)
result = pca.fit_transform(X)
# 绘制二维投影图
pyplot.scatter(result[:, 0], result[:, 1])
words = list(fast.wv.index_to_key)
for i, word in enumerate(words):
pyplot.annotate(word, xy=(result[i, 0], result[i, 1]))
pyplot.show()
输出如下:
2 总结
现在我们已经掌握了从 Word2Vec 到 fastText 的实现与使用方式,下一步可以基于这些词嵌入结果,构建面向实际业务的自然语言处理应用。