常见的文本特征(句向量)提取方法有哪些?什么是One-Hot、TF-IDF?word2vec如何训练?【Python】

文本特征提取的方法目前已经有很多种,传统的提取方法有平权统计、TF-IDF等,神经网络的方法有word2vec,接下来我会具体对这三种方法进行介绍,以及如何用代码实现。

本文全程干货 ,建议收藏。

One-Hot
One-Hot编码,又称独热编码,从提取方法来看也可以叫平权统计,非常容易理解,参见下述代码。

# 特征向量化——稀疏表示
from sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer()
corpus = ['This is the first document.',
          'This is the second document.',
          'And the third one',
          'Is this the first document?'
          ]
"""
this is the first document second third and one
排序:
        and document first is one second the third this
    1    0      1      1    1  0    0     1    0     1
    2    0      1      0    1  0    1     1    0     1
    3    1      0      0    0  1    0     1    1     0
    4    0      1      1    1  0    0     1    0     1
"""
X = vectorizer.fit_transform(corpus)
print(X)

上述代码中corpus这个list共有四句话,平权统计就是先统计好一共有哪些词(会统一小写化),像上文就一共有9个词,同时调用CountVectorizer时会对词库进行排序,如上所示。接着就是生成每一句的特征,这句话中出现了哪个词,就在对应的地方标1,其他地方就标0。

最终这个X就是我们提取到的文本特征啦。

另外,如果想要降低特征的稀疏性的话,可以使用CountVectorizer(min_df=2),这里min_df=2代表着只有频数(出现次数)超过2的词才会被记录。

注意,中文的话要事先分好词,即按空格分好。

TF-IDF

顾名思义,平权统计对于每一个词都一视同仁,但现实生活中我们都知道不同词语在句子中的重要性是不一样的,也就是说词与词之间的重要性不同。

TF-IDF(Term Frequency/Inverse Document Frequency)是信息检索领域非常重要的搜索词重要性度量;用以衡量一个关键词w对于查询(Query,可看作文档)所能提供的信息。

词频(Term Frequency, TF)表示关键词w在文档Di中出现的频率:
在这里插入图片描述
其中,count(w)为关键词w的出现次数,|Di|为文档Di中所有词的数量。

逆文档频率(Inverse Document Frequency, IDF)反映关键词的普遍程度——当一个词越普遍(即有大量文档包含这个词)时,其IDF值越低;反之,则IDF值越高。IDF定义如下:
在这里插入图片描述
其中,N为所有的文档总数,I(w,Di)表示文档Di是否包含关键词,若包含则为1,若不包含则为0。若词w在所有文档中均未出现,则IDF公式中的分母为0;因此需要对IDF做平滑(smooth):
在这里插入图片描述
最终关键词w在文档Di的TF-IDF值:
在这里插入图片描述
还是用上面那个例子:

from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer()
corpus = ['This is the first document.',
          'This is the second document.',
          'And the third one',
          'Is this the first document?'
          ]

X = vectorizer.fit_transform(corpus)
print(X)

其中,X[0]即为第一句话的文本特征,X[1]即为第二句话的文本特征…

同样的,我们也可以用min_df这个参数来除去低频词。

word2vec
在这里插入图片描述

Word2vec,是一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系,该向量为神经网络之隐藏层。

通过Word2Vec算法得到每个词语的高维向量(词向量,Word Embedding)表示,词向量把相近意思的词语放在相近的位置。我们只需要有大量的某语言的语料,就可以用它来训练模型,获得词向量。(建议语料库的文本内容要和自己后面做的任务涉及的领域相同或相似,且语料库要足够大)

第一步:将one-hot形式的词向量输入到单层神经网络中,其中输入层的神经元结点个数应该和one-hot形式的词向量维数相对应。比如,输入词是“夏天”,它对应的one-hot词向量[0,0,1],那么,我们设置输入层的神经元个数就应该是3。
第二步:通过神经网络中的映射层中的激活函数,计算目标单词与其他词汇的关联概率,其中在计算时,使用了负采样(negative sampling)的方式来提高其训练速度和正确率。
第三步:通过使用随机梯度下降(SGD)的优化算法计算损失。
第四步:通过反向传播算法将神经元的各个权重和偏置进行更新。

那么怎么利用语料库来训练word2vec呢?

下面我们来实战演练一下。

假设我们现在已经有了一个语料库.txt,内容如下:
在这里插入图片描述

import jieba

import multiprocessing
from gensim.models.word2vec import Word2Vec

with open('./语料库.txt', 'r', encoding='utf-8') as f:
    corpus = f.readlines()

vocab = []  
# 分词
for line in corpus:
    seg = jieba.lcut(line)
    vocab.append(seg)

cpu_count = multiprocessing.cpu_count()
vocab_dim = 100 # 词向量对应的维度
n_iterations = 1
n_exposures = 10  # 所有频数超过10的词语
window_size = 7

model = Word2Vec(size=vocab_dim,
                     min_count=n_exposures,
                     window=window_size,
                     workers=cpu_count,
                     iter=n_iterations)
model.build_vocab(vocab)  # input: list
model.train(vocab, total_examples=model.corpus_count, epochs=model.iter)
model.save('./w2v.pkl')
# print('加载word2vec模型')
# model = Word2Vec.load('./w2v.pkl')
print(model['舆情'])

如果是英文的话,除了前面的分词不一样,其余部分也是同样的步骤。

其中vocab_dim为词向量对应的维度,一般选100-200之间。

到现在呢,我们已经能够提取每个词的特征了,但是我们的任务是针对句子进行分类或者回归,对象是句子而非词语,所以我们需要进一步得到句子的特征。

我们用到的是求平均的方法,即通过将句子中出现的词的词向量的相加之后,再除以词的数量,得到句子的特征,这种方法简单,容易实现,但确实不可避免会忽视掉句子的语序信息。(但效果也不见得就比较差)

具体举例如下:

import numpy as np
import jieba

# 直接词向量相加求平均
def fea_sentence(list_w):
    n0 = np.array([0. for i in range(vocab_dim)], dtype=np.float32)
    for i in list_w:
        n0 += i
    fe = n0 / len(list_w)
    fe = fe.tolist()
    return fe

def parse(data, word2vec):
    xVec = []
    for x in data:
        sentence = []
        for word in x:
            if word in word2vec:
                sentence.append(word2vec[word])
            else:  # 词不存在,则补零向量。
                sentence.append([0. for i in range(vocab_dim)])
        xVec.append(fea_sentence(sentence))

    xVec = np.array(xVec)

    return xVec

if __name__ == '__main__':
	texts = ['如果是英文的话,除了前面的分词不一样,其余部分也是同样的步骤。',
        '其中vocab_dim为词向量对应的维度,一般选100-200之间。',
        '到现在呢,我们已经能够提取每个词的特征了,但是我们的任务是针对句子进行分类或者回归,对象是句子而非词语,所以我们需要进一步得到句子的特征。',
        '我们用到的是求平均的方法,即通过将句子中出现的词的词向量的相加之后,再除以词的数量,得到句子的特征.'
        ]

	data = []
	for sentence in texts:
    	seg = jieba.lcut(sentence)
    	data.append(seg)
    print('加载word2vec模型')
	model = Word2Vec.load('./w2v.pkl')
    xVec = parse(data, model)

此时,xVec[0]即为第一句话的文本特征,xVec[1]即为第二句话的文本特征……


推荐关注的专栏

👨‍👩‍👦‍👦 机器学习:分享机器学习理论基础和常用模型讲解
👨‍👩‍👦‍👦 数据分析:分享数据分析实战项目和常用技能整理


关注我,了解更多相关知识!

CSDN@报告,今天也有好好学习

  • 32
    点赞
  • 153
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
好的,这是一个关于Python文本预处理的问题,我可以回答。以下是一些示例代码,展示如何使用Python进行文本分词、停用词处理和文本向量化: # 导入所需的库 import jieba from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer from gensim.models.word2vec import Word2Vec # 正例和反例的文本数据 positive_texts = ["这个产品真是太棒了!", "我喜欢这个东西的颜色和外观。", "这家餐厅的服务很好,菜品也很美味。", "我很满意这次旅行的住宿条件。", "这本书写得非常好,推荐给大家。", "这个电影非常值得一看。", "我觉得这个游戏还可以,但还有待提升。", "这种汽车的性能非常出色。", "这个新闻报道非常准确,我对新闻媒体充满信心。", "我喜欢这个设计的简洁和实用。"] negative_texts = ["这个产品很差,根本没什么用。", "这个东西的质量很差,很快就坏了。", "这家餐厅的服务态度很差,菜品也不好吃。", "这次旅行的住宿条件很糟糕,让人很不满意。", "这本书很烂,不建议大家看。", "这个电影很差,浪费时间和金钱。", "这个游戏太难了,不好玩。", "这种汽车的性能不如其他同类车型。", "这个新闻报道有很多错误和不实之处,让人很失望。", "这个设计很糟糕,不方便使用。"] # 对每个文本进行分词 positive_texts_list = [jieba.lcut(text) for text in positive_texts] negative_texts_list = [jieba.lcut(text) for text in negative_texts] # 加载停用词 with open("stopwords.txt", "r", encoding="utf-8") as f: stopwords = [line.strip() for line in f] # 对每个文本进行停用词处理 positive_texts_list = [[word for word in text if word not in stopwords] for text in positive_texts_list] negative_texts_list = [[word for word in text if word not in stopwords] for text in negative_texts_list] # 使用CountVectorizer对文本进行向量化 count_vectorizer = CountVectorizer() positive_texts_vectors = count_vectorizer.fit_transform([" ".join(text) for text in positive_texts_list]) negative_texts_vectors = count_vectorizer.transform([" ".join(text) for text in negative_texts_list]) # 使用TfidfVectorizer对文本进行向量化 tfidf_vectorizer = TfidfVectorizer() positive_texts_vectors = tfidf_vectorizer.fit_transform([" ".join(text) for text in positive_texts_list]) negative_texts_vectors = tfidf_vectorizer.transform([" ".join(text) for text in negative_texts_list]) # 使用Word2Vec文本进行向量word2vec_model = Word2Vec(positive_texts_list+negative_texts_list, size=100, window=5, min_count=1, workers=4) positive_texts_vectors = [sum([word2vec_model.wv[word] for word in text])/len(text) for text in positive_texts_list] negative_texts_vectors = [sum([word2vec_model.wv[word] for word in text])/len(text) for text in negative_texts_list] 请注意,以上代码只是示例,你需要根据你的具体需求进行修改和优化。另外,请不要忘记对你的文本数据进行清洗和预处理,例如去除HTML标签、转换大小写、替换缩写词等。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

报告,今天也有好好学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值