-
Notifications
You must be signed in to change notification settings - Fork 0
/
gradient_boosting_classifier.rb
52 lines (40 loc) · 1.66 KB
/
gradient_boosting_classifier.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# lib/ruby/gradient_boosting_classifier.rb
#
# See: https://www.fastruby.io/blog/introduction-to-gradient-boosting.html?ck_subscriber_id=791584073
require_relative "decision_tree"
class GradientBoostingClassifier
attr_accessor :n_trees, :learning_rate, :max_tree_depth, :trees, :initial_prediction
def initialize(max_tree_depth: 3, n_trees: 100, learning_rate: 0.1)
@n_trees = n_trees
@learning_rate = learning_rate
@max_tree_depth = max_tree_depth
@trees = []
@initial_prediction = nil
end
def train(data, labels)
positive_probability = labels.count(1).to_f / labels.size
@initial_prediction = Math.log(positive_probability / (1 - positive_probability))
residuals = Array.new(labels.size, @initial_prediction)
@n_trees.times do
probabilities = residuals.map { |log_odds| 1.0 / (1.0 + Math.exp(-log_odds)) }
pseudo_residuals = labels.zip(probabilities).map { |y, prob| y - prob }
tree = DecisionTree.new
tree.train(data, pseudo_residuals, @max_tree_depth) # Ensure max_tree_depth attribute is properly used
@trees << tree
# Iterate through data for predictions and update residuals
data.each_with_index do |sample, index|
tree_prediction = tree.predict(sample, 0) # Providing 0 as a default label
residuals[index] += @learning_rate * tree_prediction
end
end
end
def predict(sample)
log_odds = @initial_prediction
@trees.each do |tree|
prediction = tree.predict(sample, 0) # Providing 0 as default prediction
log_odds += @learning_rate * prediction
end
probability = 1.0 / (1.0 + Math.exp(-log_odds))
probability >= 0.5 ? 1 : 0
end
end