文本数据处理

涉及:

  • 文本数据的特征提取
  • 中文文本的分词方法
  • 用n-Garm模型优化文本数据
  • 使用tf-idf模型改善特征提取
  • 删除停用词

1.使用CountVectorizer对文本进行特征提取

前面,用来展示的数据特征分为:

  1. 用来表示数值的连续特征
  2. 表示样本所在分类的类型特征

第三种数据类型:文本数据

 

文本数据在计算机中往往被存储为字符串类型(String)

 

中文的处理相比较英文很难,因为在一个句子中,中文的词与词不像英文有空格作为分界线——处理中文时,先进行分词处理

如句子“The quick brown fos jumps over a lazy dog”:

#导入向量化工具CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
#拟合文本数据
en = ['The quick brown fos jumps over a lazy dog']
vect.fit(en)
print('单词数:',len(vect.vocabulary_))
print('分词:',vect.vocabulary_)
单词数: 8
分词: {'the': 7, 'quick': 6, 'brown': 0, 'fos': 2, 'jumps': 3, 'over': 5, 'lazy': 4, 'dog': 1}

【结果分析】

'a' 是冠词,没被程序作为一个单词

 

中文:

#使用中文文本进行实验
cn = ['那只敏捷的棕色狐狸跳过了一只懒惰的狗']
#拟合中文数据
vect.fit(cn)
print('单词数:',len(vect.vocabulary_))
print('分词:',vect.vocabulary_)
单词数: 1
分词: {'那只敏捷的棕色狐狸跳过了一只懒惰的狗': 0}

【结果分析】

程序无法对中文语句进行分词(没有空格)

 

2.使用分词工具对中文文本进行分词

pip install jieba 安装结巴分词

 

#导入结巴分词
import jieba
#对中文文本分词
cn = jieba.cut('那只敏捷的棕色狐狸跳过了一只懒惰的狗')
#实验空格‘ ’作为词与词的分界线
cn = [' '.join(cn)]
print(cn)

 

【结果分析】

红底黑字是“结巴分词”导入词典和建立模型的信息

 分词完成,接着进行特征提取:

#使用CountVectorizer对中文文本进行向量化
vect.fit(cn)
print('单词数:',len(vect.vocabulary_))
print('分词:',vect.vocabulary_)
单词数: 6
分词: {'敏捷': 2, '棕色': 3, '狐狸': 4, '跳过': 5, '一只': 0, '懒惰': 1}

 【结果分析】

 CountVectorizer已经可以从中文文本中提取若干个整型数值,并且生成了一个字典

 

接下来,使用这个字典将文本的特征表达出来,以便训练模型:

3.使用词袋模型将文本数据转为数组

上面的实验中,CountVectorizer给每个词编码为0-5的整型数,结果这样的处理,可以用一个稀疏矩阵对这个文本数据进行表示

#定义词袋模型
bag_of_words = vect.transform(cn)
#打印词袋模型中的数据特征
print('转化为词袋的特征:',repr(bag_of_words))
转化为词袋的特征: <1x6 sparse matrix of type '<class 'numpy.int64'>'
	with 6 stored elements in Compressed Sparse Row format>

【结果分析】

原来的语句,被转化成一个1行16列的稀疏矩阵,类型为64位整型数值,其中有6个元素

6个元素都是什么?

#打印词袋模型的密度表达
print(bag_of_words.toarray())
[[1 1 1 1 1 1]]

 

换一句话看看结果有啥不同:

#输入新的中文文本
cn_1 = jieba.cut('懒惰的狐狸不如敏捷的狐狸敏捷,敏捷的狐狸不如懒惰的狐狸懒惰')
cn2 = [' '.join(cn_1)]
print(cn2)
['懒惰 的 狐狸 不如 敏捷 的 狐狸 敏捷 , 敏捷 的 狐狸 不如 懒惰 的 狐狸 懒惰']
#建立新的词袋模型
new_bag = vect.transform(cn2)
#打印词袋中的数据特征
print('转化为词袋的特征:',repr(new_bag))
#打印词袋的密度表达
print(new_bag.toarray())
转化为词袋的特征: <1x6 sparse matrix of type '<class 'numpy.int64'>'
	with 3 stored elements in Compressed Sparse Row format>
[[0 3 3 0 4 0]]

 

上而这种用数组表示一句话中单词出现次数的方法,被称为“词袋模型 "

这种方法是忽略一个文本中的词序和语法,仅仅将它看作个词的集合

这种方法对于自然语言进行了简化,以便于机器可以读取井进行模型的训练

但模型也具有一定的局限性

 

 对文本类型数据的进一步优化处理

1. 使用n_Gram算法改善词袋模型

词袋模型劣势——把句子看作单词的简单集合,忽略单词的顺序

比如:

#随便写
joke = jieba.cut('道士看见和尚吻了尼姑的嘴唇')
joke = [' '.join(joke)]
#转化为向量
vect.fit(joke)
joke_feature = vect.transform(joke)
#打印文本数据特征
print(joke_feature.toarray())
[[1 1 1 1 1]]

顺序打乱:

#将刚才的文本打乱
joke2 = jieba.cut('尼姑看见道士的嘴唇亲吻了和尚')
joke2 = [' '.join(joke2)]
#转化为向量
vect.fit(joke2)
joke2_feature = vect.transform(joke2)
#打印文本数据特征
print(joke2_feature.toarray())
[[1 1 1 1 1 1]]

【结果分析】

对于机器来说,意思一模一样

在CountVectorize 中调节n-Gram函数:

#修改CountVectorizer的ngram参数
vect = CountVectorizer(ngram_range=(2,2))
#重新进行文本数据的特征提取
cv = vect.fit(joke)
joke_feature = cv.transform(joke)
print('调整ngram参数后的词典:',cv.get_feature_names())
print('新的特征表达:',joke_feature.toarray())
调整ngram参数后的词典: ['和尚 尼姑', '尼姑 嘴唇', '看见 和尚', '道士 看见']
新的特征表达: [[1 1 1 1]]

【结果分析】

将CountVectorizer的ngram_range参数调节为(2,2),意思是,进行组合的单词数量下线是2,上线也是2【即限制CountVectorizer将句子中相邻两个单词进行组合】

试试另一句:

#调整文本顺序
joke2 = jieba.cut('尼姑看见道士的嘴唇亲吻了和尚')
joke2 = [' '.join(joke2)]
#转化为向量
#vect.fit(joke2)   //这句书上没有,不知道是否必须
joke2_feature = vect.transform(joke2)
#打印文本数据特征
print(joke2_feature.toarray())
[[0 0 0 0]]

 

 

2.使用tf-idf模型对文本数据进行处理

使用tf-idf模型来进行文本特征提取的类,称为TfidfVectorizer

tf-idf全称为 词频-逆向文件频率

tf-idf是一种用来评估某个词对于一个语料库中某一份文件的重要程度

如果某个词在某个文件中出现的次数非常高,但在其他文件中出现的次数非常少,那么tf-idf就会认为这个词可以很好的将文件进行区分,重要程度会较高

【注意】tf-idf公式有很多变体

 

介绍TfidVectorizer用法和CountVectorizer的区别:

下载数据集  http://ai.stanford.edu/~amaas/data/sentiment  

 

 

 载入影评数据集:

 

!tree C:\Users\DELL\Desktop\aclImdb

使用sklearn载入这些文本数据:

#导入文件载入工具
from sklearn.datasets import load_files
#定义训练集
train_set = load_files('C:/Users/DELL/Desktop/aclImdb/train')
X_train,y_train = train_set.data,train_set.target
print('训练集文件数量:',len(X_train))
print('随机选一个',X_train[22])

有些评论有<br />的符号,用空格替换掉,避免影响模型

#将文本的<br />去掉
X_train = [doc.replace(b'<br />',b' ') for doc in X_train]

再载入数据集:

#载入测试集
test = load_files('C:/Users/DELL/Desktop/aclImdb/test')
X_test,y_test = test.data,test.target
X_test = [doc.replace(b'<br />',b' ') for doc in X_test]
#测试集文件数量
len(X_test)

25000

对文本数据进行特征提取:

使用CountVectorizer

 

#用CountVectorize拟合训练数据
vect = CountVectorizer().fit(X_train)
#将文本转化为向量
X_train_vect = vect.transform(X_train)
print('训练集样本特征数量:',len(vect.get_feature_names()))
print('最后10个训练集样本特征:',vect.get_feature_names()[-10:])
训练集样本特征数量: 124255
最后10个训练集样本特征: ['üvegtigris', 'üwe', 'ÿou', 'ıslam', 'ōtomo', 'şey', 'дом', 'книги', '色戒', 'rock']

 使用有监督学习算法进行交叉验证评分:

看看模型能否较好的拟合训练集

 

#导入线性SVC分类模型
from sklearn.svm import LinearSVC
#导入交叉验证工具
from sklearn.model_selection import cross_val_score
#使用交叉验证对模型评分
scores = cross_val_score(LinearSVC(),X_train_vect,y_train)
print('模型平均分:',scores.mean())

。。。。。。数据集太大,十分钟还没好。。。。。。就用书上截图了.。。。

0.778

泛化到测试集:

#把测试数据集转化为向量
X_test_vect = vect.transform(X_test)
#使用线性SVC拟合训练集
clf = LinearSVC().fit(X_train_vect,y_train)
print('测试集得分:',clf.score(X_test_vect,y_test))

0.58

 

接下来用tf-idf算法处理数据:

#导入tfidf转化工具
from sklearn.feature_extraction.text import TfidfTransformer
#用tfidf工具转化训练集和测试集
tfidf = TfidfTransformer(smooth_idf = False)
tfidf.fit(X_train_vect)
X_train_tfidf = tfidf.transform(X_train_vect)
X_test_tfidf = tfidf.transform(X_test_vect)
print('未处理的特征:',X_train_vect[:5,:5].toarray())
print('经tfidf处理的特征:',X_train_tfidf[:5,:5].toarray())

 

 

结果处理后的数据集训练的模型评分:

#重新训练线性SVC模型
clf = LinearSVC().fit(X_train_tfidf,y_train)
#使用新的数据进行交叉验证
scores2 = cross_val_score(LinearSVC(),X_train_tfidf,y_train)
print('经过tfidf处理的训练集交叉验证得分:',scores.mean())
print('经过tfidf处理的测试集得分:',clf.score(X_test_tfidf,y_test))

【结果分析】

 继续对模型继续改进——删除“停用词”

 

 

 

3.删除停用词

停用词,指在文本处理过程中被筛选出去的,出现频率高,但无意义,比如各种语气词、连词、介词

 目前没有通用的定义“停用词”的规则或工具

常见方法:

  • 统计文本中出现频率最高的,然后把他们作为“停用词”
  •  使用现有的停用词表

 载入sklearn内置的停用词表:

#导入内置的停用词库
from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS
#打印停用词个数
print(len(ENGLISH_STOP_WORDS))
#打印前20和后20个
print(list(ENGLISH_STOP_WORDS)[:20],list(ENGLISH_STOP_WORDS)[:-20:])

在上方的影视评语数据集继续停用词删除:

#导入Tfidf模型
from sklearn.feature_extraction.text import TfidfVectorizer
#激活英语停用词参数
tfidf = TfidfVectorizer(smooth_idf=False,stop_words='english')
#拟合训练集
tfidf.fit(X_train)
#将训练集文本转化为向量
X_train_tfidf = tfidf.transform(X_train)
#使用交叉验证进行评分
scores3 = cross_val_score(LinearSVC(),X_train_tfidf,y_train)
clf.fit(X_train_tfidf,y_train)
#将测试集转化为向量
X_test_tfidf = tfidf.transform(X_test)
print('去掉停用词后训练集交叉验证平均分:',scores3.mean())
print('去掉停用词后测试集模型得分:',clf.score(X_test_tfidf,y_test))

 

【结果分析】

 去掉停用词,可以让机器学习模型更好的拟合文本数据,并提高模型的泛化能力

 

转载于:https://www.cnblogs.com/expedition/p/10836378.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值