-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnlp100utils.py
178 lines (159 loc) · 6.48 KB
/
nlp100utils.py
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
import re
from collections import OrderedDict
def ngram(seq,n,char=False):
if isinstance(seq,str):
#seqがstr型だったらカンマとピリオドの処理
seq = re.sub(",|\.","",seq)
if not char:
#単語n-gramならseqをスペースで分割してリスト化
seq = seq.split()
return [seq[i:i+n] for i in range(len(seq) - n + 1)]
class Jawiki:
def __init__(self,filepath="./data/jawiki-country.json"):
import json
self.text = ""
self.data = [json.loads(line) for line in open(filepath)]
return
def getArticle(self,key):
#タイトルをキーに記事全文を取得する
#結果はインスタンス変数に代入される
for article in self.data:
if key == article["title"]:
self.text = article["text"]
break
return self.text
def extractRow(self,regExp):
#regExpで与えられた正規表現にマッチした行を返す
return [line for line in self.text.split("\n") if regExp.match(line)]
def rMatch(self,regExp):
#regExpで与えられた正規表現に対し、マッチした部分だけ返す
return [match for match in regExp.findall(self.text)]
def getAllTitles(self):#使わない
#全記事のタイトルを返す
return [self.data[i]["title"] for i in range(len(self.data))]
def getBasicInfo(self,preProcess=lambda x: x):
#基礎情報を辞書形式で返す
#テキストに対して前処理を施したい場合はpreProcessに関数オブジェクトを渡す
reg = re.compile("\{\{(基礎情報[\s\S]+?)\}\}\n")
text = self.rMatch(reg)
dic = OrderedDict()
reg = re.compile("\|(.+)\s\=\s(.+)")
for match in self.rMatch(reg):
dic[match[0]] = preProcess(match[1])
return dic
class CabochaDoc:
import CaboCha
def __init__(self,fp='./data/neko.txt.cabocha'):
#めんどくさいので40と41を一気に
chunkInfo = re.compile("([0-9]+?)\s([0-9\-]+?)D\s(.+?)\s(.+?)")
cSentences = []
mSentences = []
for sent in open(fp).read().split('EOS\n'):
chunkList = []
morphList = []
for chunk in sent.strip('* ').split('* '):
if chunkInfo.match(chunk):
_,dst,_,_ = chunkInfo.findall(chunk)[0]
dst=int(dst)
chunk = chunk.strip()
morphs = [self.morphParse(line) for line in chunk.split('\n')[1:]]
morphList.extend(morphs)
chunkList.append(Chunk(morphs,dst))
else:
pass
for i,chunk in enumerate(chunkList):
chunkList[chunk.dst].srcs.append(i)
chunkList[i].next = chunkList[chunk.dst]
cSentences.append(chunkList)
mSentences.append(morphList)
self.cSentences = cSentences
self.mSentences = mSentences
def __call__(self,sid):
print("-----sentence info------")
print("sentence ID :",sid)
print("surface :"," ".join(morph.surface for morph in self.mSentences[sid]))
print("chunks :","/".join(chunk.surface() for chunk in self.cSentences[sid]))
def morphParse(self,text):
tmp = text.strip().split('\t')
if len(tmp)==1:
surface = ' '
pos,pos1,_,_,_,_,base = text.strip().split(',')[:7]
else:
surface = tmp[0]
pos,pos1,_,_,_,_,base = tmp[1].strip().split(',')[:7]
return Morph(surface,pos,pos1,base)
class Chunk:
def __init__(self,morphs,dst):
self.morphs = morphs
self.dst = dst
self.srcs = []
def surface(self):
return " ".join(morph.surface for morph in self.morphs)
class Morph:
def __init__(self,surface,pos,pos1,base):
self.surface = surface
self.pos = pos
self.pos1 = pos1
self.base = base
def __call__(self):
#pprint用。呼ばれたら辞書で返事
return {"surface":self.surface,
"pos":self.pos,
"pos1":self.base,
"freq:":self.freq}
class MecabLoader:
"""
mecab解析結果のテキストファイルを読み込んでいい感じに処理してくれるやつ
第4章で使用
"""
def __init__(self,filepath="./data/neko.txt.mecab"):
separator = re.compile('\t|\,')
self.sentences = []
morphDict = dict()
tmp = []
for line in open(filepath):
line = line.strip()
if 'EOS' in line:
if len(tmp) is not 0:
self.sentences.append(tmp)
tmp = []
continue
if line in morphDict.keys():
"""
既知の形態素なら過去に生成した辞書オブジェクトを再利用
"""
tmp.append(morphDict[line])
else:
"""
未知の形態素なら辞書オブジェクトを生成
morphDictにkey:line,value:生成した辞書オブジェクト を追加し、
以降同じ形態素が出てきたら再利用できるようにする。
全単語数200000以上に対し使われている語彙数は15000とかなので
メモリ使用量をかなり節約できるはず
"""
surface,pos,pos1,_,_,_,_,base = separator.split(line)[:8]
tmp_m = {
"surface":surface,
"pos":pos,
"pos1":pos1,
"base":base,
}
#tmp_m = Morph(surf,pos,pos1,base)
morphDict[line] = tmp_m
tmp.append(tmp_m)
self.morphs = list(morphDict.values())
return
def __call__(self):
return self.sentences
def extractByPOS(self,pos=None,pos1=None):
"""
品詞または品詞細目で検索して、一致する形態素を返す
31,32,33で使用
"""
c_pos = lambda x: x["pos"] if pos else None
c_pos1 = lambda x: x["pos1"] if pos1 else None
tmp = [morph
for sent in self.sentences
for morph in sent
if pos == c_pos(morph) and pos1 == c_pos1(morph)]
return tmp