rubykov 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9827c73272cba93ae8557afe9cd9158175f5710c
4
- data.tar.gz: 3cafc24fa4870f60450dae6d2a5aa692ee3f72c7
3
+ metadata.gz: be1de15771cfa1694a274b2ad2659c565c0898f1
4
+ data.tar.gz: 1cc4d87fbacfeeaeebf0ad8c32e15cff7887e480
5
5
  SHA512:
6
- metadata.gz: b62a34df1580d94914ca0fe4bb171ba5d7449857e3f7323d72958930a912e9b69e67664eb23ce1b7562f14168890a8b46c549d754848951eaa94998ee875074f
7
- data.tar.gz: bc3f35303e83992f01ec220d032a70371682e4a173912807219a34cd924f1416defc62cdf014bb30ffccf9fbb3b2abb42cf8371b0264659ad0637f4490945545
6
+ metadata.gz: 0fcc4cd9b24f2185c2ee429fbf37de51c0ef8ec0efd5c117afb42632a0d34662131e48c056b01496d682f663ea636cee1b5774b1ea89ca1d06f854de5e19236b
7
+ data.tar.gz: bfa02c7f821816395aaf2266fdb85cd94ce798453121fda7d73ebd3fb3912ec9b44c48e8b6684920a3ac7cff20d55ef0ffd983644ae99b24da980d987434aed3
data/lib/rubykov.rb CHANGED
@@ -1,2 +1,4 @@
1
1
  require 'rubykov/markov_model'
2
2
  require 'rubykov/text_generator'
3
+ require 'rubykov/hidden_markov_model'
4
+ require 'rubykov/word_generator'
@@ -0,0 +1,58 @@
1
+ module Rubykov
2
+ class HiddenMarkovModel
3
+ def initialize(states, observations, start_probability, transition_probabilities, emission_probabilities)
4
+ @states = states
5
+ @observations = observations
6
+ @start_probability = start_probability
7
+ @transition_probabilities = transition_probabilities
8
+ @observation_probabilities = emission_probabilities
9
+ end
10
+
11
+ def most_likely_state_sequence(observation_sequence)
12
+ max_probabilities(observation_sequence).map(&:first)
13
+ end
14
+
15
+ def most_likely_state_sequence_probability(observation_sequence)
16
+ max_probabilities(observation_sequence).last.last
17
+ end
18
+
19
+ private
20
+
21
+ def max_probabilities(observation_sequence)
22
+ compute_viterbi_probabilities(observation_sequence.map(&:to_sym)).map do |probability|
23
+ probability.max_by { |k,v| v }
24
+ end
25
+ end
26
+
27
+ def compute_viterbi_probabilities(observations)
28
+ state_max_probabilities = []
29
+
30
+ observations.each_with_index do |observation, index|
31
+ state_max_probabilities[index] = {}
32
+ @states.each do |state|
33
+ state_max_probabilities[index][state] = 0
34
+ state_max_probabilities.first[state] = @start_probability[state] * @observation_probabilities[state][observations.first]
35
+ end
36
+ end
37
+
38
+ observations[1..-1].each_with_index do |observation, index|
39
+ @states.each do |state|
40
+ max_probability = state_max_probabilities[index].map { |previous_state, previous_probability| @transition_probabilities[previous_state][state] * previous_probability }.max
41
+ state_max_probabilities[index+1][state] = @observation_probabilities[state][observation] * max_probability
42
+ end
43
+ end
44
+
45
+ state_max_probabilities
46
+ end
47
+
48
+ def sample(probability_distribution)
49
+ random_value = rand
50
+
51
+ probability_ranges = probability_distribution.inject([0]) do |memo, p|
52
+ memo << p.last + memo.last
53
+ end
54
+
55
+ probability_distribution[probability_ranges.rindex { |x| x <= random_value }].first
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,44 @@
1
+ module Rubykov
2
+ class WordGenerator < MarkovModel
3
+ def initialize(order, training_data)
4
+ super(order, training_data)
5
+ end
6
+
7
+ def train(training_data)
8
+ add_data_to_model(training_data)
9
+ end
10
+
11
+ def word
12
+ chain.to_a.join('').capitalize
13
+ end
14
+
15
+ private
16
+
17
+ def massage_training_data(training_data)
18
+ training_data.map { |datum| datum.downcase.split('') + ['\n'] }
19
+ end
20
+
21
+ def add_data_to_model(training_data)
22
+ massage_training_data(training_data).each do |datum|
23
+ super(datum)
24
+ end
25
+ end
26
+
27
+ def chain_enumerator(seed_state = states.sample)
28
+ Enumerator.new do |output|
29
+ current_state = seed_state
30
+ current_state.each do |word|
31
+ output << word
32
+ end
33
+
34
+ loop do
35
+ break if @representation[current_state].nil?
36
+ next_letter = @representation[current_state].sample
37
+ break if next_letter == '\\n'
38
+ output << next_letter
39
+ current_state = current_state.last(@order-1) + [next_letter]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubykov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Hemsley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-10 00:00:00.000000000 Z
11
+ date: 2017-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -38,8 +38,10 @@ extra_rdoc_files: []
38
38
  files:
39
39
  - README.md
40
40
  - lib/rubykov.rb
41
+ - lib/rubykov/hidden_markov_model.rb
41
42
  - lib/rubykov/markov_model.rb
42
43
  - lib/rubykov/text_generator.rb
44
+ - lib/rubykov/word_generator.rb
43
45
  - license.md
44
46
  homepage: https://gitlab.com/ehemsley/rubykov
45
47
  licenses:
@@ -61,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
63
  version: '0'
62
64
  requirements: []
63
65
  rubyforge_project:
64
- rubygems_version: 2.2.2
66
+ rubygems_version: 2.5.1
65
67
  signing_key:
66
68
  specification_version: 4
67
69
  summary: Sensible, easy Markov models in Ruby.