文本挖掘——实践总结(
以下内容都是在工作中的一些小实践,代码部分是参考网上的已有的然后再自行根据情况修改过的。记载主要是想以后用的时候可以更方便的直接拿过来用。
注:工作所需,程序是在knime这个数据挖掘软件的python下运行的,结果是截图过来的,可能模糊,可以自己实践代码。
文章内容: jieba分词(包括分词、关键词提取、词性标记)、word2vec、LDA、Kmeans四大模块算法的理论归纳及简单实现代码与果。
完成时间:1个星期左右时间。 其中,python部分2天左右,knime部分花费时间较长。
所用软件:python, Knime(python脚本完成)。
所用主要模块:NLTK、 Sklearn、pandas、Scipy、numpy、gensim(Word2vec部分),jieba。
遇到的主要问题:KNIME软件python脚本里中文编码问题、KNIME运行非常慢、KNIME的文件流入流出端还不是很熟练、KNIME其他数据预处理结点还不是很熟练。
后续计划:首先,因为之前时间并不多,所以还未实现其他文本挖掘算法,比如,SVM、 随机森林、kNN、CNN(类似其他神经网络算法)、 NLP其他功能、朴素贝叶斯等,这些算法在python里很好实现,在KNIME里需要改进运行效率。其次,希望可以对knime的python脚本运行效率作以改进,对KNIME数据流入流出数据库作以实践与熟练,还有就是对模型参数的多次训练,比如,本文实践的kmeans算法,参数K目前设置的是3,聚类预测准确率也就在60%左右,模型还不是很好,需要时间再调参训练。最后,希望对knime其他挖掘软件及结点作以实践,比如weka(这个软件比较熟悉,希望后面多了解)、R、matlab等。
jieba分词:
词性标记代码部分:
# Copy input to output
output_table_1 = input_table_1.copy()
output_table_2 = input_table_2.copy()
#!/usr/bin/python
import sys
#reload(sys)
#sys.setdefaultencoding('utf-8')
import jieba
import jieba.posseg as pseg #主要用jieba里的pseg做词性标记
import jieba.analyse
# 对句子进行分词
def seg_sentence(sentence):
sentence_seged = pseg.cut(sentence.strip())
stopwords = []
for line in output_table_2.values: #遍历停用词DataFrame
line[0]
stopwords.append(line[0])
outstr = ''
for word in sentence_seged:
if word not in stopwords: #去除停用词
if word!='\t':
for word1, flag in
sentence_seged: #遍历分词及分词词性
#print'%s %s' % (word1,
flag)
outstr
+=word1+'\t'+flag+'\n'
else:
outstr += " "
return outstr
#out_table=DataFrame()
for line in output_table_1.values:
line_seg = seg_sentence(line[0]) # 这里的返回值是字符串
print line_seg
#output_table_1['fenci']=line_seg
词性标记脚本结果:
特征词提取代码部分(提取了权重top100的词):
# Copy input to output
output_table = input_table.copy()
#!/usr/bin/python
import sys
import pandas
from pandas import DataFrame
#reload(sys)
#sys.setdefaultencoding('utf-8')
import jieba
import jieba.posseg as pseg
import jieba.analyse #主要用到jieba里的analyse做特征词提取
#finename='C:\\Users\\AAS-1413\\Desktop\\r.txt'
words = ''
#f = open("goods11.txt",
"w")
#with open(finename,'r') as f1:
for line in input_table['Col0']:
line
words+=line
words
#f2=f1.readlines()
tags = jieba.analyse.extract_tags(words,
topK=100, withWeight=True, allowPOS=()) #特征词提取关键部分,该函数里的参数可以自行修改,allowPOS参数可以自行设置提取词的词性
for wd, weight in tags:
wd, weight
#output_table['fe']=wd
#output_table['f']=weight
#f.close()
特征词提取脚本结果:
jieba分词:
# Copy input to output
output_table_1 = input_table_1.copy()
output_table_2 = input_table_2.copy()
#!/usr/bin/python
import sys
#(sys)
#sys.setdefaultencoding('utf-8')
import jieba #该部分主要用jieba
import jieba.posseg as pseg
import jieba.analyse
# 对句子进行分词
def seg_sentence(sentence):
sentence_seged = jieba.cut(sentence.strip())
stopwords = []
for line in output_table_2.values:
line[0]
stopwords.append(line[0])
outstr = ''
for word in sentence_seged:
if word not in stopwords:
if word != '\t':
outstr +='/'+word
else:
outstr += " "
return outstr
#out_table=DataFrame()
for line in output_table_1.values:
line_seg = seg_sentence(line[0])
print line_seg
分词脚本结果:
word2vec:
word2vev是一个浅层的神经网络算法。本文主要是利用python模块下gensim框架来调用word2vec实现先对文本分词,再对分词结果训练word2vec模型(word2vec模型训练过程中的参数可以修改),然后利用训练好的word2vec模型来做了简单的应用,比如,计算两个词的相似度,计算与一个词相关的所有其他词,寻找词语之间的对应关系,在一堆词语里寻找出不合群的词语。该模型目前大多用于对词语的分析挖掘中,所以对拿到的文本首先要做分词。
对文档分词脚本结果:
训练word2vec模型及简单应用代码:
import pandas
import numpy
# Copy input to output
output_table = input_table.copy()
from gensim.models import word2vec
sentences=word2vec.Text8Corpus(u'C:\\Python27\\fenci_result.txt')
model=word2vec.Word2Vec(sentences,
size=100) #训练模型,很多默认参数在此省略
#计算两个词的相似度/相关程度
y1=model.similarity(u"包装",
u"物流")
print "包装和物流的相似度为:", y1
print "-------------\n"
# 计算某个词的相关词列表
y2 = model.most_similar(u"不错",
topn=10) # 10个最相关的
#rint u"和【配置】最相关的词有:\n"
for item in y2:
print item[0], item[1]
print"--------------\n"
# 寻找对应关系
print u"包装-可以,物流-"
y3 =model.most_similar([u'包装', u'可以'], [u'物流'],
topn=10)
for item in y3:
print item[0], item[1]
"--------------------------\n"
# 寻找不合群的词
y4 =model.doesnt_match(u"包装 细心 可以 精美 不错 喜欢 很好".split())
print u"不合群的词:", y4
print"--------------------------------\n"
计算两个词的相似度/相关程度脚本结果:
计算某个词的相关词列表脚本结果:
寻找对应关系脚本结果:
寻找不合群的词脚本结果:
LDA模型部分:
LDA模型主要应用于对很多文档的主题分析上。关键部分是建立各个文档与词干的矩阵向量,该部分可以有很多方法,比如用tfidf或者本文用的doc2bow等。
本LDA模型建立步骤:导入文档——清洗文档——分词——去除停用词——词干提取——创建 document-term matrix矩阵(算法主旨部分)——训练LDA——应用LDA
LDA脚本代码:
import sys
# Copy input to output
output_table = input_table.copy()
#print input_table.values
#!/usr/bin/env python
import nltk
from nltk.tokenize import RegexpTokenizer
from stop_words import get_stop_words
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models
import gensim
import jieba
# 创建词干
p_stemmer = PorterStemmer()
# 创建简单文档
doc_a = "活动非常不错,本来准备让美国同学带的,一合计还不如旗舰店买划算。我膝关节滑膜炎自己吃保健用的。"
doc_b = "价格钜惠,家人腰椎间盘滑脱随时脚麻,希望吃了有效果,有效果来追加评价通过扫码查了下,的确是美国进口,相信旗舰店的品质!"
doc_c = "前半小时包税,结果我过了3分钟,没包成税,多花了70多,老人家长期吃长期需要买,看来要收藏好随时关注活动!"
doc_d = "听别人说这种保健品很有效,老人膝盖很疼,希望吃了会有效果。货物发自保税仓,验证码很麻烦,就没有试。吃过再追评。"
doc_e = "有时会觉得膝盖活动不那么灵活,关键才三十多岁,在网上看到大家评价不错,先买两瓶试试。"
#简单文档列表
doc_set = [doc_a, doc_b, doc_c, doc_d,
doc_e]
# 对文档列表作循环
texts=[]
for i in doc_set:
#
clean and tokenize document string
tokens = jieba.cut(i)
stopped_tokens = [i for i in tokens if not i in input_table.values]
stemmed_tokens = [p_stemmer.stem(i) for i in stopped_tokens]
texts.append(stemmed_tokens)
#print texts
#print stemmed_tokens
# 创建字典
dictionary = corpora.Dictionary(texts)
#print dictionary
#print dictionary.token2id#不重复的词的ID
# 创建 词-文档 矩阵
corpus = [dictionary.doc2bow(text) for text
in texts]
print corpus[0]#词向量
# 应用LDA模型
ldamodel =
gensim.models.ldamodel.LdaModel(corpus, num_topics=2, id2word = dictionary,
passes=20) #训练模型,该部分参数可自行修改
print ldamodel.print_topics(num_topics=2,
num_words=8)#应用LDA模型,该处自行设置2个主题,8个分词
t=''
for i in
ldamodel.print_topics(num_topics=2, num_words=8): #2个主题,8个分词
for
w in i:
t+=str(w)+'\n'
print t
主题生成脚本结果:
应用模型结果解释:打印出的corpus[0]([0]表示第一文档)就是截图结果里的第一行的向量部分,该部分的每个向量第一个数字表示词干ID,第二个数字表示该词干在第一个文档里出现的次数。打印出的 ldamodel.print_topics(num_topics=2, num_words=8),就是最下面的8个随机词干组成的两个主题,每个词干前对应该词干的权重。打印出的中间部分编码暂时有点问题。
Kmeans:
聚类算法
from __future__ import print_function
from sklearn.feature_extraction.text import
TfidfVectorizer
from sklearn.feature_extraction.text import
HashingVectorizer
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans,
MiniBatchKMeans
import os
# Copy input to output
output_table = input_table.copy()
def loadDataset():
'''导入文本数据集'''
#FindPath = 'C:\\Users\\AAS-1413\\Desktop\\tokens\\pos\\'
#
FileNames = os.listdir(FindPath)
dataset=[]
for line in input_table['Col0']:
#print (line)
dataset.append(line)
return dataset
def transform(dataset,n_features=1000):
vectorizer = TfidfVectorizer(max_df=0.5, max_features=n_features,
min_df=2,use_idf=True)
X
= vectorizer.fit_transform(dataset)
return X,vectorizer
def train(X,vectorizer,true_k=3,minibatch =
False,showLable = False):
#使用采样数据还是原始数据训练k-means,
if minibatch:
km = MiniBatchKMeans(n_clusters=true_k, init='k-means++', n_init=1,
init_size=1000,
batch_size=1000, verbose=False)
else:
km = KMeans(n_clusters=true_k, init='k-means++', max_iter=300, n_init=1,
verbose=False)
km.fit(X)
if showLable:
print (u"聚类结果主要词条:")#
top terms per cluster
order_centroids = km.cluster_centers_.argsort()[:, ::-1]
terms = vectorizer.get_feature_names()
#print (vectorizer.get_stop_words())
for i in range(true_k):
print("\n Cluster %d:\n" % i, end='')
for ind in order_centroids[i, :10]:
print(' %s' % terms[ind], end='')
result = list(km.predict(X))
#print('\n----------------------------------------------------------')
print (u'\n\n类分配:')#Cluster distribution
print (dict([(i, result.count(i)) for i in result]))
return -km.score(X)
def test():
'''测试选择最优参数'''
dataset = loadDataset()
print("%d documents" % len(dataset))
X,vectorizer = transform(dataset,n_features=500)
true_ks = []
scores = []
for i in xrange(3,80,1):
score = train(X,vectorizer,true_k=i)/len(dataset)
print (i,score)
true_ks.append(i)
scores.append(score)
plt.figure(figsize=(8,4))
plt.plot(true_ks,scores,label="error",color="red",linewidth=1)
plt.xlabel("n_features")
plt.ylabel("error")
plt.legend()
plt.show()
def out():
'''在最优参数下输出聚类结果'''
dataset = loadDataset()
X,vectorizer = transform(dataset,n_features=500)
score = train(X,vectorizer,true_k=3,showLable=True)/len(dataset)
#print('\n----------------------------------------------------------')
print (u'\n聚类预测准确率:')
print (score)
#test()
out()
聚类结果:
结果解释: 本模型设置k参数为3,聚成3类。