实战NLP:文本数据处理到词向量的转化

本文将探讨自然语言处理的实践应用,涵盖从原始文本数据的预处理到词向量表示的转化的整个流程。我们将通过Python和相关库(如NLTK, scikit-learn, Gensim)逐步演示如何对文本数据进行清洗、分词,以及应用N-Grams、TF-IDF、余弦相似度、K-Means聚类、LDA主题建模和Word2Vec模型等核心NLP技术。

import nltk
import numpy as np
import pandas as pd
import re
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import KMeans
from sklearn.decomposition import LatentDirichletAllocation
from gensim.models import word2vec

# 加载英文的停用词列表
stop_words = nltk.corpus.stopwords.words('english')

# 创建一个词和标点符号的分词器
wpt = nltk.WordPunctTokenizer()

# 定义文档语料库
corpus = [
    'The sun is blazing and the air is dry',
    'The snow is thick, covering the mountains',
    'Clouds gather, promising a heavy rain soon',
    'Winds howl through the empty streets at night',
    'Morning frost blankets the green fields',
    'A lion roars under the blazing sun',
    'A thick-furred bear roams snowy mountains',
    'Birds sing before the rain, atop the city trees',
    'Wolves howl, echoing through the forest',
    'Deer graze as morning frost melts around them'
]

# 定义每个文档对应的类别标签
labels = ['weather', 'weather', 'weather', 'weather', 'weather', 'animals', 'animals', 'animals', 'animals', 'animals']

# 将文档列表转换为NumPy数组
corpus = np.array(corpus)

# 创建一个包含文档及其类别标签的DataFrame
corpus_df = pd.DataFrame({'Document': corpus, 'Category': labels})

# 定义文档预处理函数
def normalizedoc(doc):
    # 使用正则表达式删除非字母数字字符
    doc = re.sub(r'[^a-zA-Z0-9\s]', '', doc, flags=re.I)
    # 转换为小写
    doc = doc.lower()
    # 去除首尾空白
    doc = doc.strip()
    # 分词
    tokens = wpt.tokenize(doc)
    # 过滤掉停用词
    filtered_tokens = [token for token in tokens if token not in stop_words]
    # 重新组合为文档字符串
    doc = ' '.join(filtered_tokens)
    return doc

# 使用np.vectorize函数向量化预处理函数,以便一次性处理整个数组
normalize_corpus = np.vectorize(normalizedoc)

# 对语料库中的每个文档应用预处理
normcorpus = normalize_corpus(corpus)

# N-Grams模型
bv = CountVectorizer(ngram_range=(2,2))     # ngram_range=(2,2)表示只考虑二元词组,用于捕获相邻单词的关系
bv_matrix = bv.fit_transform(normcorpus)
bv_matrix = bv_matrix.toarray()
vocab = bv.get_feature_names_out()
pd.set_option('display.max_columns', None)  # 设置显示最大列数为无限
pd.DataFrame(bv_matrix, columns = vocab)

# TF-IDF模型
tv = TfidfVectorizer(min_df=0, max_df=5, use_idf=True)  # 将文档集合转换为TF-IDF特征矩阵
tv_matrix = tv.fit_transform(normcorpus)
tv_matrix = tv_matrix.toarray()
vocab = tv.get_feature_names_out()
pd.DataFrame(np.round(tv_matrix, 2), columns = vocab)

# Similarity特征
similarity_matrix = cosine_similarity(tv_matrix)    # 计算两个或多个文档之间的余弦相似度
similarity_df = pd.DataFrame(similarity_matrix)
similarity_df

# 聚类特征
km = KMeans(n_clusters = 2)
km.fit_transform(similarity_df)
cluster_labels = km.labels_
cluster_labels = pd.DataFrame(cluster_labels, columns = ['ClusterLabel'])
pd.concat([corpus_df, cluster_labels], axis = 1)

# LDA主题模型
lda = LatentDirichletAllocation(n_components=2, n_jobs=2, max_iter=100, random_state=42) # # n_components=2表示提取的主题数量,max_iter=100表示迭代次数,n_jobs=2表示并行运行的作业数量,random_state用于随机数生成器
dt_matrix = lda.fit_transform(tv_matrix)
features = pd.DataFrame(dt_matrix, columns=['T1', 'T2'])
features

# 词向量模型
wpt = nltk.WordPunctTokenizer()
tokenized_corpus = [wpt.tokenize(document) for document in normcorpus]
feature_size = 10           # 词向量的维度
window_context = 10         # 上下文窗口大小
min_word_count = 1          # 忽略总频率低于此值的所有单词
sample = 1e-3               # 对高频词进行下采样的配置阈值

w2v_model = word2vec.Word2Vec(tokenized_corpus, vector_size=10,
                              window=window_context, min_count=min_word_count,
                              sample=sample)

w2v_model.wv['sun']
# array([-0.01577653,  0.00321372, -0.0414063 , -0.07682689, -0.01508008,
#         0.02469795, -0.00888027,  0.05533662, -0.02742977,  0.02260065],
#       dtype=float32)
# 这个数组是单词'sun'在模型中的词向量表示,每个数字对应词向量空间中的一个维度。
# 由于设置的feature_size为10,因此这个向量有10个维度。这个向量可以用来在
# 词向量空间中表示'sun',用于计算词语之间的相似度、寻找同义词等NLP任务。

def average_word_vectors(words, model, vocabulary, num_features):
    """
    功能:计算给定单词列表的平均词向量。
    参数:
    - words: 单词列表。
    - model: 训练好的Word2Vec模型。
    - vocabulary: 模型词汇表。
    - num_features: 词向量的维度。
    
    返回值:给定单词列表的平均词向量。
    """
    feature_vector = np.zeros((num_features,), dtype='float64')
    nwords = 0
    
    for word in words:
        if word in vocabulary:
            nwords += 1
            feature_vector = np.add(feature_vector, model.wv[word])
    
    if nwords:
        feature_vector = np.divide(feature_vector, nwords)
    
    return feature_vector

def average_word_vectorizer(corpus, model, num_features):
    """
    功能:为整个语料库计算平均词向量。
    参数:
    - corpus: 分词后的语料库,每个元素是单词列表。
    - model: 训练好的Word2Vec模型。
    - num_features: 词向量的维度。
    
    返回值:整个语料库的平均词向量数组。
    """
    vocabulary = set(model.wv.index_to_key)
    features = [average_word_vectors(tokenized_sentence, model, vocabulary, num_features)
                for tokenized_sentence in corpus]
    return np.array(features)

# 使用average_word_vectorizer函数计算语料库的平均词向量,并将结果转换为DataFrame
w2v_feature_array = average_word_vectorizer(corpus=tokenized_corpus, model=w2v_model, num_features=feature_size)
pd.DataFrame(w2v_feature_array)

# 输出结果(Out[18])示例:
# 0        1        2        3        4        5        6        7        8        9
# 0  0.002978  0.013262  0.012789 -0.018555  0.050005  0.000842 -0.000868  0.059669 -0.067598 -0.001516
# ...
# 9 -0.010244 -0.020123 -0.020692  0.016608 -0.004070 -0.016828  0.049279  0.033294 -0.028813 -0.020145

"""
输出结果说明:每行代表语料库中一个文档(或句子)的平均词向量。每列代表词向量的一个维度。
例如,第一行的词向量是第一个文档的平均词向量,由10个维度组成。
这些平均词向量可以用于文档的向量表示,适用于后续的机器学习或文本分析任务。
"""  

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值