bp_net 0.0.2

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/bp_net.rb +108 -0
  3. metadata +43 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4ae78900480ba50a21932b089dfb61c8008e4094255da4c76f1b8897ee3a9b8b
4
+ data.tar.gz: ea012ac44327f5e91df5da58c131c0df5a637aa27a613200ae21b1a2f2ed92f7
5
+ SHA512:
6
+ metadata.gz: 9fe9e7a877f4dbc80c403bcb072bf9051dc9c77a7ad182ce5a4f737beb3d0e082e6fa7b40af6bd4ce954c919d17d0b11e7dd9b49ccac0b1ec01b0e37910a5fbe
7
+ data.tar.gz: e4b2b7e6a1269ea7659e0de5bb8ade20e247172490a74432e6aa3a0a219ba3c0ba1f037fa4b5d15ef2b1d40d92cc5b23e4047037f7a0286499de2476874b7f8f
data/lib/bp_net.rb ADDED
@@ -0,0 +1,108 @@
1
+ require 'matrix'
2
+
3
+ class Matrix
4
+ def disp(line_feed: 1)
5
+ row_vectors.each do |row| # self.row_vectors...
6
+ row.each do |ele| # print elements by row
7
+ print "#{ele}\t"
8
+ end
9
+ line_feed.times { puts } # Line Feed
10
+ end
11
+ self
12
+ end
13
+ end
14
+
15
+ class BpNet
16
+ # accessable attributes
17
+ ACCESSABLE_ATTRS = %i[inodes hnodes onodes lr wih who]
18
+ attr_accessor(*ACCESSABLE_ATTRS)
19
+
20
+ # initialization
21
+ def initialize(inputnodes:, hiddennodes:, outputnodes:, learningrate:)
22
+ @inodes = inputnodes # input nodes
23
+ @hnodes = hiddennodes # hidden nodes
24
+ @onodes = outputnodes # output nodes
25
+ @lr = learningrate # learning rate
26
+
27
+ # weight matrixes
28
+ @wih = Matrix.build(hiddennodes, inputnodes) { rand - 0.5 }
29
+ @who = Matrix.build(outputnodes, hiddennodes) { rand - 0.5 }
30
+ end
31
+
32
+ # train
33
+ def train(inputs_mat, targets_mat)
34
+ inputs_mat = arr2mat(inputs_mat) # convert array to matrix
35
+ targets_mat = arr2mat(targets_mat) # convert arr 2 mat
36
+
37
+ hidden_inputs = @wih * inputs_mat # Hi = Wih * I
38
+ hidden_outputs = BpNet.sigmoid(hidden_inputs) # H = sigmoid(Hi)
39
+ outputs_inputs = @who * hidden_outputs # Oi = Who * H
40
+ outputs_outputs = BpNet.sigmoid(outputs_inputs) # O = sigmoid(Oi)
41
+
42
+ output_errors = targets_mat - outputs_outputs
43
+ @who += update(output_errors, outputs_inputs, hidden_outputs)
44
+
45
+ hidden_errors = @who.t * output_errors
46
+ @wih += update(hidden_errors, hidden_inputs, inputs_mat)
47
+ end
48
+
49
+ # query
50
+ # Hi = Wih * I
51
+ # H = sigmoid(Hi)
52
+ # Oi = Who * H
53
+ # O = sigmoid(Oi)
54
+ def query(inputs_mat)
55
+ inputs_mat = arr2mat(inputs_mat) # convert array to matrix
56
+
57
+ hidden_inputs = @wih * inputs_mat # Hi = Wih * I
58
+ hidden_outputs = BpNet.sigmoid(hidden_inputs) # H = sigmoid(Hi)
59
+ outputs_inputs = @who * hidden_outputs # Oi = Who * H
60
+ outputs_outputs = BpNet.sigmoid(outputs_inputs) # O = sigmoid(Oi)
61
+ end
62
+
63
+ def arr2mat(arr)
64
+ if arr.is_a? Array
65
+ Matrix[arr].t
66
+ else
67
+ arr
68
+ end
69
+ end
70
+
71
+ ## calculations goes here
72
+ # singular sigmoid
73
+ @singular_sigmoid = ->(x) { 1 / (1 + Math::E**-x) }
74
+
75
+ # singular sigmoid differentiation
76
+ @singular_sigmoid_diff = lambda do |x|
77
+ @singular_sigmoid.call(x) * (1 - @singular_sigmoid.call(x))
78
+ end
79
+
80
+ def update(errors, next_inputs, prev_outputs)
81
+ @lr *
82
+ errors.hadamard_product(BpNet.sigmoid_diff(next_inputs)) *
83
+ prev_outputs.t
84
+ end
85
+
86
+ ## packed enumerable calculations
87
+ # sigmoid
88
+ def self.sigmoid(x)
89
+ enum_calc(x, @singular_sigmoid) { |param| sigmoid(param) }
90
+ end
91
+
92
+ # sigmoid differentiation
93
+ def self.sigmoid_diff(x)
94
+ enum_calc(x, @singular_sigmoid_diff) { |param| sigmoid_diff(param) }
95
+ end
96
+
97
+ ## enumerable calculation
98
+ def self.enum_calc(x, calc, &block)
99
+ if x.is_a? Enumerable
100
+ x.map(&block) # return values recursively
101
+ else
102
+ calc.call(x) # return value
103
+ end
104
+ end
105
+
106
+ # private class methods
107
+ private_class_method :enum_calc
108
+ end
metadata ADDED
@@ -0,0 +1,43 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bp_net
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Rurika Misaka
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-05-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A sipmle BP Neural Network gem
14
+ email: goblinmaiden1931@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/bp_net.rb
20
+ homepage:
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubygems_version: 3.2.3
40
+ signing_key:
41
+ specification_version: 4
42
+ summary: Simple BP Neural Network
43
+ test_files: []