OBIEE 中有一些聚合函数可以对事实表的数据进行排序,比如 Max() 、 Min() 、 Median() 分别可以取最大值、最小值、中间值。而函数 Rank() 可以对某一数值列进行排序,并返回整数型的序号; TopN() 和 BottomN() 不仅可以对某一数值列进行排序返回整数型序号,还可以只返回固定的行数。由于 TopN() 和 BottomN() 功能类似只不过一个升序一个降序,下文中只用 TopN() 做示例。
创新互联公司专注于企业全网营销推广、网站重做改版、罗山网站定制设计、自适应品牌网站建设、H5建站、成都商城网站开发、集团公司官网建设、成都外贸网站制作、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为罗山等各大城市提供网站开发制作服务。
一、 Rank() 和 TopN() 两个函数的介绍:
二、 用法示例:
在分析中拖拽同一个数值列,分别对其编写 TopN() 和 Rank() 公式:
得到并查看结果。可以看到, TopN() 和 Rank() 返回的是序号,并且结果集按照 TopN() 的表达式,只取了最大的前 10 行数据,并且 TopN() 和 Rank() 的排序结果是一致的:
自然语言处理(NLP)是机器学习重要分支之一,主要应用于篇章理解、文本摘要、情感分析、知识图谱、文本翻译等领域。而NLP应用首先是对文本进行分词,当前中文分词器有Ansj、paoding、盘古分词等多种,而最基础的分词器应该属于jieba分词器(比较见下图)。
下面将分别应用R和python对jieba分词器在中文分词、词性标注和关键词提取领域的应用进行比较。
R实现
通过函数worker()来初始化分词引擎,使用segment()进行分词。有四种分词模式:最大概率法(MP)、隐马尔科夫模型(HMM)、混合模型(Mix)及索引模型(query),默认为混合模型。具体可查看help(worker).
#install.packages('jiebaR')library(jiebaR)mixseg - worker()segment( "这是一段测试文本" , mixseg ) #或者用以下操作mixseg['这是一段测试文本']mixseg = "这是一段测试文本"
python实现
python中需安装jieba库,运用jieba.cut实现分词。cut_all参数为分词类型,默认为精确模式。
import jiebaseg_list = jieba.cut(u"这是一段测试文本",cut_all = False)print("Full mode: "+ ",".join(seg_list)) #默认精确模式
无论是R还是python都为utf—8编码。
R实现
可以使用=.tagger 或者tag 来进行分词和词性标注,词性标注使用混合模型模型分词,标注采用和 ictclas 兼容的标记法。
words = "我爱北京天安门"tagger = worker("tag") #开启词性标注启发器tagger = words # r v ns ns # "我" "爱" "北京" "天安门"
python实现
#词性标注import jieba.posseg as psegwords = pseg.cut("我爱北京天安门")for word,flag in words: print('%s, %s' %(word,flag))
R实现
R关键词提取使用逆向文件频率(IDF)文本语料库,通过worker参数“keywords”开启关键词提取启发器,topn参数为关键词的个数。
keys = worker("keywords",topn = 5, idf = IDFPATH)keys = "会议邀请到美国密歇根大学(University of Michigan, Ann Arbor)环境健康科学系副教授奚传武博士作题为“Multibarrier approach for safe drinking waterin the US : Why it failed in Flint”的学术讲座,介绍美国密歇根Flint市饮用水污染事故的发生发展和处置等方面内容。讲座后各相关单位同志与奚传武教授就生活饮用水在线监测系统、美国水污染事件的处置方式、生活饮用水老旧管网改造、如何有效减少消毒副产物以及美国涉水产品和二次供水单位的监管模式等问题进行了探讨和交流。本次交流会是我市生活饮用水卫生管理工作洽商机制运行以来的又一次新尝试,也为我市卫生计生综合监督部门探索生活饮用水卫生安全管理模式及突发水污染事件的应对措施开拓了眼界和思路。"#结果:# 48.8677 23.4784 22.1402 20.326 18.5354 # "饮用水" "Flint" "卫生" "水污染" "生活"
python实现
python实现关键词提取可运用TF-IDF方法和TextRank方法。allowPOS参数为限定范围词性类型。
#关键词提取import jieba.analysecontent = u'会议邀请到美国密歇根大学(University of Michigan, Ann Arbor)环境健康科学系副教授奚传武博士作题为“Multibarrier approach for safe drinking waterin the US : Why it failed in Flint”的学术讲座,介绍美国密歇根Flint市饮用水污染事故的发生发展和处置等方面内容。讲座后各相关单位同志与奚传武教授就生活饮用水在线监测系统、美国水污染事件的处置方式、生活饮用水老旧管网改造、如何有效减少消毒副产物以及美国涉水产品和二次供水单位的监管模式等问题进行了探讨和交流。本次交流会是我市生活饮用水卫生管理工作洽商机制运行以来的又一次新尝试,也为我市卫生计生综合监督部门探索生活饮用水卫生安全管理模式及突发水污染事件的应对措施开拓了眼界和思路。'#基于TF-IDFkeywords = jieba.analyse.extract_tags(content,topK = 5,withWeight = True,allowPOS = ('n','nr','ns'))for item in keywords: print item[0],item[1] #基于TF-IDF结果# 饮用水 0.448327672795# Flint 0.219353532163# 卫生 0.203120821773# 水污染 0.186477211628# 生活 0.170049997544
#基于TextRankkeywords = jieba.analyse.textrank(content,topK = 5,withWeight = True,allowPOS = ('n','nr','ns'))for item in keywords: print item[0],item[1] #基于TextRank结果:# 饮用水 1.0# 美国 0.570564785973# 奚传武 0.510738424509# 单位 0.472841889334# 讲座 0.443770732053
写在文后
自然语言处理(NLP)在数据分析领域有其特殊的应用,在R中除了jiebaR包,中文分词Rwordseg包也非常常用。一般的文本挖掘步骤包括:文本获取(主要用网络爬取)——文本处理(分词、词性标注、删除停用词等)——文本分析(主题模型、情感分析)——分析可视化(词云、知识图谱等)。本文是自然语言处理的第一篇,后续将分别总结下应用深度学习Word2vec进行词嵌入以及主题模型、情感分析的常用NLP方法。
参考资料
Introduction · jiebaR 中文分词
知乎:【文本分析】利用jiebaR进行中文分词
雪晴数据网:全栈数据工程师养成攻略
搜狗实验室,词性标注应用
【R文本挖掘】中文分词Rwordseg
string为你需要获取向量的词,
double[] array = vec.getWordVector(string);
array是这个词的向量。
首先在创建vec的时候要保证.minWordFrequency(1),否则有些词你是得不到向量的,这个方法是设置词的最小使用频率。
词向量(word2vec)原始的代码是C写的,python也有对应的版本,被集成在一个非常牛逼的框架gensim中。
我在自己的开源语义网络项目graph-mind(其实是我自己写的小玩具)中使用了这些功能,大家可以直接用我在上面做的进一步的封装傻瓜式地完成一些操作,下面分享调用方法和一些code上的心得。
1.一些类成员变量:
[python] view plain copy
def __init__(self, modelPath, _size=100, _window=5, _minCount=1, _workers=multiprocessing.cpu_count()):
self.modelPath = modelPath
self._size = _size
self._window = _window
self._minCount = _minCount
self._workers = _workers
modelPath是word2vec训练模型的磁盘存储文件(model在内存中总是不踏实),_size是词向量的维度,_window是词向量训练时的上下文扫描窗口大小,后面那个不知道,按默认来,_workers是训练的进程数(需要更精准的解释,请指正),默认是当前运行机器的处理器核数。这些参数先记住就可以了。
2.初始化并首次训练word2vec模型
完成这个功能的核心函数是initTrainWord2VecModel,传入两个参数:corpusFilePath和safe_model,分别代表训练语料的路径和是否选择“安全模式”进行初次训练。关于这个“安全模式”后面会讲,先看代码:
[python] view plain copy
def initTrainWord2VecModel(self, corpusFilePath, safe_model=False):
'''''
init and train a new w2v model
(corpusFilePath can be a path of corpus file or directory or a file directly, in some time it can be sentences directly
about soft_model:
if safe_model is true, the process of training uses update way to refresh model,
and this can keep the usage of os's memory safe but slowly.
and if safe_model is false, the process of training uses the way that load all
corpus lines into a sentences list and train them one time.)
'''
extraSegOpt().reLoadEncoding()
fileType = localFileOptUnit.checkFileState(corpusFilePath)
if fileType == u'error':
warnings.warn('load file error!')
return None
else:
model = None
if fileType == u'opened':
print('training model from singleFile!')
model = Word2Vec(LineSentence(corpusFilePath), size=self._size, window=self._window, min_count=self._minCount, workers=self._workers)
elif fileType == u'file':
corpusFile = open(corpusFilePath, u'r')
print('training model from singleFile!')
model = Word2Vec(LineSentence(corpusFile), size=self._size, window=self._window, min_count=self._minCount, workers=self._workers)
elif fileType == u'directory':
corpusFiles = localFileOptUnit.listAllFileInDirectory(corpusFilePath)
print('training model from listFiles of directory!')
if safe_model == True:
model = Word2Vec(LineSentence(corpusFiles[0]), size=self._size, window=self._window, min_count=self._minCount, workers=self._workers)
for file in corpusFiles[1:len(corpusFiles)]:
model = self.updateW2VModelUnit(model, file)
else:
sentences = self.loadSetencesFromFiles(corpusFiles)
model = Word2Vec(sentences, size=self._size, window=self._window, min_count=self._minCount, workers=self._workers)
elif fileType == u'other':
# TODO add sentences list directly
pass
model.save(self.modelPath)
model.init_sims()
print('producing word2vec model ... ok!')
return model
首先是一些杂七杂八的,判断一下输入文件路径下访问结果的类型,根据不同的类型做出不同的文件处理反应,这个大家应该能看懂,以corpusFilePath为一个已经打开的file对象为例,创建word2vec model的代码为:
[python] view plain copy
model = Word2Vec(LineSentence(corpusFilePath), size=self._size, window=self._window, min_count=self._minCount, workers=self._workers)
其实就是这么简单,但是为了代码健壮一些,就变成了上面那么长。问题是在面对一个路径下的许多训练文档且数目巨大的时候,一次性载入内存可能不太靠谱了(没有细研究gensim在Word2Vec构造方法中有没有考虑这个问题,只是一种习惯性的警惕),于是我设定了一个参数safe_model用于判断初始训练是否开启“安全模式”,所谓安全模式,就是最初只载入一篇语料的内容,后面的初始训练文档通过增量式学习的方式,更新到原先的model中。
上面的代码里,corpusFilePath可以传入一个已经打开的file对象,或是一个单个文件的地址,或一个文件夹的路径,通过函数checkFileState已经做了类型的判断。另外一个函数是updateW2VModelUnit,用于增量式训练更新w2v的model,下面会具体介绍。loadSetencesFromFiles函数用于载入一个文件夹中全部语料的所有句子,这个在源代码里有,很简单,哥就不多说了。
3.增量式训练更新word2vec模型
增量式训练w2v模型,上面提到了一个这么做的原因:避免把全部的训练语料一次性载入到内存中。另一个原因是为了应对语料随时增加的情况。gensim当然给出了这样的solution,调用如下:
[python] view plain copy
def updateW2VModelUnit(self, model, corpusSingleFilePath):
'''''
(only can be a singleFile)
'''
fileType = localFileOptUnit.checkFileState(corpusSingleFilePath)
if fileType == u'directory':
warnings.warn('can not deal a directory!')
return model
if fileType == u'opened':
trainedWordCount = model.train(LineSentence(corpusSingleFilePath))
print('update model, update words num is: ' + trainedWordCount)
elif fileType == u'file':
corpusSingleFile = open(corpusSingleFilePath, u'r')
trainedWordCount = model.train(LineSentence(corpusSingleFile))
print('update model, update words num is: ' + trainedWordCount)
else:
# TODO add sentences list directly (same as last function)
pass
return model
简单检查文件type之后,调用model对象的train方法就可以实现对model的更新,这个方法传入的是新语料的sentences,会返回模型中新增词汇的数量。函数全部执行完后,return更新后的model,源代码中在这个函数下面有能够处理多类文件参数(同2)的增强方法,这里就不多介绍了。
4.各种基础查询
当你确定model已经训练完成,不会再更新的时候,可以对model进行锁定,并且据说是预载了相似度矩阵能够提高后面的查询速度,但是你的model从此以后就read only了。
[python] view plain copy
def finishTrainModel(self, modelFilePath=None):
'''''
warning: after this, the model is read-only (can't be update)
'''
if modelFilePath == None:
modelFilePath = self.modelPath
model = self.loadModelfromFile(modelFilePath)
model.init_sims(replace=True)
可以看到,所谓的锁定模型方法,就是init_sims,并且把里面的replace参数设定为True。
然后是一些word2vec模型的查询方法:
[python] view plain copy
def getWordVec(self, model, wordStr):
'''''
get the word's vector as arrayList type from w2v model
'''
return model[wordStr]
[python] view plain copy
def queryMostSimilarWordVec(self, model, wordStr, topN=20):
'''''
MSimilar words basic query function
return 2-dim List [0] is word [1] is double-prob
'''
similarPairList = model.most_similar(wordStr.decode('utf-8'), topn=topN)
return similarPairList
[python] view plain copy
def culSimBtwWordVecs(self, model, wordStr1, wordStr2):
'''''
two words similar basic query function
return double-prob
'''
similarValue = model.similarity(wordStr1.decode('utf-8'), wordStr2.decode('utf-8'))
return similarValue
上述方法都很简单,基本上一行解决,在源代码中,各个函数下面依然是配套了相应的model文件处理版的函数。其中,getWordVec是得到查询词的word2vec词向量本身,打印出来是一个纯数字的array;queryMostSimilarWordVec是得到与查询词关联度最高的N个词以及对应的相似度,返回是一个二维list(注释里面写的蛮清楚);culSimBtwWordVecs是得到两个给定词的相似度值,直接返回double值。
5.Word2Vec词向量的计算
研究过w2v理论的童鞋肯定知道词向量是可以做加减计算的,基于这个性质,gensim给出了相应的方法,调用如下:
[python] view plain copy
def queryMSimilarVecswithPosNeg(self, model, posWordStrList, negWordStrList, topN=20):
'''''
pos-neg MSimilar words basic query function
return 2-dim List [0] is word [1] is double-prob
'''
posWordList = []
negWordList = []
for wordStr in posWordStrList:
posWordList.append(wordStr.decode('utf-8'))
for wordStr in negWordStrList:
negWordList.append(wordStr.decode('utf-8'))
pnSimilarPairList = model.most_similar(positive=posWordList, negative=negWordList, topn=topN)
return pnSimilarPairList
由于用的是py27,所以之前对传入的词列表数据进行编码过滤,这里面posWordList可以认为是对结果产生正能量的词集,negWordList则是对结果产生负能量的词集,同时送入most_similar方法,在设定return答案的topN,得到的返回结果形式同4中的queryMostSimilarWordVec函数,大家可以这样数学地理解这个操作:
下面一个操作是我自创的,假设我想用上面词向量topN“词-关联度”的形式展现两个词或两组词之间的关联,我是这么做的:
[python] view plain copy
def copeMSimilarVecsbtwWordLists(self, model, wordStrList1, wordStrList2, topN_rev=20, topN=20):
'''''
range word vec res for two wordList from source to target
use wordVector to express the relationship between src-wordList and tag-wordList
first, use the tag-wordList as neg-wordList to get the rev-wordList,
then use the scr-wordList and the rev-wordList as the new src-tag-wordList
topN_rev is topN of rev-wordList and topN is the final topN of relationship vec
'''
srcWordList = []
tagWordList = []
srcWordList.extend(wordStr.decode('utf-8') for wordStr in wordStrList1)
tagWordList.extend(wordStr.decode('utf-8') for wordStr in wordStrList2)
revSimilarPairList = self.queryMSimilarVecswithPosNeg(model, [], tagWordList, topN_rev)
revWordList = []
revWordList.extend(pair[0].decode('utf-8') for pair in revSimilarPairList)
stSimilarPairList = self.queryMSimilarVecswithPosNeg(model, srcWordList, revWordList, topN)
return stSimilarPairList
这个操作的思路就是,首先用两组词中的一组作为negWordList,传入上面的queryMSimilarVecswithPosNeg函数,得到topN一组的中转词,在使用这些中转词与原先的另一组词进行queryMSimilarVecswithPosNeg操作,很容易理解,第一步得到的是一组词作为negWordList的反向结果,再通过这个反向结果与另一组词得到“负负得正”的效果。这样就可以通过一组topN的“词-关联度”配对List表示两组词之间的关系。
因为你有这样一句判断语句
if x in "0123456789"
只要x不是0123456789,那x就不是数字了,你编的这个计算器就结束运算了
x=50就会被判断为非数字。
isinstance(var, type)这个函数会告诉你变量是否属于某个变量类型,相符返回True,反之False
如果只支持整数运算,改成:
if isinstance(x,int):
如果要支持小数运算,改成:
if isinstance(x,int) or isinstance(x,float):