modelfox 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +15 -0
  4. data/LICENSE +21 -0
  5. data/README.md +36 -0
  6. data/docs/Tangram/BagOfWordsCosineSimilarityFeatureContribution.html +518 -0
  7. data/docs/Tangram/BagOfWordsFeatureContribution.html +518 -0
  8. data/docs/Tangram/Bigram.html +370 -0
  9. data/docs/Tangram/BinaryClassificationPredictOutput.html +502 -0
  10. data/docs/Tangram/FeatureContributions.html +444 -0
  11. data/docs/Tangram/IdentityFeatureContribution.html +444 -0
  12. data/docs/Tangram/LibTangram/TangramStringView.html +193 -0
  13. data/docs/Tangram/LibTangram.html +161 -0
  14. data/docs/Tangram/LoadModelOptions.html +296 -0
  15. data/docs/Tangram/Model.html +1290 -0
  16. data/docs/Tangram/MulticlassClassificationPredictOutput.html +576 -0
  17. data/docs/Tangram/NormalizedFeatureContribution.html +444 -0
  18. data/docs/Tangram/OneHotEncodedFeatureContribution.html +518 -0
  19. data/docs/Tangram/PredictOptions.html +428 -0
  20. data/docs/Tangram/RegressionPredictOutput.html +428 -0
  21. data/docs/Tangram/Unigram.html +296 -0
  22. data/docs/Tangram/WordEmbeddingFeatureContribution.html +444 -0
  23. data/docs/Tangram.html +128 -0
  24. data/docs/_index.html +317 -0
  25. data/docs/class_list.html +51 -0
  26. data/docs/css/common.css +1 -0
  27. data/docs/css/full_list.css +58 -0
  28. data/docs/css/style.css +497 -0
  29. data/docs/file.README.html +107 -0
  30. data/docs/file_list.html +56 -0
  31. data/docs/frames.html +17 -0
  32. data/docs/index.html +107 -0
  33. data/docs/js/app.js +314 -0
  34. data/docs/js/full_list.js +216 -0
  35. data/docs/js/jquery.js +4 -0
  36. data/docs/method_list.html +595 -0
  37. data/docs/top-level-namespace.html +110 -0
  38. data/lib/modelfox/libmodelfox/aarch64-linux-gnu/libmodelfox.so +0 -0
  39. data/lib/modelfox/libmodelfox/aarch64-linux-musl/libmodelfox.so +0 -0
  40. data/lib/modelfox/libmodelfox/aarch64-macos/libmodelfox.dylib +0 -0
  41. data/lib/modelfox/libmodelfox/x86_64-linux-gnu/libmodelfox.so +0 -0
  42. data/lib/modelfox/libmodelfox/x86_64-linux-musl/libmodelfox.so +0 -0
  43. data/lib/modelfox/libmodelfox/x86_64-macos/libmodelfox.dylib +0 -0
  44. data/lib/modelfox/libmodelfox/x86_64-windows-msvc/modelfox.dll +0 -0
  45. data/lib/modelfox/modelfox.rb +895 -0
  46. data/lib/modelfox.rb +1 -0
  47. data/modelfox.gemspec +15 -0
  48. data/scripts/build +11 -0
  49. data/scripts/dev +6 -0
  50. data/scripts/docs +2 -0
  51. data/scripts/fmt +0 -0
  52. data/scripts/release +1 -0
  53. metadata +109 -0
@@ -0,0 +1,895 @@
1
+ require 'date'
2
+ require 'ffi'
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'rbconfig'
6
+
7
+ # This is the main module in the `modelfox` gem.
8
+ module ModelFox
9
+
10
+ # These are the options passed when loading a model.
11
+ class LoadModelOptions
12
+ # If you are running the app locally or on your own server, use this field to provide the url to it. If not specified, the default value is https://app.modelfox.dev.
13
+ attr_reader :modelfox_url
14
+ def initialize(modelfox_url:)
15
+ @modelfox_url = modelfox_url
16
+ end
17
+ end
18
+
19
+ # These are the options passed to `predict`.
20
+ class PredictOptions
21
+ # If your model is a binary classifier, use this field to make predictions using a threshold chosen on the tuning page of the app. The default value is `0.5`.
22
+ attr_reader :threshold
23
+ # Computing feature contributions is disabled by default. If you set this field to `true`, you will be able to access the feature contributions with the `feature_contributions` field of the predict output.
24
+ attr_reader :compute_feature_contributions
25
+ def initialize(compute_feature_contributions:, threshold: nil)
26
+ @threshold = threshold
27
+ @compute_feature_contributions = compute_feature_contributions
28
+ end
29
+ def to_json(*args)
30
+ {'threshold' => @threshold, 'compute_feature_contributions' => @compute_feature_contributions}.to_json(*args)
31
+ end
32
+ end
33
+
34
+ # `predict` outputs `RegressionPredictOutput` when the model's task is regression.
35
+ class RegressionPredictOutput
36
+ # This is the predicted value.
37
+ attr_reader :value
38
+ # If computing feature contributions was enabled in the predict options, this value will explain the model's output, showing how much each feature contributed to the output.
39
+ attr_reader :feature_contributions
40
+ def initialize(value:, feature_contributions:)
41
+ @value = value
42
+ @feature_contributions = feature_contributions
43
+ end
44
+ def to_json(*args)
45
+ {'value' => @value}.to_json(*args)
46
+ end
47
+ end
48
+
49
+ # `predict` outputs `BinaryClassificationPredictOutput` when the model's task is binary classification.
50
+ class BinaryClassificationPredictOutput
51
+ # This is the name of the predicted class.
52
+ attr_reader :class_name
53
+ # This is the probability the model assigned to the predicted class.
54
+ attr_reader :probability
55
+ # If computing feature contributions was enabled in the predict options, this value will explain the model's output, showing how much each feature contributed to the output.
56
+ attr_reader :feature_contributions
57
+ def initialize(class_name:, probability:, feature_contributions:)
58
+ @class_name = class_name
59
+ @probability = probability
60
+ @feature_contributions = feature_contributions
61
+ end
62
+ def to_json(*args)
63
+ {'class_name' => @class_name, "probability" => @probability}.to_json(*args)
64
+ end
65
+ end
66
+
67
+ # `predict` outputs `MulticlassClassificationPredictOutput` when the model's task is multiclass classification.
68
+ class MulticlassClassificationPredictOutput
69
+ # This is the name of the predicted class.
70
+ attr_reader :class_name
71
+ # This is the probability the model assigned to the predicted class.
72
+ attr_reader :probability
73
+ # This value maps from class names to the probability the model assigned to each class.
74
+ attr_reader :probabilities
75
+ # If computing feature contributions was enabled in the predict options, this value will explain the model's output, showing how much each feature contributed to the output. This value maps from class names to `FeatureContributions` values for each class. The class with the `FeatureContributions` value with the highest `output_value` is the predicted class.
76
+ attr_reader :feature_contributions
77
+ def initialize(class_name:, probability:, probabilities:, feature_contributions:)
78
+ @class_name = class_name
79
+ @probability = probability
80
+ @probabilities = probabilities
81
+ @feature_contributions = feature_contributions
82
+ end
83
+ def to_json(*args)
84
+ {'class_name' => @class_name, "probability" => @probability, "probabilities" => @probabilities}.to_json(*args)
85
+ end
86
+ end
87
+
88
+ # This is a description of the feature contributions for the prediction if the task is regression or binary classification, or for a single class if the task is multiclass classification.
89
+ class FeatureContributions
90
+ # This is the value the model would output if all features had baseline values.
91
+ attr_reader :baseline
92
+ # This is the value the model output. Any difference from the `baseline_value` is because of the deviation of the features from their baseline values.
93
+ attr_reader :output
94
+ # This list will contain one entry for each of the model's features. Note that features are computed from columns, so there will likely be more features than columns.
95
+ attr_reader :entries
96
+ def initialize(baseline:, output:, entries:)
97
+ @baseline = baseline
98
+ @output = output
99
+ @entries = entries
100
+ end
101
+ end
102
+
103
+ # This describes the contribution of a feature from an identity feature group.
104
+ class IdentityFeatureContribution
105
+ # This is the name of the source column for the feature group.
106
+ attr_reader :column_name
107
+ # This is the value of the feature.
108
+ attr_reader :feature_value
109
+ # This is the amount that the feature contributed to the output.
110
+ attr_reader :feature_contribution_value
111
+ def initialize(column_name:, feature_contribution_value:, feature_value:)
112
+ @column_name = column_name
113
+ @feature_value = feature_value
114
+ @feature_contribution_value = feature_contribution_value
115
+ end
116
+ end
117
+
118
+ # This describes the contribution of a feature from a normalized feature group.
119
+ class NormalizedFeatureContribution
120
+ # This is the name of the source column for the feature group.
121
+ attr_reader :column_name
122
+ # This is the value of the feature.
123
+ attr_reader :feature_value
124
+ # This is the amount that the feature contributed to the output.
125
+ attr_reader :feature_contribution_value
126
+ def initialize(column_name:, feature_value:, feature_contribution_value:)
127
+ @column_name = column_name
128
+ @feature_value = feature_value
129
+ @feature_contribution_value = feature_contribution_value
130
+ end
131
+ end
132
+
133
+ # This describes the contribution of a feature from a one hot encoded feature group.
134
+ class OneHotEncodedFeatureContribution
135
+ # This is the name of the source column for the feature group.
136
+ attr_reader :column_name
137
+ # This is the enum variant the feature indicates the presence of.
138
+ attr_reader :variant
139
+ # This is the value of the feature.
140
+ attr_reader :feature_value
141
+ # This is the amount that the feature contributed to the output.b
142
+ attr_reader :feature_contribution_value
143
+ def initialize(column_name:, variant:, feature_contribution_value:, feature_value:)
144
+ @column_name = column_name
145
+ @variant = variant
146
+ @feature_contribution_value = feature_contribution_value
147
+ @feature_value = feature_value
148
+ end
149
+ end
150
+
151
+ # This describes the contribution of a feature from a bag of words feature group.
152
+ class BagOfWordsFeatureContribution
153
+ # This is the name of the source column for the feature group.
154
+ attr_reader :column_name
155
+ # This is the ngram for the feature.
156
+ attr_reader :ngram
157
+ # This is the value of the feature.
158
+ attr_reader :feature_value
159
+ # This is the amount that the feature contributed to the output.
160
+ attr_reader :feature_contribution_value
161
+ def initialize(column_name:, ngram:, feature_contribution_value:, feature_value:)
162
+ @column_name = column_name
163
+ @ngram = ngram
164
+ @feature_contribution_value = feature_contribution_value
165
+ @feature_value = feature_value
166
+ end
167
+ end
168
+
169
+ # This describes a unigram ngram.
170
+ class Unigram
171
+ # This is the token.
172
+ attr_reader :token
173
+ def initialize(token)
174
+ @token = token
175
+ end
176
+ end
177
+
178
+ # This describes a bigram ngram.
179
+ class Bigram
180
+ # This is the first token in the bigram.
181
+ attr_reader :token_a
182
+ # This is the second token in the bigram.
183
+ attr_reader :token_b
184
+ def initialize(token_a:, token_b:)
185
+ @token_a = token_a
186
+ @token_b = token_b
187
+ end
188
+ end
189
+
190
+ # This describes the contribution of a feature from a bag of words cosine similarity feature group.
191
+ class BagOfWordsCosineSimilarityFeatureContribution
192
+ # This is the name of the source column a for the feature group.
193
+ attr_reader :column_name_a
194
+ # This is the name of the source column b for the feature group.
195
+ attr_reader :column_name_b
196
+ # This is the value of the feature.
197
+ attr_reader :feature_value
198
+ # This is the amount that the feature contributed to the output.
199
+ attr_reader :feature_contribution_value
200
+ def initialize(column_name_a:, column_name_b:, feature_contribution_value:, feature_value:)
201
+ @column_name_a = column_name_a
202
+ @column_name_b = column_name_b
203
+ @feature_contribution_value = feature_contribution_value
204
+ @feature_value = feature_value
205
+ end
206
+ end
207
+
208
+ # This describes the contribution of a feature from a word embedding feature group.
209
+ class WordEmbeddingFeatureContribution
210
+ # This is the name of the source column for the feature group.
211
+ attr_reader :column_name
212
+ # This is the index of the feature in the word embedding.
213
+ attr_reader :value_index
214
+ # This is the amount that the feature contributed to the output.
215
+ attr_reader :feature_contribution_value
216
+ def initialize(column_name:, value_index:, feature_contribution_value:)
217
+ @column_name = column_name
218
+ @value_index = value_index
219
+ @feature_contribution_value = feature_contribution_value
220
+ end
221
+ end
222
+
223
+ # Use this class to load a model, make predictions, and log events to the app.
224
+ class Model
225
+ # Load a model from the `.modelfox` file at `path`.
226
+ # @param path [String] The path to the `.modelfox` file.
227
+ # @param options [LoadModelOptions] The options to use when loading the model.
228
+ # @return [Model]
229
+ def self.from_path(path, options: nil)
230
+ c_model = FFI::MemoryPointer.new(:pointer)
231
+ c_err = LibModelFox.modelfox_model_from_path(path, c_model)
232
+ unless c_err.null?
233
+ c_err = FFI::AutoPointer.new(c_err, LibModelFox.method(:modelfox_error_delete))
234
+ c_error_s = LibModelFox::ModelFoxStringView.new
235
+ LibModelFox.modelfox_error_get_message(c_err, c_error_s)
236
+ raise c_error_s.into_string
237
+ end
238
+ new(c_model, options: options)
239
+ end
240
+
241
+ # Load a model from bytes instead of a file. You should use this only if you already have a `.modelfox` loaded into memory. Otherwise, use `Model.from_path`, which is faster because it memory maps the file.
242
+ # @param bytes [String] The bytes for the .modelfox model.
243
+ # @param options [LoadModelOptions] The options to use when loading the model.
244
+ # @return [Model]
245
+ def self.from_bytes(bytes, options: nil)
246
+ c_model = FFI::MemoryPointer.new(:pointer)
247
+ c_err = LibModelFox.modelfox_model_from_bytes(bytes, bytes.size, c_model)
248
+ unless err.null?
249
+ c_err = FFI::AutoPointer.new(c_err, LibModelFox.method(:modelfox_error_delete))
250
+ c_error_s = LibModelFox::ModelFoxStringView.new
251
+ LibModelFox.modelfox_error_get_message(c_err, c_error_s)
252
+ raise errors.into_string
253
+ end
254
+ new(c_model, options: options)
255
+ end
256
+
257
+ def initialize(c_model, options: nil)
258
+ @modelfox_url = options&.modelfox_url.nil? ? 'https://app.modelfox.dev' : options&.modelfox_url
259
+ @log_queue = []
260
+ @model = FFI::AutoPointer.new(c_model.read_pointer, LibModelFox.method(:modelfox_model_delete))
261
+ end
262
+
263
+ # Retrieve the model's id.
264
+ def id
265
+ c_id = LibModelFox::ModelFoxStringView.new
266
+ LibModelFox.modelfox_model_get_id(@model, c_id)
267
+ c_id.into_string
268
+ end
269
+
270
+ # Make a prediction!
271
+ # @param input [Array<Hash{String, Symbol => String, Number}>, Hash{String, Symbol => String, Number}] A predict input is either a single predict input which is a map from symbols or strings to strings or floats or an array of such maps. The keys should match the columns in the CSV file you trained your model with.
272
+ # @param options [PredictOptions] These are the predict options.
273
+ # @return [Array<RegressionPredictOutput, BinaryClassificationPredictOutput, MulticlassClassificationPredictOutput>, RegressionPredictOutput, BinaryClassificationPredictOutput, MulticlassClassificationPredictOutput]. Return a single output if `input` was a single input, or an array if `input` was an array of `input`s.
274
+ def predict(input, options: nil)
275
+ is_array = input.is_a?(Array)
276
+ input = is_array ? input : [input]
277
+ c_input_vec = new_predict_input_vec(input)
278
+ c_options = new_predict_options(options)
279
+ c_output_vec = FFI::MemoryPointer.new(:pointer)
280
+ c_error = LibModelFox.modelfox_model_predict(@model, c_input_vec, c_options, c_output_vec)
281
+ raise 'modelfox error' unless c_error.null?
282
+ c_output_vec = FFI::AutoPointer.new(c_output_vec.read_pointer, LibModelFox.method(:modelfox_predict_output_vec_delete))
283
+ output = predict_output_vec_from_modelfox_predict_output_vec(c_output_vec)
284
+ is_array ? output : output[0]
285
+ end
286
+
287
+ # Send a prediction event to the app. If you want to batch events, you can use `enqueue_log_prediction` instead.
288
+ # @param identifier [String, Number] This is a unique identifier for the prediction, which will associate it with a true value event and allow you to look it up in the app.
289
+ # @param input [Hash{String, Symbol => String, Number}] A single `PredictInput`.
290
+ # @param output [PredictOutput] A single `PredictOutput`.
291
+ # @param options [PredictOptions] This is the same `predictOptions` value that you passed to `predict`.
292
+ def log_prediction(identifier:, input:, output:, options: nil)
293
+ event = prediction_event(
294
+ identifier: identifier,
295
+ input: input,
296
+ output: output,
297
+ options: options
298
+ )
299
+ log_event(event)
300
+ end
301
+
302
+ # Add a prediction event to the queue. Remember to call `flush_log_queue` at a later point to send the event to the app.
303
+ # @param identifier [String, Number] This is a unique identifier for the prediction, which will associate it with a true value event and allow you to look it up in the app.
304
+ # @param input [Hash{String, Symbol => String, Number}] A single `PredictInput`.
305
+ # @param output [PredictOutput] A single `PredictOutput`.
306
+ # @param options [PredictOptions] This is the same `predictOptions` value that you passed to `predict`.
307
+ def enqueue_log_prediction(identifier:, input:, output:, options: nil)
308
+ event = prediction_event(
309
+ identifier: identifier,
310
+ input: input,
311
+ output: output,
312
+ options: options
313
+ )
314
+ log_queue.push(event)
315
+ end
316
+
317
+ # Send a true value event to the app. If you want to batch events, you can use `enqueue_log_true_value` instead.
318
+ # @param identifier [String, Number] This is a unique identifier for the prediction, which will associate it with a true value event and allow you to look it up in the app.
319
+ # @param true_value [String, Number] This is the true value for the prediction.
320
+ def log_true_value(identifier:, true_value:)
321
+ event = true_value_event(
322
+ identifier: identifier,
323
+ true_value: true_value
324
+ )
325
+ log_event(event)
326
+ end
327
+
328
+ # Add a true value event to the queue. Remember to call `flush_log_queue` at a later point to send the event to the app.
329
+ # @param identifier [String, Number] This is a unique identifier for the prediction, which will associate it with a true value event and allow you to look it up in the app.
330
+ # @param true_value [String, Number] This is the true value for the prediction.
331
+ def enqueue_log_true_value(identifier:, true_value:)
332
+ event = true_value_event(
333
+ identifier: identifier,
334
+ true_value: true_value
335
+ )
336
+ log_queue.push(event)
337
+ end
338
+
339
+ # Send all events in the queue to the app.
340
+ def flush_log_queue
341
+ log_events(@log_queue)
342
+ @log_queue = []
343
+ end
344
+
345
+ private
346
+
347
+ def log_event(event)
348
+ log_events([event])
349
+ end
350
+
351
+ def log_events(events)
352
+ headers = {
353
+ 'Content-Type': 'application/json'
354
+ }
355
+ uri = URI("#{@modelfox_url}/track")
356
+ http = Net::HTTP.new(uri.host, uri.port)
357
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
358
+ request.body = events.to_json
359
+ response = http.request(request)
360
+ raise response unless response.is_a? Net::HTTPSuccess
361
+ end
362
+
363
+ def prediction_event(identifier:, input:, output:, options: nil)
364
+ {
365
+ date: DateTime.now.rfc3339,
366
+ identifier: identifier,
367
+ input: input,
368
+ model_id: id,
369
+ options: options,
370
+ output: output,
371
+ type: 'prediction'
372
+ }
373
+ end
374
+
375
+ def true_value_event(identifier:, true_value:)
376
+ {
377
+ date: DateTime.now.rfc3339,
378
+ identifier: identifier,
379
+ model_id: id,
380
+ true_value: true_value,
381
+ type: 'true_value'
382
+ }
383
+ end
384
+
385
+ def new_predict_options(options)
386
+ c_options = FFI::MemoryPointer.new(:pointer)
387
+ LibModelFox.modelfox_predict_options_new(c_options)
388
+ c_options = FFI::AutoPointer.new(c_options.read_pointer, LibModelFox.method(:modelfox_predict_options_delete))
389
+ unless options.nil?
390
+ unless options.threshold.nil?
391
+ LibModelFox.modelfox_predict_options_set_threshold(c_options, options.threshold)
392
+ end
393
+ unless options.compute_feature_contributions.nil?
394
+ LibModelFox.modelfox_predict_options_set_compute_feature_contributions(c_options, options.compute_feature_contributions)
395
+ end
396
+ end
397
+ c_options
398
+ end
399
+
400
+ def new_predict_input_vec(input_vec)
401
+ c_inputs = FFI::MemoryPointer.new(:pointer)
402
+ LibModelFox.modelfox_predict_input_vec_new(c_inputs)
403
+ c_inputs = FFI::AutoPointer.new(c_inputs.read_pointer, LibModelFox.method(:modelfox_predict_input_vec_delete))
404
+ (0...input_vec.length).each do |input_index|
405
+ input = input_vec[input_index]
406
+ predict_input = new_predict_input(input)
407
+ LibModelFox.modelfox_predict_input_vec_push(c_inputs, predict_input)
408
+ end
409
+ c_inputs
410
+ end
411
+
412
+ def new_predict_input(input)
413
+ c_input = FFI::MemoryPointer.new(:pointer)
414
+ LibModelFox.modelfox_predict_input_new(c_input)
415
+ c_input = c_input.read_pointer
416
+ input.each do |key, value|
417
+ is_float = value.is_a?(Float)
418
+ is_string = value.is_a?(String)
419
+ if is_float
420
+ LibModelFox.modelfox_predict_input_set_value_number(c_input, key.to_s, value)
421
+ elsif is_string
422
+ LibModelFox.modelfox_predict_input_set_value_string(c_input, key.to_s, value)
423
+ else
424
+ raise 'value for key %s is not a float or a string' % key
425
+ end
426
+ end
427
+ c_input
428
+ end
429
+
430
+ def predict_output_vec_from_modelfox_predict_output_vec(c_output_vec)
431
+ outputs = []
432
+ c_output_len = FFI::MemoryPointer.new(:int)
433
+ LibModelFox.modelfox_predict_output_vec_len(c_output_vec, c_output_len)
434
+ output_len = c_output_len.read(:int)
435
+ (0...output_len).each do |output_index|
436
+ c_output = FFI::MemoryPointer.new(:pointer)
437
+ LibModelFox.modelfox_predict_output_vec_get_at_index(c_output_vec, output_index, c_output)
438
+ c_output = c_output.read_pointer
439
+ outputs.push(predict_output_from_modelfox_predict_output(c_output))
440
+ end
441
+
442
+ outputs
443
+ end
444
+
445
+ def predict_output_from_modelfox_predict_output(c_output)
446
+ c_task_type = FFI::MemoryPointer.new(:int)
447
+ LibModelFox.modelfox_model_get_task(@model, c_task_type)
448
+ case c_task_type.read(:int)
449
+ when LibModelFox::ModelFoxTaskType[:regression]
450
+ regression_output_from_modelfox_predict_output(c_output)
451
+ when LibModelFox::ModelFoxTaskType[:binary_classification]
452
+ binary_classification_output_from_modelfox_predict_output(c_output)
453
+ when LibModelFox::ModelFoxTaskType[:multiclass_classification]
454
+ multiclass_classification_output_from_modelfox_predict_output(c_output)
455
+ end
456
+ end
457
+
458
+ def regression_output_from_modelfox_predict_output(c_output)
459
+ c_regression_output = FFI::MemoryPointer.new(:pointer)
460
+ LibModelFox.modelfox_predict_output_as_regression(c_output, c_regression_output)
461
+ c_regression_output = c_regression_output.read_pointer
462
+ c_value = FFI::MemoryPointer.new(:float)
463
+ LibModelFox.modelfox_regression_predict_output_get_value(c_regression_output, c_value)
464
+ value = c_value.read(:float)
465
+ c_feature_contributions = FFI::MemoryPointer.new(:pointer)
466
+ LibModelFox.modelfox_regression_predict_output_get_feature_contributions(c_regression_output, c_feature_contributions)
467
+ c_feature_contributions = c_feature_contributions.read_pointer
468
+ feature_contributions = c_feature_contributions.null? ? {} : get_feature_contributions(c_feature_contributions)
469
+ RegressionPredictOutput.new(
470
+ value: value,
471
+ feature_contributions: feature_contributions
472
+ )
473
+ end
474
+
475
+ def binary_classification_output_from_modelfox_predict_output(c_output)
476
+ c_binary_classification_output = FFI::MemoryPointer.new(:pointer)
477
+ LibModelFox.modelfox_predict_output_as_binary_classification(c_output, c_binary_classification_output)
478
+ c_binary_classification_output = c_binary_classification_output.read_pointer
479
+ c_probability = FFI::MemoryPointer.new(:float)
480
+ LibModelFox.modelfox_binary_classification_predict_output_get_probability(c_binary_classification_output, c_probability)
481
+ probability = c_probability.read(:float)
482
+ c_class_name = LibModelFox::ModelFoxStringView.new
483
+ LibModelFox.modelfox_binary_classification_predict_output_get_class_name(c_binary_classification_output, c_class_name)
484
+ class_name = c_class_name.into_string
485
+ c_feature_contributions = FFI::MemoryPointer.new(:pointer)
486
+ LibModelFox.modelfox_binary_classification_predict_output_get_feature_contributions(c_binary_classification_output, c_feature_contributions)
487
+ c_feature_contributions = c_feature_contributions.read_pointer
488
+ feature_contributions = c_feature_contributions.null? ? {} : get_feature_contributions(c_feature_contributions)
489
+ BinaryClassificationPredictOutput.new(
490
+ class_name: class_name,
491
+ probability: probability,
492
+ feature_contributions: feature_contributions
493
+ )
494
+ end
495
+
496
+ def multiclass_classification_output_from_modelfox_predict_output(c_output)
497
+ c_multiclass_classification_output = FFI::MemoryPointer.new(:pointer)
498
+ LibModelFox.modelfox_predict_output_as_multiclass_classification(c_output, c_multiclass_classification_output)
499
+ c_multiclass_classification_output = c_multiclass_classification_output.read_pointer
500
+ c_probability = FFI::MemoryPointer.new(:float)
501
+ LibModelFox.modelfox_multiclass_classification_predict_output_get_probability(c_multiclass_classification_output, c_probability)
502
+ probability = c_probability.read(:float)
503
+ c_class_name = LibModelFox::ModelFoxStringView.new
504
+ LibModelFox.modelfox_multiclass_classification_predict_output_get_class_name(c_multiclass_classification_output, c_class_name)
505
+ class_name = c_class_name.into_string
506
+ probabilities = multiclass_classification_output_get_probabilities(c_multiclass_classification_output)
507
+ feature_contributions = multiclass_classification_output_get_feature_contributions(c_multiclass_classification_output)
508
+ MulticlassClassificationPredictOutput.new(
509
+ class_name: class_name,
510
+ probability: probability,
511
+ probabilities: probabilities,
512
+ feature_contributions: feature_contributions
513
+ )
514
+ end
515
+
516
+ def multiclass_classification_output_get_probabilities(c_multiclass_classification_output)
517
+ probabilities = {}
518
+ c_probabilities_iter = FFI::MemoryPointer.new(:pointer)
519
+ LibModelFox.modelfox_multiclass_classification_predict_output_get_probabilities_iter(c_multiclass_classification_output, c_probabilities_iter)
520
+ c_probabilities_iter = FFI::AutoPointer.new(c_probabilities_iter.read_pointer, LibModelFox.method(:modelfox_multiclass_classification_predict_output_probabilities_iter_delete))
521
+ c_class_probability = FFI::MemoryPointer.new(:float)
522
+ c_class_name = LibModelFox::ModelFoxStringView.new
523
+ while LibModelFox.modelfox_multiclass_classification_predict_output_probabilities_iter_next(c_probabilities_iter, c_class_name, c_class_probability)
524
+ class_name = c_class_name.into_string
525
+ probabilities[class_name] = c_class_probability.read(:float)
526
+ end
527
+ probabilities
528
+ end
529
+
530
+ def multiclass_classification_output_get_feature_contributions(c_multiclass_classification_output)
531
+ c_feature_contributions_iter = FFI::MemoryPointer.new(:pointer)
532
+ LibModelFox.modelfox_multiclass_classification_predict_output_get_feature_contributions_iter(c_multiclass_classification_output, c_feature_contributions_iter)
533
+ c_feature_contributions_iter = FFI::AutoPointer.new(c_feature_contributions_iter.read_pointer, LibModelFox.method(:modelfox_multiclass_classification_predict_output_feature_contributions_iter_delete))
534
+ feature_contributions = {}
535
+ unless c_feature_contributions_iter.null?
536
+ c_class_name = LibModelFox::ModelFoxStringView.new
537
+ c_feature_contributions_ptr = FFI::MemoryPointer.new(:pointer)
538
+ while LibModelFox.modelfox_multiclass_classification_predict_output_feature_contributions_iter_next(c_feature_contributions_iter, c_class_name, c_feature_contributions_ptr)
539
+ class_name = c_class_name.into_string
540
+ c_feature_contributions = c_feature_contributions_ptr.read_pointer
541
+ unless c_feature_contributions.null?
542
+ feature_contributions[class_name] = get_feature_contributions(c_feature_contributions)
543
+ end
544
+ end
545
+ end
546
+ feature_contributions
547
+ end
548
+
549
+ def get_feature_contributions(c_feature_contributions)
550
+ c_baseline = FFI::MemoryPointer.new(:float)
551
+ LibModelFox.modelfox_feature_contributions_get_baseline_value(c_feature_contributions, c_baseline)
552
+ baseline = c_baseline.read(:float)
553
+ c_output = FFI::MemoryPointer.new(:float)
554
+ LibModelFox.modelfox_feature_contributions_get_output_value(c_feature_contributions, c_output)
555
+ output = c_output.read(:float)
556
+ feature_contribution_entries = get_feature_contributions_entries(c_feature_contributions)
557
+ FeatureContributions.new(
558
+ baseline: baseline,
559
+ output: output,
560
+ entries: feature_contribution_entries
561
+ )
562
+ end
563
+
564
+ def get_feature_contributions_entries(c_feature_contributions)
565
+ c_len = FFI::MemoryPointer.new(:int)
566
+ LibModelFox.modelfox_feature_contributions_get_entries_len(c_feature_contributions, c_len)
567
+ len = c_len.read(:int)
568
+ feature_contributions = []
569
+ (0...len).each do |i|
570
+ c_feature_contribution = FFI::MemoryPointer.new(:pointer)
571
+ LibModelFox.modelfox_feature_contributions_get_entry_at_index(c_feature_contributions, i, c_feature_contribution)
572
+ c_feature_contribution = c_feature_contribution.read_pointer
573
+ feature_contributions.push(get_feature_contribution(c_feature_contribution))
574
+ end
575
+ feature_contributions
576
+ end
577
+
578
+ def get_feature_contribution(c_feature_contribution)
579
+ c_feature_contribution_type = FFI::MemoryPointer.new(:int)
580
+ LibModelFox.modelfox_feature_contribution_entry_get_type(c_feature_contribution, c_feature_contribution_type)
581
+ case c_feature_contribution_type.read(:int)
582
+ when LibModelFox::ModelFoxFeatureContributionEntryType[:identity]
583
+ get_identity_feature_contribution(c_feature_contribution)
584
+ when LibModelFox::ModelFoxFeatureContributionEntryType[:normalized]
585
+ get_normalized_feature_contribution(c_feature_contribution)
586
+ when LibModelFox::ModelFoxFeatureContributionEntryType[:one_hot_encoded]
587
+ get_one_hot_encoded_feature_contribution(c_feature_contribution)
588
+ when LibModelFox::ModelFoxFeatureContributionEntryType[:bag_of_words]
589
+ get_bag_of_words_feature_contribution(c_feature_contribution)
590
+ when LibModelFox::ModelFoxFeatureContributionEntryType[:bag_of_words_cosine_similarity]
591
+ get_bag_of_words_cosine_similarity_feature_contribution(c_feature_contribution)
592
+ when LibModelFox::ModelFoxFeatureContributionEntryType[:word_embedding]
593
+ get_word_embedding_feature_contribution(c_feature_contribution)
594
+ end
595
+ end
596
+
597
+ def get_identity_feature_contribution(c_feature_contribution)
598
+ c_identity_feature_contribution = FFI::MemoryPointer.new(:pointer)
599
+ LibModelFox.modelfox_feature_contribution_entry_as_identity(c_feature_contribution, c_identity_feature_contribution)
600
+ c_identity_feature_contribution = c_identity_feature_contribution.read_pointer
601
+ c_column_name = LibModelFox::ModelFoxStringView.new
602
+ LibModelFox.modelfox_identity_feature_contribution_get_column_name(c_identity_feature_contribution, c_column_name)
603
+ column_name = c_column_name.into_string
604
+ c_feature_contribution_value = FFI::MemoryPointer.new(:float)
605
+ LibModelFox.modelfox_identity_feature_contribution_get_feature_contribution_value(c_identity_feature_contribution, c_feature_contribution_value)
606
+ feature_contribution_value = c_feature_contribution_value.read(:float)
607
+ c_feature_value = FFI::MemoryPointer.new(:float)
608
+ LibModelFox.modelfox_identity_feature_contribution_get_feature_value(c_identity_feature_contribution, c_feature_value)
609
+ feature_value = c_feature_value.read(:float)
610
+ IdentityFeatureContribution.new(
611
+ column_name: column_name,
612
+ feature_value: feature_value,
613
+ feature_contribution_value: feature_contribution_value
614
+ )
615
+ end
616
+
617
+ def get_normalized_feature_contribution(c_feature_contribution)
618
+ c_normalized_feature_contribution = FFI::MemoryPointer.new(:pointer)
619
+ LibModelFox.modelfox_feature_contribution_entry_as_normalized(
620
+ c_feature_contribution, c_normalized_feature_contribution
621
+ )
622
+ c_normalized_feature_contribution = c_normalized_feature_contribution.read_pointer
623
+ c_column_name = LibModelFox::ModelFoxStringView.new
624
+ LibModelFox.modelfox_normalized_feature_contribution_get_column_name(c_normalized_feature_contribution, c_column_name)
625
+ column_name = c_column_name.into_string
626
+ c_feature_value = FFI::MemoryPointer.new(:float)
627
+ LibModelFox.modelfox_normalized_feature_contribution_get_feature_value(c_normalized_feature_contribution, c_feature_value)
628
+ feature_value = c_feature_value.read(:float)
629
+ c_feature_contribution_value = FFI::MemoryPointer.new(:float)
630
+ LibModelFox.modelfox_normalized_feature_contribution_get_feature_contribution_value(c_normalized_feature_contribution, c_feature_contribution_value)
631
+ feature_contribution_value = c_feature_contribution_value.read(:float)
632
+ NormalizedFeatureContribution.new(
633
+ column_name: column_name,
634
+ feature_value: feature_value,
635
+ feature_contribution_value: feature_contribution_value
636
+ )
637
+ end
638
+
639
+ def get_one_hot_encoded_feature_contribution(c_feature_contribution)
640
+ c_one_hot_encoded_feature_contribution = FFI::MemoryPointer.new(:pointer)
641
+ LibModelFox.modelfox_feature_contribution_entry_as_one_hot_encoded(c_feature_contribution, c_one_hot_encoded_feature_contribution)
642
+ c_one_hot_encoded_feature_contribution = c_one_hot_encoded_feature_contribution.read_pointer
643
+ c_column_name = LibModelFox::ModelFoxStringView.new
644
+ LibModelFox.modelfox_one_hot_encoded_feature_contribution_get_column_name(c_one_hot_encoded_feature_contribution, c_column_name)
645
+ column_name = c_column_name.into_string
646
+ c_feature_contribution_value = FFI::MemoryPointer.new(:float)
647
+ LibModelFox.modelfox_one_hot_encoded_feature_contribution_get_feature_contribution_value(c_one_hot_encoded_feature_contribution, c_feature_contribution_value)
648
+ feature_contribution_value = c_feature_contribution_value.read(:float)
649
+ c_feature_value = FFI::MemoryPointer.new(:bool)
650
+ LibModelFox.modelfox_one_hot_encoded_feature_contribution_get_feature_value(c_one_hot_encoded_feature_contribution, c_feature_value)
651
+ feature_value = c_feature_value.read(:bool)
652
+ c_variant = LibModelFox::ModelFoxStringView.new
653
+ LibModelFox.modelfox_one_hot_encoded_feature_contribution_get_variant(c_one_hot_encoded_feature_contribution, c_variant)
654
+ variant = c_variant[:ptr].null? ? nil : c_variant.into_string
655
+ OneHotEncodedFeatureContribution.new(
656
+ column_name: column_name,
657
+ variant: variant,
658
+ feature_contribution_value: feature_contribution_value,
659
+ feature_value: feature_value
660
+ )
661
+ end
662
+
663
+ def get_bag_of_words_feature_contribution(c_feature_contribution)
664
+ c_bag_of_words_feature_contribution = FFI::MemoryPointer.new(:pointer)
665
+ LibModelFox.modelfox_feature_contribution_entry_as_bag_of_words(c_feature_contribution, c_bag_of_words_feature_contribution)
666
+ c_bag_of_words_feature_contribution = c_bag_of_words_feature_contribution.read_pointer
667
+ c_column_name = LibModelFox::ModelFoxStringView.new
668
+ LibModelFox.modelfox_bag_of_words_feature_contribution_get_column_name(c_bag_of_words_feature_contribution, c_column_name)
669
+ column_name = c_column_name.into_string
670
+ c_feature_contribution_value = FFI::MemoryPointer.new(:float)
671
+ LibModelFox.modelfox_bag_of_words_feature_contribution_get_feature_contribution_value(c_bag_of_words_feature_contribution, c_feature_contribution_value)
672
+ feature_contribution_value = c_feature_contribution_value.read(:float)
673
+ c_feature_value = FFI::MemoryPointer.new(:float)
674
+ LibModelFox.modelfox_bag_of_words_feature_contribution_get_feature_value(c_bag_of_words_feature_contribution, c_feature_value)
675
+ feature_value = c_feature_value.read(:float)
676
+ c_ngram = FFI::MemoryPointer(:pointer)
677
+ LibModelFox.modelfox_bag_of_words_feature_contribution_get_ngram(c_bag_of_words_feature_contribution, c_ngram)
678
+ c_ngram = c_ngram.read_pointer
679
+ ngram = get_ngram(c_ngram)
680
+ BagOfWordsFeatureContribution.new(
681
+ column_name: column_name,
682
+ ngram: ngram,
683
+ feature_contribution_value: feature_contribution_value,
684
+ feature_value: feature_value
685
+ )
686
+ end
687
+
688
+ def get_bag_of_words_cosine_similarity_feature_contribution(c_feature_contribution)
689
+ c_bag_of_words_cosine_similarity_feature_contribution = FFI::MemoryPointer.new(:pointer)
690
+ LibModelFox.modelfox_feature_contribution_entry_as_bag_of_words_cosine_similarity(c_feature_contribution, c_bag_of_words_cosine_similarity_feature_contribution)
691
+ c_bag_of_words_cosine_similarity_feature_contribution = c_bag_of_words_cosine_similarity_feature_contribution.read_pointer
692
+ c_column_name_a = LibModelFox::ModelFoxStringView.new
693
+ LibModelFox.modelfox_bag_of_words_feature_contribution_get_column_name_a(c_bag_of_words_cosine_similarity_feature_contribution, c_column_name_a)
694
+ column_name_a = c_column_name_a.into_string
695
+ c_column_name_b = LibModelFox::ModelFoxStringView.new
696
+ LibModelFox.modelfox_bag_of_words_feature_contribution_get_column_name_b(c_bag_of_words_cosine_similarity_feature_contribution, c_column_name_b)
697
+ column_name_b = c_column_name_b.into_string
698
+ c_feature_contribution_value = FFI::MemoryPointer.new(:float)
699
+ LibModelFox.modelfox_bag_of_words_cosine_similarity_feature_contribution_get_feature_contribution_value(c_bag_of_words_cosine_similarity_feature_contribution, c_feature_contribution_value)
700
+ feature_contribution_value = c_feature_contribution_value.read(:float)
701
+ c_feature_value = FFI::MemoryPointer.new(:float)
702
+ LibModelFox.modelfox_bag_of_words_cosine_similarity_feature_contribution_get_feature_value(c_bag_of_words_cosine_similarity_feature_contribution, c_feature_value)
703
+ feature_value = c_feature_value.read(:float)
704
+ BagOfWordsCosineSimilarityFeatureContribution.new(
705
+ column_name_a: column_name_a,
706
+ column_name_b: column_name_b,
707
+ feature_contribution_value: feature_contribution_value,
708
+ feature_value: feature_value
709
+ )
710
+ end
711
+
712
+ def get_word_embedding_feature_contribution(c_feature_contribution)
713
+ c_word_embedding_feature_contribution = FFI::MemoryPointer.new(:pointer)
714
+ LibModelFox.modelfox_feature_contribution_entry_as_word_embedding(
715
+ c_feature_contribution, c_word_embedding_feature_contribution
716
+ )
717
+ c_word_embedding_feature_contribution = c_word_embedding_feature_contribution.read_pointer
718
+ c_column_name = LibModelFox::ModelFoxStringView.new
719
+ LibModelFox.modelfox_word_embedding_feature_contribution_get_column_name(c_word_embedding_feature_contribution, c_column_name)
720
+ column_name = c_column_name.into_string
721
+ c_feature_contribution_value = FFI::MemoryPointer.new(:float)
722
+ LibModelFox.modelfox_word_embedding_feature_contribution_get_feature_contribution_value(c_word_embedding_feature_contribution, c_feature_contribution_value)
723
+ feature_contribution_value = c_feature_contribution_value.read(:float)
724
+ c_value_index = FFI::MemoryPointer.new(:int)
725
+ LibModelFox.modelfox_word_embedding_feature_contribution_get_value_index(c_word_embedding_feature_contribution, c_value_index)
726
+ value_index = c_value_index.read(:int)
727
+ WordEmbeddingFeatureContribution.new(
728
+ column_name: column_name,
729
+ value_index: value_index,
730
+ feature_contribution_value: feature_contribution_value
731
+ )
732
+ end
733
+
734
+ def get_ngram(ngram)
735
+ c_ngram_type = FFI::MemoryPointer.new(:int)
736
+ LibModelFox.modelfox_ngram_get_type(ngram, c_ngram_type)
737
+ case c_ngram_type.read(:int)
738
+ when LibModelFox::ModelFoxNGramType[:unigram]
739
+ get_unigram_ngram(ngram)
740
+ when LibModelFox::ModelFoxNGramType[:bigram]
741
+ get_bigram_ngram(ngram)
742
+ end
743
+ end
744
+
745
+ def get_unigram_ngram(ngram)
746
+ c_token = LibModelFox::ModelFoxStringView.new
747
+ LibModelFox.modelfox_unigram_get_token(ngram, c_token)
748
+ token = c_token.into_string
749
+ Unigram.new(
750
+ token: token
751
+ )
752
+ end
753
+
754
+ def get_bigram_ngram(ngram)
755
+ c_token_a = LibModelFox::ModelFoxStringView.new
756
+ c_token_b = LibModelFox::ModelFoxStringView.new
757
+ LibModelFox.modelfox_bigram_get_token_a(ngram, c_token_a)
758
+ LibModelFox.modelfox_bigram_get_token_b(ngram, c_token_b)
759
+ token_a = c_token_a.into_string
760
+ token_b = c_token_b.into_string
761
+ Bigram.new(
762
+ token_a: token_a,
763
+ token_b: token_b
764
+ )
765
+ end
766
+ end
767
+
768
+ module LibModelFox
769
+ cpu = RbConfig::CONFIG['host_cpu']
770
+ os = RbConfig::CONFIG['host_os']
771
+ if cpu == 'x86_64' && os =~ /linux/
772
+ library_path = 'libmodelfox/x86_64-unknown-linux-gnu/libmodelfox.so'
773
+ elsif cpu == 'aarch64' && os =~ /linux/
774
+ library_path = 'libmodelfox/aarch64-unknown-linux-gnu/libmodelfox.so'
775
+ elsif cpu == 'x86_64' && os =~ /darwin/
776
+ library_path = 'libmodelfox/x86_64-apple-darwin/libmodelfox.dylib'
777
+ elsif (cpu == 'arm' || cpu == 'arm64') && os =~ /darwin/
778
+ library_path = 'libmodelfox/aarch64-apple-darwin/libmodelfox.dylib'
779
+ elsif cpu == 'x86_64' && os =~ /mingw/
780
+ library_path = 'libmodelfox/x86_64-pc-windows-msvc/modelfox.dll'
781
+ else
782
+ raise 'ModelFox for Ruby does not yet support your combination of CPU architecture and operating system. Open an issue at https://github.com/modelfoxdotdev/modelfox/issues/new or email us at help@modelfox.dev to complain.'
783
+ end
784
+ extend FFI::Library
785
+ ffi_lib File.expand_path(library_path.to_s, __dir__)
786
+
787
+ class ModelFoxStringView < FFI::Struct
788
+ layout :ptr, :pointer,
789
+ :len, :int
790
+ def into_string
791
+ self[:ptr].read_string(self[:len]).force_encoding('utf-8')
792
+ end
793
+ end
794
+
795
+ ModelFoxTaskType = enum(
796
+ :regression,
797
+ :binary_classification,
798
+ :multiclass_classification
799
+ )
800
+
801
+ ModelFoxFeatureContributionEntryType = enum(
802
+ :identity,
803
+ :normalized,
804
+ :one_hot_encoded,
805
+ :bag_of_words,
806
+ :bag_of_words_cosine_similarity,
807
+ :word_embedding
808
+ )
809
+
810
+ ModelFoxNGramType = enum(
811
+ :unigram,
812
+ :bigram
813
+ )
814
+
815
+ typedef :pointer, :modelfox_error
816
+
817
+ attach_function :modelfox_error_get_message, [:pointer, ModelFoxStringView.by_ref], :void
818
+ attach_function :modelfox_error_delete, [:pointer], :void
819
+ attach_function :modelfox_version, [ModelFoxStringView.by_ref], :void
820
+ attach_function :modelfox_model_from_bytes, [:pointer, :int, :pointer], :modelfox_error
821
+ attach_function :modelfox_model_from_path, [:string, :pointer], :modelfox_error
822
+ attach_function :modelfox_model_delete, [:pointer], :void
823
+ attach_function :modelfox_model_get_id, [:pointer, ModelFoxStringView.by_ref], :void
824
+ attach_function :modelfox_model_get_task, [:pointer, :pointer], :void
825
+ attach_function :modelfox_predict_input_new, [:pointer], :void
826
+ attach_function :modelfox_predict_input_delete, [:pointer], :void
827
+ attach_function :modelfox_predict_input_set_value_number, [:pointer, :string, :double], :int
828
+ attach_function :modelfox_predict_input_set_value_string, [:pointer, :string, :string], :int
829
+ attach_function :modelfox_predict_input_vec_new, [:pointer], :void
830
+ attach_function :modelfox_predict_input_vec_delete, [:pointer], :void
831
+ attach_function :modelfox_predict_input_vec_push, [:pointer, :pointer], :void
832
+ attach_function :modelfox_predict_options_new, [:pointer], :void
833
+ attach_function :modelfox_predict_options_delete, [:pointer], :void
834
+ attach_function :modelfox_predict_options_set_threshold, [:pointer, :float], :void
835
+ attach_function :modelfox_predict_options_set_compute_feature_contributions, [:pointer, :bool], :void
836
+ attach_function :modelfox_model_predict, [:pointer, :pointer, :pointer, :pointer], :modelfox_error
837
+ attach_function :modelfox_predict_output_delete, [:pointer], :void
838
+ attach_function :modelfox_predict_output_vec_delete, [:pointer], :void
839
+ attach_function :modelfox_predict_output_vec_len, [:pointer, :pointer], :void
840
+ attach_function :modelfox_predict_output_vec_get_at_index, [:pointer, :int, :pointer], :void
841
+ attach_function :modelfox_predict_output_as_regression, [:pointer, :pointer], :void
842
+ attach_function :modelfox_predict_output_as_binary_classification, [:pointer, :pointer], :void
843
+ attach_function :modelfox_predict_output_as_multiclass_classification, [:pointer, :pointer], :void
844
+ attach_function :modelfox_regression_predict_output_get_value, [:pointer, :pointer], :void
845
+ attach_function :modelfox_regression_predict_output_get_feature_contributions, [:pointer, :pointer], :void
846
+ attach_function :modelfox_binary_classification_predict_output_get_class_name, [:pointer, ModelFoxStringView.by_ref], :void
847
+ attach_function :modelfox_binary_classification_predict_output_get_probability, [:pointer, :pointer], :void
848
+ attach_function :modelfox_binary_classification_predict_output_get_feature_contributions, [:pointer, :pointer], :void
849
+ attach_function :modelfox_multiclass_classification_predict_output_get_class_name, [:pointer, ModelFoxStringView.by_ref], :void
850
+ attach_function :modelfox_multiclass_classification_predict_output_get_probability, [:pointer, :pointer], :void
851
+ attach_function :modelfox_multiclass_classification_predict_output_get_probabilities_len, [:pointer, :pointer], :void
852
+ attach_function :modelfox_multiclass_classification_predict_output_probabilities_iter_delete, [:pointer], :void
853
+ attach_function :modelfox_multiclass_classification_predict_output_get_probabilities_iter, [:pointer, :pointer], :void
854
+ attach_function :modelfox_multiclass_classification_predict_output_probabilities_iter_next, [:pointer, :pointer, :pointer], :bool
855
+ attach_function :modelfox_multiclass_classification_predict_output_feature_contributions_iter_delete, [:pointer], :void
856
+ attach_function :modelfox_multiclass_classification_predict_output_get_feature_contributions_iter, [:pointer, :pointer], :void
857
+ attach_function :modelfox_multiclass_classification_predict_output_feature_contributions_iter_next, [:pointer, :pointer, :pointer], :bool
858
+ attach_function :modelfox_feature_contributions_get_baseline_value, [:pointer, :pointer], :void
859
+ attach_function :modelfox_feature_contributions_get_output_value, [:pointer, :pointer], :void
860
+ attach_function :modelfox_feature_contributions_get_entries_len, [:pointer, :pointer], :void
861
+ attach_function :modelfox_feature_contributions_get_entry_at_index, [:pointer, :int, :pointer], :void
862
+ attach_function :modelfox_feature_contribution_entry_get_type, [:pointer, :pointer], :void
863
+ attach_function :modelfox_feature_contribution_entry_as_identity, [:pointer, :pointer], :void
864
+ attach_function :modelfox_feature_contribution_entry_as_normalized, [:pointer, :pointer], :void
865
+ attach_function :modelfox_feature_contribution_entry_as_one_hot_encoded, [:pointer, :pointer], :void
866
+ attach_function :modelfox_feature_contribution_entry_as_bag_of_words, [:pointer, :pointer], :void
867
+ attach_function :modelfox_feature_contribution_entry_as_bag_of_words_cosine_similarity, [:pointer, :pointer], :void
868
+ attach_function :modelfox_feature_contribution_entry_as_word_embedding, [:pointer, :pointer], :void
869
+ attach_function :modelfox_identity_feature_contribution_get_column_name, [:pointer, ModelFoxStringView.by_ref], :void
870
+ attach_function :modelfox_identity_feature_contribution_get_feature_value, [:pointer, :pointer], :void
871
+ attach_function :modelfox_identity_feature_contribution_get_feature_contribution_value, [:pointer, :pointer], :void
872
+ attach_function :modelfox_normalized_feature_contribution_get_column_name, [:pointer, ModelFoxStringView.by_ref], :void
873
+ attach_function :modelfox_normalized_feature_contribution_get_feature_value, [:pointer, :pointer], :void
874
+ attach_function :modelfox_normalized_feature_contribution_get_feature_contribution_value, [:pointer, :pointer], :void
875
+ attach_function :modelfox_one_hot_encoded_feature_contribution_get_column_name, [:pointer, ModelFoxStringView.by_ref], :void
876
+ attach_function :modelfox_one_hot_encoded_feature_contribution_get_variant, [:pointer, ModelFoxStringView.by_ref], :void
877
+ attach_function :modelfox_one_hot_encoded_feature_contribution_get_feature_value, [:pointer, :pointer], :void
878
+ attach_function :modelfox_one_hot_encoded_feature_contribution_get_feature_contribution_value, [:pointer, :pointer], :void
879
+ attach_function :modelfox_bag_of_words_feature_contribution_get_column_name, [:pointer, ModelFoxStringView.by_ref], :void
880
+ attach_function :modelfox_bag_of_words_feature_contribution_get_feature_value, [:pointer, :pointer], :void
881
+ attach_function :modelfox_bag_of_words_feature_contribution_get_feature_contribution_value, [:pointer, :pointer], :void
882
+ attach_function :modelfox_bag_of_words_feature_contribution_get_ngram, [:pointer, :pointer], :void
883
+ attach_function :modelfox_ngram_get_type, [:pointer, :pointer], :void
884
+ attach_function :modelfox_unigram_get_token, [:pointer, ModelFoxStringView.by_ref], :void
885
+ attach_function :modelfox_bigram_get_token_a, [:pointer, ModelFoxStringView.by_ref], :void
886
+ attach_function :modelfox_bigram_get_token_b, [:pointer, ModelFoxStringView.by_ref], :void
887
+ attach_function :modelfox_bag_of_words_cosine_similarity_feature_contribution_get_column_name_a, [:pointer, ModelFoxStringView.by_ref], :void
888
+ attach_function :modelfox_bag_of_words_cosine_similarity_feature_contribution_get_column_name_b, [:pointer, ModelFoxStringView.by_ref], :void
889
+ attach_function :modelfox_bag_of_words_cosine_similarity_feature_contribution_get_feature_value, [:pointer, :pointer], :void
890
+ attach_function :modelfox_bag_of_words_cosine_similarity_feature_contribution_get_feature_contribution_value, [:pointer, :pointer], :void
891
+ attach_function :modelfox_word_embedding_feature_contribution_get_column_name, [:pointer, ModelFoxStringView.by_ref], :void
892
+ attach_function :modelfox_word_embedding_feature_contribution_get_value_index, [:pointer, :pointer], :void
893
+ attach_function :modelfox_word_embedding_feature_contribution_get_feature_contribution_value, [:pointer, :pointer], :void
894
+ end
895
+ end