petrovich 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +101 -37
- data/Rakefile +14 -8
- data/lib/petrovich.rb +8 -8
- data/lib/tasks/evaluate.rake +89 -0
- metadata +9 -6
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-

|
2
2
|
|
3
|
-
Склонение падежей русских имён, фамилий и отчеств. Вы задаёте начальное имя
|
3
|
+
Склонение падежей русских имён, фамилий и отчеств. Вы задаёте начальное имя
|
4
|
+
в именительном падеже, а получаете в нужном вам.
|
4
5
|
|
5
6
|
[](http://travis-ci.org/rocsci/petrovich)
|
6
7
|
|
@@ -10,36 +11,47 @@
|
|
10
11
|
|
11
12
|
gem 'petrovich'
|
12
13
|
|
13
|
-
Установите
|
14
|
+
Установите гем cредствами Bundler:
|
14
15
|
|
15
16
|
$ bundle
|
16
17
|
|
17
|
-
|
18
|
+
Или установите его отдельно:
|
18
19
|
|
19
20
|
$ gem install petrovich
|
20
21
|
|
21
|
-
##
|
22
|
+
## Зависимости
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
Для работы гема требуется Ruby не младше версии 1.9.1. Petrovich не
|
25
|
+
привязан к Ruby on Rails и может свободно использоваться практически
|
26
|
+
в любых приложениях и библиотеках на Ruby.
|
25
27
|
|
26
28
|
## Использование
|
27
29
|
|
28
|
-
Вы задаёте начальные значения (фамилию, имя и отчество) в именительном
|
30
|
+
Вы задаёте начальные значения (фамилию, имя и отчество) в именительном
|
31
|
+
падеже.
|
29
32
|
|
30
33
|
```ruby
|
31
|
-
# Указание пола снижает количество отказов
|
32
34
|
p = Petrovich.new(:male)
|
33
35
|
p.lastname('Иванов', :dative) # => Иванову
|
34
36
|
p.firstname('Пётр', :dative) # => Петру
|
35
37
|
p.middlename('Сергеевич', :dative) # => Сергеевичу
|
36
38
|
```
|
37
39
|
|
38
|
-
Конструктор класса `Petrovich` принимает пол в качестве единственного
|
40
|
+
Конструктор класса `Petrovich` принимает пол в качестве единственного
|
41
|
+
аргумента. Пол может принимать значения `:male`, `:female` или
|
42
|
+
`:androgynous`. Последнее означает, что слово не склоняется по родам.
|
43
|
+
По нормам языка, некоторые фамилии не склоняются. Например, такие
|
44
|
+
украинские фамилии, как Симоненко, а также заимствованные фамилии,
|
45
|
+
такие как Нельсон.
|
46
|
+
|
47
|
+
Важно понимать, что явное указание пола повышает точность обработки слов.
|
48
|
+
Если пол не известен, однако известно отчество, то гем постарается
|
49
|
+
определить по пол отчеству на основе простой эвристики.
|
39
50
|
|
40
51
|
### Продвинутое использование
|
41
52
|
|
42
|
-
Вы можете подмешать модуль `Petrovich::Extension` в любой класс. Это
|
53
|
+
Вы можете подмешать модуль `Petrovich::Extension` в любой класс. Это
|
54
|
+
особенно полезно при использовании ActiveRecord и подобных ORM.
|
43
55
|
|
44
56
|
```ruby
|
45
57
|
class User < ActiveRecord::Base
|
@@ -71,7 +83,8 @@ class User < ActiveRecord::Base
|
|
71
83
|
end
|
72
84
|
```
|
73
85
|
|
74
|
-
|
86
|
+
Ничего не мешает подмешать модуль `Petrovich::Extension` в самый обычный
|
87
|
+
класс.
|
75
88
|
|
76
89
|
```ruby
|
77
90
|
class Person
|
@@ -96,7 +109,13 @@ class Person
|
|
96
109
|
end
|
97
110
|
```
|
98
111
|
|
99
|
-
|
112
|
+
При помощи метода `petrovich` указываются методы, представляющие фамилию,
|
113
|
+
имя и отчество. В данном примере указано, что метод `name` представляет
|
114
|
+
имя, метод `lastname` представляет фамилию, метод `patronymic` представляет
|
115
|
+
отчество.
|
116
|
+
|
117
|
+
После конфигурации Petrovich можно легко выполнять склонение необходимых
|
118
|
+
строк.
|
100
119
|
|
101
120
|
```ruby
|
102
121
|
user = User.new
|
@@ -107,8 +126,6 @@ user.my_middlename_dative # => Петровичу
|
|
107
126
|
user.my_lastname_dative # => Петренко
|
108
127
|
```
|
109
128
|
|
110
|
-
и для второго примера:
|
111
|
-
|
112
129
|
```ruby
|
113
130
|
person = Person.new
|
114
131
|
person.name # => Иван
|
@@ -117,44 +134,91 @@ person.my_firstname_dative # => Ивану
|
|
117
134
|
person.my_middlename_dative # => Олеговичу
|
118
135
|
person.my_lastname_dative # => Сафронову
|
119
136
|
```
|
120
|
-
Изначальное имя должно быть в именительнои падеже. Вы просто добавляете `_падеж` в конец имени оригинального метода и получаете нужное значение. Вот список суффиксов, которые вы можете добавить к имени оригинального метода, чтобы получить имя в нужном падаже:
|
121
137
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
* instrumentative - творительный
|
126
|
-
* prepositional - предложный
|
138
|
+
Базовое имя должно быть в именительном падеже. Вы просто добавляете
|
139
|
+
`_падеж` в конец имени оригинального метода и получаете заданное имя
|
140
|
+
в требуемом падеже.
|
127
141
|
|
128
|
-
|
142
|
+
Вот список суффиксов, которые вы можете добавить к имени метода, чтобы
|
143
|
+
получить имя в нужном падеже:
|
129
144
|
|
130
|
-
*
|
131
|
-
*
|
145
|
+
* genitive — родительный;
|
146
|
+
* dative — дательный;
|
147
|
+
* accusative — винительный;
|
148
|
+
* instrumental — творительный;
|
149
|
+
* prepositional — предложный.
|
132
150
|
|
133
|
-
##
|
151
|
+
## Оценка точности
|
134
152
|
|
135
|
-
|
153
|
+
Тестирование гема при склонении коллекции фамилий из морфологического
|
154
|
+
словаря [АОТ] показало точность около 99%. Оригинальный словарь
|
155
|
+
распространяется по лицензии LGPL версии 2.1, однако используется
|
156
|
+
только в задаче оценки точности данного гема.
|
136
157
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
* Веб-интерфейс для проверки имён (ф.и.о) и их логгирования, для улучшения правил распознавания.
|
141
|
-
* Проверка работы с mongoid и mongo-mapper
|
158
|
+
Для оценки точности достаточно выполнить команду `rake evaluate`. После
|
159
|
+
выполнения этой команды в поток стандартного вывода будут напечатаны
|
160
|
+
результаты оценки с данными в словаре АОТ.
|
142
161
|
|
143
|
-
|
162
|
+
```
|
163
|
+
Pr(nominative|male) = 100.0000%
|
164
|
+
Pr(genitive|male) = 99.6763%
|
165
|
+
Pr(dative|male) = 99.7012%
|
166
|
+
Pr(accusative|male) = 99.7261%
|
167
|
+
Pr(instrumental|male) = 97.9485%
|
168
|
+
Pr(prepositional|male) = 99.6888%
|
169
|
+
```
|
170
|
+
```
|
171
|
+
Pr(nominative|female) = 100.0000%
|
172
|
+
Pr(genitive|female) = 99.8652%
|
173
|
+
Pr(dative|female) = 99.8952%
|
174
|
+
Pr(accusative|female) = 99.9251%
|
175
|
+
Pr(instrumental|female) = 99.4189%
|
176
|
+
Pr(prepositional|female) = 99.8952%
|
177
|
+
```
|
144
178
|
|
145
|
-
|
179
|
+
В настоящий момент наблюдается точность в 99.6275% на основе обработки
|
180
|
+
88314 примеров.
|
146
181
|
|
147
|
-
|
182
|
+
[АОТ]: http://seman.svn.sourceforge.net/viewvc/seman/trunk/Docs/Morph_UNIX.txt?revision=HEAD&view=markup
|
148
183
|
|
149
|
-
|
184
|
+
## Модульные тесты
|
185
|
+
|
186
|
+
Чтобы запустить тесты, тестирующие фамилии, нужно установить переменную
|
187
|
+
окружения `TEST_SURNAMES`:
|
188
|
+
|
189
|
+
```shell
|
150
190
|
TEST_SURNAMES=1 rspec
|
151
191
|
```
|
152
192
|
|
193
|
+
## Разработчики
|
194
|
+
|
195
|
+
* [Андрей Козлов](https://github.com/tanraya) — идея, реализация.
|
196
|
+
* [Дмитрий Усталов](http://eveel.ru) — неоценимая помощь.
|
197
|
+
|
198
|
+
## Дальнейшее развитие
|
199
|
+
|
200
|
+
Мы планируем и далее улучшать этот проект. Поэтому нам важен отклик от
|
201
|
+
пользователей данного гема. Вот наши планы:
|
202
|
+
|
203
|
+
* добавить отладочный режим, чтобы видеть, какое именно правило было
|
204
|
+
использовано при словообразовании;
|
205
|
+
* интерфейс командной строки, чтобы работать с гемом из командной строки;
|
206
|
+
* Web-интерфейс для обработки ФИО;
|
207
|
+
* проверка совместимости с различными ORM и сторонними библиотеками.
|
208
|
+
|
209
|
+
Если вы хотите помочь этому проекту, вы можете реализовать любую
|
210
|
+
вышеперечисленную идею. Перед этим желательно связаться с нами,
|
211
|
+
чтобы мы были в курсе.
|
212
|
+
|
153
213
|
## Содействие
|
154
214
|
|
155
|
-
Если вы нашли баги, как программной части, так и в
|
215
|
+
Если вы нашли баги, как программной части, так и в базе правил, то вы всегда
|
216
|
+
можете форкнуть репозиторий и внести необходимые изменения. Ваша помощь не
|
217
|
+
останется незамеченной! Если вы заметили ошибки при склонении падежей имён,
|
218
|
+
фамилий или отчеств, можете написать об этом в Issues на GitHub.
|
219
|
+
Проблема будет сразу же исследована и, по возможности, решена.
|
156
220
|
|
157
|
-
Не стесняйтесь добавлять улучшения.
|
221
|
+
Не стесняйтесь добавлять улучшения.
|
158
222
|
|
159
223
|
1. Fork it
|
160
224
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
data/Rakefile
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
|
7
6
|
begin
|
8
7
|
require 'rdoc/task'
|
9
8
|
rescue LoadError
|
@@ -12,7 +11,14 @@ rescue LoadError
|
|
12
11
|
RDoc::Task = Rake::RDocTask
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
require 'rspec/core/rake_task'
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
16
|
+
|
17
|
+
task :petrovich do
|
18
|
+
require 'petrovich'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Run tests and perform evaluation by default
|
22
|
+
task :default => [:spec, :evaluate]
|
17
23
|
|
18
|
-
|
24
|
+
Dir.glob('lib/tasks/*.rake').each { |r| import r }
|
data/lib/petrovich.rb
CHANGED
@@ -31,18 +31,18 @@ require 'petrovich/extension'
|
|
31
31
|
# * +:genitive+ - родительный
|
32
32
|
# * +:dative+ - дательный
|
33
33
|
# * +:accusative+ - винительный
|
34
|
-
# * +:
|
34
|
+
# * +:instrumental+ - творительный
|
35
35
|
# * +:prepositional+ - предложный
|
36
36
|
#
|
37
37
|
class Petrovich
|
38
|
-
CASES = [:nominative, :genitive, :dative, :accusative, :
|
38
|
+
CASES = [:nominative, :genitive, :dative, :accusative, :instrumental, :prepositional]
|
39
39
|
|
40
|
-
NOMINATIVE = :nominative
|
41
|
-
GENITIVE = :genitive
|
42
|
-
DATIVE = :dative
|
43
|
-
ACCUSATIVE = :accusative
|
44
|
-
INSTRUMENTATIVE = :
|
45
|
-
PREPOSITIONAL = :prepositional
|
40
|
+
NOMINATIVE = :nominative # именительный
|
41
|
+
GENITIVE = :genitive # родительный
|
42
|
+
DATIVE = :dative # дательный
|
43
|
+
ACCUSATIVE = :accusative # винительный
|
44
|
+
INSTRUMENTATIVE = :instrumental # творительный
|
45
|
+
PREPOSITIONAL = :prepositional # предложный
|
46
46
|
|
47
47
|
def initialize(gender = nil)
|
48
48
|
@gender = gender.to_s
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
CASES = [
|
6
|
+
:nominative,
|
7
|
+
:genitive,
|
8
|
+
:dative,
|
9
|
+
:accusative,
|
10
|
+
:instrumental,
|
11
|
+
:prepositional
|
12
|
+
]
|
13
|
+
|
14
|
+
def check!(errors, correct, total, lemma, gender, gcase, expected)
|
15
|
+
inflector = Petrovich.new(gender)
|
16
|
+
inflection = begin
|
17
|
+
UnicodeUtils.upcase(inflector.lastname(lemma, gcase))
|
18
|
+
rescue
|
19
|
+
''
|
20
|
+
end
|
21
|
+
|
22
|
+
total[[gender, gcase]] += 1
|
23
|
+
|
24
|
+
if inflection == expected
|
25
|
+
correct[[gender, gcase]] += 1
|
26
|
+
true
|
27
|
+
else
|
28
|
+
errors << [lemma, expected, inflection, [gender, gcase]]
|
29
|
+
inflection
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Evaluate the inflector on surnames'
|
34
|
+
task :evaluate => :petrovich do
|
35
|
+
filename = File.expand_path('../../../spec/data/surnames.tsv', __FILE__)
|
36
|
+
errors_filename = ENV['errors'] || 'errors.tsv'
|
37
|
+
|
38
|
+
correct, total = Hash.new(0), Hash.new(0)
|
39
|
+
|
40
|
+
puts 'I will evaluate the inflector on "%s" ' \
|
41
|
+
'and store errors to "%s".' % [filename, errors_filename]
|
42
|
+
|
43
|
+
CSV.open(errors_filename, 'w', col_sep: "\t") do |errors|
|
44
|
+
errors << %w(lemma expected actual params)
|
45
|
+
|
46
|
+
CSV.open(filename, col_sep: "\t", headers: true).each do |row|
|
47
|
+
word = row['word'].force_encoding('UTF-8')
|
48
|
+
lemma = row['lemma'].force_encoding('UTF-8')
|
49
|
+
|
50
|
+
grammemes = if row['grammemes']
|
51
|
+
row['grammemes'].force_encoding('UTF-8').split(',')
|
52
|
+
else
|
53
|
+
[]
|
54
|
+
end
|
55
|
+
|
56
|
+
gender = grammemes.include?('мр') ? :male : :female
|
57
|
+
|
58
|
+
if grammemes.include? '0'
|
59
|
+
# some words are aptotic so we have to ensure that
|
60
|
+
CASES.each do |gcase|
|
61
|
+
check! errors, correct, total, lemma, gender, gcase, word
|
62
|
+
end
|
63
|
+
elsif grammemes.include? 'им'
|
64
|
+
check! errors, correct, total, lemma, gender, :nominative, word
|
65
|
+
elsif grammemes.include? 'рд'
|
66
|
+
check! errors, correct, total, lemma, gender, :genitive, word
|
67
|
+
elsif grammemes.include? 'дт'
|
68
|
+
check! errors, correct, total, lemma, gender, :dative, word
|
69
|
+
elsif grammemes.include? 'вн'
|
70
|
+
check! errors, correct, total, lemma, gender, :accusative, word
|
71
|
+
elsif grammemes.include? 'тв'
|
72
|
+
# actually, it's called the instrumetal case
|
73
|
+
check! errors, correct, total, lemma, gender, :instrumental, word
|
74
|
+
elsif grammemes.include? 'пр'
|
75
|
+
check! errors, correct, total, lemma, gender, :prepositional, word
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
total.each do |(gender, gcase), correct_count|
|
81
|
+
precision = correct[[gender, gcase]] / correct_count.to_f * 100
|
82
|
+
puts "\tPr(%s|%s) = %.4f%%" % [gcase, gender, precision]
|
83
|
+
end
|
84
|
+
|
85
|
+
correct_size = correct.values.inject(&:+)
|
86
|
+
total_size = total.values.inject(&:+)
|
87
|
+
puts 'Well, the precision on %d examples is about %.4f%%.' %
|
88
|
+
[total_size, (correct_size / total_size.to_f * 100)]
|
89
|
+
end
|
metadata
CHANGED
@@ -1,32 +1,33 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: petrovich
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrew Kozloff
|
9
|
+
- Dmitry Ustalov
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2013-
|
13
|
+
date: 2013-05-13 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: unicode_utils
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
|
-
- -
|
20
|
+
- - ~>
|
20
21
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.4
|
22
|
+
version: '1.4'
|
22
23
|
type: :runtime
|
23
24
|
prerelease: false
|
24
25
|
version_requirements: !ruby/object:Gem::Requirement
|
25
26
|
none: false
|
26
27
|
requirements:
|
27
|
-
- -
|
28
|
+
- - ~>
|
28
29
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.4
|
30
|
+
version: '1.4'
|
30
31
|
- !ruby/object:Gem::Dependency
|
31
32
|
name: rspec
|
32
33
|
requirement: !ruby/object:Gem::Requirement
|
@@ -63,6 +64,7 @@ description: Вы задаёте начальное имя в именитель
|
|
63
64
|
вам
|
64
65
|
email:
|
65
66
|
- demerest@gmail.com
|
67
|
+
- dmitry@eveel.ru
|
66
68
|
executables: []
|
67
69
|
extensions: []
|
68
70
|
extra_rdoc_files: []
|
@@ -71,6 +73,7 @@ files:
|
|
71
73
|
- lib/petrovich/rules.rb
|
72
74
|
- lib/petrovich/rules.yml
|
73
75
|
- lib/petrovich.rb
|
76
|
+
- lib/tasks/evaluate.rake
|
74
77
|
- MIT-LICENSE
|
75
78
|
- Rakefile
|
76
79
|
- README.md
|