Module: FastForward
- Defined in:
- lib/fast_forward.rb,
lib/fast_forward/nn.rb,
lib/fast_forward/version.rb
Defined Under Namespace
Classes: NN
Constant Summary collapse
- DEFAULT_TOL =
Default tolerance for integrity check
1e-8
- SUPPORTED_ACTIVATIONS =
Supported activation functions
["identity", "relu", "sigmoid", "tanh", "softmax"].freeze
- VERSION =
"0.1.0"
Class Method Summary collapse
-
.load(data, tol: DEFAULT_TOL, exception_if_fail: true) ⇒ Object
Loads neural network data into a NN object.
-
.load_json(data, tol: DEFAULT_TOL, exception_if_fail: true) ⇒ Object
Loads neural network from JSON data/string into a NN object.
-
.load_pmml(data, sample_data: nil, tol: DEFAULT_TOL, exception_if_fail: true) ⇒ Object
Loads neural network from PMML file into a NN object.
-
.load_sample_data(data) ⇒ Object
Loads sample data.
Class Method Details
.load(data, tol: DEFAULT_TOL, exception_if_fail: true) ⇒ Object
data is supposed to have the following structure: data = { weights: [weights_array_0, weights_array_1 , …], biases: [biases_array_0, biases_array_1 , …], activations: [activation_fct_0, activation_fct_1, …], samples: (optional) { X: sample_inputs_array, y: sample_outputs_array } }
Loads neural network data into a NN object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/fast_forward.rb', line 35 def self.load(data, tol: DEFAULT_TOL, exception_if_fail: true) # check inputs if data[:weights].nil? || data[:weights].count == 0 raise ArgumentError, "Missing weights data" elsif data[:biases].nil? || data[:biases].count == 0 raise ArgumentError, "Missing biases data" elsif data[:activations].nil? || data[:activations].count == 0 raise ArgumentError, "Missing activation functions" elsif data[:weights].size != data[:biases].size raise ArgumentError, "Array of weights and biases must have the same size" elsif data[:weights].size != data[:activations].size raise ArgumentError, "Array of weights and activations must have the same size" elsif !data[:activations].map{ |act| SUPPORTED_ACTIVATIONS.include?(act) }.all? raise ArgumentError, "Some activation functions are not supported" end layer_sizes = data[:weights].map(&:count) + [data[:weights].last.first.count] nn = NN.new(layer_sizes, data[:activations], data[:weights], data[:biases]) if !data[:samples].nil? && tol >= 0 FastForward.check_model_integrity(nn, data[:samples], tol: tol, exception_if_fail: exception_if_fail, verbose: true) end return nn end |
.load_json(data, tol: DEFAULT_TOL, exception_if_fail: true) ⇒ Object
data is supposed to have the following structure: data = { “weights”: { “0”: weights_array_0, “1”: weights_array_1, … }, “biases”: “0”: biases_array_0, “1”: biases_array_1, … }, “activations”: “0”: activation_fct_0, “1”: activation_fct_1, … }, “samples”: (optional) { “X”: sample_inputs_array, “y”: sample_outputs_array } }
Loads neural network from JSON data/string into a NN object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/fast_forward.rb', line 94 def self.load_json(data, tol: DEFAULT_TOL, exception_if_fail: true) data = JSON.parse(data) if data.is_a?(String) if data["weights"].keys != data["biases"].keys raise ArgumentError, "Incoherent weights and biases data" end n_layers = data["weights"].count # data["weights"] & data["biases"] are dictionaries of `"idx": array` d = { weights: n_layers.times.map{ |i| data["weights"][i.to_s] }, biases: n_layers.times.map{ |i| data["biases"][i.to_s] }, activations: n_layers.times.map{ |i| FastForward.rename_activation(data["activations"][i.to_s]) }, samples: FastForward.load_sample_data(data) } return FastForward.load(d, tol: tol, exception_if_fail: exception_if_fail) end |
.load_pmml(data, sample_data: nil, tol: DEFAULT_TOL, exception_if_fail: true) ⇒ Object
sample_data is supposed to have the following structure: sample_data = { “samples”: { “X”: sample_inputs_array, “y”: sample_outputs_array } }
Loads neural network from PMML file into a NN object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/fast_forward.rb', line 130 def self.load_pmml(data, sample_data: nil, tol: DEFAULT_TOL, exception_if_fail: true) # Load from PMML format: http://dmg.org/pmml/v4-3/NeuralNetwork.html # Note: does not support input transforms like NormContinuous # TODO: use element ids to check order data = Nokogiri::XML(data) if data.is_a?(String) all_weights = [] all_biases = [] all_activations = [] default_act = data.at_css("NeuralNetwork").attribute("activationFunction").value layers = data.css("NeuralLayer") layers.each do |layer| w = [] b = [] layer.css("Neuron").each do |neuron| b << neuron.attribute("bias").value.to_f w << neuron.css("Con").map{ |wi| wi.attribute("weight").value.to_f } end all_weights << w.transpose all_biases << b # in PMML format, softmax is a normalization and not an activation normalization = layer.attribute("normalizationMethod") && layer.attribute("normalizationMethod").value if normalization == "softmax" activation = "softmax" else layer_activation = layer.attribute("activationFunction") activation = layer_activation.nil? ? default_act : layer_activation.value end all_activations << FastForward.rename_activation(activation) end d = { weights: all_weights, biases: all_biases, activations: all_activations } d[:samples] = FastForward.load_sample_data(sample_data) unless sample_data.nil? return FastForward.load(d, tol: tol, exception_if_fail: exception_if_fail) end |
.load_sample_data(data) ⇒ Object
data is supposed to have the following structure: data = { “samples”: { “X”: sample_inputs_array, “y”: sample_outputs_array } }
Loads sample data
189 190 191 192 193 194 195 196 |
# File 'lib/fast_forward.rb', line 189 def self.load_sample_data(data) data = JSON.parse(data) if data.is_a?(String) d = { X: data["samples"]["X"], y: data["samples"]["y"] } return d end |