【Python机器学习】NLP词频背后的含义——反馈及改进

之前学习的LSA方法都没有考虑文档之间的相似度信息,创建的主题对一组通用规则来说是最优的。在这些特征(主题)提取模型的无监督学习中,没有任何关于主题向量之间应该多么接近的数据。我们也不允许任何关于主题向量在哪里结束或者它们之间相关性如何的反馈。引导或者"习得型距离指标"是在降维和特征提取方面的最新进展。通过调整向聚类和嵌入算法报告的距离分数,我们可以控制自己的向量,从而让它们使一些代价函数最小化。通过这种方式,可以"强制"向量专注于我们感兴趣的信息内容的某个方面。

线性判别分析

下面是在一个标注好的短消息数据集上训练一个线性判别分析(LDA)模型。LDA的工作原理与LSA类似,但是它需要分类标签或其他分数才能找到高维空间中维度(词袋或TF-IDF向量中的词项)的最佳线性组合。LDA没有最大化新空间中所有向量之间的分离程度(方差),而是最大化了每个类质心向量之间的距离。

但是,这意味着必须通过给出样例(标注好的向量)来告诉LDA算法想对哪些主题建模。只有这样,算法才能计算出从高维空间到低维空间的最优转换。得到的低维向量的维数不能超过所能提供的类标签或分数的数量。

因为只需要训练一个"垃圾性"主题,下面看一维主题模型在垃圾短消息分类方面能达到多高的精确率:

python 复制代码
from nlpia.data.loaders import get_data
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from nltk.tokenize import casual_tokenize

sms=get_data('sms-spam')
index=['sms{}{}'.format(i,'!'*j) for (i,j) in zip(range(len(sms)),sms.spam)]
sms.index=index
tfidf=TfidfVectorizer(tokenizer=casual_tokenize)
tfidf_docs=tfidf.fit_transform(raw_documents=sms.text).toarray()
tfidf_docs=tfidf_docs-tfidf_docs.mean(axis=0)

lda=LDA(n_components=1)
lda=lda.fit(tfidf_docs,sms.spam)
sms['lda_spaminess']=lda.predict(tfidf_docs)
print(((sms.spam-sms.lda_spaminess)**2.0).sum()**0.5)
print((sms.spam==sms.lda_spaminess).sum())
print(len(sms))

可以看到,精确率为100%。在TF-IDF向量中有10000个词项,它可以"记住"答案。

下面做一些交叉验证:

python 复制代码
from sklearn.model_selection import cross_val_score
lds=LDA(n_components=1)
scores=cross_val_score(lda,tfidf_docs,sms.spam,cv=5)
print('精确率:',scores.mean(),scores.std()*2)

可以看到,效果并不好。为了确保76%的精确率数值是正确的,下面保留1/3的数据集用于测试:

python 复制代码
from sklearn.model_selection import train_test_split
X_train,X_text,y_train,y_test=train_test_split(tfidf_docs,sms.spam,test_size=0.33,random_state=271828)
lda=LDA(n_components=1)
lda.fit(X_train,y_train)

print(lda.score(X_text,y_test).round(3))

同样的,测试集的精确率也很低。因此,并不像是数据抽样做的不好,这是一个糟糕的过拟合模型。

下面看LSA和LDA结合起来是否有助于创建一个精确的、泛化能力强的模型,这样面对新的短消息时就不会出错:

python 复制代码
import pandas as pd
from sklearn.decomposition import PCA
pca=PCA(n_components=16)
pca=pca.fit(tfidf_docs)
pca_topicvectors=pca.transform(tfidf_docs)
columns=['topic{}'.format(i) for i in range(pca.n_components)]
pca_topicvectors=pd.DataFrame(pca_topicvectors,columns=columns,index=index)
X_train,X_text,y_train,y_test=train_test_split(pca_topicvectors.values,sms.spam,test_size=0.3,random_state=271828)
lda=LDA(n_components=1)
lda.fit(X_train,y_train)
print(lda.score(X_text,y_test).round(3))
lda=LDA(n_components=1)
scores=cross_val_score(lda,pca_topicvectors,sms.spam,cv=10)
print('精确率:',scores.mean())

因此,通过使用LSA,我们可以刻画一个只有16个维度的短消息,并且仍然有足够的信息将它们分类为垃圾信息或非垃圾信息。低维模型不太可能过拟合,它应该有很好的泛化能力,并且能够对尚未看到的短消息或聊天信息进行分类。

在尝试所有这些语义分析之前,使用简单的LDA模型可以获得更高的精确率,这个新模型的优点是:现在可以在多于一个的维度上创建表示语句语义的向量。

相关推荐
AI新兵1 小时前
AI大事记10:从对抗到创造——生成对抗网络 (GANs)
人工智能·神经网络·生成对抗网络
却道天凉_好个秋1 小时前
深度学习(十五):Dropout
人工智能·深度学习·dropout
板鸭〈小号〉2 小时前
Socket网络编程(1)——Echo Server
开发语言·网络·php
明天会有多晴朗2 小时前
C语言入门教程(第1讲):最通俗的C语言常见概念详解与实战讲解
c语言·开发语言·c++
爱上妖精的尾巴2 小时前
5-20 WPS JS宏 every与some数组的[与或]迭代(数组的逻辑判断)
开发语言·前端·javascript·wps·js宏·jsa
你好~每一天2 小时前
2025 中小企业 AI 转型:核心岗技能 “怎么证、怎么用”?
人工智能·百度·数据挖掘·数据分析·职业·转行
gopher95112 小时前
Go 语言的 panic 和 recover
开发语言·golang
浔川python社2 小时前
《网络爬虫技术规范与应用指南系列》(xc—5)完
爬虫·python
豆沙沙包?2 小时前
2025年--Lc165--H637.二叉树的层平均值(二叉树的层序遍历)--Java版
java·开发语言
Chunyyyen2 小时前
【第十六周】自然语言处理的学习笔记01
笔记·学习·自然语言处理