文章目录
在自然语言处理中,文本向量化(Text Embedding)是很重要的一环,是将文本数据转换成向量表示,包括词、句子、文档级别的文本,深度学习向量表征就是通过算法将数据转换成计算机可处理的数字化形式。
概念
参考文章(转载):大模型开发 - 一文搞懂Embedding工作原理;
从不同文本级别出发,文本向量化包含以下方法:
-
词级别向量化:将单个词汇转换成数值向量
-
独热编码(One-Hot Encoding):为每个词分配一个唯一的二进制向量,其中只有一个位置是1,其余位置是0。
-
TF-IDF:通过统计词频和逆文档频率来生成词向量或文档向量。
-
N-gram:基于统计的n个连续词的频率来生成向量。
-
词嵌入(Word Embeddings):如Word2Vec, GloVe, FastText等,将每个词映射到一个高维实数向量,这些向量在语义上是相关的。
-
-
句子向量化:将整个句子转换为一个数值向量。
- 简单平均/加权平均:对句子中的词向量进行平均或根据词频进行加权平均。
- 递归神经网络(RNN):通过递归地处理句子中的每个词来生成句子表示。
- 卷积神经网络(CNN):使用卷积层来捕捉句子中的局部特征,然后生成句子表示。
- 自注意力机制(如Transformer):如BERT模型,通过对句子中的每个词进行自注意力计算来生成句子表示;再比如现在的大模型,很多都会有对应的训练好的tokenizer,直接采用对应的tokenizer进行文本向量化。
-
文档向量化:将整个文档(如一篇文章或一组句子)转换为一个数值向量。
- 简单平均/加权平均:对文档中的句子向量进行平均或加权平均。
- 文档主题模型(如LDA):通过捕捉文档中的主题分布来生成文档表示。
- 层次化模型:如Doc2Vec,它扩展了Word2Vec,可以生成整个文档的向量表示。
代码实战
经典向量化模型
参考链接(转载):NLP-(1)-文本向量化;
One-Hot编码
又称独热编码,将每个词表示成具有n个元素的向量,这个词向量中只有一个元素是1,其他元素都是0,不同词汇元素为0的位置不同,其中n的大小是整个语料中不同词汇的总数。One-Hot编码的缺点是完全割裂了词与词之间的联系,而且在大语料集下,每个向量的长度过大,且较为稀疏,占据大量内存。
# 导入keras中的词汇映射器Tokenizer
from tensorflow.keras.preprocessing.text import Tokenizer
# 假定vocab为语料集所有不同词汇集合
vocab = {
"我", "爱", "北京", "天安门", "升国旗"}
# 实例化一个词汇映射器对象
t = Tokenizer(num_words=None, char_level=False)
# 使用映射器拟合现有文本数据
t.fit_on_texts(vocab)
for token in vocab:
zero_list = [0]*len(vocab)
# 使用映射器转化现有文本数据, 每个词汇对应从1开始的自然数
# 返回样式如: [[2]], 取出其中的数字需要使用[0][0]
token_index = t.texts_to_sequences([token])[0][0] - 1
zero_list[token_index] = 1
print(token, "的one-hot编码为:", zero_list)
词袋模型(Bag Of Words,BOW)
词袋是指把一篇文章进行词汇的整理,然后统计每个词汇出现的次数,由前几名的词汇猜测全文大意。具体做法包括:
分词:将整篇文章中的每个词汇切开,整理成生字表或字典。英文一般以空白或者句点隔开,中文需要通过特殊的方法进行处理如jieba等。
前置处理:先将词汇做词性还原,转换成小写。词性还原和转换小写都是为了避免,词汇统计出现分歧。
去除停用词:be动词、助动词、介词、冠词等不具有特殊意义的词汇称为停用词在文章中是大量存在的,需要将它们剔除,否则统计结果都是这些词汇。
词频统计:计算每个词汇在文章中出现的次数,由高到低进行排序。
# coding=utf-8
import collections
stop_words = ['\n', 'or', 'are', 'they', 'i', 'some', 'by', '—',
'even', 'the', 'to', 'a', 'and', 'of', 'in', 'on', 'for',
'that', 'with', 'is', 'as', 'could', 'its', 'this', 'other',
'an', 'have', 'more', 'at', "don’t", 'can', 'only', 'most']
maxlen = 1000
word_freqs = collections.Counter()
# word_freqs = {}
# print(word_freqs)
with open('../data/NLP_data/news.txt', 'r+', encoding='utf8') as f:
for line in f:
words = line.lower().split(' ')
if len(words) > maxlen:
maxlen = len(words)
for word in words:
if not (word in stop_words):
word_freqs[word] += 1
# 词频统计
# count = word_freqs.get(word, 0)
# print(count)
# word_freqs[word] = count + 1
# print(word_freqs)
print(word_freqs.most_common(20))
# 按照字典的value进行排序
# a1 = sorted(word_freqs.items(), key=lambda x: x[1], reverse=True)
# print(a1[:20])
"""
[('stores', 15), ('convenience', 14), ('korean', 6), ('these', 6), ('one', 6), ('it’s', 6), ('from', 5), ('my', 5), ('you', 5), ('their', 5), ('just', 5), ('has', 5), ('new', 4), ('do', 4), ('also', 4), ('which', 4), ('find', 4), ('would', 4), ('like', 4), ('up', 4)]
"""
TF-IDF
BOW方法十分简单,效果也不错,不过他有个缺点,有些词汇不是停用词,但是在文章中经常出现,但对全文并不重要,比如only、most等,对猜测全文大意没有太多的帮助,所以提出了改良算法tf-idf,他会针对跨文件常出现的词汇给与较低的分数,如only在每一个文件中都出现过,那么tf-idf对他的评分就会很低。
# TF-IDF匹配问答对
# coding=utf-8
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
import numpy as np
corpus = [
'This is the first document.',
'This is the second document.',
'And the third document.',
'Is this the first document?'
]
vectorizer = CountVectorizer()
x = vectorizer.fit_transform(corpus)
word = vectorizer.get_feature_names()
print('Vocabulary:', word)
print(x.toarray())
# TF-IDF转换
transfomers = TfidfTransformer()
tfidf = transfomers.fit_transform(x)
print(np.around(tfidf.toarray(), 4))
from sklearn.metrics.pairwise import cosine_similarity
# 比较最后一句与其他句子的相似度
print</