110 lines
3.8 KiB
Python
110 lines
3.8 KiB
Python
|
# Boltzmann Machines
|
||
|
|
||
|
# Importing the libraries
|
||
|
import numpy as np
|
||
|
import pandas as pd
|
||
|
import torch
|
||
|
import torch.nn.parallel
|
||
|
import torch.utils.data
|
||
|
|
||
|
# Importing the dataset
|
||
|
movies = pd.read_csv('ml-1m/movies.dat', sep = '::', header = None, engine = 'python', encoding = 'latin-1')
|
||
|
users = pd.read_csv('ml-1m/users.dat', sep = '::', header = None, engine = 'python', encoding = 'latin-1')
|
||
|
ratings = pd.read_csv('ml-1m/ratings.dat', sep = '::', header = None, engine = 'python', encoding = 'latin-1')
|
||
|
|
||
|
# Preparing the training set and the test set
|
||
|
training_set = pd.read_csv('ml-100k/u1.base', delimiter = '\t')
|
||
|
training_set = np.array(training_set, dtype = 'int')
|
||
|
test_set = pd.read_csv('ml-100k/u1.test', delimiter = '\t')
|
||
|
test_set = np.array(test_set, dtype = 'int')
|
||
|
|
||
|
# Getting the number of users and movies
|
||
|
nb_users = int(max(max(training_set[:,0]), max(test_set[:,0])))
|
||
|
nb_movies = int(max(max(training_set[:,1]), max(test_set[:,1])))
|
||
|
|
||
|
# Converting the data into an array with users in lines and movies in columns
|
||
|
def convert(data):
|
||
|
new_data = []
|
||
|
for id_users in range(1, nb_users + 1):
|
||
|
id_movies = data[:,1][data[:,0] == id_users]
|
||
|
id_ratings = data[:,2][data[:,0] == id_users]
|
||
|
ratings = np.zeros(nb_movies)
|
||
|
ratings[id_movies - 1] = id_ratings
|
||
|
new_data.append(list(ratings))
|
||
|
return new_data
|
||
|
training_set = convert(training_set)
|
||
|
test_set = convert(test_set)
|
||
|
|
||
|
# Converting the data into Torch tensors
|
||
|
training_set = torch.FloatTensor(training_set)
|
||
|
test_set = torch.FloatTensor(test_set)
|
||
|
|
||
|
# Converting the ratings into binary ratings 1 (Liked) or 0 (Not Liked)
|
||
|
training_set[training_set == 0] = -1
|
||
|
training_set[training_set == 1] = 0
|
||
|
training_set[training_set == 2] = 0
|
||
|
training_set[training_set >= 3] = 1
|
||
|
test_set[test_set == 0] = -1
|
||
|
test_set[test_set == 1] = 0
|
||
|
test_set[test_set == 2] = 0
|
||
|
test_set[test_set >= 3] = 1
|
||
|
|
||
|
# Creating the architecture of the Neural Network
|
||
|
class RBM():
|
||
|
def __init__(self, nv, nh):
|
||
|
self.W = torch.randn(nh, nv)
|
||
|
self.a = torch.randn(1, nh)
|
||
|
self.b = torch.randn(1, nv)
|
||
|
def sample_h(self, x):
|
||
|
wx = torch.mm(x, self.W.t())
|
||
|
activation = wx + self.a.expand_as(wx)
|
||
|
p_h_given_v = torch.sigmoid(activation)
|
||
|
return p_h_given_v, torch.bernoulli(p_h_given_v)
|
||
|
def sample_v(self, y):
|
||
|
wy = torch.mm(y, self.W)
|
||
|
activation = wy + self.b.expand_as(wy)
|
||
|
p_v_given_h = torch.sigmoid(activation)
|
||
|
return p_v_given_h, torch.bernoulli(p_v_given_h)
|
||
|
def train(self, v0, vk, ph0, phk):
|
||
|
# self.W += torch.mm(v0.t(), ph0) - torch.mm(vk.t(), phk)
|
||
|
self.W += torch.mm(ph0, v0) - torch.mm(phk, vk)
|
||
|
self.b += torch.sum((v0 - vk), 0)
|
||
|
self.a += torch.sum((ph0 - phk), 0)
|
||
|
nv = len(training_set[0])
|
||
|
nh = 100
|
||
|
batch_size = 100
|
||
|
rbm = RBM(nv, nh)
|
||
|
|
||
|
# Training the RBM
|
||
|
nb_epoch = 10
|
||
|
for epoch in range(1, nb_epoch + 1):
|
||
|
train_loss = 0
|
||
|
s = 0.
|
||
|
for id_user in range(0, nb_users - batch_size, batch_size):
|
||
|
vk = training_set[id_user:id_user+batch_size]
|
||
|
v0 = training_set[id_user:id_user+batch_size]
|
||
|
ph0,_ = rbm.sample_h(v0)
|
||
|
for k in range(10):
|
||
|
_,hk = rbm.sample_h(vk)
|
||
|
_,vk = rbm.sample_v(hk)
|
||
|
vk[v0<0] = v0[v0<0]
|
||
|
phk,_ = rbm.sample_h(vk)
|
||
|
rbm.train(v0, vk, ph0, phk)
|
||
|
train_loss += torch.mean(torch.abs(v0[v0>=0] - vk[v0>=0]))
|
||
|
s += 1.
|
||
|
print('epoch: '+str(epoch)+' loss: '+str(train_loss/s))
|
||
|
|
||
|
rbm.W += torch.mm(ph0, v0) - torch.mm(phk, vk)
|
||
|
|
||
|
# Testing the RBM
|
||
|
test_loss = 0
|
||
|
s = 0.
|
||
|
for id_user in range(nb_users):
|
||
|
v = training_set[id_user:id_user+1]
|
||
|
vt = test_set[id_user:id_user+1]
|
||
|
if len(vt[vt>=0]) > 0:
|
||
|
_,h = rbm.sample_h(v)
|
||
|
_,v = rbm.sample_v(h)
|
||
|
test_loss += torch.mean(torch.abs(vt[vt>=0] - v[vt>=0]))
|
||
|
s += 1.
|
||
|
print('test loss: '+str(test_loss/s))
|