magnifier-ruby 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/magnifier.rb +78 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 10ef01bc786e90cbc1f33214573a27b28ef4f00e
|
4
|
+
data.tar.gz: 3144c715c7f118d5b7462be5741f6bad4a948948
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa8f6619518a249fbd8d15f5aa504fd2a0726d451b58385dbe4741a4cfa8893d76e7a71219d4a5e3f870e5ecac48a6f3edc728eeb6ea27cb893ba6ca1627b7fd
|
7
|
+
data.tar.gz: e34d47c3359525e70066818f640df6e53017c36921219a753b71a2c6248b1f99c2b6f35fb534d20986aecf47abcbcdf4c8a1380a96eae4a526679fbc5be32cf5
|
data/lib/magnifier.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'numo/narray'
|
2
|
+
|
3
|
+
class Magnifier
|
4
|
+
# make configurable
|
5
|
+
# or check for convergence
|
6
|
+
LEARNING_STEPS = 1000
|
7
|
+
|
8
|
+
attr_reader :training_set, :training_set_size, :features_count, :f1_score
|
9
|
+
attr_accessor :mu_vector, :sigma_squared_vector, :threshold
|
10
|
+
|
11
|
+
# examples is exepcted to be 2-D array of real values
|
12
|
+
def initialize(examples, threshold = 0.01)
|
13
|
+
@training_set = Numo::DFloat[*examples].freeze
|
14
|
+
@training_set_size, @features_count = training_set.shape
|
15
|
+
@threshold = threshold
|
16
|
+
@mu_vector = Numo::DFloat.zeros(@features_count)
|
17
|
+
@sigma_squared_vector = Numo::DFloat.zeros(@features_count)
|
18
|
+
@f1_score = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def train
|
22
|
+
@mu_vector = @training_set.mean(0)
|
23
|
+
@sigma_squared_vector = (((training_set - mu_vector) ** 2).sum(0) / training_set_size).to_a
|
24
|
+
end
|
25
|
+
|
26
|
+
# optimize using F1 score
|
27
|
+
# requires cross-validation set (should differ from train set!)
|
28
|
+
# todo: convert base truth to boolean
|
29
|
+
def optimize_threshold(examples, base_truths)
|
30
|
+
boolean_base_thruths = base_truths.map{ |value| value == 1 || value == true }
|
31
|
+
examples_prob = examples.map { |example| probability(example) }
|
32
|
+
|
33
|
+
threshold_step = (examples_prob.max - examples_prob.min) / LEARNING_STEPS
|
34
|
+
@threshold = 0
|
35
|
+
|
36
|
+
(examples_prob.min..examples_prob.max).step(threshold_step) do |new_threshold|
|
37
|
+
predictions = examples_prob.map { |probability| probability < new_threshold }
|
38
|
+
current_f1 = compute_f1_score(predictions, boolean_base_thruths)
|
39
|
+
|
40
|
+
if current_f1 > @f1_score
|
41
|
+
@f1_score = current_f1
|
42
|
+
@threshold = new_threshold
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
[threshold, f1_score]
|
47
|
+
end
|
48
|
+
|
49
|
+
def probability(example)
|
50
|
+
probability = 1
|
51
|
+
example.each_with_index do |feature, i|
|
52
|
+
feature_prob = Math.exp(-((feature - mu_vector[i])**2 / (2 * sigma_squared_vector[i]))) / ((2 * Math::PI * sigma_squared_vector[i])**(0.5))
|
53
|
+
|
54
|
+
probability = probability * feature_prob
|
55
|
+
end
|
56
|
+
|
57
|
+
probability
|
58
|
+
end
|
59
|
+
|
60
|
+
def anomaly?(example)
|
61
|
+
probability(example) < threshold
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def compute_f1_score(predictions, base_truths)
|
67
|
+
true_positives = predictions.map.with_index { |val, i| val && base_truths[i] }.count(true)
|
68
|
+
false_positives = predictions.map.with_index { |val, i| val && !base_truths[i] }.count(true)
|
69
|
+
false_negatives = predictions.map.with_index { |val, i| !val && base_truths[i] }.count(true)
|
70
|
+
|
71
|
+
return 0 if true_positives == 0
|
72
|
+
|
73
|
+
precision = true_positives.to_f / (true_positives + false_positives);
|
74
|
+
recall = true_positives.to_f / (true_positives + false_negatives);
|
75
|
+
|
76
|
+
(2 * precision * recall) / (precision + recall) rescue 0;
|
77
|
+
end
|
78
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: magnifier-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Grysimov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: numo-narray
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.7.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.7.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Anomaly detection using gaussian distribution, written in ruby
|
56
|
+
email:
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/magnifier.rb
|
62
|
+
homepage: https://github.com/tuned-up/magnifier-ruby
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.6.14
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: Anomaly Detection
|
86
|
+
test_files: []
|