NLP基础(4):常见NLP处理任务的实现

在自然语言处理领域,我们经常会接触到各种基础任务,这些任务不仅构成了语言智能系统的底层能力,也在实际应用中扮演着关键角色。本文将介绍NLP中最常见的11个基础任务,涵盖从文本处理(如名词短语提取、情感分析、主题建模)到语音和语义相关的实用应用(如语音转文本、文本转语音、语音翻译)等内容。

1 提取名词短语

名词短语的提取对于分析句子中的“谁”或“什么”非常有帮助。这里使用Spacy库来提取名词短语。

代码:

import spacy

# 加载英文模型
nlp = spacy.load("en_core_web_sm")

# 输入文本
doc = nlp("John is learning natural language processing")

# 提取名词短语(noun chunks)
for np in doc.noun_chunks:
    print(np.text)

输出如下:

在这里插入图片描述

2 计算文本相似度

假设我们希望比较两段文本或文档的相似度。可以使用以下相似度算法:

  • 余弦相似度(Cosine Similarity):计算两个向量夹角的余弦值。
  • Jaccard 相似度:计算两个集合交集与并集的比例。
  • Levenshtein 距离:将字符串 A 转换为 B 所需的最小编辑次数。
  • Hamming 距离:比较两个等长字符串中不同字符的位置数。
  • 语音匹配(Phonetic Matching):比较词语在发音层面上的相似度,例如 Soundex 算法。

余弦相似度例子

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# 文本数据
documents = (
    "I like NLP",
    "I am exploring NLP",
    "I am a beginner in NLP",
    "I want to learn NLP",
    "I like advanced NLP"
)

# TF-IDF 向量化
tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform(documents)

# 计算第一句话与其他句子的相似度
similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix)
print(similarity)

输出如下:

[[1.         0.17682765 0.14284054 0.13489366 0.68374784]]

第一句与最后一句(都包含 “like NLP”)的相似度最高。

3 词性标注

现在我们希望为句子中的每个单词标注其词性(Part-of-Speech Tagging),如名词、动词、形容词等。

词性标注方法主要包括:

  • 规则式(Rule-based):基于人工制定的规则进行标注。
  • 统计式(Stochastic-based):基于词序列概率建模,如使用隐马尔可夫模型(HMM)。

例子(使用Spacy)

import spacy
from spacy.lang.en.stop_words import STOP_WORDS

# 加载英文模型
nlp = spacy.load("en_core_web_sm")

# 示例文本
text = "I love NLP and I will learn NLP in 2 month"

# 分句 + 分词 + 去除停用词 + 词性标注
doc = nlp(text)

for sent in doc.sents:
    print(f"Sentence: {sent.text}")
    tokens = [token for token in sent if token.text.lower() not in STOP_WORDS]
    tagged = [(token.text, token.pos_) for token in tokens]
    print(tagged)

输出如下:

Sentence: I love NLP and I will learn NLP in 2 month
[('love', 'VERB'), ('NLP', 'PROPN'), ('learn', 'VERB'), ('NLP', 'PROPN'), ('2', 'NUM'), ('month', 'NOUN')]

PROPN = Proper Noun

4 从文本中提取实体

现在我们要识别文本中的命名实体,如人名、组织、地点等。

这里我们使用 NLTK 和 spaCy为例进行介绍:

使用NLTK

import nltk
from nltk import ne_chunk, word_tokenize, pos_tag
nltk.download('maxent_ne_chunker_tab')
nltk.download('words')

sent = "John is studying at Stanford University in California"
tree = ne_chunk(pos_tag(word_tokenize(sent)), binary=False)
print(tree)

输出如下:

在这里插入图片描述

使用Spacy(推荐)

import spacy
nlp = spacy.load('en_core_web_sm')

doc = nlp("Apple is ready to launch new phone worth $10000 in New York time square")
for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)

输出如下:

在这里插入图片描述

实体标签含义示例
ORGOrganization(组织)Apple、Google、UN 等
MONEY金额/货币10000(美元、人民币等)
GPEGeo-Political Entity(地理-政治实体)New York、China、EU 等

5 从文本中提取主题

使用 gensim 库结合 LDA(Latent Dirichlet Allocation)模型来完成主题建模。从而从多个文档中自动识别出主要主题关键词,以实现文档聚类或内容分类。

Step 1:准备文本数据

doc1 = "I am learning NLP, it is very interesting and exciting. it includes machine learning and deep learning"
doc2 = "My father is a data scientist and he is nlp expert"
doc3 = "My sister has good exposure into android development"
doc_complete = [doc1, doc2, doc3]

Step 2:文本清洗与预处理

# 导入所需模块
from nltk.corpus import stopwords              # 停用词库
from nltk.stem.wordnet import WordNetLemmatizer # 词形还原器
import nltk
import string                                  # 包含所有标点符号

# 下载 NLTK 中的停用词和词形还原资源
nltk.download('stopwords')
nltk.download('wordnet')

# 设置停用词集合(英文)
stop = set(stopwords.words('english'))

# 设置标点符号集合
exclude = set(string.punctuation)

# 初始化词形还原器
lemma = WordNetLemmatizer()

# 文本清洗函数
def clean(doc):
    # 1. 小写化并移除停用词
    stop_free = " ".join([i for i in doc.lower().split() if i not in stop])
    
    # 2. 移除标点符号
    punc_free = "".join(ch for ch in stop_free if ch not in exclude)
    
    # 3. 对每个词做词形还原(如将 "cars" 变为 "car")
    normalized = " ".join(lemma.lemmatize(word) for word in punc_free.split())
    
    return normalized

# 对一组文档进行清洗处理,返回的是词列表的列表
doc_clean = [clean(doc).split() for doc in doc_complete]

Step 3:构建词典与文档-词频矩阵

# !pip uninstall -y numpy
# !pip install numpy==1.23.5
# !pip install --upgrade gensim
import gensim
from gensim import corpora

# 使用 gensim 的 Dictionary 对象构建词典(即将词映射为 id)
dictionary = corpora.Dictionary(doc_clean)

# 将清洗后的文档转换为词袋(Bag-of-Words)表示形式
# 每个文档表示为 (单词id, 出现次数) 的列表
doc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean]

Step 4:训练LDA模型

# 指定 LDA 模型类
Lda = gensim.models.ldamodel.LdaModel

# 创建并训练 LDA 模型
# 参数说明:
# - doc_term_matrix: 输入的词袋数据
# - num_topics=3: 希望模型识别出 3 个主题
# - id2word=dictionary: 映射词 id 到词本身(用于输出)
# - passes=50: 对整个语料重复训练 50 次,提升模型效果
ldamodel = Lda(doc_term_matrix, num_topics=3, id2word=dictionary, passes=50)

# 输出每个主题及其关键词分布
for topic in ldamodel.print_topics():
    print(topic)

输出如下:

(0, '0.129*"sister" + 0.129*"good" + 0.129*"exposure" + 0.129*"development" + 0.129*"android" + 0.032*"nlp" + 0.032*"father" + 0.032*"scientist" + 0.032*"data" + 0.032*"expert"')
(1, '0.233*"learning" + 0.093*"deep" + 0.093*"includes" + 0.093*"interesting" + 0.093*"machine" + 0.093*"exciting" + 0.093*"nlp" + 0.023*"scientist" + 0.023*"data" + 0.023*"expert"')
(2, '0.129*"nlp" + 0.129*"father" + 0.129*"data" + 0.129*"expert" + 0.129*"scientist" + 0.032*"exposure" + 0.032*"good" + 0.032*"development" + 0.032*"android" + 0.032*"sister"')

输出的格式为:

(主题编号, '关键词1权重*"关键词1" + 关键词2权重*"关键词2" + ...')

以第一个输出为例,这表示:

  • 这个主题的关键词以 “learning” 为核心(权重最高 0.173)
  • 其他关键词也较为重要,例如 “deep”、“machine”、“exciting”
  • 它很可能代表一个“学习/技术/课程”相关的主题

6 文本分类

现在我们希望将文本自动分类,比如垃圾邮件识别、情感分类等,我们可以使用 TF-IDF 特征提取 + Naive Bayes 或 Logistic Regression 模型完成分类。

Step 1:加载并清洗数据

import pandas as pd
Email_Data = pd.read_csv("spam.csv", encoding='latin1')
Email_Data = Email_Data[['v1', 'v2']].rename(columns={"v1": "Target", "v2": "Email"})

Step 2:预处理文本

from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from textblob import Word

# 第一步:将所有文本转换为小写(避免同一个词因大小写不同被分开处理)
Email_Data['Email'] = Email_Data['Email'].apply(lambda x: " ".join(x.lower() for x in x.split()))

# 第二步:去除英文停用词(如:the, is, and 等无实际意义的常见词)
stop = stopwords.words('english')
Email_Data['Email'] = Email_Data['Email'].apply(lambda x: " ".join(x for x in x.split() if x not in stop))

# 第三步:进行词干提取(将单词还原为基础形式,如 running → run)
st = PorterStemmer()
Email_Data['Email'] = Email_Data['Email'].apply(lambda x: " ".join([st.stem(word) for word in x.split()]))

# 第四步:词形还原(lemmatization),进一步标准化词形,如 better → good
Email_Data['Email'] = Email_Data['Email'].apply(lambda x: " ".join([Word(word).lemmatize() for word in x.split()]))

Step 3:构建特征并划分训练集

from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn import preprocessing

# 将数据集按 75% 训练 / 25% 验证 的比例进行划分
# Email_Data['Email'] 为文本,Email_Data['Target'] 为对应标签
train_x, valid_x, train_y, valid_y = train_test_split(Email_Data['Email'], Email_Data['Target'])

# 初始化标签编码器,将分类标签从字符串转为整数(如 spam → 1, ham → 0)
encoder = preprocessing.LabelEncoder()
train_y = encoder.fit_transform(train_y)  # 拟合并转换训练标签
valid_y = encoder.transform(valid_y)      # 对验证标签进行相同的转换

# 初始化 TF-IDF 向量器
# 参数含义:
# - analyzer='word': 按词(而非字母或短语)划分
# - token_pattern=r'\w{1,}': 匹配长度 ≥1 的词
# - max_features=5000: 只保留最常见的前 5000 个词
tfidf_vect = TfidfVectorizer(analyzer='word', token_pattern=r'\w{1,}', max_features=5000)

# 用整个文本语料拟合 TF-IDF 词表(计算 IDF)
tfidf_vect.fit(Email_Data['Email'])

# 将训练集文本转换为 TF-IDF 特征矩阵
xtrain_tfidf = tfidf_vect.transform(train_x)

# 将验证集文本转换为 TF-IDF 特征矩阵
xvalid_tfidf = tfidf_vect.transform(valid_x)

Step 4:训练模型并评估

# 导入朴素贝叶斯、逻辑回归模型,以及评价指标模块
from sklearn import naive_bayes, linear_model, metrics

# 定义通用的模型训练函数
def train_model(classifier, feature_vector_train, label, feature_vector_valid):
    # 用训练集特征和标签拟合模型
    classifier.fit(feature_vector_train, label)
    
    # 使用训练好的模型对验证集进行预测
    predictions = classifier.predict(feature_vector_valid)
    
    # 计算并返回验证集上的准确率
    return metrics.accuracy_score(predictions, valid_y)

# ---------- 使用模型1:朴素贝叶斯 ----------
# 使用 Multinomial Naive Bayes(多项式朴素贝叶斯)模型进行训练
# alpha=0.2 是平滑系数,用于防止某些词在训练集中出现频率为0
nb_acc = train_model(
    naive_bayes.MultinomialNB(alpha=0.2),
    xtrain_tfidf,
    train_y,
    xvalid_tfidf
)
print("Naive Bayes Accuracy:", nb_acc)

# ---------- 使用模型2:逻辑回归 ----------
# 使用默认参数的逻辑回归模型进行训练与预测
lr_acc = train_model(
    linear_model.LogisticRegression(),
    xtrain_tfidf,
    train_y,
    xvalid_tfidf
)
print("Logistic Regression Accuracy:", lr_acc)

输出:

Naive Bayes Accuracy: 0.9870782483847811
Logistic Regression Accuracy: 0.9662598707824839

可以尝试更多模型(如 SVM、Random Forest)进一步提升性能。

7 情感分析

现在我们想分析某段文本是积极、消极还是中性情绪。这里我们用Spacy库来实现这个功能。

# 安装依赖(只运行一次)
# !pip uninstall -y numpy
# !pip install numpy==1.23.5 --force-reinstall
# !pip install -q spacy vaderSentiment
# !python -m spacy download en_core_web_sm

# 导入库
import spacy
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer

# 加载 spaCy 英文模型
nlp = spacy.load("en_core_web_sm")

# 初始化 VADER 情感分析器
analyzer = SentimentIntensityAnalyzer()

# 示例评论
review1 = "I like this phone. screen quality and camera clarity is really good."
review2 = "This tv is not good. Bad quality, no clarity, worst experience"

# 情感分析函数
def analyze_sentiment(text):
    doc = nlp(text)  # spaCy 分词 & 预处理
    scores = analyzer.polarity_scores(doc.text)  # VADER 分析
    return scores

# 打印结果
print("Review 1:", analyze_sentiment(review1))
print("Review 2:", analyze_sentiment(review2))

输出如下:

Review 1: {'neg': 0.0, 'neu': 0.517, 'pos': 0.483, 'compound': 0.8122}
Review 2: {'neg': 0.262, 'neu': 0.393, 'pos': 0.345, 'compound': 0.357}

分析:

  • Review 1:情感积极(compound=0.8122),正面占比0.483、负面为0.0,中性为0.517,整体评价明显偏正面。
  • Review 2:情感轻度正面(compound=0.357),正面占比0.345、负面为0.262,中性为0.393,正负情绪混杂略偏积极。

8 词义消歧

现在我们想判断同一个词在不同语境中表示的不同含义,我们可以使用 Lesk 算法(通过上下文推理词义)来实现。

!pip install pywsd
import nltk
from pywsd.lesk import simple_lesk

nltk.download('averaged_perceptron_tagger_eng')
nltk.download('punkt_tab')

sentence1 = 'I went to the bank to deposit my money'
sentence2 = 'The river bank was full of dead fishes'

sense1 = simple_lesk(sentence1, 'bank')
print(sense1.name(), '→', sense1.definition())

sense2 = simple_lesk(sentence2, 'bank')
print(sense2.name(), '→', sense2.definition())

输出如下:

depository_financial_institution.n.01 → a financial institution that accepts deposits and channels the money into lending activities
bank.n.01 → sloping land (especially the slope beside a body of water)

可以看出:

  • 在 句子1 中,bank 指的是 银行,与金钱相关。

  • 在 句子2 中,bank 指的是 河岸,与自然环境相关。

9 语音转文本

我们可以使用 SpeechRecognitionPyAudio 库将语音输入转换为文本。我现在有一个sample1.wav里面的语音是"Hello I’m Jack",来看一下识别是否正确。

!pip install SpeechRecognition

import speech_recognition as sr
from google.colab import drive
drive.mount('/content/drive', force_remount=True)

# 使用已有音频文件
r = sr.Recognizer()
audio_file = sr.AudioFile('/content/drive/MyDrive/Colab Notebooks/sample1.wav')  # 替换为你上传的音频文件

with audio_file as source:
    audio = r.record(source)

# 使用 Google API 识别语音
print("识别结果:", r.recognize_google(audio))

输出如下:

在这里插入图片描述

要识别其他语言(如印地语):

r.recognize_google(audio, language='hi-IN')

10 文本转语音

我们可以使用 gTTS(Google Text-to-Speech)库将一段文本朗读出来生成音频文件。

!pip install gTTS
from gtts import gTTS

tts = gTTS(text='I like this NLP book', lang='en', slow=False)
tts.save("audio.mp3")

11 语言翻译

你希望将非英文翻译为英文,可以使用 goslate 库。

!pip install goslate
import goslate

gs = goslate.Goslate()
text = "Bonjour le monde"
translated = gs.translate(text, 'en')
print(translated)
# 输出:Hello world

12 总结

本文我们不仅介绍了名词短语提取、文本相似度计算、实体识别、主题建模、文本分类等文本处理技术,也深入了解了情感分析、词义消歧、语音与文本互转以及语言翻译等多模态应用。这些任务是构建智能对话系统、推荐系统、搜索引擎等高级应用不可或缺的部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

tilblackout

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

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

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

打赏作者

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

抵扣说明:

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

余额充值