bp_net 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/bp_net.rb +108 -0
- 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: []
|