baby_face 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +94 -0
- data/Rakefile +1 -0
- data/baby_face.gemspec +26 -0
- data/bin/baby_face +3 -0
- data/lib/baby_face/configuration.rb +9 -0
- data/lib/baby_face/stand.rb +92 -0
- data/lib/baby_face/version.rb +3 -0
- data/lib/baby_face.rb +27 -0
- data/spec/baby_face/stand_spec.rb +109 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d3c03bdf7d6799c174a0c9c535c6fab41f18bccb
|
4
|
+
data.tar.gz: a6919788bac4954f5c982c2ca359e492c5bdfae9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 20a084a3ff38c57b8d480a396a11592285287b632c61172f444bb74a4247bf763865c15a916bdf466d3dcd08d093a415ed7460d00d55d7e7caf0e915fd5de036
|
7
|
+
data.tar.gz: 2c4955b4aff1056b0022a21f3838f771aa20f698b34007b7d78024873ca89ee5a483a0788e90d1f428e4ebd6aa3d57734e66fdf498afe8efe1d1ec50b8bde788
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Yoshiori SHOJI
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# BabyFace
|
2
|
+
|
3
|
+
baby_face is a simple machine learning module.
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'baby_face'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install baby_face
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### target model( Poro, ActiveModel, ...)
|
24
|
+
```ruby
|
25
|
+
class Jedi
|
26
|
+
include BabyFace
|
27
|
+
acts_as_babyface features: :name,
|
28
|
+
categories: [:light_side, :dark_side]
|
29
|
+
|
30
|
+
attr_accessor :name
|
31
|
+
def initialize(name)
|
32
|
+
@name = name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
### training
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
Jedi.new("Anakin Skywalker").babyface.train_light_side
|
41
|
+
Jedi.new("Darth Maul").babyface.train_dark_side
|
42
|
+
```
|
43
|
+
|
44
|
+
### classify
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
Jedi.new("Luke Skywalker").babyface.light_side? # => true
|
48
|
+
Jedi.new("Darth Vader").babyface.dark_side? # => true
|
49
|
+
```
|
50
|
+
|
51
|
+
### save training data
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
BabyFace.configuration.data_dir = "/tmp/baby_face"
|
55
|
+
Jedi.new("Luke Skywalker").babyface.save # => /tmp/baby_face/jedi.babyface
|
56
|
+
```
|
57
|
+
|
58
|
+
|
59
|
+
## more
|
60
|
+
### tokenizer
|
61
|
+
default : String#split
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
acts_as_babyface features: :name,
|
65
|
+
categories: [:ham, :spam],
|
66
|
+
tokenizer: ->(text) {[text.upcase]}
|
67
|
+
|
68
|
+
```
|
69
|
+
|
70
|
+
### nested object
|
71
|
+
support nested BabyFace object, array and hash.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
class Entry < ActiveRecord::Base
|
75
|
+
has_many :comments
|
76
|
+
include BabyFace
|
77
|
+
acts_as_babyface features: :title, :body, :comments,
|
78
|
+
categories: [:ham, :spam]
|
79
|
+
end
|
80
|
+
|
81
|
+
class Comment < ActiveRecord::Base
|
82
|
+
include BabyFace
|
83
|
+
acts_as_babyface features: :title, :message
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
1. Fork it
|
91
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
92
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
93
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
94
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/baby_face.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'baby_face/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "baby_face"
|
8
|
+
spec.version = BabyFace::VERSION
|
9
|
+
spec.authors = ["Yoshiori SHOJI"]
|
10
|
+
spec.email = ["yoshiori@gmail.com"]
|
11
|
+
spec.description = "baby_face is a simple machine learning module."
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = "https://github.com/yoshiori/baby_face"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "classifier"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
end
|
data/bin/baby_face
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "baby_face/configuration"
|
2
|
+
require 'pstore'
|
3
|
+
require 'classifier'
|
4
|
+
|
5
|
+
class BabyFace::Stand
|
6
|
+
def initialize(mod)
|
7
|
+
@mod = mod
|
8
|
+
@categories = mod.class.class_variable_get(:@@_categories)
|
9
|
+
@categories.each do |category|
|
10
|
+
self.class.class_eval do
|
11
|
+
define_method("#{category}?") {
|
12
|
+
bayes.classify(to_feature).gsub(" ", "_").downcase == category.to_s
|
13
|
+
}
|
14
|
+
|
15
|
+
define_method("train_#{category}") {
|
16
|
+
bayes.train(category, to_feature)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@tokenizer = mod.class.class_variable_get(:@@_tokenizer)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_feature
|
24
|
+
def scan(prefix, obj)
|
25
|
+
obj.class.class_variable_get(:@@_features).map do |attr|
|
26
|
+
_prefix = prefix.nil? ? attr : "#{prefix}_#{attr}"
|
27
|
+
value = obj.send(attr)
|
28
|
+
if value.is_a? BabyFace
|
29
|
+
scan(_prefix, value)
|
30
|
+
elsif value.is_a? Array
|
31
|
+
value.map do |val|
|
32
|
+
scan(_prefix, val)
|
33
|
+
end
|
34
|
+
elsif value.is_a? Hash
|
35
|
+
value.map do |key, val|
|
36
|
+
scan("#{_prefix}_#{key}", val)
|
37
|
+
end
|
38
|
+
else
|
39
|
+
wakachi(value.to_s).map do |text|
|
40
|
+
"#{_prefix}_#{text}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
scan(nil, @mod).flatten.join(" ")
|
46
|
+
end
|
47
|
+
|
48
|
+
def wakachi(text)
|
49
|
+
@tokenizer ? @tokenizer.call(text) : text.split
|
50
|
+
end
|
51
|
+
|
52
|
+
def save
|
53
|
+
bayes # Memoization (first access is in transaction)
|
54
|
+
pstore.transaction do
|
55
|
+
pstore[@mod.class.name] = bayes
|
56
|
+
pstore.commit
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def data_path
|
62
|
+
if BabyFace.configuration.data_dir
|
63
|
+
Pathname.new(BabyFace.configuration.data_dir).join("#{@mod.class.name.downcase}.babyface")
|
64
|
+
else
|
65
|
+
Pathname.new("#{@mod.class.name.downcase}.babyface")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def pstore
|
70
|
+
if @mod.class.class_variable_defined?(:@@_pstore)
|
71
|
+
@mod.class.class_variable_get(:@@_pstore)
|
72
|
+
else
|
73
|
+
@mod.class.class_variable_set(:@@_pstore, PStore.new(data_path))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def bayes
|
78
|
+
if @mod.class.class_variable_defined?(:@@_bayes)
|
79
|
+
@mod.class.class_variable_get(:@@_bayes)
|
80
|
+
else
|
81
|
+
@mod.class.class_variable_set(:@@_bayes,
|
82
|
+
if data_path && data_path.exist?
|
83
|
+
pstore.transaction(true) do
|
84
|
+
pstore[@mod.class.name]
|
85
|
+
end
|
86
|
+
else
|
87
|
+
::Classifier::Bayes.new *@categories
|
88
|
+
end
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/baby_face.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "baby_face/stand"
|
2
|
+
require "baby_face/configuration"
|
3
|
+
require "baby_face/version"
|
4
|
+
|
5
|
+
module BabyFace
|
6
|
+
|
7
|
+
def self.configuration
|
8
|
+
@configuration ||= Configuration.instance
|
9
|
+
end
|
10
|
+
|
11
|
+
def BabyFace.included(mod)
|
12
|
+
mod.define_singleton_method(
|
13
|
+
:acts_as_babyface,
|
14
|
+
lambda { |config|
|
15
|
+
features = *config[:features]
|
16
|
+
categories = *config[:categories]
|
17
|
+
mod.class_variable_set(:@@_features, features)
|
18
|
+
mod.class_variable_set(:@@_categories, categories)
|
19
|
+
mod.class_variable_set(:@@_tokenizer, config[:tokenizer])
|
20
|
+
}
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def babyface
|
25
|
+
@_babyface ||= BabyFace::Stand.new(self)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require "baby_face"
|
2
|
+
|
3
|
+
describe BabyFace::Stand do
|
4
|
+
|
5
|
+
describe "#to_feature" do
|
6
|
+
subject { target.babyface.to_feature }
|
7
|
+
|
8
|
+
class Hoge
|
9
|
+
include BabyFace
|
10
|
+
attr_accessor :title, :name
|
11
|
+
acts_as_babyface features: [:title, :name]
|
12
|
+
|
13
|
+
def initialize(title: "Revenge of the Sith", name: "Anakin Skywalker")
|
14
|
+
@title = title
|
15
|
+
@name = name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Bar
|
20
|
+
include BabyFace
|
21
|
+
attr_accessor :attr1, :attr2
|
22
|
+
acts_as_babyface features: [:attr1, :attr2]
|
23
|
+
|
24
|
+
def initialize(attr1: "foo", attr2: "bar")
|
25
|
+
@attr1 = attr1
|
26
|
+
@attr2 = attr2
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "Simple object" do
|
31
|
+
let(:target) { Hoge.new }
|
32
|
+
|
33
|
+
it { should eq "title_Revenge title_of title_the title_Sith name_Anakin name_Skywalker" }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "Nested object" do
|
37
|
+
let(:target) { Hoge.new(name: Bar.new) }
|
38
|
+
|
39
|
+
it { should eq "title_Revenge title_of title_the title_Sith name_attr1_foo name_attr2_bar" }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Nested array" do
|
43
|
+
let(:target) { Hoge.new(name: [Bar.new, Bar.new]) }
|
44
|
+
|
45
|
+
it { should eq "title_Revenge title_of title_the title_Sith name_attr1_foo name_attr2_bar name_attr1_foo name_attr2_bar" }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "Nested hash" do
|
49
|
+
let(:target) { Hoge.new(name: {bar1: Bar.new,bar2: Bar.new}) }
|
50
|
+
|
51
|
+
it { should eq "title_Revenge title_of title_the title_Sith name_bar1_attr1_foo name_bar1_attr2_bar name_bar2_attr1_foo name_bar2_attr2_bar" }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#wakachi" do
|
56
|
+
context "Default" do
|
57
|
+
class Dummy
|
58
|
+
include BabyFace
|
59
|
+
attr_accessor :name
|
60
|
+
acts_as_babyface features: :name
|
61
|
+
end
|
62
|
+
let(:babyface) { Dummy.new.babyface }
|
63
|
+
|
64
|
+
it { expect(babyface.wakachi("aaa bbb")).to eq ["aaa", "bbb"] }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "Use tokenizer" do
|
68
|
+
class Dummy2
|
69
|
+
include BabyFace
|
70
|
+
attr_accessor :name
|
71
|
+
acts_as_babyface features: :name,
|
72
|
+
tokenizer: ->(text) {[text.upcase]}
|
73
|
+
|
74
|
+
end
|
75
|
+
let(:babyface) { Dummy2.new.babyface }
|
76
|
+
|
77
|
+
it { expect(babyface.wakachi("aaa bbb")).to eq ["AAA BBB"] }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#train" do
|
82
|
+
class Jedi
|
83
|
+
include BabyFace
|
84
|
+
attr_accessor :name
|
85
|
+
acts_as_babyface features: :name,
|
86
|
+
categories: [:light_side, :dark_side]
|
87
|
+
|
88
|
+
def initialize(name)
|
89
|
+
@name = name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'train jedi' do
|
94
|
+
10.times {
|
95
|
+
Jedi.new("Anakin Skywalker").babyface.train_light_side
|
96
|
+
}
|
97
|
+
|
98
|
+
10.times {
|
99
|
+
Jedi.new("Darth Maul").babyface.train_dark_side
|
100
|
+
}
|
101
|
+
|
102
|
+
luke = Jedi.new("Luke Skywalker")
|
103
|
+
vader = Jedi.new("Darth Vader")
|
104
|
+
|
105
|
+
expect(luke.babyface).to be_light_side
|
106
|
+
expect(vader.babyface).to be_dark_side
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: baby_face
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yoshiori SHOJI
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: classifier
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: baby_face is a simple machine learning module.
|
70
|
+
email:
|
71
|
+
- yoshiori@gmail.com
|
72
|
+
executables:
|
73
|
+
- baby_face
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- baby_face.gemspec
|
83
|
+
- bin/baby_face
|
84
|
+
- lib/baby_face.rb
|
85
|
+
- lib/baby_face/configuration.rb
|
86
|
+
- lib/baby_face/stand.rb
|
87
|
+
- lib/baby_face/version.rb
|
88
|
+
- spec/baby_face/stand_spec.rb
|
89
|
+
homepage: https://github.com/yoshiori/baby_face
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.0.0
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: baby_face is a simple machine learning module.
|
113
|
+
test_files:
|
114
|
+
- spec/baby_face/stand_spec.rb
|