cofi_cost 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. data/lib/cofi_cost.rb +15 -33
  2. metadata +16 -6
data/lib/cofi_cost.rb CHANGED
@@ -6,10 +6,10 @@ include GSL::MultiMin
6
6
 
7
7
  class CofiCost
8
8
 
9
- attr_accessor :ratings, :num_features, :cost, :lambda, :iterations, :features, :theta
9
+ attr_accessor :ratings, :num_features, :cost, :regularization, :iterations, :features, :theta
10
10
  attr_reader :boolean_rated, :num_tracks, :num_users, :ratings_mean, :ratings_norm, :predictions
11
11
 
12
- def initialize(ratings, num_features = 2, lambda = 1, iterations = 10, features = nil, theta = nil)
12
+ def initialize(ratings, num_features = 2, regularization = 1, iterations = 10, features = nil, theta = nil)
13
13
  @ratings = ratings.to_f # make sure it's a float for correct normalization
14
14
  @num_features = num_features
15
15
  @cost = 0
@@ -24,7 +24,7 @@ class CofiCost
24
24
  @ratings_mean = NArray.float(1, @num_tracks).fill(0.0)
25
25
  @ratings_norm = NArray.float(@num_users, @num_tracks).fill(0.0)
26
26
  @ratings_mean, @ratings_norm = normalize_ratings
27
- @lambda = lambda
27
+ @regularization = regularization
28
28
  @predictions = nil
29
29
  @iterations = iterations
30
30
  end
@@ -32,7 +32,7 @@ class CofiCost
32
32
  def normalize_ratings
33
33
  for i in 0..@num_tracks-1 # sadly, @num_tracks.each_index does not work with NArray yet
34
34
  track_rating = @ratings[true,i] # get all user ratings for track i (including unrated)
35
- boolean_track_rating = boolean_rated[true,i] # get all user ratings that exist for track i
35
+ boolean_track_rating = @boolean_rated[true,i] # get all user ratings that exist for track i
36
36
  track_rating_boolean = track_rating[boolean_track_rating]
37
37
  if track_rating_boolean.size == 0
38
38
  @ratings_mean[i] = 0
@@ -54,21 +54,15 @@ class CofiCost
54
54
  return theta, features
55
55
  end
56
56
 
57
- def partial_cost_calc(theta,features)
57
+ def partial_cost_calc(theta=@theta,features=@features)
58
58
  (NArray.ref(NMatrix.ref(features) * NMatrix.ref(theta.transpose(1,0))) - @ratings_norm) * @boolean_rated
59
59
  end
60
60
 
61
61
  def roll_up_theta_and_features
62
- # roll up theta and features together
63
- # (oddly, NArray objects created don't seem to recognize the hcat method
64
- # added to the open class NArray
65
- # x = GSL:: Vector.alloc(@theta.reshape(true).hcat(@features.reshape(true)))
66
- # will fail)
67
- # I don't understand why this is/how to fix it.
68
62
  theta_reshaped = @theta.reshape(true)
69
63
  features_reshaped = @features.reshape(true)
70
64
  rolled = NArray.hcat(theta_reshaped,features_reshaped)
71
- GSL:: Vector.alloc(rolled) # starting point
65
+ GSL::Vector.alloc(rolled) # starting point
72
66
  end
73
67
 
74
68
  def unroll_params_init_shape(x)
@@ -79,22 +73,22 @@ class CofiCost
79
73
 
80
74
  def min_cost
81
75
  cost_f = Proc.new { |v|
82
- theta, features = unroll_params(v)
76
+ theta_l, features_l = unroll_params(v)
83
77
  # In octave:
84
- # 1/2 * sum(sum(((X * Theta.transpose - Y).*R).^2)) + lambda/2 * sum(sum((Theta).^2)) + lambda/2 * sum(sum((X).^2))
85
- (partial_cost_calc(theta,features)**2).sum + @lambda/2 * (features**2).sum
78
+ # 1/2 * sum(sum(((X * Theta.transpose - Y).*R).^2)) + regularization/2 * sum(sum((Theta).^2)) + regularization/2 * sum(sum((X).^2))
79
+ 0.5 * (partial_cost_calc(theta_l,features_l)**2).sum + @regularization/2 * (features_l**2).sum
86
80
  }
87
81
  cost_df = Proc.new { |v, df|
88
- theta, features = unroll_params(v)
82
+ theta_l, features_l = unroll_params(v)
89
83
  # In octave:
90
- # xgrad = ((X * Theta.transpose - Y).* R) * Theta + lambda * X # X_grad
91
- # thetagrad = ((X * Theta.transpose - Y).* R).transpose * X + lambda * Theta
84
+ # xgrad = ((X * Theta.transpose - Y).* R) * Theta + regularization * X # X_grad
85
+ # thetagrad = ((X * Theta.transpose - Y).* R).transpose * X + regularization * Theta
92
86
 
93
87
  # I realize this is a hack. I'm not totally sure why or how but just setting
94
- # df = NArray.hcat(dfzero,dfone) results in no steps being made in gradient descent.
88
+ # df = NArray.hcat(dfzero,dfone).to_gv results in no steps being made in gradient descent.
95
89
  # ideas/suggestions welcome :)
96
- dfzero = (NArray.ref(NMatrix.ref(partial_cost_calc(theta,features)) * NMatrix.ref(theta)) + @lambda * features).flatten
97
- dfone = (NArray.ref(NMatrix.ref((partial_cost_calc(theta,features)).transpose(1,0)) * NMatrix.ref(features)) + @lambda * theta).flatten
90
+ dfzero = (NArray.ref(NMatrix.ref(partial_cost_calc(theta_l,features_l)) * NMatrix.ref(theta_l)) + @regularization * features_l).flatten
91
+ dfone = (NArray.ref(NMatrix.ref((partial_cost_calc(theta_l,features_l)).transpose(1,0)) * NMatrix.ref(features_l)) + @regularization * theta_l).flatten
98
92
  dfcomp = NArray.hcat(dfzero,dfone)
99
93
  for i in 0..dfcomp.size-1 # again .each_index does not yet work with NArray
100
94
  df[i] = dfcomp[i]
@@ -157,15 +151,3 @@ class NArray
157
151
  def hcat(*narrays) ; cat(0, *narrays) end
158
152
  end
159
153
  end
160
-
161
- ##ratings = NArray.float(4,5).indgen(0,2)
162
- #ratings = NArray[[1.0,4.0],[4.0,0.0],[0.0,0.0]]
163
- #g = CofiCost.new(ratings, 5, 1, 10, nil, nil)
164
- #puts g.theta.nil?
165
- #g.min_cost
166
- #puts "new theta"
167
- #puts g.theta.to_a.to_s
168
- #puts "new features"
169
- #puts g.features.to_a.to_s
170
- #puts "predictions"
171
- #puts g.predictions.to_a.to_s
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cofi_cost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-09-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gsl
16
- requirement: &77565430 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *77565430
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: narray
27
- requirement: &77565210 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *77565210
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  description: Playground for collaborative filtering in Ruby using NArray and rb-gsl.
37
47
  email: tomwolfe@gmail.com
38
48
  executables: []
@@ -64,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
74
  requirements:
65
75
  - libgsl0-dev
66
76
  rubyforge_project:
67
- rubygems_version: 1.8.11
77
+ rubygems_version: 1.8.23
68
78
  signing_key:
69
79
  specification_version: 3
70
80
  summary: Collaborative filtering