質問編集履歴
27
あ
title
CHANGED
@@ -1,1 +1,1 @@
|
|
1
|
-
|
1
|
+
Ruby製ライブラリlemmatizerのコード解読
|
body
CHANGED
File without changes
|
26
あ
title
CHANGED
File without changes
|
body
CHANGED
@@ -336,15 +336,15 @@
|
|
336
336
|
・@wordlistsと@exceptions、2つのハッシュを辞書として作成。
|
337
337
|
・それぞれ、次のような構造。これらにデータを登録する。
|
338
338
|
{:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
339
|
-
・見出し語を
|
339
|
+
・wordlistsに見出し語を登録する目的は、品詞を特定せずにlemmaを呼び出した際、どの品詞に属しているかを特定するため。
|
340
340
|
|
341
341
|
2. lemmaメソッドの呼び出し
|
342
342
|
<品詞を特定する場合>
|
343
343
|
・@exceptionsに単語があれば、そのデータを元に原形を返す
|
344
344
|
・なければ、morphological substitution (形態論の置き換え)のルールにしたがって置き換える。
|
345
|
-
<品詞を特定しない場合
|
345
|
+
<品詞を特定しない場合>
|
346
|
-
・[:verb, :noun, :adj, :adv, :abbr]
|
346
|
+
・動詞->名詞->形容詞->副詞の順で[:verb, :noun, :adj, :adv, :abbr]、見出し語から品詞を特定する。
|
347
|
-
・@exceptionsに単語があれば、そ
|
347
|
+
・@exceptionsに単語があれば、そこから原形を返す
|
348
348
|
・なければ、morphological substitution (形態論の置き換え)のルールにしたがって置き換える。
|
349
349
|
|
350
350
|
コードの解読を難しくしていた要因:
|
25
あ
title
CHANGED
File without changes
|
body
CHANGED
@@ -339,8 +339,13 @@
|
|
339
339
|
・見出し語をwordlistsに登録する理由は、品詞を特定せずにlemmaを呼び出した際、どの品詞に属しているかを検索するため。
|
340
340
|
|
341
341
|
2. lemmaメソッドの呼び出し
|
342
|
+
<品詞を特定する場合>
|
342
|
-
|
343
|
+
・@exceptionsに単語があれば、そのデータを元に原形を返す
|
343
|
-
|
344
|
+
・なければ、morphological substitution (形態論の置き換え)のルールにしたがって置き換える。
|
345
|
+
<品詞を特定しない場合場合>
|
346
|
+
・[:verb, :noun, :adj, :adv, :abbr]の順に、見出し語を元に、どの品詞なのかを検索する。
|
347
|
+
・@exceptionsに単語があれば、そのデータを元に原形を返す
|
348
|
+
・なければ、morphological substitution (形態論の置き換え)のルールにしたがって置き換える。
|
344
349
|
|
345
350
|
コードの解読を難しくしていた要因:
|
346
351
|
・辞書データを作成するためのメソッドが多かったこと
|
24
あ
title
CHANGED
@@ -1,1 +1,1 @@
|
|
1
|
-
Ruby製ライブラリlemmatizerのソースコード解読
|
1
|
+
あRuby製ライブラリlemmatizerのソースコード解読
|
body
CHANGED
@@ -334,8 +334,10 @@
|
|
334
334
|
|
335
335
|
1. 辞書の作成
|
336
336
|
・@wordlistsと@exceptions、2つのハッシュを辞書として作成。
|
337
|
-
・次のような構造。これらにデータを登録する。
|
337
|
+
・それぞれ、次のような構造。これらにデータを登録する。
|
338
338
|
{:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
339
|
+
・見出し語をwordlistsに登録する理由は、品詞を特定せずにlemmaを呼び出した際、どの品詞に属しているかを検索するため。
|
340
|
+
|
339
341
|
2. lemmaメソッドの呼び出し
|
340
342
|
・@exceptionsに単語があれば、そのデータを元に原形を返す
|
341
343
|
・なければ、morphological substitution (形態論の置き換え)のルールにしたがって置き換える。
|
23
a
title
CHANGED
File without changes
|
body
CHANGED
File without changes
|
22
あ
title
CHANGED
File without changes
|
body
CHANGED
@@ -68,7 +68,7 @@
|
|
68
68
|
module Lemmatizer
|
69
69
|
class Lemmatizer
|
70
70
|
|
71
|
-
#########################辞書データ
|
71
|
+
#########################辞書データの作成#####################################
|
72
72
|
# 辞書データがディレクトリのPATH
|
73
73
|
# 大文字で始まる場合は「定数」。各メソッドから参照可能。
|
74
74
|
DATA_DIR = File.expand_path('..', File.dirname(__FILE__))
|
@@ -134,11 +134,10 @@
|
|
134
134
|
]
|
135
135
|
}
|
136
136
|
|
137
|
-
# @wordlistsと@exceptionsに辞書データを登録する
|
137
|
+
# @wordlistsと@exceptionsに辞書データを登録する
|
138
138
|
def load_wordnet_files(pos, list, exc)
|
139
|
-
# 実行前、@wordlistsと@exceptionsは次のような構造
|
139
|
+
# 実行前、@wordlistsと@exceptionsは次のような構造。これらにデータを登録する。
|
140
140
|
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
141
|
-
# ここにデータを登録していく。
|
142
141
|
|
143
142
|
# 見出し語の登録
|
144
143
|
# "acculturation"での例
|
@@ -151,6 +150,7 @@
|
|
151
150
|
@wordlists[pos][w] = w
|
152
151
|
end
|
153
152
|
end
|
153
|
+
|
154
154
|
# 例外語の登録
|
155
155
|
# 例外語の辞書の各行は、"活用形 原形"(went go)の形式
|
156
156
|
# 活用形をwに、原形をsとして、ハッシュに追加していく
|
@@ -306,12 +306,12 @@
|
|
306
306
|
# インスタンス変数
|
307
307
|
# スコープ:クラス内で全メソッドで共通して使用することが出来る。
|
308
308
|
# クラスから作成されるオブジェクト毎に固有のもの。
|
309
|
-
# インスタンスごとに独立してもつ変数のため、インスタンス変数という。
|
310
309
|
|
311
310
|
MORPHOLOGICAL_SUBSTITUTIONS.keys.each do |x|
|
312
311
|
@wordlists[x] = {}
|
313
312
|
@exceptions[x] = {}
|
314
313
|
end
|
314
|
+
|
315
315
|
# 実行後、@wordlistsと@exceptionsは次のデータになる
|
316
316
|
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
317
317
|
|
@@ -330,4 +330,16 @@
|
|
330
330
|
|
331
331
|
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。
|
332
332
|
|
333
|
+
lemmaの動作についてまとめ:
|
334
|
+
|
335
|
+
1. 辞書の作成
|
336
|
+
・@wordlistsと@exceptions、2つのハッシュを辞書として作成。
|
337
|
+
・次のような構造。これらにデータを登録する。
|
338
|
+
{:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
339
|
+
2. lemmaメソッドの呼び出し
|
340
|
+
・@exceptionsに単語があれば、そのデータを元に原形を返す
|
333
|
-
|
341
|
+
・なければ、morphological substitution (形態論の置き換え)のルールにしたがって置き換える。
|
342
|
+
|
343
|
+
コードの解読を難しくしていた要因:
|
344
|
+
・辞書データを作成するためのメソッドが多かったこと
|
345
|
+
(NLTKの辞書を再利用していたため)
|
21
あ
title
CHANGED
File without changes
|
body
CHANGED
@@ -68,6 +68,7 @@
|
|
68
68
|
module Lemmatizer
|
69
69
|
class Lemmatizer
|
70
70
|
|
71
|
+
#########################辞書データを作成#####################################
|
71
72
|
# 辞書データがディレクトリのPATH
|
72
73
|
# 大文字で始まる場合は「定数」。各メソッドから参照可能。
|
73
74
|
DATA_DIR = File.expand_path('..', File.dirname(__FILE__))
|
@@ -133,74 +134,8 @@
|
|
133
134
|
]
|
134
135
|
}
|
135
136
|
|
136
|
-
# インスタンスの生成時に実行される
|
137
|
-
# オプショナル変数。dictに値を渡さない場合はnilになる。
|
138
|
-
def initialize(dict = nil)
|
139
|
-
|
140
|
-
@wordlists = {}
|
141
|
-
@exceptions = {}
|
142
|
-
# インスタンス変数
|
143
|
-
# スコープ:クラス内で全メソッドで共通して使用することが出来る。
|
144
|
-
# クラスから作成されるオブジェクト毎に固有のもの。
|
145
|
-
# インスタンスごとに独立してもつ変数のため、インスタンス変数という。
|
146
|
-
|
147
|
-
MORPHOLOGICAL_SUBSTITUTIONS.keys.each do |x|
|
148
|
-
@wordlists[x] = {}
|
149
|
-
@exceptions[x] = {}
|
150
|
-
end
|
151
|
-
|
137
|
+
# @wordlistsと@exceptionsに辞書データを登録するためのメソッド
|
152
|
-
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
153
|
-
|
154
|
-
WN_FILES.each_pair do |pos, pair|
|
155
|
-
load_wordnet_files(pos, pair[0], pair[1])
|
156
|
-
end
|
157
|
-
|
158
|
-
if dict
|
159
|
-
[dict].flatten.each do |d|
|
160
|
-
load_provided_dict(d)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def lemma(form, pos = nil)
|
166
|
-
unless pos
|
167
|
-
[:verb, :noun, :adj, :adv, :abbr].each do |p|
|
168
|
-
result = lemma(form, p)
|
169
|
-
return result unless result == form
|
170
|
-
end
|
171
|
-
|
172
|
-
return form
|
173
|
-
end
|
174
|
-
|
175
|
-
each_lemma(form, pos) do |x|
|
176
|
-
return x
|
177
|
-
end
|
178
|
-
|
179
|
-
form
|
180
|
-
end
|
181
|
-
|
182
|
-
# Print object only on init
|
183
|
-
def inspect
|
184
|
-
"#{self}"
|
185
|
-
end
|
186
|
-
|
187
|
-
private
|
188
|
-
|
189
|
-
# ファイルから見出し語を取り出す前処理?
|
190
|
-
def open_file(*args) # *argsは可変長引数
|
191
|
-
# args[0]がIOクラスかStringIOクラスなら、args[0]を返す
|
192
|
-
if args[0].is_a? IO or args[0].is_a? StringIO
|
193
|
-
yield args[0]
|
194
|
-
else
|
195
|
-
File.open(*args) do |io|
|
196
|
-
yield io
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
138
|
def load_wordnet_files(pos, list, exc)
|
202
|
-
|
203
|
-
# @wordlistsと@exceptionsに辞書データを登録するためのメソッド
|
204
139
|
# 実行前、@wordlistsと@exceptionsは次のような構造
|
205
140
|
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
206
141
|
# ここにデータを登録していく。
|
@@ -216,7 +151,6 @@
|
|
216
151
|
@wordlists[pos][w] = w
|
217
152
|
end
|
218
153
|
end
|
219
|
-
|
220
154
|
# 例外語の登録
|
221
155
|
# 例外語の辞書の各行は、"活用形 原形"(went go)の形式
|
222
156
|
# 活用形をwに、原形をsとして、ハッシュに追加していく
|
@@ -246,23 +180,47 @@
|
|
246
180
|
# よって、pair[0]は見出し語、pair[1]は例外語を示す。
|
247
181
|
# load_wordnet_files(pos, pair[0], pair[1])
|
248
182
|
|
183
|
+
def load_provided_dict(dict)
|
184
|
+
num_lex_added = 0
|
185
|
+
open_file(dict) do |io|
|
186
|
+
io.each_line do |line|
|
187
|
+
# pos must be either n|v|r|a or noun|verb|adverb|adjective
|
188
|
+
p, w, s = line.split(/\s+/, 3)
|
189
|
+
pos = str_to_pos(p)
|
190
|
+
word = w
|
249
|
-
|
191
|
+
substitute = s.strip
|
192
|
+
if /\A\"(.*)\"\z/ =~ substitute
|
193
|
+
substitute = $1
|
194
|
+
end
|
195
|
+
if /\A\'(.*)\'\z/ =~ substitute
|
196
|
+
substitute = $1
|
197
|
+
end
|
198
|
+
next unless (pos && word && substitute)
|
250
|
-
|
199
|
+
if @wordlists[pos]
|
200
|
+
@wordlists[pos][word] = substitute
|
251
|
-
|
201
|
+
num_lex_added += 1
|
202
|
+
end
|
203
|
+
end
|
252
204
|
end
|
205
|
+
# puts "#{num_lex_added} items added from #{File.basename dict}"
|
206
|
+
end
|
253
207
|
|
208
|
+
#########################辞書データを検索#####################################
|
209
|
+
def lemma(form, pos = nil)
|
210
|
+
unless pos
|
254
|
-
|
211
|
+
[:verb, :noun, :adj, :adv, :abbr].each do |p|
|
212
|
+
result = lemma(form, p)
|
213
|
+
return result unless result == form
|
214
|
+
end
|
255
215
|
|
256
|
-
# entryが展開されて、oldとnewに代入される
|
257
|
-
|
216
|
+
return form
|
217
|
+
end
|
258
218
|
|
259
|
-
# formがoldで終わっている場合
|
260
|
-
if form.endwith(old)
|
261
|
-
|
219
|
+
each_lemma(form, pos) do |x|
|
262
|
-
|
220
|
+
return x
|
263
|
-
end
|
264
|
-
end
|
265
221
|
end
|
222
|
+
|
223
|
+
form
|
266
224
|
end
|
267
225
|
|
268
226
|
def each_lemma(form, pos)
|
@@ -282,6 +240,45 @@
|
|
282
240
|
end
|
283
241
|
end
|
284
242
|
|
243
|
+
# Print object only on init
|
244
|
+
def inspect
|
245
|
+
"#{self}"
|
246
|
+
end
|
247
|
+
|
248
|
+
private
|
249
|
+
|
250
|
+
# ファイルから見出し語を取り出す前処理?
|
251
|
+
def open_file(*args) # *argsは可変長引数
|
252
|
+
# args[0]がIOクラスかStringIOクラスなら、args[0]を返す
|
253
|
+
if args[0].is_a? IO or args[0].is_a? StringIO
|
254
|
+
yield args[0]
|
255
|
+
else
|
256
|
+
File.open(*args) do |io|
|
257
|
+
yield io
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
def each_substitutions(form, pos)
|
264
|
+
if lemma = @wordlists[pos][form]
|
265
|
+
yield lemma
|
266
|
+
end
|
267
|
+
|
268
|
+
MORPHOLOGICAL_SUBSTITUTIONS[pos].each do |entry|
|
269
|
+
|
270
|
+
# entryが展開されて、oldとnewに代入される
|
271
|
+
old, new = *entry
|
272
|
+
|
273
|
+
# formがoldで終わっている場合
|
274
|
+
if form.endwith(old)
|
275
|
+
each_substitutions(form[0, form.length - old.length] + new, pos) do |x|
|
276
|
+
yield x
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
285
282
|
def str_to_pos(str)
|
286
283
|
case str
|
287
284
|
when "n", "noun"
|
@@ -298,32 +295,36 @@
|
|
298
295
|
return :unknown
|
299
296
|
end
|
300
297
|
end
|
298
|
+
end
|
301
299
|
|
302
|
-
|
300
|
+
##################辞書を利用するための初期化##############################
|
303
|
-
|
301
|
+
# インスタンスの生成時に実行される
|
302
|
+
# オプショナル変数。dictに値を渡さない場合はnilになる。
|
304
|
-
|
303
|
+
def initialize(dict = nil)
|
305
|
-
io.each_line do |line|
|
306
|
-
# pos must be either n|v|r|a or noun|verb|adverb|adjective
|
307
|
-
p, w, s = line.split(/\s+/, 3)
|
308
|
-
pos = str_to_pos(p)
|
309
|
-
|
304
|
+
@wordlists = {}
|
310
|
-
substitute = s.strip
|
311
|
-
if /\A\"(.*)\"\z/ =~ substitute
|
312
|
-
|
305
|
+
@exceptions = {}
|
306
|
+
# インスタンス変数
|
307
|
+
# スコープ:クラス内で全メソッドで共通して使用することが出来る。
|
308
|
+
# クラスから作成されるオブジェクト毎に固有のもの。
|
309
|
+
# インスタンスごとに独立してもつ変数のため、インスタンス変数という。
|
310
|
+
|
311
|
+
MORPHOLOGICAL_SUBSTITUTIONS.keys.each do |x|
|
312
|
+
@wordlists[x] = {}
|
313
|
+
@exceptions[x] = {}
|
313
|
-
|
314
|
+
end
|
315
|
+
# 実行後、@wordlistsと@exceptionsは次のデータになる
|
316
|
+
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
317
|
+
|
318
|
+
WN_FILES.each_pair do |pos, pair|
|
314
|
-
|
319
|
+
load_wordnet_files(pos, pair[0], pair[1])
|
315
|
-
substitute = $1
|
316
|
-
|
320
|
+
end
|
317
|
-
|
321
|
+
|
318
|
-
|
322
|
+
if dict
|
319
|
-
|
323
|
+
[dict].flatten.each do |d|
|
320
|
-
|
324
|
+
load_provided_dict(d)
|
321
|
-
end
|
322
325
|
end
|
323
326
|
end
|
324
|
-
# puts "#{num_lex_added} items added from #{File.basename dict}"
|
325
327
|
end
|
326
|
-
end
|
327
328
|
end
|
328
329
|
```
|
329
330
|
|
20
あ
title
CHANGED
File without changes
|
body
CHANGED
@@ -7,6 +7,8 @@
|
|
7
7
|
|
8
8
|
読み込まれる辞書データは次のような形式になっています。
|
9
9
|
|
10
|
+
不規則活用の辞書では、”不規則活用形 原形”で各行が並んでいます。
|
11
|
+
|
10
12
|
```
|
11
13
|
# noun.exc
|
12
14
|
aardwolves aardwolf
|
@@ -16,6 +18,8 @@
|
|
16
18
|
abscissae abscissa
|
17
19
|
```
|
18
20
|
|
21
|
+
index.品詞のファイルでは、規則変化、不規則変化に関わらず、単語のリストが並んでいます。この辞書で活用されるのは、最初の1単語のみです。
|
22
|
+
|
19
23
|
```
|
20
24
|
# index.noun
|
21
25
|
acculturation n 3 3 @ ~ + 3 1 01128984 05984936 05757049
|
19
だいぶOK
title
CHANGED
File without changes
|
body
CHANGED
@@ -144,6 +144,8 @@
|
|
144
144
|
@wordlists[x] = {}
|
145
145
|
@exceptions[x] = {}
|
146
146
|
end
|
147
|
+
# 実行後、@wordlistsと@exceptionsは次のデータになる
|
148
|
+
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
147
149
|
|
148
150
|
WN_FILES.each_pair do |pos, pair|
|
149
151
|
load_wordnet_files(pos, pair[0], pair[1])
|
@@ -180,7 +182,9 @@
|
|
180
182
|
|
181
183
|
private
|
182
184
|
|
185
|
+
# ファイルから見出し語を取り出す前処理?
|
183
186
|
def open_file(*args) # *argsは可変長引数
|
187
|
+
# args[0]がIOクラスかStringIOクラスなら、args[0]を返す
|
184
188
|
if args[0].is_a? IO or args[0].is_a? StringIO
|
185
189
|
yield args[0]
|
186
190
|
else
|
@@ -192,9 +196,16 @@
|
|
192
196
|
|
193
197
|
def load_wordnet_files(pos, list, exc)
|
194
198
|
|
199
|
+
# @wordlistsと@exceptionsに辞書データを登録するためのメソッド
|
200
|
+
# 実行前、@wordlistsと@exceptionsは次のような構造
|
201
|
+
# {:noun=>{}, :verb=>{}, :adj=>{}, :adv=>{}, :abbr=>{}, :unknown=>{}}
|
202
|
+
# ここにデータを登録していく。
|
203
|
+
|
195
|
-
|
204
|
+
# 見出し語の登録
|
196
|
-
|
205
|
+
# "acculturation"での例
|
197
|
-
|
206
|
+
# w = "acculturation n 3 3 @~省略~".split(/\s+/)[0]
|
207
|
+
# w は "acculturation"
|
208
|
+
# wordlists[:noun]["acculturation"] = "acculturation"
|
198
209
|
open_file(list) do |io|
|
199
210
|
io.each_line do |line|
|
200
211
|
w = line.split(/\s+/)[0]
|
@@ -202,10 +213,10 @@
|
|
202
213
|
end
|
203
214
|
end
|
204
215
|
|
205
|
-
# 例外語
|
216
|
+
# 例外語の登録
|
206
|
-
# 例外語の辞書の各行は、"活用形 原形"(
|
217
|
+
# 例外語の辞書の各行は、"活用形 原形"(went go)の形式
|
207
218
|
# 活用形をwに、原形をsとして、ハッシュに追加していく
|
208
|
-
# @exceptions[pos][w]が
|
219
|
+
# @exceptions[pos][w]が空ならば[]を代入する
|
209
220
|
# @exceptions[pos][w]に、原形をpush << する。
|
210
221
|
open_file(exc) do |io|
|
211
222
|
io.each_line do |line|
|
@@ -214,7 +225,6 @@
|
|
214
225
|
@exceptions[pos][w] << s
|
215
226
|
end
|
216
227
|
end
|
217
|
-
|
218
228
|
end
|
219
229
|
|
220
230
|
# インスタンスの初期化の際、次のように呼び出される
|
18
助言
title
CHANGED
File without changes
|
body
CHANGED
@@ -48,9 +48,9 @@
|
|
48
48
|
require 'lemmatizer/core_ext'
|
49
49
|
require 'lemmatizer/lemmatizer'
|
50
50
|
|
51
|
+
# asmさんからの助言
|
52
|
+
# lem = Lemmatizer::Lemmatizer.new と書くのがめんどくさいから
|
51
|
-
#
|
53
|
+
# lem = Lemmatizer.new と書けるようにしている
|
52
|
-
# ?? `lemmatizer/lib/lemmatizer.rb`で、モジュール読み込み時に、Lemmatizer.new(dict)を実行?
|
53
|
-
# ?? このコードは何のため?
|
54
54
|
module Lemmatizer
|
55
55
|
def self.new(dict = nil)
|
56
56
|
Lemmatizer.new(dict)
|
@@ -58,7 +58,7 @@
|
|
58
58
|
end
|
59
59
|
```
|
60
60
|
|
61
|
-
次は、'lemmatizer/lemmatizer.rb'のコード
|
61
|
+
次は、'lemmatizer/lemmatizer.rb'のコードです。
|
62
62
|
|
63
63
|
```
|
64
64
|
module Lemmatizer
|
@@ -90,7 +90,7 @@
|
|
90
90
|
]
|
91
91
|
}
|
92
92
|
|
93
|
-
# morphological(形態論の
|
93
|
+
# morphological substitution (形態論の置き換え)
|
94
94
|
# 規則的に置き換え可能な場合のルール
|
95
95
|
# 重複するものは、ing, es, ed, er, est。
|
96
96
|
MORPHOLOGICAL_SUBSTITUTIONS = {
|
17
nnn
title
CHANGED
File without changes
|
body
CHANGED
@@ -29,12 +29,39 @@
|
|
29
29
|
Wordnetの他の相関データがそのまま入っていて、
|
30
30
|
ここの辞書データの全てを利用している訳ではないのでは?と推測しています。
|
31
31
|
|
32
|
-
[lemmatizer/lib/lemmatizer/lemmatizer.rb](https://github.com/yohasebe/lemmatizer/blob/master/lib/lemmatizer/lemmatizer.rb)
|
33
|
-
が、どのように
|
32
|
+
以下、ソースコードを読み解きながら、どのようにlemmaメソッドが動作しているかを解読しようと試みます。
|
34
33
|
|
34
|
+
まずは、ライブラリを管理する`lemmatizer.gemspec`です。以下の箇所では、Gemをrequireしたとき、実際にロードするファイルのパスが指定されています。libフォルダ以下にあるファイル群が読み込まれます。
|
35
|
+
|
35
36
|
```
|
37
|
+
Gem::Specification.new do |gem|
|
38
|
+
(省略)
|
39
|
+
gem.require_paths = ['lib']
|
40
|
+
end
|
41
|
+
```
|
36
42
|
|
43
|
+
`lib/lemmatizer.rb`では、次の順でモジュールが読み込まれます。
|
44
|
+
|
45
|
+
```
|
46
|
+
require 'stringio'
|
47
|
+
require 'lemmatizer/version'
|
48
|
+
require 'lemmatizer/core_ext'
|
49
|
+
require 'lemmatizer/lemmatizer'
|
50
|
+
|
51
|
+
# ?? モジュールで self.new を定義すると、モジュールに対してnewが呼べる。
|
52
|
+
# ?? `lemmatizer/lib/lemmatizer.rb`で、モジュール読み込み時に、Lemmatizer.new(dict)を実行?
|
53
|
+
# ?? このコードは何のため?
|
37
54
|
module Lemmatizer
|
55
|
+
def self.new(dict = nil)
|
56
|
+
Lemmatizer.new(dict)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
次は、'lemmatizer/lemmatizer.rb'のコード内を読みます。
|
62
|
+
|
63
|
+
```
|
64
|
+
module Lemmatizer
|
38
65
|
class Lemmatizer
|
39
66
|
|
40
67
|
# 辞書データがディレクトリのPATH
|
@@ -103,8 +130,8 @@
|
|
103
130
|
}
|
104
131
|
|
105
132
|
# インスタンスの生成時に実行される
|
133
|
+
# オプショナル変数。dictに値を渡さない場合はnilになる。
|
106
134
|
def initialize(dict = nil)
|
107
|
-
# オプショナル変数。dictに値を渡さない場合はnilになる。
|
108
135
|
|
109
136
|
@wordlists = {}
|
110
137
|
@exceptions = {}
|
16
a
title
CHANGED
File without changes
|
body
CHANGED
@@ -286,4 +286,6 @@
|
|
286
286
|
end
|
287
287
|
```
|
288
288
|
|
289
|
-
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。
|
289
|
+
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。
|
290
|
+
|
291
|
+
それぞれのメソッドを追っていますが、どのようにファイル群から辞書を構築して、どのようにlemmaメソッドが動作しているのか、まだ解読できていません。
|
15
a
title
CHANGED
File without changes
|
body
CHANGED
@@ -211,7 +211,11 @@
|
|
211
211
|
end
|
212
212
|
|
213
213
|
MORPHOLOGICAL_SUBSTITUTIONS[pos].each do |entry|
|
214
|
+
|
215
|
+
# entryが展開されて、oldとnewに代入される
|
214
|
-
old, new = *entry
|
216
|
+
old, new = *entry
|
217
|
+
|
218
|
+
# formがoldで終わっている場合
|
215
219
|
if form.endwith(old)
|
216
220
|
each_substitutions(form[0, form.length - old.length] + new, pos) do |x|
|
217
221
|
yield x
|
14
a
title
CHANGED
File without changes
|
body
CHANGED
@@ -33,49 +33,7 @@
|
|
33
33
|
が、どのように辞書データを参照して、原形に変換しているのかをご助言いただけないでしょうか?
|
34
34
|
|
35
35
|
```
|
36
|
-
WN_FILES
|
37
|
-
-> 。
|
38
36
|
|
39
|
-
MORPHOLOGICAL_SUBSTITUTIONS
|
40
|
-
-> 形態素に基づく変換規則。
|
41
|
-
|
42
|
-
# メソッド
|
43
|
-
lemma(form, pos = nil)
|
44
|
-
-> 単語(form)と品詞(pos)を受け取り、原形を返す。
|
45
|
-
|
46
|
-
initialize(dict = nil)
|
47
|
-
-> インスタンスが生成されたときに実行される。
|
48
|
-
-> wordlistsとexceptionsの空のハッシュを宣言後、単語を追加していく。
|
49
|
-
|
50
|
-
each_lemma(form, pos)
|
51
|
-
-> メインのメソッド?
|
52
|
-
-> 単語(form)と品詞(pos)を受け取り、
|
53
|
-
1. 例外の単語ペアに合致すれば返す
|
54
|
-
2. `ful`で終わっている場合の対応
|
55
|
-
3. 原則どおりの場合の対応
|
56
|
-
each_substitutions(form, pos)が呼び出される。
|
57
|
-
|
58
|
-
each_substitutions(form, pos)
|
59
|
-
-> 形態素を元に原則どおり変換する場合の変換。
|
60
|
-
|
61
|
-
inspect
|
62
|
-
-> インスタンス生成時に、オブジェクトを印字する。
|
63
|
-
|
64
|
-
open_file(*args)
|
65
|
-
-> ファイルを開く。
|
66
|
-
|
67
|
-
load_wordnet_files(pos, list, exc)
|
68
|
-
-> wordnet_filesを読み込む。
|
69
|
-
|
70
|
-
str_to_pos(str)
|
71
|
-
-> 文字列をシンボルに変換して返す。
|
72
|
-
|
73
|
-
load_provided_dict(dict)
|
74
|
-
-> 辞書を読み込む
|
75
|
-
```
|
76
|
-
|
77
|
-
```
|
78
|
-
|
79
37
|
module Lemmatizer
|
80
38
|
class Lemmatizer
|
81
39
|
|
@@ -85,7 +43,7 @@
|
|
85
43
|
|
86
44
|
# 辞書データのPATH
|
87
45
|
# noun(名詞)、verb(動詞)、adj(形容詞)、adv(副詞)
|
88
|
-
# index.品詞は見出し語。品詞.excは不規則活用。
|
46
|
+
# index.品詞は見出し語。品詞.excは不規則活用。excはexception(例外)。
|
89
47
|
WN_FILES = {
|
90
48
|
:noun => [
|
91
49
|
DATA_DIR + '/dict/index.noun',
|
@@ -206,6 +164,10 @@
|
|
206
164
|
end
|
207
165
|
|
208
166
|
def load_wordnet_files(pos, list, exc)
|
167
|
+
|
168
|
+
# 見出し語への処理
|
169
|
+
# 辞書データの各行(line)を文字列に分解して、見出し語[0]をwに入れる
|
170
|
+
# @ハッシュのwordlistsに、{品詞 => 単語}の形式で見出し語を追加していく
|
209
171
|
open_file(list) do |io|
|
210
172
|
io.each_line do |line|
|
211
173
|
w = line.split(/\s+/)[0]
|
@@ -213,15 +175,36 @@
|
|
213
175
|
end
|
214
176
|
end
|
215
177
|
|
178
|
+
# 例外語への処理
|
179
|
+
# 例外語の辞書の各行は、"活用形 原形"(例、aardwolves aardwolf)の形式
|
180
|
+
# 活用形をwに、原形をsとして、ハッシュに追加していく
|
181
|
+
# @exceptions[pos][w]が未定義ならば[]を代入する
|
182
|
+
# @exceptions[pos][w]に、原形をpush << する。
|
216
183
|
open_file(exc) do |io|
|
217
184
|
io.each_line do |line|
|
218
185
|
w, s = line.split(/\s+/)
|
219
|
-
@exceptions[pos][w] ||= []
|
186
|
+
@exceptions[pos][w] ||= []
|
220
187
|
@exceptions[pos][w] << s
|
221
188
|
end
|
222
189
|
end
|
190
|
+
|
223
191
|
end
|
224
192
|
|
193
|
+
# インスタンスの初期化の際、次のように呼び出される
|
194
|
+
# WN_FILES.each_pair do |pos, pair|
|
195
|
+
# load_wordnet_files(pos, pair[0], pair[1])
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# WN_FILESは、{品詞 => [index.品詞, 品詞.例外]}を持つハッシュ
|
199
|
+
# WN_FILES = {
|
200
|
+
# :noun => [
|
201
|
+
# DATA_DIR + '/dict/index.noun',
|
202
|
+
# DATA_DIR + '/dict/noun.exc'
|
203
|
+
# ],
|
204
|
+
#
|
205
|
+
# よって、pair[0]は見出し語、pair[1]は例外語を示す。
|
206
|
+
# load_wordnet_files(pos, pair[0], pair[1])
|
207
|
+
|
225
208
|
def each_substitutions(form, pos)
|
226
209
|
if lemma = @wordlists[pos][form]
|
227
210
|
yield lemma
|
13
ok
title
CHANGED
File without changes
|
body
CHANGED
@@ -33,12 +33,8 @@
|
|
33
33
|
が、どのように辞書データを参照して、原形に変換しているのかをご助言いただけないでしょうか?
|
34
34
|
|
35
35
|
```
|
36
|
-
# 変数
|
37
|
-
DATA_DIR
|
38
|
-
-> 辞書があるディレクトリの指定。
|
39
|
-
|
40
36
|
WN_FILES
|
41
|
-
->
|
37
|
+
-> 。
|
42
38
|
|
43
39
|
MORPHOLOGICAL_SUBSTITUTIONS
|
44
40
|
-> 形態素に基づく変換規則。
|
@@ -82,8 +78,14 @@
|
|
82
78
|
|
83
79
|
module Lemmatizer
|
84
80
|
class Lemmatizer
|
81
|
+
|
82
|
+
# 辞書データがディレクトリのPATH
|
83
|
+
# 大文字で始まる場合は「定数」。各メソッドから参照可能。
|
85
84
|
DATA_DIR = File.expand_path('..', File.dirname(__FILE__))
|
85
|
+
|
86
|
-
|
86
|
+
# 辞書データのPATH
|
87
|
+
# noun(名詞)、verb(動詞)、adj(形容詞)、adv(副詞)
|
88
|
+
# index.品詞は見出し語。品詞.excは不規則活用。
|
87
89
|
WN_FILES = {
|
88
90
|
:noun => [
|
89
91
|
DATA_DIR + '/dict/index.noun',
|
@@ -102,7 +104,10 @@
|
|
102
104
|
DATA_DIR + '/dict/adv.exc'
|
103
105
|
]
|
104
106
|
}
|
107
|
+
|
105
|
-
|
108
|
+
# morphological(形態論の)substitution(置き換え)
|
109
|
+
# 規則的に置き換え可能な場合のルール
|
110
|
+
# 重複するものは、ing, es, ed, er, est。
|
106
111
|
MORPHOLOGICAL_SUBSTITUTIONS = {
|
107
112
|
:noun => [
|
108
113
|
['s', '' ],
|
@@ -139,9 +144,16 @@
|
|
139
144
|
]
|
140
145
|
}
|
141
146
|
|
147
|
+
# インスタンスの生成時に実行される
|
142
148
|
def initialize(dict = nil)
|
149
|
+
# オプショナル変数。dictに値を渡さない場合はnilになる。
|
150
|
+
|
143
151
|
@wordlists = {}
|
144
152
|
@exceptions = {}
|
153
|
+
# インスタンス変数
|
154
|
+
# スコープ:クラス内で全メソッドで共通して使用することが出来る。
|
155
|
+
# クラスから作成されるオブジェクト毎に固有のもの。
|
156
|
+
# インスタンスごとに独立してもつ変数のため、インスタンス変数という。
|
145
157
|
|
146
158
|
MORPHOLOGICAL_SUBSTITUTIONS.keys.each do |x|
|
147
159
|
@wordlists[x] = {}
|
@@ -183,7 +195,7 @@
|
|
183
195
|
|
184
196
|
private
|
185
197
|
|
186
|
-
def open_file(*args)
|
198
|
+
def open_file(*args) # *argsは可変長引数
|
187
199
|
if args[0].is_a? IO or args[0].is_a? StringIO
|
188
200
|
yield args[0]
|
189
201
|
else
|
12
a
title
CHANGED
File without changes
|
body
CHANGED
@@ -78,4 +78,213 @@
|
|
78
78
|
-> 辞書を読み込む
|
79
79
|
```
|
80
80
|
|
81
|
+
```
|
82
|
+
|
83
|
+
module Lemmatizer
|
84
|
+
class Lemmatizer
|
85
|
+
DATA_DIR = File.expand_path('..', File.dirname(__FILE__))
|
86
|
+
|
87
|
+
WN_FILES = {
|
88
|
+
:noun => [
|
89
|
+
DATA_DIR + '/dict/index.noun',
|
90
|
+
DATA_DIR + '/dict/noun.exc'
|
91
|
+
],
|
92
|
+
:verb => [
|
93
|
+
DATA_DIR + '/dict/index.verb',
|
94
|
+
DATA_DIR + '/dict/verb.exc'
|
95
|
+
],
|
96
|
+
:adj => [
|
97
|
+
DATA_DIR + '/dict/index.adj',
|
98
|
+
DATA_DIR + '/dict/adj.exc'
|
99
|
+
],
|
100
|
+
:adv => [
|
101
|
+
DATA_DIR + '/dict/index.adv',
|
102
|
+
DATA_DIR + '/dict/adv.exc'
|
103
|
+
]
|
104
|
+
}
|
105
|
+
|
106
|
+
MORPHOLOGICAL_SUBSTITUTIONS = {
|
107
|
+
:noun => [
|
108
|
+
['s', '' ],
|
109
|
+
['ses', 's' ],
|
110
|
+
['ves', 'f' ],
|
111
|
+
['xes', 'x' ],
|
112
|
+
['zes', 'z' ],
|
113
|
+
['ches', 'ch' ],
|
114
|
+
['shes', 'sh' ],
|
115
|
+
['men', 'man'],
|
116
|
+
['ies', 'y' ]
|
117
|
+
],
|
118
|
+
:verb => [
|
119
|
+
['s', '' ],
|
120
|
+
['ies', 'y'],
|
121
|
+
['es', 'e'],
|
122
|
+
['es', '' ],
|
123
|
+
['ed', 'e'],
|
124
|
+
['ed', '' ],
|
125
|
+
['ing', 'e'],
|
126
|
+
['ing', '' ]
|
127
|
+
],
|
128
|
+
:adj => [
|
129
|
+
['er', '' ],
|
130
|
+
['est', '' ],
|
131
|
+
['er', 'e'],
|
132
|
+
['est', 'e']
|
133
|
+
],
|
134
|
+
:adv => [
|
135
|
+
],
|
136
|
+
:abbr => [
|
137
|
+
],
|
138
|
+
:unknown => [
|
139
|
+
]
|
140
|
+
}
|
141
|
+
|
142
|
+
def initialize(dict = nil)
|
143
|
+
@wordlists = {}
|
144
|
+
@exceptions = {}
|
145
|
+
|
146
|
+
MORPHOLOGICAL_SUBSTITUTIONS.keys.each do |x|
|
147
|
+
@wordlists[x] = {}
|
148
|
+
@exceptions[x] = {}
|
149
|
+
end
|
150
|
+
|
151
|
+
WN_FILES.each_pair do |pos, pair|
|
152
|
+
load_wordnet_files(pos, pair[0], pair[1])
|
153
|
+
end
|
154
|
+
|
155
|
+
if dict
|
156
|
+
[dict].flatten.each do |d|
|
157
|
+
load_provided_dict(d)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def lemma(form, pos = nil)
|
163
|
+
unless pos
|
164
|
+
[:verb, :noun, :adj, :adv, :abbr].each do |p|
|
165
|
+
result = lemma(form, p)
|
166
|
+
return result unless result == form
|
167
|
+
end
|
168
|
+
|
169
|
+
return form
|
170
|
+
end
|
171
|
+
|
172
|
+
each_lemma(form, pos) do |x|
|
173
|
+
return x
|
174
|
+
end
|
175
|
+
|
176
|
+
form
|
177
|
+
end
|
178
|
+
|
179
|
+
# Print object only on init
|
180
|
+
def inspect
|
181
|
+
"#{self}"
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def open_file(*args)
|
187
|
+
if args[0].is_a? IO or args[0].is_a? StringIO
|
188
|
+
yield args[0]
|
189
|
+
else
|
190
|
+
File.open(*args) do |io|
|
191
|
+
yield io
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def load_wordnet_files(pos, list, exc)
|
197
|
+
open_file(list) do |io|
|
198
|
+
io.each_line do |line|
|
199
|
+
w = line.split(/\s+/)[0]
|
200
|
+
@wordlists[pos][w] = w
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
open_file(exc) do |io|
|
205
|
+
io.each_line do |line|
|
206
|
+
w, s = line.split(/\s+/)
|
207
|
+
@exceptions[pos][w] ||= []
|
208
|
+
@exceptions[pos][w] << s
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def each_substitutions(form, pos)
|
214
|
+
if lemma = @wordlists[pos][form]
|
215
|
+
yield lemma
|
216
|
+
end
|
217
|
+
|
218
|
+
MORPHOLOGICAL_SUBSTITUTIONS[pos].each do |entry|
|
219
|
+
old, new = *entry
|
220
|
+
if form.endwith(old)
|
221
|
+
each_substitutions(form[0, form.length - old.length] + new, pos) do |x|
|
222
|
+
yield x
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def each_lemma(form, pos)
|
229
|
+
if lemma = @exceptions[pos][form]
|
230
|
+
lemma.each { |x| yield x }
|
231
|
+
end
|
232
|
+
|
233
|
+
if pos == :noun && form.endwith('ful')
|
234
|
+
each_lemma(form[0, form.length-3], pos) do |x|
|
235
|
+
yield x + 'ful'
|
236
|
+
end
|
237
|
+
else
|
238
|
+
|
239
|
+
each_substitutions(form, pos) do|x|
|
240
|
+
yield x
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def str_to_pos(str)
|
246
|
+
case str
|
247
|
+
when "n", "noun"
|
248
|
+
return :noun
|
249
|
+
when "v", "verb"
|
250
|
+
return :noun
|
251
|
+
when "a", "j", "adjective", "adj"
|
252
|
+
return :adj
|
253
|
+
when "r", "adverb", "adv"
|
254
|
+
return :adv
|
255
|
+
when "b", "abbrev", "abbr", "abr"
|
256
|
+
return :abbr
|
257
|
+
else
|
258
|
+
return :unknown
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def load_provided_dict(dict)
|
263
|
+
num_lex_added = 0
|
264
|
+
open_file(dict) do |io|
|
265
|
+
io.each_line do |line|
|
266
|
+
# pos must be either n|v|r|a or noun|verb|adverb|adjective
|
267
|
+
p, w, s = line.split(/\s+/, 3)
|
268
|
+
pos = str_to_pos(p)
|
269
|
+
word = w
|
270
|
+
substitute = s.strip
|
271
|
+
if /\A\"(.*)\"\z/ =~ substitute
|
272
|
+
substitute = $1
|
273
|
+
end
|
274
|
+
if /\A\'(.*)\'\z/ =~ substitute
|
275
|
+
substitute = $1
|
276
|
+
end
|
277
|
+
next unless (pos && word && substitute)
|
278
|
+
if @wordlists[pos]
|
279
|
+
@wordlists[pos][word] = substitute
|
280
|
+
num_lex_added += 1
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
# puts "#{num_lex_added} items added from #{File.basename dict}"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
81
290
|
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。
|
11
a
title
CHANGED
File without changes
|
body
CHANGED
@@ -78,4 +78,4 @@
|
|
78
78
|
-> 辞書を読み込む
|
79
79
|
```
|
80
80
|
|
81
|
-
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。
|
81
|
+
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。
|
10
a
title
CHANGED
File without changes
|
body
CHANGED
@@ -25,13 +25,6 @@
|
|
25
25
|
accuracy n 2 5 ! @ ~ = ; 2 2 04802907 04803209
|
26
26
|
```
|
27
27
|
|
28
|
-
次の点に気が付きました。
|
29
|
-
・単語の後にpos(品詞)の省略形が続き、その後に、2つ数字があること。
|
30
|
-
・@の後には、 ~ + ; %pなどが続くこと。
|
31
|
-
・@の後に続く数字は2つであること。
|
32
|
-
・@の後に続く数字と、そのあとに続く数字(8桁)の数が一致していること。
|
33
|
-
・pos直後の数字2つと、@に続く数字2つの最初の数字は同じであること。
|
34
|
-
|
35
28
|
この辞書は、PythonのNLTKライブラリのWordnetの辞書から借用されているようなので、
|
36
29
|
Wordnetの他の相関データがそのまま入っていて、
|
37
30
|
ここの辞書データの全てを利用している訳ではないのでは?と推測しています。
|
9
good
title
CHANGED
File without changes
|
body
CHANGED
@@ -85,4 +85,4 @@
|
|
85
85
|
-> 辞書を読み込む
|
86
86
|
```
|
87
87
|
|
88
|
-
|
88
|
+
`index.品詞`の辞書は、各行の見出しだけを読み込んでいるとasmさんから助言をうけました。変形、活用しない単語であり、そのまま値を返しているようです。
|
8
fix
title
CHANGED
File without changes
|
body
CHANGED
@@ -8,6 +8,16 @@
|
|
8
8
|
読み込まれる辞書データは次のような形式になっています。
|
9
9
|
|
10
10
|
```
|
11
|
+
# noun.exc
|
12
|
+
aardwolves aardwolf
|
13
|
+
abaci abacus
|
14
|
+
aboideaux aboideau
|
15
|
+
aboiteaux aboiteau
|
16
|
+
abscissae abscissa
|
17
|
+
```
|
18
|
+
|
19
|
+
```
|
20
|
+
# index.noun
|
11
21
|
acculturation n 3 3 @ ~ + 3 1 01128984 05984936 05757049
|
12
22
|
accumulation n 4 4 @ ~ + ; 4 3 13424865 07951464 00372013 13366693
|
13
23
|
accumulator n 3 4 @ ~ %p ; 3 0 09936362 04328329 02673078
|
7
分析
title
CHANGED
File without changes
|
body
CHANGED
@@ -26,6 +26,53 @@
|
|
26
26
|
Wordnetの他の相関データがそのまま入っていて、
|
27
27
|
ここの辞書データの全てを利用している訳ではないのでは?と推測しています。
|
28
28
|
|
29
|
+
[lemmatizer/lib/lemmatizer/lemmatizer.rb](https://github.com/yohasebe/lemmatizer/blob/master/lib/lemmatizer/lemmatizer.rb)
|
29
|
-
|
30
|
+
が、どのように辞書データを参照して、原形に変換しているのかをご助言いただけないでしょうか?
|
30
31
|
|
32
|
+
```
|
33
|
+
# 変数
|
34
|
+
DATA_DIR
|
35
|
+
-> 辞書があるディレクトリの指定。
|
36
|
+
|
37
|
+
WN_FILES
|
38
|
+
-> 辞書データの指定。
|
39
|
+
|
40
|
+
MORPHOLOGICAL_SUBSTITUTIONS
|
41
|
+
-> 形態素に基づく変換規則。
|
42
|
+
|
43
|
+
# メソッド
|
44
|
+
lemma(form, pos = nil)
|
45
|
+
-> 単語(form)と品詞(pos)を受け取り、原形を返す。
|
46
|
+
|
47
|
+
initialize(dict = nil)
|
48
|
+
-> インスタンスが生成されたときに実行される。
|
49
|
+
-> wordlistsとexceptionsの空のハッシュを宣言後、単語を追加していく。
|
50
|
+
|
51
|
+
each_lemma(form, pos)
|
52
|
+
-> メインのメソッド?
|
53
|
+
-> 単語(form)と品詞(pos)を受け取り、
|
54
|
+
1. 例外の単語ペアに合致すれば返す
|
55
|
+
2. `ful`で終わっている場合の対応
|
56
|
+
3. 原則どおりの場合の対応
|
57
|
+
each_substitutions(form, pos)が呼び出される。
|
58
|
+
|
59
|
+
each_substitutions(form, pos)
|
60
|
+
-> 形態素を元に原則どおり変換する場合の変換。
|
61
|
+
|
62
|
+
inspect
|
63
|
+
-> インスタンス生成時に、オブジェクトを印字する。
|
64
|
+
|
65
|
+
open_file(*args)
|
66
|
+
-> ファイルを開く。
|
67
|
+
|
68
|
+
load_wordnet_files(pos, list, exc)
|
69
|
+
-> wordnet_filesを読み込む。
|
70
|
+
|
71
|
+
str_to_pos(str)
|
72
|
+
-> 文字列をシンボルに変換して返す。
|
73
|
+
|
74
|
+
load_provided_dict(dict)
|
75
|
+
-> 辞書を読み込む
|
76
|
+
```
|
77
|
+
|
31
78
|
よろしくお願いいたします。
|
6
ふぃx
title
CHANGED
File without changes
|
body
CHANGED
@@ -24,7 +24,7 @@
|
|
24
24
|
|
25
25
|
この辞書は、PythonのNLTKライブラリのWordnetの辞書から借用されているようなので、
|
26
26
|
Wordnetの他の相関データがそのまま入っていて、
|
27
|
-
|
27
|
+
ここの辞書データの全てを利用している訳ではないのでは?と推測しています。
|
28
28
|
|
29
29
|
辞書のどこのデータを参照して原形を特定しているのかをご助言いただけないでしょうか?
|
30
30
|
|
5
fix
title
CHANGED
@@ -1,1 +1,1 @@
|
|
1
|
-
Rubyのソースコード
|
1
|
+
Ruby製ライブラリlemmatizerのソースコード解読
|
body
CHANGED
File without changes
|
4
tweak
title
CHANGED
File without changes
|
body
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
・@の後には、 ~ + ; %pなどが続くこと。
|
21
21
|
・@の後に続く数字は2つであること。
|
22
22
|
・@の後に続く数字と、そのあとに続く数字(8桁)の数が一致していること。
|
23
|
+
・pos直後の数字2つと、@に続く数字2つの最初の数字は同じであること。
|
23
24
|
|
24
25
|
この辞書は、PythonのNLTKライブラリのWordnetの辞書から借用されているようなので、
|
25
26
|
Wordnetの他の相関データがそのまま入っていて、
|
3
改善
title
CHANGED
File without changes
|
body
CHANGED
@@ -15,12 +15,16 @@
|
|
15
15
|
accuracy n 2 5 ! @ ~ = ; 2 2 04802907 04803209
|
16
16
|
```
|
17
17
|
|
18
|
-
ここでの`@`や`+`、またそのあとに続く数字の羅列が何を意味しているかご助言いただけないでしょうか?
|
19
|
-
|
20
18
|
次の点に気が付きました。
|
21
19
|
・単語の後にpos(品詞)の省略形が続き、その後に、2つ数字があること。
|
22
20
|
・@の後には、 ~ + ; %pなどが続くこと。
|
23
21
|
・@の後に続く数字は2つであること。
|
24
22
|
・@の後に続く数字と、そのあとに続く数字(8桁)の数が一致していること。
|
25
23
|
|
24
|
+
この辞書は、PythonのNLTKライブラリのWordnetの辞書から借用されているようなので、
|
25
|
+
Wordnetの他の相関データがそのまま入っていて、
|
26
|
+
@以降の数字は原形を特定するためには不要なのかも?と推測しています。
|
27
|
+
|
28
|
+
辞書のどこのデータを参照して原形を特定しているのかをご助言いただけないでしょうか?
|
29
|
+
|
26
|
-
|
30
|
+
よろしくお願いいたします。
|
2
tweak
title
CHANGED
File without changes
|
body
CHANGED
@@ -19,6 +19,8 @@
|
|
19
19
|
|
20
20
|
次の点に気が付きました。
|
21
21
|
・単語の後にpos(品詞)の省略形が続き、その後に、2つ数字があること。
|
22
|
+
・@の後には、 ~ + ; %pなどが続くこと。
|
23
|
+
・@の後に続く数字は2つであること。
|
22
|
-
・@
|
24
|
+
・@の後に続く数字と、そのあとに続く数字(8桁)の数が一致していること。
|
23
25
|
|
24
26
|
ご助言をよろしくお願いいたします。
|
1
tweak
title
CHANGED
File without changes
|
body
CHANGED
@@ -17,4 +17,8 @@
|
|
17
17
|
|
18
18
|
ここでの`@`や`+`、またそのあとに続く数字の羅列が何を意味しているかご助言いただけないでしょうか?
|
19
19
|
|
20
|
+
次の点に気が付きました。
|
21
|
+
・単語の後にpos(品詞)の省略形が続き、その後に、2つ数字があること。
|
22
|
+
・@直後の数字と、そのあとに続く数字の数が一致していること。
|
23
|
+
|
20
|
-
よろしくお願いいたします。
|
24
|
+
ご助言をよろしくお願いいたします。
|