forked from blmoistawinde/HarvestText
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.html
408 lines (400 loc) · 18.7 KB
/
README.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="harvesttext">HarvestText</h1>
<p>Sow with little data seed, harvest much from a text field.</p>
<p>播撒几多种子词,收获万千领域实</p>
<p>
<img src="https://img.shields.io/badge/python-3.6-blue.svg" alt="PyPI - Python Version" />
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="GitHub" />
<img src="https://img.shields.io/badge/version-V0.3-red.svg" alt="Version" />
</p>
<h2 id="section">用途</h2>
<p>HarvestText是一个专注无(弱)监督方法,能够整合领域知识(如类型,别名)对特定领域文本进行简单高效地处理和分析的库。</p>
<p>具体功能如下:</p>
<p>
<a id="目录">目录:</a>
</p>
<ul>
<li>
<a href="#%E5%AE%9E%E4%BD%93%E9%93%BE%E6%8E%A5">精细分词分句</a>
<ul>
<li>可包含指定词和类别的分词。充分考虑省略号,双引号等特殊标点的分句。</li>
</ul>
</li>
<li>
<a href="#%E5%AE%9E%E4%BD%93%E9%93%BE%E6%8E%A5">实体链接</a>
<ul>
<li>把别名,缩写与他们的标准名联系起来。</li>
</ul>
</li>
<li>
<a href="#%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90">情感分析</a>
<ul>
<li>给出少量种子词(通用的褒贬义词语),得到语料中各个词语和语段的褒贬度。</li>
</ul>
</li>
<li>
<a href="#%E4%BF%A1%E6%81%AF%E6%A3%80%E7%B4%A2">信息检索</a>
<ul>
<li>统计特定实体出现的位置,次数等。</li>
</ul>
</li>
<li>
<a href="#%E5%85%B3%E7%B3%BB%E7%BD%91%E7%BB%9C">关系网络</a>
<ul>
<li>利用共现关系,获得关键词之间的网络。或者以一个给定词语为中心,探索与其相关的词语网络。</li>
</ul>
</li>
<li>
<a href="#%E5%86%85%E7%BD%AE%E8%B5%84%E6%BA%90">内置资源</a>
<ul>
<li>通用停用词,通用情感词,IT、财经、饮食、法律等领域词典。可直接用于以上任务。</li>
</ul>
</li>
<li>
<a href="#%E6%96%B0%E8%AF%8D%E5%8F%91%E7%8E%B0">新词发现</a>
<ul>
<li>利用统计规律发现语料中可能会被传统分词遗漏的特殊词汇。也便于从文本中快速筛选出关键词。</li>
</ul>
</li>
<li>
<a href="#%E6%96%87%E6%9C%AC%E6%91%98%E8%A6%81">文本摘要</a>
<ul>
<li>基于Textrank得到一系列句子中的代表性句子中。</li>
</ul>
</li>
<li>
<a href="#%E5%AD%98%E5%8F%96%E4%B8%8E%E6%B6%88%E9%99%A4">存取消除</a>
</li>
</ul>
<p>在很多领域文本分析中,我们往往已经了解其中的一些关键词语或实体,例如小说文本分析中的人物名,电影评论中的演员名、角色名、影片名,足球评论文本中的球员、球队、乃至一些术语。在后面的分析中,它们可能是我们的重点关注对象,或者是可以利用它们来改进分词等基础任务、提供机器学习的一些基础特征。</p>
<p>内置停用词,特殊类型词,情感词等资源,并以简单清晰的方式与本库的分词、分析等流程结合。</p>
<p>本库就旨在于提供解决这些问题的一个简单易用的方案。</p>
<h2 id="section-1">依赖</h2>
<ul>
<li>jieba</li>
<li>numpy, pandas</li>
<li>networkx</li>
</ul>
<h2 id="section-2">用法</h2>
<p>首先安装,
使用pip</p>
<pre>
<code>pip install harvesttext
</code>
</pre>
<p>或进入setup.py所在目录,然后命令行:</p>
<pre>
<code>python setup.py install
</code>
</pre>
<p>随后在代码中:</p>
<pre>
<code class="language-python3">from harvesttext import HarvestText
ht = HarvestText()
</code>
</pre>
<p>即可调用本库的功能接口。</p>
<p>
<a id="实体链接"></a>
</p>
<h3 id="section-3">实体链接</h3>
<p>给定某些实体及其可能的代称,以及实体对应类型。将其登录到词典中,在分词时优先切分出来,并且以对应类型作为词性。也可以单独获得语料中的所有实体及其位置:</p>
<pre>
<code class="language-python3">para = "上港的武磊和恒大的郜林,谁是中国最好的前锋?那当然是武磊武球王了,他是射手榜第一,原来是弱点的单刀也有了进步"
entity_mention_dict = {'武磊':['武磊','武球王'],'郜林':['郜林','郜飞机'],'前锋':['前锋'],'上海上港':['上港'],'广州恒大':['恒大'],'单刀球':['单刀']}
entity_type_dict = {'武磊':'球员','郜林':'球员','前锋':'位置','上海上港':'球队','广州恒大':'球队','单刀球':'术语'}
ht.add_entities(entity_mention_dict,entity_type_dict)
print("\nSentence segmentation")
print(ht.seg(para,return_sent=True)) # return_sent=False时,则返回词语列表
</code>
</pre>
<blockquote>
<p>上港 的 武磊 和 恒大 的 郜林 , 谁 是 中国 最好 的 前锋 ? 那 当然 是 武磊 武球王 了, 他 是 射手榜 第一 , 原来 是 弱点 的 单刀 也 有 了 进步</p>
</blockquote>
<p>采用传统的分词工具很容易把“武球王”拆分为“武 球王”</p>
<p>词性标注,包括指定的特殊类型。</p>
<pre>
<code class="language-python3">print("\nPOS tagging with entity types")
for word, flag in ht.posseg(para):
print("%s:%s" % (word, flag),end = " ")
</code>
</pre>
<blockquote>
<p>上港:球队 的:uj 武磊:球员 和:c 恒大:球队 的:uj 郜林:球员 ,:x 谁:r 是:v 中国:ns 最好:a 的:uj 前锋:位置 ?:x 那:r 当然:d 是:v 武磊:球员 武球王:球员 了:ul ,:x 他:r 是:v 射手榜:n 第一:m ,:x 原来:d 是:v 弱点:n 的:uj 单刀:术语 也:d 有:v 了:ul 进步:d</p>
</blockquote>
<pre>
<code class="language-python3">for span, entity in ht.entity_linking(para):
print(span, entity)
</code>
</pre>
<blockquote>
<p>[0, 2] ('上海上港', '#球队#')
[3, 5] ('武磊', '#球员#')
[6, 8] ('广州恒大', '#球队#')
[9, 11] ('郜林', '#球员#')
[19, 21] ('前锋', '#位置#')
[26, 28] ('武磊', '#球员#')
[28, 31] ('武磊', '#球员#')
[47, 49] ('单刀球', '#术语#')</p>
</blockquote>
<p>这里把“武球王”转化为了标准指称“武磊”,可以便于标准统一的统计工作。</p>
<p>分句:</p>
<pre>
<code class="language-python3">print(ht.cut_sentences(para))
</code>
</pre>
<blockquote>
<p>['上港的武磊和恒大的郜林,谁是中国最好的前锋?', '那当然是武磊武球王了,他是射手榜第一,原来是弱点的单刀也有了进步']</p>
</blockquote>
<p>现在本库能够也用一些基本策略来处理复杂的实体消歧任务(比如一词多义【"老师"是指"A老师"还是"B老师"?】、候选词重叠【xx市长/江yy?、xx市长/江yy?】)。
具体可见<a href="./examples/basics.py#linking_strategy">linking_strategy()</a></p>
<p>
<a id="情感分析"></a>
</p>
<h3 id="section-4">情感分析</h3>
<p>本库采用情感词典方法进行情感分析,通过提供少量标准的褒贬义词语(“种子词”),从语料中自动学习其他词语的情感倾向,形成情感词典。对句中情感词的加总平均则用于判断句子的情感倾向:</p>
<pre>
<code class="language-python3">print("\nsentiment dictionary")
sents = ["武磊威武,中超第一射手!",
"武磊强,中超最第一本土球员!",
"郜林不行,只会抱怨的球员注定上限了",
"郜林看来不行,已经到上限了"]
sent_dict = ht.build_sent_dict(sents,min_times=1,pos_seeds=["第一"],neg_seeds=["不行"])
print("%s:%f" % ("威武",sent_dict["威武"]))
print("%s:%f" % ("球员",sent_dict["球员"]))
print("%s:%f" % ("上限",sent_dict["上限"]))
</code>
</pre>
<blockquote>
<p>sentiment dictionary
威武:1.000000
球员:0.000000
上限:-1.000000</p>
</blockquote>
<pre>
<code class="language-python3">print("\nsentence sentiment")
sent = "武球王威武,中超最强球员!"
print("%f:%s" % (ht.analyse_sent(sent),sent))
</code>
</pre>
<blockquote>
<p>0.600000:武球王威武,中超最强球员!</p>
</blockquote>
<p>如果没想好选择哪些词语作为“种子词”,本库中也内置了一个通用情感词典<a href="#%E5%86%85%E7%BD%AE%E8%B5%84%E6%BA%90">内置资源</a>,可以从中挑选。</p>
<p>
<a id="信息检索"></a>
</p>
<h3 id="section-5">信息检索</h3>
<p>可以从文档列表中查找出包含对应实体(及其别称)的文档,以及统计包含某实体的文档数。使用倒排索引的数据结构完成快速检索。</p>
<pre>
<code class="language-python3">docs = ["武磊威武,中超第一射手!",
"郜林看来不行,已经到上限了。",
"武球王威武,中超最强前锋!",
"武磊和郜林,谁是中国最好的前锋?"]
inv_index = ht.build_index(docs)
print(ht.get_entity_counts(docs, inv_index)) # 获得文档中所有实体的出现次数
# {'武磊': 3, '郜林': 2, '前锋': 2}
print(ht.search_entity("武磊", docs, inv_index)) # 单实体查找
# ['武磊威武,中超第一射手!', '武球王威武,中超最强前锋!', '武磊和郜林,谁是中国最好的前锋?']
print(ht.search_entity("武磊 郜林", docs, inv_index)) # 多实体共现
# ['武磊和郜林,谁是中国最好的前锋?']
# 谁是最被人们热议的前锋?用这里的接口可以很简便地回答这个问题
subdocs = ht.search_entity("#球员# 前锋", docs, inv_index)
print(subdocs) # 实体、实体类型混合查找
# ['武球王威武,中超最强前锋!', '武磊和郜林,谁是中国最好的前锋?']
inv_index2 = ht.build_index(subdocs)
print(ht.get_entity_counts(subdocs, inv_index2, used_type=["球员"])) # 可以限定类型
# {'武磊': 2, '郜林': 1}
</code>
</pre>
<p>
<a id="关系网络"></a>
</p>
<h3 id="section-6">关系网络</h3>
<p>(使用networkx实现)
利用词共现关系,建立其实体间图结构的网络关系(返回networkx.Graph类型)。可以用来建立人物之间的社交网络等。</p>
<pre>
<code class="language-python3"># 在现有实体库的基础上随时新增,比如从新词发现中得到的漏网之鱼
ht.add_new_entity("颜骏凌", "颜骏凌", "球员")
docs = ["武磊和颜骏凌是队友",
"武磊和郜林都是国内顶尖前锋"]
G = ht.build_entity_graph(docs)
print(dict(G.edges.items()))
G = ht.build_entity_graph(docs, used_types=["球员"])
print(dict(G.edges.items()))
</code>
</pre>
<p>获得以一个词语为中心的词语网络,下面以三国第一章为例,探索主人公刘备的遭遇(下为主要代码,例子见<a href="./examples/basics.py#linking_strategy">build_word_ego_graph()</a>)。</p>
<pre>
<code class="language-python3">entity_mention_dict, entity_type_dict = get_sanguo_entity_dict()
ht0.add_entities(entity_mention_dict, entity_type_dict)
sanguo1 = get_sanguo()[0]
stopwords = get_baidu_stopwords()
docs = ht0.cut_sentences(sanguo1)
G = ht0.build_word_ego_graph(docs,"刘备",min_freq=3,other_min_freq=2,stopwords=stopwords)
</code>
</pre>
<p>
<img src="file:///./images/word_ego_net.jpg" alt="word_ego_net" />
</p>
<p>刘关张之情谊,刘备投奔的靠山,以及刘备讨贼之经历尽在于此。</p>
<p>
<a id="文本摘要"></a>
</p>
<h3 id="section-7">文本摘要</h3>
<p>(使用networkx实现)
使用Textrank算法,得到从文档集合中抽取代表句作为摘要信息:</p>
<pre>
<code class="language-python3">print("\nText summarization")
docs = ["武磊威武,中超第一射手!",
"郜林看来不行,已经到上限了。",
"武球王威武,中超最强前锋!",
"武磊和郜林,谁是中国最好的前锋?"]
for doc in ht.get_summary(docs, topK=2):
print(doc)
# 武球王威武,中超最强前锋!
# 武磊威武,中超第一射手!
</code>
</pre>
<p>
<a id="内置资源"></a>
</p>
<h3 id="section-8">内置资源</h3>
<p>现在本库内集成了一些资源,方便使用和建立demo。</p>
<p>资源包括:</p>
<ul>
<li>褒贬义词典 清华大学 李军 整理自http://nlp.csai.tsinghua.edu.cn/site2/index.php/13-sms</li>
<li>百度停用词词典 来自网络:https://wenku.baidu.com/view/98c46383e53a580216fcfed9.html</li>
<li>IT、财经、饮食、法律等领域词典 来自清华THUNLP: <a href="http://thuocl.thunlp.org/">http://thuocl.thunlp.org/</a></li>
</ul>
<p>此外,还提供了一个特殊资源——《三国演义》,包括:</p>
<ul>
<li>三国演义文言文文本</li>
<li>三国演义人名、州名、势力知识库</li>
</ul>
<p>大家可以探索从其中能够得到什么有趣发现😁。</p>
<pre>
<code class="language-python3">def load_resources():
from harvesttext.resources import get_qh_sent_dict,get_baidu_stopwords,get_sanguo,get_sanguo_entity_dict
sdict = get_qh_sent_dict() # {"pos":[积极词...],"neg":[消极词...]}
print("pos_words:",list(sdict["pos"])[10:15])
print("neg_words:",list(sdict["neg"])[5:10])
stopwords = get_baidu_stopwords()
print("stopwords:", list(stopwords)[5:10])
docs = get_sanguo() # 文本列表,每个元素为一章的文本
print("三国演义最后一章末16字:\n",docs[-1][-16:])
entity_mention_dict, entity_type_dict = get_sanguo_entity_dict()
print("刘备 指称:",entity_mention_dict["刘备"])
print("刘备 类别:",entity_type_dict["刘备"])
print("蜀 类别:", entity_type_dict["蜀"])
print("益州 类别:", entity_type_dict["益州"])
load_resources()
</code>
</pre>
<pre>
<code>pos_words: ['宰相肚里好撑船', '查实', '忠实', '名手', '聪明']
neg_words: ['散漫', '谗言', '迂执', '肠肥脑满', '出卖']
stopwords: ['apart', '左右', '结果', 'probably', 'think']
三国演义最后一章末16字:
鼎足三分已成梦,后人凭吊空牢骚。
刘备 指称: ['刘备', '刘玄德', '玄德']
刘备 类别: 人名
蜀 类别: 势力
益州 类别: 州名
</code>
</pre>
<p>加载清华领域词典,并使用停用词</p>
<pre>
<code class="language-python3">def using_typed_words():
from harvesttext.resources import get_qh_typed_words,get_baidu_stopwords
ht0 = HarvestText()
typed_words, stopwords = get_qh_typed_words(), get_baidu_stopwords()
ht0.add_typed_words(typed_words)
sentence = "THUOCL是自然语言处理的一套中文词库,词表来自主流网站的社会标签、搜索热词、输入法词库等。"
print(sentence)
print(ht0.posseg(sentence,stopwords=stopwords))
using_typed_words()
</code>
</pre>
<pre>
<code>THUOCL是自然语言处理的一套中文词库,词表来自主流网站的社会标签、搜索热词、输入法词库等。
[('THUOCL', 'eng'), ('自然语言处理', 'IT'), ('一套', 'm'), ('中文', 'nz'), ('词库', 'n'), ('词表', 'n'), ('来自', 'v'), ('主流', 'b'), ('网站', 'n'), ('社会', 'n'), ('标签', '财经'), ('搜索', 'v'), ('热词', 'n'), ('输入法', 'IT'), ('词库', 'n')]
</code>
</pre>
<p>一些词语被赋予特殊类型IT,而“是”等词语被筛出。</p>
<p>
<a id="新词发现"></a>
</p>
<h3 id="section-9">新词发现</h3>
<p>从比较大量的文本中利用一些统计指标发现新词。(可选)通过提供一些种子词语来确定怎样程度质量的词语可以被发现。(即至少所有的种子词会被发现,在满足一定的基础要求的前提下。)</p>
<pre>
<code class="language-python3">para = "上港的武磊和恒大的郜林,谁是中国最好的前锋?那当然是武磊武球王了,他是射手榜第一,原来是弱点的单刀也有了进步"
#返回关于新词质量的一系列信息,允许手工改进筛选(pd.DataFrame型)
new_words_info = ht.word_discover(para)
#new_words_info = ht.word_discover(para, threshold_seeds=["武磊"])
new_words = new_words_info.index.tolist()
print(new_words)
</code>
</pre>
<blockquote>
<p>["武磊"]</p>
</blockquote>
<p>具体的方法和指标含义,参考:http://www.matrix67.com/blog/archives/5044</p>
<p>发现的新词很多都可能是文本中的特殊关键词,故可以把找到的新词登录,使后续的分词优先分出这些词。</p>
<pre>
<code class="language-python3">def new_word_register():
new_words = ["落叶球","666"]
ht.add_new_words(new_words) # 作为广义上的"新词"登录
ht.add_new_entity("落叶球", mention0="落叶球", type0="术语") # 作为特定类型登录
print(ht.seg("这个落叶球踢得真是666", return_sent=True))
for word, flag in ht.posseg("这个落叶球踢得真是666"):
print("%s:%s" % (word, flag), end=" ")
</code>
</pre>
<blockquote>
<p>这个 落叶球 踢 得 真是 666</p>
</blockquote>
<blockquote>
<p>这个:r 落叶球:术语 踢:v 得:ud 真是:d 666:新词</p>
</blockquote>
<p>
<a id="存取与消除"></a>
</p>
<h3 id="section-10">存取消除</h3>
<p>可以本地保存模型再读取复用(pickle),也可以消除当前模型的记录。</p>
<pre>
<code class="language-python3">from harvesttext import loadHT,saveHT
para = "上港的武磊和恒大的郜林,谁是中国最好的前锋?那当然是武磊武球王了,他是射手榜第一,原来是弱点的单刀也有了进步"
saveHT(ht,"ht_model1")
ht2 = loadHT("ht_model1")
# 消除记录
ht2.clear()
print("cut with cleared model")
print(ht2.seg(para))
</code>
</pre>
<h2 id="more">More</h2>
<p>本库正在开发中,关于现有功能的改善和更多功能的添加可能会陆续到来。欢迎在issues里提供意见建议。觉得好用的话,也不妨来个Star~</p>
<p>感谢以下repo带来的启发:
<img src="https://github.com/isnowfy/snownlp" alt="snownlp" /></p>
<p>
<img src="https://github.com/fighting41love/funNLP" alt="funNLP" />
</p>
<p>
<img src="https://github.com/Moonshile/ChineseWordSegmentation" alt="ChineseWordSegmentation" />
</p>
</body>
</html>