Skip to content

Instantly share code, notes, and snippets.

@baharefatemi
Created April 13, 2017 21:02
Show Gist options
  • Save baharefatemi/fc4855242ef587a4582c3b9d6e882d6a to your computer and use it in GitHub Desktop.
Save baharefatemi/fc4855242ef587a4582c3b9d6e882d6a to your computer and use it in GitHub Desktop.
class MF
attr_accessor :base_file, :tag_file, :train_users, :test_users, :genders, :ratings, :items, :users, :r_matrix
def initialize()
@base_file = File.read("u.data")
@tag_file = File.read("u.user")
@train_users = Array.new
@test_users = Array.new
@users = Array.new
@genders = Hash.new
@items = Array.new
@ratings = Hash.new
@k = 1
end
def sigmoid(x)
return 1.0 / (1 + Math.exp(-x))
end
def read_tag_file()
splitted = Array.new
@tag_file.each_line.with_index do |line, i|
splitted = line.split("|")
user = splitted[0].to_i
gender = splitted[2]
@genders[user] = gender
end
end
def read_base_file()
@base_file.each_line.with_index do |line, i|
splitted = line.split(" ")
user = splitted[0].to_i
item = splitted[1].to_i
rating = splitted[2].to_i
time_stamp = splitted[3].to_i
if(time_stamp <= 880845177)
if(not train_users.include? user)
@train_users << user
@ratings[user] = Hash.new
end
if(not items.include? item)
@items << item
end
@ratings[user][item] = rating
elsif(time_stamp <= 884673930)
if(not test_users.include? user)
@test_users << user
@ratings[user] = Hash.new
end
if(not items.include? item)
@items << item
end
@ratings[user][item] = rating
end
end
@test_users -= @train_users
@users = @train_users + @test_users
end
def edit_rating()
@r_matrix = Array.new(@users.size) {Array.new(@items.size)}
@users.each.with_index do |user, u_i|
@items.each.with_index do |item, i_i|
if(@ratings[user][item].nil?)
@r_matrix[u_i][i_i] = 0
# elsif(@ratings[user][item] > 3)
# @r_matrix[u_i][i_i] = 1
# elsif(@ratings[user][item] > 3)
# @r_matrix[u_i][i_i] = 2
else
@r_matrix[u_i][i_i] = 1
end
end
end
end
def learn()
step_size = 0.001
theta = 0.0001
steps = 150
mu = 0.5
alpha = Array.new(@users.size, 0)
betha = Array.new(@items.size, 0)
@p_matrix = Array.new(@users.size) {Array.new(@k, 0)}
q_matrix = Array.new(@k) {Array.new(@items.size, 0)}
alpha.each.with_index do |user, i|
alpha[i] = rand
end
betha.each.with_index do |user, i|
betha[i] = rand
end
@p_matrix.each.with_index do |array, i|
array.each.with_index do |b, j|
@p_matrix[i][j] = rand
end
end
q_matrix.each.with_index do |array, i|
array.each.with_index do |b, j|
q_matrix[i][j] = rand
end
end
p_matrix_old = Array.new(@k, 0)
steps.times do |iteration|
if(iteration % 10 == 0)
puts iteration
end
@users.each.with_index do |user, i|
@items.each.with_index do |item, j|
if(@r_matrix[i][j] != 0)
sigma = 0.0
@k.times do |counter|
sigma += @p_matrix[i][counter] * q_matrix[counter][j]
end
r_prime = sigmoid(mu + alpha[i] + betha[j] + sigma)
diff = (@r_matrix[i][j] - r_prime)
@k.times do |counter|
p_matrix_old[counter] = @p_matrix[i][counter]
end
@k.times do |counter|
@p_matrix[i][counter] += step_size * (diff * q_matrix[counter][j] - theta * @p_matrix[i][counter])
q_matrix[counter][j] += step_size * (diff * p_matrix_old[counter] - theta * q_matrix[counter][j])
end
alpha[i] += step_size * diff
betha[j] += step_size * diff
mu += step_size * diff
end
end
end
end
def write_in_file()
mf_train = File.open("mf_train#{@k}.csv", "w")
mf_test = File.open("mf_test#{@k}.csv", "w")
feature_line = ""
@k.times do |counter|
feature_line << counter.to_s
feature_line << ","
end
feature_line << "label"
mf_train.puts(feature_line)
mf_test.puts(feature_line)
@users.each.with_index do |user, i|
new_line = ""
@k.times do |counter|
new_line << @p_matrix[i][counter].to_s
new_line << ","
end
new_line << genders[users[i]].to_s
if(@train_users.include? users[i])
mf_train.puts(new_line)
elsif(@test_users.include? users[i])
mf_test.puts(new_line)
else
puts "error"
end
end
end
end
end
mf = MF.new
mf.read_tag_file()
mf.read_base_file()
mf.edit_rating()
mf.learn()
mf.write_in_file()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment